accelr8 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{chunk-GXDRLI6N.js → chunk-SY2ASAWX.js} +1 -1
- package/dist/chunks/{client-36OXOMLV.js → client-HLMFYYAQ.js} +138 -52
- package/dist/chunks/install-DL5WLVXN.js +72 -0
- package/dist/chunks/{server-NWTBQYCW.js → server-IVR5UHTM.js} +1 -1
- package/dist/cli.js +3 -3
- package/package.json +2 -2
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
VERSION,
|
|
8
8
|
decode,
|
|
9
9
|
encode
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SY2ASAWX.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_MODEL,
|
|
13
13
|
addAccount,
|
|
@@ -1181,6 +1181,7 @@ var SAMPLE_RATE = 16e3;
|
|
|
1181
1181
|
var CHUNK_BYTES = 1280;
|
|
1182
1182
|
var KILL_GRACE_MS = 300;
|
|
1183
1183
|
var SPEAKER_IDLE_MS = 2e3;
|
|
1184
|
+
var PREBUFFER_BYTES = 4800;
|
|
1184
1185
|
var DRAIN_KILL_MS = 2e3;
|
|
1185
1186
|
var MAX_PLAYERS = 8;
|
|
1186
1187
|
var STDERR_TAIL = 400;
|
|
@@ -1190,7 +1191,9 @@ var PLAYBACK_ARGS = [
|
|
|
1190
1191
|
"-loglevel",
|
|
1191
1192
|
"error",
|
|
1192
1193
|
"-nodisp",
|
|
1193
|
-
"-
|
|
1194
|
+
"-sync",
|
|
1195
|
+
"audio",
|
|
1196
|
+
"-infbuf",
|
|
1194
1197
|
"-f",
|
|
1195
1198
|
"s16le",
|
|
1196
1199
|
"-ar",
|
|
@@ -1352,16 +1355,35 @@ var VoicePlayback = class {
|
|
|
1352
1355
|
if (!spawned) return;
|
|
1353
1356
|
p = spawned;
|
|
1354
1357
|
}
|
|
1355
|
-
if (!
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1358
|
+
if (!p.flowing) {
|
|
1359
|
+
p.pre.push(bytes);
|
|
1360
|
+
if (p.pre.reduce((n, b) => n + b.length, 0) >= PREBUFFER_BYTES) {
|
|
1361
|
+
const cushion = Buffer.concat(p.pre);
|
|
1362
|
+
p.pre = [];
|
|
1363
|
+
p.flowing = true;
|
|
1364
|
+
const np2 = this.writeOrRespawn(speakerId, p, cushion);
|
|
1365
|
+
if (np2) this.touch(speakerId, np2);
|
|
1366
|
+
} else {
|
|
1367
|
+
this.touch(speakerId, p);
|
|
1368
|
+
}
|
|
1369
|
+
return;
|
|
1360
1370
|
}
|
|
1361
|
-
this.
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1371
|
+
const np = this.writeOrRespawn(speakerId, p, bytes);
|
|
1372
|
+
if (np) this.touch(speakerId, np);
|
|
1373
|
+
}
|
|
1374
|
+
/** Write to a player; on EPIPE (it died) respawn once and write there. Returns
|
|
1375
|
+
* the live player, or null if it couldn't be (re)spawned. */
|
|
1376
|
+
writeOrRespawn(speakerId, p, buf) {
|
|
1377
|
+
if (this.write(p, buf)) return p;
|
|
1378
|
+
this.reap(speakerId, p);
|
|
1379
|
+
const fresh = this.players.size < MAX_PLAYERS ? this.spawnPlayer(speakerId) : null;
|
|
1380
|
+
if (!fresh || !this.write(fresh, buf)) return null;
|
|
1381
|
+
fresh.flowing = true;
|
|
1382
|
+
return fresh;
|
|
1383
|
+
}
|
|
1384
|
+
/** Graceful close for one speaker (voiceStop): end stdin so ffplay drains
|
|
1385
|
+
* its buffered audio, then a SIGKILL backstop after 2s (we dropped -autoexit,
|
|
1386
|
+
* so the backstop is what actually reaps the idle player). */
|
|
1365
1387
|
end(speakerId) {
|
|
1366
1388
|
const p = this.players.get(speakerId);
|
|
1367
1389
|
if (!p) return;
|
|
@@ -1404,7 +1426,7 @@ var VoicePlayback = class {
|
|
|
1404
1426
|
} catch {
|
|
1405
1427
|
return null;
|
|
1406
1428
|
}
|
|
1407
|
-
const p = { child, alive: true, idleTimer: null };
|
|
1429
|
+
const p = { child, alive: true, idleTimer: null, pre: [], flowing: false };
|
|
1408
1430
|
child.stdin?.on("error", () => {
|
|
1409
1431
|
p.alive = false;
|
|
1410
1432
|
});
|
|
@@ -1508,24 +1530,74 @@ var overlay = null;
|
|
|
1508
1530
|
var accessAgentId = null;
|
|
1509
1531
|
var overlayFocus = 0;
|
|
1510
1532
|
var updateInfo = null;
|
|
1511
|
-
var
|
|
1512
|
-
var
|
|
1533
|
+
var task = null;
|
|
1534
|
+
var cancelTask = null;
|
|
1513
1535
|
function startUpdate() {
|
|
1514
|
-
if (
|
|
1515
|
-
|
|
1536
|
+
if (task && task.phase === "running") return;
|
|
1537
|
+
task = { title: "updating accelr8", phase: "running", line: "starting npm\u2026", okLabel: "quit now \xB7 enter", onOk: () => shutdown() };
|
|
1516
1538
|
import("./update-UEPNGB6Y.js").then(({ runUpdate }) => {
|
|
1517
|
-
|
|
1539
|
+
cancelTask = runUpdate({
|
|
1518
1540
|
onLine: (l) => {
|
|
1519
|
-
if (
|
|
1541
|
+
if (task) task.line = l.slice(0, 120);
|
|
1520
1542
|
},
|
|
1521
1543
|
onDone: (ok, message) => {
|
|
1522
|
-
|
|
1523
|
-
|
|
1544
|
+
if (task) {
|
|
1545
|
+
task.phase = "done";
|
|
1546
|
+
task.ok = ok;
|
|
1547
|
+
task.line = message;
|
|
1548
|
+
}
|
|
1549
|
+
cancelTask = null;
|
|
1524
1550
|
if (ok) updateInfo = null;
|
|
1525
1551
|
}
|
|
1526
1552
|
});
|
|
1527
1553
|
}).catch(() => {
|
|
1528
|
-
|
|
1554
|
+
if (task) {
|
|
1555
|
+
task.phase = "done";
|
|
1556
|
+
task.ok = false;
|
|
1557
|
+
task.line = "could not load the updater \xB7 npm i -g accelr8@latest";
|
|
1558
|
+
}
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
function startVoiceInstall() {
|
|
1562
|
+
import("./install-DL5WLVXN.js").then(({ ffmpegInstallPlan, runCommand }) => {
|
|
1563
|
+
const plan = ffmpegInstallPlan();
|
|
1564
|
+
if (!plan.auto) {
|
|
1565
|
+
state.status = `voice needs ffmpeg \xB7 ${plan.manual}`;
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
const auto = plan.auto;
|
|
1569
|
+
task = {
|
|
1570
|
+
title: "enable voice",
|
|
1571
|
+
phase: "confirm",
|
|
1572
|
+
line: `voice needs ffmpeg \xB7 ${auto.label} \xB7 press enter`,
|
|
1573
|
+
run: () => {
|
|
1574
|
+
if (!task) return;
|
|
1575
|
+
task.phase = "running";
|
|
1576
|
+
task.line = "installing ffmpeg\u2026";
|
|
1577
|
+
cancelTask = runCommand(auto.cmd, auto.args, {
|
|
1578
|
+
onLine: (l) => {
|
|
1579
|
+
if (task) task.line = l.slice(0, 120);
|
|
1580
|
+
},
|
|
1581
|
+
onDone: (ok, message) => {
|
|
1582
|
+
if (task) {
|
|
1583
|
+
task.phase = "done";
|
|
1584
|
+
task.ok = ok;
|
|
1585
|
+
task.line = ok ? "ffmpeg ready \xB7 voice is on" : message + " \xB7 " + auto.label;
|
|
1586
|
+
task.okLabel = ok ? "start voice \xB7 enter" : void 0;
|
|
1587
|
+
}
|
|
1588
|
+
cancelTask = null;
|
|
1589
|
+
}
|
|
1590
|
+
});
|
|
1591
|
+
},
|
|
1592
|
+
onOk: () => {
|
|
1593
|
+
voiceTools = null;
|
|
1594
|
+
task = null;
|
|
1595
|
+
toggleVoice();
|
|
1596
|
+
}
|
|
1597
|
+
// re-detect + join
|
|
1598
|
+
};
|
|
1599
|
+
}).catch(() => {
|
|
1600
|
+
state.status = "could not load the installer";
|
|
1529
1601
|
});
|
|
1530
1602
|
}
|
|
1531
1603
|
var voiceTools = null;
|
|
@@ -1541,7 +1613,7 @@ function toggleVoice() {
|
|
|
1541
1613
|
}
|
|
1542
1614
|
voiceTools = voiceTools ?? detectVoiceTools();
|
|
1543
1615
|
if (!voiceTools.capture && !voiceTools.playback) {
|
|
1544
|
-
|
|
1616
|
+
startVoiceInstall();
|
|
1545
1617
|
return;
|
|
1546
1618
|
}
|
|
1547
1619
|
voicePlayback = new VoicePlayback(voiceTools);
|
|
@@ -1549,7 +1621,7 @@ function toggleVoice() {
|
|
|
1549
1621
|
voiceOn = true;
|
|
1550
1622
|
voiceTransmit = false;
|
|
1551
1623
|
sendMsg({ t: "voiceJoin" });
|
|
1552
|
-
state.status = voiceTools.capture ? "voice on \xB7 ctrl-g to
|
|
1624
|
+
state.status = voiceTools.capture ? "voice on \xB7 /talk (or ctrl-g) to speak" : "voice on \xB7 listen only (no mic found)";
|
|
1553
1625
|
}
|
|
1554
1626
|
function leaveVoice() {
|
|
1555
1627
|
if (!voiceOn) return;
|
|
@@ -1572,10 +1644,10 @@ function toggleTalk() {
|
|
|
1572
1644
|
if (voiceTransmit) {
|
|
1573
1645
|
voiceCapture.stop();
|
|
1574
1646
|
voiceTransmit = false;
|
|
1575
|
-
state.status = "muted \xB7 ctrl-g to
|
|
1647
|
+
state.status = "muted \xB7 /talk (or ctrl-g) to speak";
|
|
1576
1648
|
} else {
|
|
1577
1649
|
voiceTransmit = true;
|
|
1578
|
-
state.status = "\u25CF live \xB7 ctrl-g to
|
|
1650
|
+
state.status = "\u25CF live \xB7 /mute (or ctrl-g) to stop";
|
|
1579
1651
|
voiceCapture.start({
|
|
1580
1652
|
onChunk: (b64) => {
|
|
1581
1653
|
if (voiceTransmit) sendMsg({ t: "voiceFrame", data: b64 });
|
|
@@ -2203,6 +2275,9 @@ function __curTheme() {
|
|
|
2203
2275
|
function __setUpdate(latest, current = "3.0.0") {
|
|
2204
2276
|
updateInfo = latest ? { latest, current } : null;
|
|
2205
2277
|
}
|
|
2278
|
+
function __taskDemo(phase, ok = true) {
|
|
2279
|
+
task = { title: "enable voice", phase, ok, line: phase === "confirm" ? "voice needs ffmpeg \xB7 brew install ffmpeg \xB7 press enter" : phase === "running" ? "installing ffmpeg\u2026" : ok ? "ffmpeg ready \xB7 voice is on" : "brew exited 1 \xB7 brew install ffmpeg", okLabel: "start voice \xB7 enter" };
|
|
2280
|
+
}
|
|
2206
2281
|
function __closeOverlay() {
|
|
2207
2282
|
overlay = null;
|
|
2208
2283
|
}
|
|
@@ -2288,28 +2363,36 @@ function render() {
|
|
|
2288
2363
|
overlayFocus = clickables.length ? Math.max(0, Math.min(overlayFocus, clickables.length - 1)) : 0;
|
|
2289
2364
|
}
|
|
2290
2365
|
if (state.modal && bigEnough) renderModal();
|
|
2291
|
-
if (
|
|
2366
|
+
if (task && bigEnough) renderTask();
|
|
2292
2367
|
if (screen.dst) screen.draw({ delta: true });
|
|
2293
2368
|
}
|
|
2294
|
-
function
|
|
2369
|
+
function renderTask() {
|
|
2295
2370
|
clickables = [];
|
|
2296
2371
|
const w = W(), h = H();
|
|
2297
2372
|
const bw = Math.min(66, w - 6), bh = 7;
|
|
2298
2373
|
const x0 = Math.floor((w - bw) / 2), y0 = Math.floor((h - bh) / 2);
|
|
2299
2374
|
for (let yy = y0; yy < y0 + bh; yy++) puts(x0, yy, " ".repeat(bw), { bgColor: C.panel });
|
|
2300
|
-
box(x0, y0, x0 + bw - 1, y0 + bh - 1, { color: C.accent, bgColor: C.panel },
|
|
2301
|
-
const
|
|
2302
|
-
if (
|
|
2303
|
-
puts(x0 + 2, y0 + 2,
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2375
|
+
box(x0, y0, x0 + bw - 1, y0 + bh - 1, { color: C.accent, bgColor: C.panel }, task.title);
|
|
2376
|
+
const t = task;
|
|
2377
|
+
if (t.phase === "confirm") {
|
|
2378
|
+
puts(x0 + 2, y0 + 2, t.line.slice(0, bw - 4), { color: C.bright, bgColor: C.panel, bold: true });
|
|
2379
|
+
button(x0 + 2, y0 + 4, " install \xB7 enter ", { bgColor: C.accent, color: onFill(C.accent), bold: true }, () => t.run?.());
|
|
2380
|
+
button(x0 + 20, y0 + 4, " not now \xB7 esc ", { bgColor: C.tabOff, color: C.text }, () => {
|
|
2381
|
+
task = null;
|
|
2382
|
+
});
|
|
2383
|
+
} else if (t.phase === "running") {
|
|
2384
|
+
puts(x0 + 2, y0 + 2, `${SPINNER[frame % SPINNER.length]} ${t.title}\u2026`, { color: C.bright, bgColor: C.panel, bold: true });
|
|
2385
|
+
puts(x0 + 2, y0 + 4, ("\xB7 " + t.line).slice(0, bw - 4), { color: C.dim, bgColor: C.panel });
|
|
2386
|
+
} else if (t.ok) {
|
|
2387
|
+
puts(x0 + 2, y0 + 2, "\u2713 " + t.line.slice(0, bw - 6), { color: C.good, bgColor: C.panel, bold: true });
|
|
2388
|
+
if (t.okLabel) button(x0 + 2, y0 + 4, ` ${t.okLabel} `, { bgColor: C.good, color: onFill(C.good), bold: true }, () => t.onOk?.());
|
|
2389
|
+
else button(x0 + 2, y0 + 4, " close \xB7 enter ", { bgColor: C.good, color: onFill(C.good), bold: true }, () => {
|
|
2390
|
+
task = null;
|
|
2391
|
+
});
|
|
2309
2392
|
} else {
|
|
2310
|
-
puts(x0 + 2, y0 + 2, "\u2715 " +
|
|
2393
|
+
puts(x0 + 2, y0 + 2, "\u2715 " + t.line.slice(0, bw - 6), { color: C.danger, bgColor: C.panel, bold: true });
|
|
2311
2394
|
button(x0 + 2, y0 + 4, " close \xB7 esc ", { bgColor: C.tabOff, color: C.text }, () => {
|
|
2312
|
-
|
|
2395
|
+
task = null;
|
|
2313
2396
|
});
|
|
2314
2397
|
}
|
|
2315
2398
|
}
|
|
@@ -2591,7 +2674,7 @@ function renderHome(rung) {
|
|
|
2591
2674
|
}
|
|
2592
2675
|
y += 1;
|
|
2593
2676
|
}
|
|
2594
|
-
if (updateInfo && !
|
|
2677
|
+
if (updateInfo && !task) {
|
|
2595
2678
|
puts(2, y, "\u21BB", { color: C.warn, bold: true });
|
|
2596
2679
|
const w2 = W();
|
|
2597
2680
|
const label = ` update to v${updateInfo.latest} \xB7 press enter `;
|
|
@@ -2652,7 +2735,7 @@ function renderStatusBar(rung) {
|
|
|
2652
2735
|
const drawn = left.slice(0, w - 24);
|
|
2653
2736
|
puts(0, sy, drawn, { bgColor: C.panel, color: C.dim });
|
|
2654
2737
|
if (voiceOn) {
|
|
2655
|
-
const label = voiceTransmit ? " \u25CF live \xB7
|
|
2738
|
+
const label = voiceTransmit ? " \u25CF live \xB7 /mute" : ` \u25CB voice ${state.voicePeers.length} \xB7 /talk`;
|
|
2656
2739
|
if (drawn.length + label.length < w - 24) puts(drawn.length, sy, label, { bgColor: C.panel, color: voiceTransmit ? C.good : C.accent, bold: voiceTransmit });
|
|
2657
2740
|
}
|
|
2658
2741
|
const hint = state.modal ? "[enter] ok \xB7 [esc] cancel " : "[tab] tabs \xB7 [^C] quit ";
|
|
@@ -3333,7 +3416,7 @@ function onMouse(name, data) {
|
|
|
3333
3416
|
return;
|
|
3334
3417
|
}
|
|
3335
3418
|
if (state.modal) return;
|
|
3336
|
-
if (
|
|
3419
|
+
if (task) {
|
|
3337
3420
|
if (name === "MOUSE_LEFT_BUTTON_PRESSED") {
|
|
3338
3421
|
for (const r of clickables) if (mx >= r.x0 && mx <= r.x1 && my >= r.y0 && my <= r.y1) {
|
|
3339
3422
|
r.action();
|
|
@@ -3479,25 +3562,27 @@ function sendChat() {
|
|
|
3479
3562
|
}
|
|
3480
3563
|
function onKey(name) {
|
|
3481
3564
|
if (name === "CTRL_C") return shutdown();
|
|
3482
|
-
if (name === "CTRL_G" && voiceOn) return toggleTalk();
|
|
3565
|
+
if ((name === "CTRL_G" || name === "CTRL_ALT_G") && voiceOn) return toggleTalk();
|
|
3483
3566
|
if (boot) return skipBoot();
|
|
3484
3567
|
const rung = rungFor(W(), H());
|
|
3485
3568
|
if (rung === "micro" || rung === "orb") return;
|
|
3486
3569
|
const paused = rung === "ticker";
|
|
3487
|
-
if (
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
}
|
|
3570
|
+
if (task && !paused) {
|
|
3571
|
+
const enter = name === "ENTER" || name === "KP_ENTER";
|
|
3572
|
+
if (task.phase === "confirm") {
|
|
3573
|
+
if (enter) task.run?.();
|
|
3574
|
+
else if (name === "ESCAPE") task = null;
|
|
3493
3575
|
return;
|
|
3494
3576
|
}
|
|
3495
|
-
if (
|
|
3496
|
-
if (name === "
|
|
3497
|
-
|
|
3577
|
+
if (task.phase === "running") {
|
|
3578
|
+
if (name === "ESCAPE") {
|
|
3579
|
+
cancelTask?.();
|
|
3580
|
+
task = null;
|
|
3581
|
+
}
|
|
3498
3582
|
return;
|
|
3499
3583
|
}
|
|
3500
|
-
if (
|
|
3584
|
+
if (enter && task.ok && task.onOk) return task.onOk();
|
|
3585
|
+
if (enter || name === "ESCAPE") task = null;
|
|
3501
3586
|
return;
|
|
3502
3587
|
}
|
|
3503
3588
|
if (state.modal && !paused) {
|
|
@@ -3807,6 +3892,7 @@ export {
|
|
|
3807
3892
|
__setMySid,
|
|
3808
3893
|
__setNav,
|
|
3809
3894
|
__setUpdate,
|
|
3895
|
+
__taskDemo,
|
|
3810
3896
|
chatLog,
|
|
3811
3897
|
cursors,
|
|
3812
3898
|
editor,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/install.ts
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
function which(bin) {
|
|
8
|
+
const exts = process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""];
|
|
9
|
+
for (const dir of (process.env.PATH ?? "").split(path.delimiter).filter(Boolean)) {
|
|
10
|
+
for (const ext of exts) {
|
|
11
|
+
const p = path.join(dir, bin + ext);
|
|
12
|
+
try {
|
|
13
|
+
fs.accessSync(p, fs.constants.X_OK);
|
|
14
|
+
if (fs.statSync(p).isFile()) return true;
|
|
15
|
+
} catch {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
function ffmpegInstallPlan(platform = process.platform) {
|
|
22
|
+
if (platform === "darwin") {
|
|
23
|
+
if (which("brew")) return { auto: { cmd: "brew", args: ["install", "ffmpeg"], label: "brew install ffmpeg" }, manual: "brew install ffmpeg" };
|
|
24
|
+
return { manual: "install Homebrew from brew.sh, then: brew install ffmpeg", note: "Homebrew not found" };
|
|
25
|
+
}
|
|
26
|
+
if (platform === "win32") {
|
|
27
|
+
if (which("winget")) return { auto: { cmd: "winget", args: ["install", "--silent", "--accept-package-agreements", "--accept-source-agreements", "Gyan.FFmpeg"], label: "winget install ffmpeg" }, manual: "winget install Gyan.FFmpeg" };
|
|
28
|
+
if (which("choco")) return { auto: { cmd: "choco", args: ["install", "-y", "ffmpeg-full"], label: "choco install ffmpeg-full" }, manual: "choco install ffmpeg-full" };
|
|
29
|
+
return { manual: "install ffmpeg from ffmpeg.org and add it to PATH", note: "no winget/choco found" };
|
|
30
|
+
}
|
|
31
|
+
if (which("apt-get") || which("apt")) return { manual: "sudo apt install ffmpeg", note: "needs sudo \u2014 run it in your shell" };
|
|
32
|
+
if (which("dnf")) return { manual: "sudo dnf install ffmpeg", note: "needs sudo \u2014 run it in your shell" };
|
|
33
|
+
if (which("pacman")) return { manual: "sudo pacman -S ffmpeg", note: "needs sudo \u2014 run it in your shell" };
|
|
34
|
+
return { manual: "install ffmpeg with your package manager", note: "unknown package manager" };
|
|
35
|
+
}
|
|
36
|
+
function runCommand(cmd, args, cb) {
|
|
37
|
+
let child;
|
|
38
|
+
try {
|
|
39
|
+
child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
40
|
+
} catch (e) {
|
|
41
|
+
queueMicrotask(() => cb.onDone(false, `couldn't start ${cmd}`));
|
|
42
|
+
return () => {
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
let tail = "";
|
|
46
|
+
const feed = (chunk) => {
|
|
47
|
+
tail += chunk.toString();
|
|
48
|
+
let nl;
|
|
49
|
+
while ((nl = tail.indexOf("\n")) >= 0) {
|
|
50
|
+
const line = tail.slice(0, nl).trim();
|
|
51
|
+
tail = tail.slice(nl + 1);
|
|
52
|
+
if (line) cb.onLine(line);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
child.stdout?.on("data", feed);
|
|
56
|
+
child.stderr?.on("data", feed);
|
|
57
|
+
child.on("error", (e) => cb.onDone(false, e.code === "ENOENT" ? `${cmd} not found` : e.message));
|
|
58
|
+
child.on("close", (code) => {
|
|
59
|
+
if (tail.trim()) cb.onLine(tail.trim());
|
|
60
|
+
cb.onDone(code === 0, code === 0 ? "installed" : `${cmd} exited ${code}`);
|
|
61
|
+
});
|
|
62
|
+
return () => {
|
|
63
|
+
try {
|
|
64
|
+
child.kill();
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
ffmpegInstallPlan,
|
|
71
|
+
runCommand
|
|
72
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DEFAULT_SERVER,
|
|
4
4
|
PORT,
|
|
5
5
|
VERSION
|
|
6
|
-
} from "./chunks/chunk-
|
|
6
|
+
} from "./chunks/chunk-SY2ASAWX.js";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
var HELP = `
|
|
@@ -52,7 +52,7 @@ async function main() {
|
|
|
52
52
|
console.error(`invalid port: ${argVal(args, "--port")}`);
|
|
53
53
|
process.exit(1);
|
|
54
54
|
}
|
|
55
|
-
const { runServer } = await import("./chunks/server-
|
|
55
|
+
const { runServer } = await import("./chunks/server-IVR5UHTM.js");
|
|
56
56
|
runServer(port);
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
@@ -76,7 +76,7 @@ async function main() {
|
|
|
76
76
|
const { cachedUpdate, refreshUpdateCache } = await import("./chunks/update-UEPNGB6Y.js");
|
|
77
77
|
refreshUpdateCache();
|
|
78
78
|
const update = cachedUpdate(VERSION);
|
|
79
|
-
const { runClient } = await import("./chunks/client-
|
|
79
|
+
const { runClient } = await import("./chunks/client-HLMFYYAQ.js");
|
|
80
80
|
runClient({
|
|
81
81
|
name: argVal(args, "--name"),
|
|
82
82
|
server: argVal(args, "--server"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "accelr8",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Collaborative ascii canvas in your terminal. Real multiplayer, live cursors, mouse-driven TUI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "ISC",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"chattest": "tsx src/chattest.ts",
|
|
43
43
|
"inputtest": "tsx src/inputtest.ts",
|
|
44
44
|
"torturetest": "tsx src/torturetest.ts",
|
|
45
|
-
"test": "for t in core chat input ladder boot orb crypto accounts executor agentcontext map voice glyph materialize update contrast; do tsx src/${t}test.ts || exit 1; done && tsx src/rendertest.ts > /dev/null && echo RENDER OK",
|
|
45
|
+
"test": "for t in core chat input ladder boot orb crypto accounts executor agentcontext map voice glyph materialize update install contrast; do tsx src/${t}test.ts || exit 1; done && tsx src/rendertest.ts > /dev/null && echo RENDER OK",
|
|
46
46
|
"laddertest": "tsx src/laddertest.ts",
|
|
47
47
|
"boottest": "tsx src/boottest.ts",
|
|
48
48
|
"reconnecttest": "tsx src/reconnecttest.ts",
|