svamp-cli 0.2.90 → 0.2.92
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/{agentCommands-BjhBmutV.mjs → agentCommands-t6HbehoC.mjs} +2 -2
- package/dist/{auth-LB4hwDfW.mjs → auth-Dx09pKt3.mjs} +3 -3
- package/dist/cli.mjs +105 -53
- package/dist/{commands-Bg7NZ6PK.mjs → commands-BHSvizSp.mjs} +3 -3
- package/dist/{commands-mlxYf-v-.mjs → commands-BR_lAgZ0.mjs} +39 -6
- package/dist/{commands-sQMe36dC.mjs → commands-BxluPors.mjs} +2 -2
- package/dist/{commands-C-5cSioE.mjs → commands-Dfyuenmi.mjs} +5 -5
- package/dist/{commands-XrfOgVzR.mjs → commands-pVw3CcRo.mjs} +3 -3
- package/dist/{fleet-Dts-Z6LV.mjs → fleet-C3KLMFeD.mjs} +3 -3
- package/dist/{frpc-DTA0--Z7.mjs → frpc-D_1pEpUY.mjs} +3 -3
- package/dist/headlessCli-D-unuCQt.mjs +331 -0
- package/dist/index.mjs +3 -3
- package/dist/{package-DR--K5aO.mjs → package-_Qk8lnvq.mjs} +2 -2
- package/dist/{run-1BK4-WPo.mjs → run-BF4AmFz8.mjs} +3047 -2182
- package/dist/{run-DrC7KnK3.mjs → run-l1OtW948.mjs} +2 -2
- package/dist/{serveCommands-BXn2hnJ0.mjs → serveCommands-CvhlM4Iz.mjs} +5 -5
- package/dist/{serveManager-Cd2gJI7J.mjs → serveManager-DNlqB0r6.mjs} +4 -4
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import { createServer } from 'node:http';
|
|
3
|
-
import { R as RoutineStore, m as RoutineRunner } from './run-
|
|
3
|
+
import { R as RoutineStore, m as RoutineRunner } from './run-BF4AmFz8.mjs';
|
|
4
4
|
import 'os';
|
|
5
5
|
import 'fs/promises';
|
|
6
6
|
import 'fs';
|
|
@@ -9,11 +9,11 @@ import 'url';
|
|
|
9
9
|
import 'child_process';
|
|
10
10
|
import 'crypto';
|
|
11
11
|
import 'node:fs';
|
|
12
|
+
import 'ws';
|
|
12
13
|
import 'util';
|
|
13
14
|
import 'node:crypto';
|
|
14
15
|
import 'node:path';
|
|
15
16
|
import 'node:os';
|
|
16
|
-
import 'node:vm';
|
|
17
17
|
import '@agentclientprotocol/sdk';
|
|
18
18
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
19
19
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -58,7 +58,7 @@ async function serviceExpose(args) {
|
|
|
58
58
|
process.exit(1);
|
|
59
59
|
}
|
|
60
60
|
if (foreground) {
|
|
61
|
-
const { runFrpcTunnel } = await import('./frpc-
|
|
61
|
+
const { runFrpcTunnel } = await import('./frpc-D_1pEpUY.mjs');
|
|
62
62
|
await runFrpcTunnel(name, ports, void 0, {
|
|
63
63
|
group,
|
|
64
64
|
groupKey,
|
|
@@ -68,7 +68,7 @@ async function serviceExpose(args) {
|
|
|
68
68
|
});
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
71
|
+
const { connectAndGetMachine } = await import('./commands-BR_lAgZ0.mjs');
|
|
72
72
|
const { server, machine } = await connectAndGetMachine();
|
|
73
73
|
try {
|
|
74
74
|
const status = await machine.tunnelStart({
|
|
@@ -123,7 +123,7 @@ async function serviceServe(args) {
|
|
|
123
123
|
};
|
|
124
124
|
process.on("SIGINT", cleanup);
|
|
125
125
|
process.on("SIGTERM", cleanup);
|
|
126
|
-
const { runFrpcTunnel } = await import('./frpc-
|
|
126
|
+
const { runFrpcTunnel } = await import('./frpc-D_1pEpUY.mjs');
|
|
127
127
|
await runFrpcTunnel(name, [caddyPort]);
|
|
128
128
|
} catch (err) {
|
|
129
129
|
console.error(`Error serving directory: ${err.message}`);
|
|
@@ -132,7 +132,7 @@ async function serviceServe(args) {
|
|
|
132
132
|
}
|
|
133
133
|
async function serviceList(_args) {
|
|
134
134
|
try {
|
|
135
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
135
|
+
const { connectAndGetMachine } = await import('./commands-BR_lAgZ0.mjs');
|
|
136
136
|
const { server, machine } = await connectAndGetMachine();
|
|
137
137
|
try {
|
|
138
138
|
const tunnels = await machine.tunnelList({});
|
|
@@ -161,7 +161,7 @@ async function serviceDelete(args) {
|
|
|
161
161
|
process.exit(1);
|
|
162
162
|
}
|
|
163
163
|
try {
|
|
164
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
164
|
+
const { connectAndGetMachine } = await import('./commands-BR_lAgZ0.mjs');
|
|
165
165
|
const { server, machine } = await connectAndGetMachine();
|
|
166
166
|
try {
|
|
167
167
|
await machine.tunnelStop({ name });
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { writeFileSync, readFileSync } from 'fs';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import { connectAndGetMachine } from './commands-
|
|
3
|
+
import { connectAndGetMachine } from './commands-BR_lAgZ0.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'node:child_process';
|
|
6
6
|
import 'node:path';
|
|
7
7
|
import 'node:os';
|
|
8
|
-
import './run-
|
|
8
|
+
import './run-BF4AmFz8.mjs';
|
|
9
9
|
import 'os';
|
|
10
10
|
import 'fs/promises';
|
|
11
11
|
import 'url';
|
|
12
12
|
import 'child_process';
|
|
13
13
|
import 'crypto';
|
|
14
|
+
import 'ws';
|
|
14
15
|
import 'util';
|
|
15
16
|
import 'node:crypto';
|
|
16
|
-
import 'node:vm';
|
|
17
17
|
import '@agentclientprotocol/sdk';
|
|
18
18
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
19
19
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import { c as connectToHypha } from './run-
|
|
4
|
+
import { c as connectToHypha } from './run-BF4AmFz8.mjs';
|
|
5
5
|
import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-HydRNEt7.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
@@ -10,10 +10,10 @@ import 'path';
|
|
|
10
10
|
import 'url';
|
|
11
11
|
import 'child_process';
|
|
12
12
|
import 'crypto';
|
|
13
|
+
import 'node:child_process';
|
|
14
|
+
import 'ws';
|
|
13
15
|
import 'util';
|
|
14
16
|
import 'node:crypto';
|
|
15
|
-
import 'node:vm';
|
|
16
|
-
import 'node:child_process';
|
|
17
17
|
import '@agentclientprotocol/sdk';
|
|
18
18
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
19
19
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -3,16 +3,16 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
|
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { homedir, platform, arch } from 'os';
|
|
5
5
|
import { createHash, randomUUID } from 'crypto';
|
|
6
|
-
import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-
|
|
6
|
+
import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-BF4AmFz8.mjs';
|
|
7
7
|
import 'fs/promises';
|
|
8
8
|
import 'url';
|
|
9
9
|
import 'node:fs';
|
|
10
|
+
import 'node:child_process';
|
|
11
|
+
import 'ws';
|
|
10
12
|
import 'util';
|
|
11
13
|
import 'node:crypto';
|
|
12
14
|
import 'node:path';
|
|
13
15
|
import 'node:os';
|
|
14
|
-
import 'node:vm';
|
|
15
|
-
import 'node:child_process';
|
|
16
16
|
import '@agentclientprotocol/sdk';
|
|
17
17
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
18
18
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { I as handleRealtimeEvent, z as resolveModel, J as describeMisconfiguration, K as buildMachineDeps, L as initMachineVoiceSession } from './run-BF4AmFz8.mjs';
|
|
2
|
+
import { WebSocket } from 'ws';
|
|
3
|
+
import { execSync, spawn } from 'child_process';
|
|
4
|
+
import 'os';
|
|
5
|
+
import 'fs/promises';
|
|
6
|
+
import 'fs';
|
|
7
|
+
import 'path';
|
|
8
|
+
import 'url';
|
|
9
|
+
import 'crypto';
|
|
10
|
+
import 'node:fs';
|
|
11
|
+
import 'node:child_process';
|
|
12
|
+
import 'util';
|
|
13
|
+
import 'node:crypto';
|
|
14
|
+
import 'node:path';
|
|
15
|
+
import 'node:os';
|
|
16
|
+
import '@agentclientprotocol/sdk';
|
|
17
|
+
import '@modelcontextprotocol/sdk/client/index.js';
|
|
18
|
+
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
19
|
+
import '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
import 'zod';
|
|
21
|
+
import 'node:fs/promises';
|
|
22
|
+
import 'node:util';
|
|
23
|
+
|
|
24
|
+
const PCM_RATE = 24e3;
|
|
25
|
+
function buildHeadlessSessionUpdate(cfg) {
|
|
26
|
+
const turn = cfg.vad ? {
|
|
27
|
+
type: "server_vad",
|
|
28
|
+
threshold: cfg.vad.threshold ?? 0.5,
|
|
29
|
+
prefix_padding_ms: cfg.vad.prefixPaddingMs ?? 300,
|
|
30
|
+
silence_duration_ms: cfg.vad.silenceDurationMs ?? 600
|
|
31
|
+
} : { type: "server_vad" };
|
|
32
|
+
return {
|
|
33
|
+
type: "session.update",
|
|
34
|
+
session: {
|
|
35
|
+
type: "realtime",
|
|
36
|
+
instructions: cfg.instructions,
|
|
37
|
+
tools: cfg.tools.map((t) => ({ type: "function", name: t.name, description: t.description, parameters: t.parameters })),
|
|
38
|
+
tool_choice: "auto",
|
|
39
|
+
output_modalities: ["audio"],
|
|
40
|
+
audio: {
|
|
41
|
+
input: {
|
|
42
|
+
format: { type: "audio/pcm", rate: PCM_RATE },
|
|
43
|
+
turn_detection: turn,
|
|
44
|
+
transcription: { model: "gpt-4o-mini-transcribe" }
|
|
45
|
+
},
|
|
46
|
+
output: {
|
|
47
|
+
format: { type: "audio/pcm", rate: PCM_RATE },
|
|
48
|
+
...cfg.voice ? { voice: cfg.voice } : {}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function appendAudioEvent(pcm) {
|
|
55
|
+
return { type: "input_audio_buffer.append", audio: pcm.toString("base64") };
|
|
56
|
+
}
|
|
57
|
+
const AUDIO_DELTA_TYPES = /* @__PURE__ */ new Set(["response.output_audio.delta", "response.audio.delta"]);
|
|
58
|
+
async function handleHeadlessEvent(ev, tools, send, onAudioOut, onInterrupt, nameByCallId) {
|
|
59
|
+
if (ev?.type && AUDIO_DELTA_TYPES.has(ev.type) && typeof ev.delta === "string") {
|
|
60
|
+
onAudioOut(Buffer.from(ev.delta, "base64"));
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (ev?.type === "input_audio_buffer.speech_started") {
|
|
64
|
+
onInterrupt();
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return handleRealtimeEvent(ev, tools, send, nameByCallId);
|
|
68
|
+
}
|
|
69
|
+
const realHeadlessFactory = (url, headers) => new WebSocket(url, { headers });
|
|
70
|
+
let _testHeadlessFactory;
|
|
71
|
+
async function openHeadlessSession(opts) {
|
|
72
|
+
const base = (opts.baseUrl || "https://api.openai.com").replace(/^http/, "ws").replace(/\/+$/, "");
|
|
73
|
+
const model = opts.config.model || "gpt-realtime-mini";
|
|
74
|
+
const url = `${base}/v1/realtime?model=${encodeURIComponent(model)}`;
|
|
75
|
+
const ws = (opts.wsFactory || _testHeadlessFactory || realHeadlessFactory)(url, { Authorization: `Bearer ${opts.apiKey}` });
|
|
76
|
+
const send = (e) => {
|
|
77
|
+
try {
|
|
78
|
+
ws.send(JSON.stringify(e));
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const nameByCallId = /* @__PURE__ */ new Map();
|
|
83
|
+
const idleMs = opts.idleTimeoutMs ?? 3e4;
|
|
84
|
+
let idleTimer;
|
|
85
|
+
let closed = false;
|
|
86
|
+
const closeSession = () => {
|
|
87
|
+
if (closed) return;
|
|
88
|
+
closed = true;
|
|
89
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
90
|
+
opts.audio.stopCapture();
|
|
91
|
+
try {
|
|
92
|
+
ws.close();
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const bumpIdle = () => {
|
|
97
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
98
|
+
idleTimer = setTimeout(closeSession, idleMs);
|
|
99
|
+
};
|
|
100
|
+
ws.on("open", () => {
|
|
101
|
+
send(buildHeadlessSessionUpdate(opts.config));
|
|
102
|
+
opts.audio.startCapture((pcm) => send(appendAudioEvent(pcm)));
|
|
103
|
+
bumpIdle();
|
|
104
|
+
});
|
|
105
|
+
ws.on("message", async (data) => {
|
|
106
|
+
let ev;
|
|
107
|
+
try {
|
|
108
|
+
ev = JSON.parse(typeof data === "string" ? data : data?.toString?.() ?? "");
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
bumpIdle();
|
|
113
|
+
try {
|
|
114
|
+
const r = await handleHeadlessEvent(ev, opts.config.tools, send, (pcm) => opts.audio.play(pcm), () => opts.audio.clearPlayback(), nameByCallId);
|
|
115
|
+
if (r) opts.onTool?.(r);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
opts.onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
ws.on("close", () => {
|
|
121
|
+
closed = true;
|
|
122
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
123
|
+
opts.audio.stopCapture();
|
|
124
|
+
opts.onClose?.();
|
|
125
|
+
});
|
|
126
|
+
ws.on("error", (e) => opts.onError?.(e instanceof Error ? e : new Error(String(e))));
|
|
127
|
+
return { close: closeSession };
|
|
128
|
+
}
|
|
129
|
+
function runHeadlessVoice(opts) {
|
|
130
|
+
let current = null;
|
|
131
|
+
let stopped = false;
|
|
132
|
+
const openOne = async () => {
|
|
133
|
+
if (stopped || current) return;
|
|
134
|
+
try {
|
|
135
|
+
current = await openHeadlessSession({
|
|
136
|
+
...opts,
|
|
137
|
+
onClose: () => {
|
|
138
|
+
current = null;
|
|
139
|
+
opts.onClose?.();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
} catch (e) {
|
|
143
|
+
opts.onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
if (opts.wakeWord) {
|
|
147
|
+
opts.wakeWord.start(() => {
|
|
148
|
+
void openOne();
|
|
149
|
+
});
|
|
150
|
+
} else {
|
|
151
|
+
void openOne();
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
stop: () => {
|
|
155
|
+
stopped = true;
|
|
156
|
+
opts.wakeWord?.stop();
|
|
157
|
+
current?.close();
|
|
158
|
+
current = null;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const RAW = ["-q", "-t", "raw", "-r", String(PCM_RATE), "-b", "16", "-e", "signed-integer", "-c", "1"];
|
|
164
|
+
function soxAvailable() {
|
|
165
|
+
try {
|
|
166
|
+
execSync("command -v sox", { stdio: "ignore" });
|
|
167
|
+
return true;
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function createSoxAudioAdapter() {
|
|
173
|
+
if (!soxAvailable()) {
|
|
174
|
+
throw new Error("headless voice needs `sox` (raw PCM mic/speaker bridge). Install it: macOS `brew install sox`, Debian `apt install sox`.");
|
|
175
|
+
}
|
|
176
|
+
let capture = null;
|
|
177
|
+
let playback = null;
|
|
178
|
+
const startPlayback = () => {
|
|
179
|
+
playback = spawn("sox", [...RAW, "-", "-d"], { stdio: ["pipe", "ignore", "ignore"] });
|
|
180
|
+
playback.on("error", () => {
|
|
181
|
+
playback = null;
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
startCapture(onChunk) {
|
|
186
|
+
if (capture) return;
|
|
187
|
+
capture = spawn("sox", ["-d", ...RAW, "-"], { stdio: ["ignore", "pipe", "ignore"] });
|
|
188
|
+
capture.stdout?.on("data", (buf) => onChunk(buf));
|
|
189
|
+
capture.on("error", () => {
|
|
190
|
+
capture = null;
|
|
191
|
+
});
|
|
192
|
+
},
|
|
193
|
+
stopCapture() {
|
|
194
|
+
try {
|
|
195
|
+
capture?.kill("SIGTERM");
|
|
196
|
+
} catch {
|
|
197
|
+
}
|
|
198
|
+
capture = null;
|
|
199
|
+
},
|
|
200
|
+
play(pcm) {
|
|
201
|
+
if (!playback) startPlayback();
|
|
202
|
+
try {
|
|
203
|
+
playback?.stdin?.write(pcm);
|
|
204
|
+
} catch {
|
|
205
|
+
playback = null;
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
clearPlayback() {
|
|
209
|
+
try {
|
|
210
|
+
playback?.kill("SIGTERM");
|
|
211
|
+
} catch {
|
|
212
|
+
}
|
|
213
|
+
playback = null;
|
|
214
|
+
},
|
|
215
|
+
close() {
|
|
216
|
+
try {
|
|
217
|
+
capture?.kill("SIGTERM");
|
|
218
|
+
} catch {
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
playback?.kill("SIGTERM");
|
|
222
|
+
} catch {
|
|
223
|
+
}
|
|
224
|
+
capture = null;
|
|
225
|
+
playback = null;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async function createPorcupineWakeWord(opts) {
|
|
231
|
+
if (!opts.accessKey) throw new Error("wake-word needs PICOVOICE_ACCESS_KEY (free at console.picovoice.ai).");
|
|
232
|
+
let Porcupine, BuiltinKeyword, PvRecorder;
|
|
233
|
+
try {
|
|
234
|
+
({ Porcupine, BuiltinKeyword } = await import('@picovoice/porcupine-node'));
|
|
235
|
+
({ PvRecorder } = await import('@picovoice/pvrecorder-node'));
|
|
236
|
+
} catch {
|
|
237
|
+
throw new Error("wake-word needs the Picovoice modules: `yarn add @picovoice/porcupine-node @picovoice/pvrecorder-node`.");
|
|
238
|
+
}
|
|
239
|
+
const keywords = opts.keywordPath ? [opts.keywordPath] : [opts.builtinKeyword || BuiltinKeyword.PORCUPINE];
|
|
240
|
+
const sensitivities = [opts.sensitivity ?? 0.5];
|
|
241
|
+
const porcupine = new Porcupine(opts.accessKey, keywords, sensitivities);
|
|
242
|
+
const recorder = new PvRecorder(porcupine.frameLength, opts.deviceIndex ?? -1);
|
|
243
|
+
let running = false;
|
|
244
|
+
return {
|
|
245
|
+
start(onWake) {
|
|
246
|
+
if (running) return;
|
|
247
|
+
running = true;
|
|
248
|
+
recorder.start();
|
|
249
|
+
(async () => {
|
|
250
|
+
while (running) {
|
|
251
|
+
let frame;
|
|
252
|
+
try {
|
|
253
|
+
frame = await recorder.read();
|
|
254
|
+
} catch {
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
if (!running) break;
|
|
258
|
+
if (porcupine.process(frame) >= 0) onWake();
|
|
259
|
+
}
|
|
260
|
+
})();
|
|
261
|
+
},
|
|
262
|
+
stop() {
|
|
263
|
+
running = false;
|
|
264
|
+
try {
|
|
265
|
+
recorder.stop();
|
|
266
|
+
} catch {
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
recorder.release?.();
|
|
270
|
+
} catch {
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
porcupine.release?.();
|
|
274
|
+
} catch {
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async function runWiseVoiceCli(opts = {}) {
|
|
281
|
+
const resolved = resolveModel({ provider: "openai" }, process.env);
|
|
282
|
+
const mis = describeMisconfiguration(resolved);
|
|
283
|
+
if (mis || !resolved.apiKey) {
|
|
284
|
+
console.error(`\u2717 ${mis || "No OpenAI API key on this machine."}
|
|
285
|
+
Configure it: svamp wise-agent auth use-openai <KEY> (or set OPENAI_API_KEY in ~/.svamp/.env)`);
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
if (!soxAvailable()) {
|
|
289
|
+
console.error("\u2717 headless voice needs `sox` for the mic/speaker bridge.\n macOS: brew install sox Debian/Ubuntu: sudo apt install sox");
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
const deps = buildMachineDeps({}, { cwd: process.env.HOME });
|
|
293
|
+
const { tools, sessionUpdate } = await initMachineVoiceSession({ deps, role: "admin", voice: opts.voice });
|
|
294
|
+
const instructions = sessionUpdate.session.instructions;
|
|
295
|
+
let wakeWord;
|
|
296
|
+
if (opts.wakeKeywordPath) {
|
|
297
|
+
try {
|
|
298
|
+
wakeWord = await createPorcupineWakeWord({ accessKey: process.env.PICOVOICE_ACCESS_KEY || "", keywordPath: opts.wakeKeywordPath });
|
|
299
|
+
} catch (e) {
|
|
300
|
+
console.error(`\u2717 wake-word: ${e.message}`);
|
|
301
|
+
process.exit(1);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const audio = createSoxAudioAdapter();
|
|
305
|
+
console.log(`\u25CF WISE headless voice \u2014 ${tools.length} tools | model ${opts.model || resolved.model || "gpt-realtime-mini"} | ${wakeWord ? `wake: "${opts.wakeKeywordPath}"` : "always-listening (Ctrl-C to stop)"}`);
|
|
306
|
+
const loop = runHeadlessVoice({
|
|
307
|
+
apiKey: resolved.apiKey,
|
|
308
|
+
baseUrl: resolved.baseUrl,
|
|
309
|
+
config: { instructions, tools, voice: opts.voice, model: opts.model || resolved.model },
|
|
310
|
+
audio,
|
|
311
|
+
wakeWord,
|
|
312
|
+
onTool: (t) => console.log(` \u21B3 ${t.name}: ${t.output.slice(0, 120).replace(/\n/g, " ")}`),
|
|
313
|
+
onError: (e) => console.error(` ! ${e.message}`)
|
|
314
|
+
});
|
|
315
|
+
const shutdown = () => {
|
|
316
|
+
console.log("\nstopping\u2026");
|
|
317
|
+
try {
|
|
318
|
+
loop.stop();
|
|
319
|
+
} catch {
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
audio.close();
|
|
323
|
+
} catch {
|
|
324
|
+
}
|
|
325
|
+
process.exit(0);
|
|
326
|
+
};
|
|
327
|
+
process.on("SIGINT", shutdown);
|
|
328
|
+
process.on("SIGTERM", shutdown);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export { runWiseVoiceCli };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as connectToHypha, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, a as registerSessionService, s as startDaemon, b as stopDaemon } from './run-
|
|
1
|
+
export { c as connectToHypha, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, a as registerSessionService, s as startDaemon, b as stopDaemon } from './run-BF4AmFz8.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -7,12 +7,12 @@ import 'url';
|
|
|
7
7
|
import 'child_process';
|
|
8
8
|
import 'crypto';
|
|
9
9
|
import 'node:fs';
|
|
10
|
+
import 'node:child_process';
|
|
11
|
+
import 'ws';
|
|
10
12
|
import 'util';
|
|
11
13
|
import 'node:crypto';
|
|
12
14
|
import 'node:path';
|
|
13
15
|
import 'node:os';
|
|
14
|
-
import 'node:vm';
|
|
15
|
-
import 'node:child_process';
|
|
16
16
|
import '@agentclientprotocol/sdk';
|
|
17
17
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
18
18
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "svamp-cli";
|
|
2
|
-
var version = "0.2.
|
|
2
|
+
var version = "0.2.92";
|
|
3
3
|
var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
|
|
4
4
|
var author = "Amun AI AB";
|
|
5
5
|
var license = "SEE LICENSE IN LICENSE";
|
|
@@ -19,7 +19,7 @@ var exports$1 = {
|
|
|
19
19
|
var scripts = {
|
|
20
20
|
build: "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && tsc --noEmit && pkgroll",
|
|
21
21
|
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-wise-
|
|
22
|
+
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-voice-attach.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs",
|
|
23
23
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
24
24
|
dev: "tsx src/cli.ts",
|
|
25
25
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|