accelr8 3.0.3 → 3.0.4
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.
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
VERSION,
|
|
8
8
|
decode,
|
|
9
9
|
encode
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-I5NIANY6.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_MODEL,
|
|
13
13
|
addAccount,
|
|
@@ -1476,6 +1476,55 @@ var VoicePlayback = class {
|
|
|
1476
1476
|
if (this.players.get(speakerId) === p) this.players.delete(speakerId);
|
|
1477
1477
|
}
|
|
1478
1478
|
};
|
|
1479
|
+
function listMicDevices() {
|
|
1480
|
+
try {
|
|
1481
|
+
if (process.platform === "darwin") {
|
|
1482
|
+
const text = runForOutput(["-hide_banner", "-f", "avfoundation", "-list_devices", "true", "-i", ""]);
|
|
1483
|
+
const out = [];
|
|
1484
|
+
let inAudio = false;
|
|
1485
|
+
for (const line of text.split("\n")) {
|
|
1486
|
+
if (/audio devices/i.test(line)) {
|
|
1487
|
+
inAudio = true;
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
if (/video devices/i.test(line)) {
|
|
1491
|
+
inAudio = false;
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
if (!inAudio) continue;
|
|
1495
|
+
const m = line.match(/\[(\d+)\]\s+(.+?)\s*$/);
|
|
1496
|
+
if (m) out.push({ index: m[1], name: m[2] });
|
|
1497
|
+
}
|
|
1498
|
+
return out;
|
|
1499
|
+
}
|
|
1500
|
+
if (process.platform === "linux") {
|
|
1501
|
+
const text = runForOutput(["-hide_banner", "-sources", "pulse"]);
|
|
1502
|
+
const out = [];
|
|
1503
|
+
for (const line of text.split("\n")) {
|
|
1504
|
+
if (/auto-detected/i.test(line)) continue;
|
|
1505
|
+
const m = line.match(/^\s*\*?\s*(\S+)\s+\[(.+)\]\s*$/);
|
|
1506
|
+
if (m) out.push({ index: m[1], name: m[2] });
|
|
1507
|
+
}
|
|
1508
|
+
return out;
|
|
1509
|
+
}
|
|
1510
|
+
if (process.platform === "win32") {
|
|
1511
|
+
const text = runForOutput(["-hide_banner", "-list_devices", "true", "-f", "dshow", "-i", "dummy"]);
|
|
1512
|
+
const out = [];
|
|
1513
|
+
for (const line of text.split("\n")) {
|
|
1514
|
+
const m = line.match(/"(.+)"\s+\(audio\)/);
|
|
1515
|
+
if (m) out.push({ index: m[1], name: m[1] });
|
|
1516
|
+
}
|
|
1517
|
+
return out;
|
|
1518
|
+
}
|
|
1519
|
+
return [];
|
|
1520
|
+
} catch {
|
|
1521
|
+
return [];
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
function runForOutput(args) {
|
|
1525
|
+
const res = spawnSync("ffmpeg", args, { encoding: "utf8", timeout: 5e3 });
|
|
1526
|
+
return (res.stderr ?? "") + (res.stdout ?? "");
|
|
1527
|
+
}
|
|
1479
1528
|
function errMsg(e) {
|
|
1480
1529
|
return e instanceof Error ? e.message : String(e);
|
|
1481
1530
|
}
|
|
@@ -1605,6 +1654,41 @@ var voiceOn = false;
|
|
|
1605
1654
|
var voiceTransmit = false;
|
|
1606
1655
|
var voiceCapture = null;
|
|
1607
1656
|
var voicePlayback = null;
|
|
1657
|
+
var voiceDevice = process.env.ACCELR8_MIC || void 0;
|
|
1658
|
+
var voiceRetries = 0;
|
|
1659
|
+
function autoPickMic() {
|
|
1660
|
+
if (process.platform !== "darwin") return void 0;
|
|
1661
|
+
const mics = listMicDevices();
|
|
1662
|
+
if (!mics.length) return void 0;
|
|
1663
|
+
const builtin = mics.find((m) => /macbook|built.?in|internal/i.test(m.name));
|
|
1664
|
+
if (builtin) return builtin.index;
|
|
1665
|
+
const notPhone = mics.find((m) => !/iphone|ipad|continuity|desk view/i.test(m.name));
|
|
1666
|
+
return notPhone?.index;
|
|
1667
|
+
}
|
|
1668
|
+
function startCapture() {
|
|
1669
|
+
if (!voiceCapture) return;
|
|
1670
|
+
voiceCapture.start({
|
|
1671
|
+
device: voiceDevice,
|
|
1672
|
+
onChunk: (b64) => {
|
|
1673
|
+
voiceRetries = 0;
|
|
1674
|
+
if (voiceTransmit) sendMsg({ t: "voiceFrame", data: b64 });
|
|
1675
|
+
},
|
|
1676
|
+
onError: (m) => {
|
|
1677
|
+
if (!voiceTransmit) return;
|
|
1678
|
+
voiceRetries++;
|
|
1679
|
+
if (voiceRetries <= 6) {
|
|
1680
|
+
state.status = `mic dropped \xB7 reconnecting ${voiceRetries}\u2026`;
|
|
1681
|
+
setTimeout(() => {
|
|
1682
|
+
if (voiceTransmit && voiceCapture && !voiceCapture.active) startCapture();
|
|
1683
|
+
}, 200);
|
|
1684
|
+
} else {
|
|
1685
|
+
voiceTransmit = false;
|
|
1686
|
+
voiceRetries = 0;
|
|
1687
|
+
state.status = "mic keeps dropping \xB7 /voice mics to pick another \xB7 " + m.slice(0, 30);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1608
1692
|
function toggleVoice() {
|
|
1609
1693
|
if (voiceOn) return leaveVoice();
|
|
1610
1694
|
if (!state.project) {
|
|
@@ -1620,6 +1704,7 @@ function toggleVoice() {
|
|
|
1620
1704
|
voiceCapture = new VoiceCapture(voiceTools);
|
|
1621
1705
|
voiceOn = true;
|
|
1622
1706
|
voiceTransmit = false;
|
|
1707
|
+
if (voiceDevice === void 0 && voiceTools.capture) voiceDevice = autoPickMic();
|
|
1623
1708
|
sendMsg({ t: "voiceJoin" });
|
|
1624
1709
|
state.status = voiceTools.capture ? "voice on \xB7 /talk (or ctrl-g) to speak" : "voice on \xB7 listen only (no mic found)";
|
|
1625
1710
|
}
|
|
@@ -1642,21 +1727,15 @@ function toggleTalk() {
|
|
|
1642
1727
|
return;
|
|
1643
1728
|
}
|
|
1644
1729
|
if (voiceTransmit) {
|
|
1645
|
-
voiceCapture.stop();
|
|
1646
1730
|
voiceTransmit = false;
|
|
1731
|
+
voiceRetries = 0;
|
|
1732
|
+
voiceCapture.stop();
|
|
1647
1733
|
state.status = "muted \xB7 /talk (or ctrl-g) to speak";
|
|
1648
1734
|
} else {
|
|
1649
1735
|
voiceTransmit = true;
|
|
1736
|
+
voiceRetries = 0;
|
|
1650
1737
|
state.status = "\u25CF live \xB7 /mute (or ctrl-g) to stop";
|
|
1651
|
-
|
|
1652
|
-
onChunk: (b64) => {
|
|
1653
|
-
if (voiceTransmit) sendMsg({ t: "voiceFrame", data: b64 });
|
|
1654
|
-
},
|
|
1655
|
-
onError: (m) => {
|
|
1656
|
-
voiceTransmit = false;
|
|
1657
|
-
state.status = "mic error \xB7 " + m.slice(0, 44);
|
|
1658
|
-
}
|
|
1659
|
-
});
|
|
1738
|
+
startCapture();
|
|
1660
1739
|
}
|
|
1661
1740
|
}
|
|
1662
1741
|
function openHelp() {
|
|
@@ -3037,7 +3116,7 @@ function renderAccounts() {
|
|
|
3037
3116
|
puts(ix + 46, y, a.auth.kind === "claude_code_login" ? "claude login" : "api key", { color: C.dim });
|
|
3038
3117
|
puts(ix + 60, y, status, { color: dotColor });
|
|
3039
3118
|
const modeColor = a.mode === "auto" ? C.warn : a.mode === "plan" ? C.accent : C.good;
|
|
3040
|
-
button(w - 22, y, ` ${a.mode} `, { bgColor: C.tabOff, color: modeColor, bold: true }, () => cycleMode(a));
|
|
3119
|
+
button(w - 22, y, ` ${a.mode} `, { bgColor: C.tabOff, color: readableFg(modeColor, C.tabOff), bold: true }, () => cycleMode(a));
|
|
3041
3120
|
button(w - 11, y, " remove ", { bgColor: C.tabOff, color: C.text }, () => removeAgentAccount(a));
|
|
3042
3121
|
y += 1;
|
|
3043
3122
|
}
|
|
@@ -3536,6 +3615,19 @@ function slashCommand(text) {
|
|
|
3536
3615
|
toggleVoice();
|
|
3537
3616
|
} else if (cmd === "/talk" || cmd === "/mute") {
|
|
3538
3617
|
toggleTalk();
|
|
3618
|
+
} else if (cmd === "/voice mics" || cmd === "/mics") {
|
|
3619
|
+
const mics = listMicDevices();
|
|
3620
|
+
sidecarBlock = { title: "microphones", at: Date.now(), lines: mics.length ? mics.map((m) => `${m.index} ${m.name}${voiceDevice === m.index ? " \xB7 selected" : ""}`).concat("use: /voice mic <index>") : ["none found (need ffmpeg)"] };
|
|
3621
|
+
state.status = `${mics.length} mics \xB7 /voice mic <index> to pick`;
|
|
3622
|
+
} else if (cmd.startsWith("/voice mic ")) {
|
|
3623
|
+
const idx = cmd.slice("/voice mic ".length).trim();
|
|
3624
|
+
voiceDevice = idx || void 0;
|
|
3625
|
+
state.status = `mic set to [${idx}]` + (voiceOn ? " \xB7 reconnecting" : "");
|
|
3626
|
+
if (voiceTransmit && voiceCapture) {
|
|
3627
|
+
voiceCapture.stop();
|
|
3628
|
+
voiceRetries = 0;
|
|
3629
|
+
startCapture();
|
|
3630
|
+
}
|
|
3539
3631
|
} else {
|
|
3540
3632
|
state.status = `unknown command: ${cmd.split(" ")[0]}`;
|
|
3541
3633
|
}
|
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-I5NIANY6.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-QZIOVRDR.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-BVLUBSS7.js");
|
|
80
80
|
runClient({
|
|
81
81
|
name: argVal(args, "--name"),
|
|
82
82
|
server: argVal(args, "--server"),
|