svamp-cli 0.2.224 → 0.2.225
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/package.json +1 -1
- package/dist/agentCommands-BignK4hn.mjs +0 -526
- package/dist/auth-tP-DHfsI.mjs +0 -83
- package/dist/caddy-CuTbE3NY.mjs +0 -322
- package/dist/cli.mjs +0 -2338
- package/dist/commands-1IupY9qh.mjs +0 -265
- package/dist/commands-Bpq8_9OU.mjs +0 -610
- package/dist/commands-C1VIwqOH.mjs +0 -428
- package/dist/commands-CA8AMvq-.mjs +0 -493
- package/dist/commands-DMoXgLUh.mjs +0 -196
- package/dist/commands-DqvzIDMK.mjs +0 -2762
- package/dist/commands-ez1xdcH5.mjs +0 -643
- package/dist/fleet-B6Rh4mje.mjs +0 -356
- package/dist/frpc-vpwKk0kV.mjs +0 -681
- package/dist/headlessCli-C51w8i7T.mjs +0 -333
- package/dist/httpServer-B1KVQJfm.mjs +0 -276
- package/dist/index.mjs +0 -22
- package/dist/package-CzzAMi8h.mjs +0 -63
- package/dist/pinnedClaudeCode-VIupR1NK.mjs +0 -58
- package/dist/rpc-CcQQrbBO.mjs +0 -92
- package/dist/rpc-D7QFTk_g.mjs +0 -194
- package/dist/run-BZrPFG_w.mjs +0 -1086
- package/dist/run-C-9ZtEi4.mjs +0 -16050
- package/dist/runStore-CtptN7US.mjs +0 -168
- package/dist/sandboxDetect-DNTcbgWD.mjs +0 -12
- package/dist/scheduler-jlX6Mkxf.mjs +0 -102
- package/dist/serveCommands-Dhrv-HAD.mjs +0 -310
- package/dist/serveManager-DtBN8E9D.mjs +0 -781
- package/dist/serviceManager-hlOVxkhW.mjs +0 -78
- package/dist/sideband-DxH9bMhv.mjs +0 -80
- package/dist/store-BTs0H_y0.mjs +0 -148
- package/dist/supervisorLock-DmfzJx7B.mjs +0 -159
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import { P as resolveModel, a2 as describeMisconfiguration, a3 as buildMachineDeps } from './run-C-9ZtEi4.mjs';
|
|
2
|
-
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-DxH9bMhv.mjs';
|
|
3
|
-
import { WebSocket } from 'ws';
|
|
4
|
-
import { execSync, spawn } from 'child_process';
|
|
5
|
-
import 'os';
|
|
6
|
-
import 'fs/promises';
|
|
7
|
-
import 'fs';
|
|
8
|
-
import 'path';
|
|
9
|
-
import 'url';
|
|
10
|
-
import 'crypto';
|
|
11
|
-
import 'node:crypto';
|
|
12
|
-
import 'node:fs';
|
|
13
|
-
import 'node:child_process';
|
|
14
|
-
import 'util';
|
|
15
|
-
import 'node:path';
|
|
16
|
-
import 'node:events';
|
|
17
|
-
import 'node:os';
|
|
18
|
-
import '@agentclientprotocol/sdk';
|
|
19
|
-
import '@modelcontextprotocol/sdk/client/index.js';
|
|
20
|
-
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
21
|
-
import '@modelcontextprotocol/sdk/types.js';
|
|
22
|
-
import 'zod';
|
|
23
|
-
import 'node:fs/promises';
|
|
24
|
-
import 'node:util';
|
|
25
|
-
|
|
26
|
-
const PCM_RATE = 24e3;
|
|
27
|
-
function buildHeadlessSessionUpdate(cfg) {
|
|
28
|
-
const turn = cfg.vad ? {
|
|
29
|
-
type: "server_vad",
|
|
30
|
-
threshold: cfg.vad.threshold ?? 0.5,
|
|
31
|
-
prefix_padding_ms: cfg.vad.prefixPaddingMs ?? 300,
|
|
32
|
-
silence_duration_ms: cfg.vad.silenceDurationMs ?? 600
|
|
33
|
-
} : { type: "server_vad" };
|
|
34
|
-
return {
|
|
35
|
-
type: "session.update",
|
|
36
|
-
session: {
|
|
37
|
-
type: "realtime",
|
|
38
|
-
instructions: cfg.instructions,
|
|
39
|
-
tools: cfg.tools.map((t) => ({ type: "function", name: t.name, description: t.description, parameters: t.parameters })),
|
|
40
|
-
tool_choice: "auto",
|
|
41
|
-
output_modalities: ["audio"],
|
|
42
|
-
audio: {
|
|
43
|
-
input: {
|
|
44
|
-
format: { type: "audio/pcm", rate: PCM_RATE },
|
|
45
|
-
turn_detection: turn,
|
|
46
|
-
transcription: { model: "gpt-4o-mini-transcribe" }
|
|
47
|
-
},
|
|
48
|
-
output: {
|
|
49
|
-
format: { type: "audio/pcm", rate: PCM_RATE },
|
|
50
|
-
...cfg.voice ? { voice: cfg.voice } : {}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
function appendAudioEvent(pcm) {
|
|
57
|
-
return { type: "input_audio_buffer.append", audio: pcm.toString("base64") };
|
|
58
|
-
}
|
|
59
|
-
const AUDIO_DELTA_TYPES = /* @__PURE__ */ new Set(["response.output_audio.delta", "response.audio.delta"]);
|
|
60
|
-
async function handleHeadlessEvent(ev, tools, send, onAudioOut, onInterrupt, nameByCallId) {
|
|
61
|
-
if (ev?.type && AUDIO_DELTA_TYPES.has(ev.type) && typeof ev.delta === "string") {
|
|
62
|
-
onAudioOut(Buffer.from(ev.delta, "base64"));
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
if (ev?.type === "input_audio_buffer.speech_started") {
|
|
66
|
-
onInterrupt();
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
return handleRealtimeEvent(ev, tools, send, nameByCallId);
|
|
70
|
-
}
|
|
71
|
-
const realHeadlessFactory = (url, headers) => new WebSocket(url, { headers });
|
|
72
|
-
let _testHeadlessFactory;
|
|
73
|
-
async function openHeadlessSession(opts) {
|
|
74
|
-
const base = (opts.baseUrl || "https://api.openai.com").replace(/^http/, "ws").replace(/\/+$/, "");
|
|
75
|
-
const model = opts.config.model || "gpt-realtime-mini";
|
|
76
|
-
const url = `${base}/v1/realtime?model=${encodeURIComponent(model)}`;
|
|
77
|
-
const ws = (opts.wsFactory || _testHeadlessFactory || realHeadlessFactory)(url, { Authorization: `Bearer ${opts.apiKey}` });
|
|
78
|
-
const send = (e) => {
|
|
79
|
-
try {
|
|
80
|
-
ws.send(JSON.stringify(e));
|
|
81
|
-
} catch {
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
const nameByCallId = /* @__PURE__ */ new Map();
|
|
85
|
-
const idleMs = opts.idleTimeoutMs ?? 3e4;
|
|
86
|
-
let idleTimer;
|
|
87
|
-
let closed = false;
|
|
88
|
-
const closeSession = () => {
|
|
89
|
-
if (closed) return;
|
|
90
|
-
closed = true;
|
|
91
|
-
if (idleTimer) clearTimeout(idleTimer);
|
|
92
|
-
opts.audio.stopCapture();
|
|
93
|
-
try {
|
|
94
|
-
ws.close();
|
|
95
|
-
} catch {
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const bumpIdle = () => {
|
|
99
|
-
if (idleTimer) clearTimeout(idleTimer);
|
|
100
|
-
idleTimer = setTimeout(closeSession, idleMs);
|
|
101
|
-
};
|
|
102
|
-
ws.on("open", () => {
|
|
103
|
-
send(buildHeadlessSessionUpdate(opts.config));
|
|
104
|
-
opts.audio.startCapture((pcm) => send(appendAudioEvent(pcm)));
|
|
105
|
-
bumpIdle();
|
|
106
|
-
});
|
|
107
|
-
ws.on("message", async (data) => {
|
|
108
|
-
let ev;
|
|
109
|
-
try {
|
|
110
|
-
ev = JSON.parse(typeof data === "string" ? data : data?.toString?.() ?? "");
|
|
111
|
-
} catch {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
bumpIdle();
|
|
115
|
-
try {
|
|
116
|
-
const r = await handleHeadlessEvent(ev, opts.config.tools, send, (pcm) => opts.audio.play(pcm), () => opts.audio.clearPlayback(), nameByCallId);
|
|
117
|
-
if (r) opts.onTool?.(r);
|
|
118
|
-
} catch (e) {
|
|
119
|
-
opts.onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
ws.on("close", () => {
|
|
123
|
-
closed = true;
|
|
124
|
-
if (idleTimer) clearTimeout(idleTimer);
|
|
125
|
-
opts.audio.stopCapture();
|
|
126
|
-
opts.onClose?.();
|
|
127
|
-
});
|
|
128
|
-
ws.on("error", (e) => opts.onError?.(e instanceof Error ? e : new Error(String(e))));
|
|
129
|
-
return { close: closeSession };
|
|
130
|
-
}
|
|
131
|
-
function runHeadlessVoice(opts) {
|
|
132
|
-
let current = null;
|
|
133
|
-
let stopped = false;
|
|
134
|
-
const openOne = async () => {
|
|
135
|
-
if (stopped || current) return;
|
|
136
|
-
try {
|
|
137
|
-
current = await openHeadlessSession({
|
|
138
|
-
...opts,
|
|
139
|
-
onClose: () => {
|
|
140
|
-
current = null;
|
|
141
|
-
opts.onClose?.();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
} catch (e) {
|
|
145
|
-
opts.onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
if (opts.wakeWord) {
|
|
149
|
-
opts.wakeWord.start(() => {
|
|
150
|
-
void openOne();
|
|
151
|
-
});
|
|
152
|
-
} else {
|
|
153
|
-
void openOne();
|
|
154
|
-
}
|
|
155
|
-
return {
|
|
156
|
-
stop: () => {
|
|
157
|
-
stopped = true;
|
|
158
|
-
opts.wakeWord?.stop();
|
|
159
|
-
current?.close();
|
|
160
|
-
current = null;
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const RAW = ["-q", "-t", "raw", "-r", String(PCM_RATE), "-b", "16", "-e", "signed-integer", "-c", "1"];
|
|
166
|
-
function soxAvailable() {
|
|
167
|
-
try {
|
|
168
|
-
execSync("command -v sox", { stdio: "ignore" });
|
|
169
|
-
return true;
|
|
170
|
-
} catch {
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function createSoxAudioAdapter() {
|
|
175
|
-
if (!soxAvailable()) {
|
|
176
|
-
throw new Error("headless voice needs `sox` (raw PCM mic/speaker bridge). Install it: macOS `brew install sox`, Debian `apt install sox`.");
|
|
177
|
-
}
|
|
178
|
-
let capture = null;
|
|
179
|
-
let playback = null;
|
|
180
|
-
const startPlayback = () => {
|
|
181
|
-
playback = spawn("sox", [...RAW, "-", "-d"], { stdio: ["pipe", "ignore", "ignore"] });
|
|
182
|
-
playback.on("error", () => {
|
|
183
|
-
playback = null;
|
|
184
|
-
});
|
|
185
|
-
};
|
|
186
|
-
return {
|
|
187
|
-
startCapture(onChunk) {
|
|
188
|
-
if (capture) return;
|
|
189
|
-
capture = spawn("sox", ["-d", ...RAW, "-"], { stdio: ["ignore", "pipe", "ignore"] });
|
|
190
|
-
capture.stdout?.on("data", (buf) => onChunk(buf));
|
|
191
|
-
capture.on("error", () => {
|
|
192
|
-
capture = null;
|
|
193
|
-
});
|
|
194
|
-
},
|
|
195
|
-
stopCapture() {
|
|
196
|
-
try {
|
|
197
|
-
capture?.kill("SIGTERM");
|
|
198
|
-
} catch {
|
|
199
|
-
}
|
|
200
|
-
capture = null;
|
|
201
|
-
},
|
|
202
|
-
play(pcm) {
|
|
203
|
-
if (!playback) startPlayback();
|
|
204
|
-
try {
|
|
205
|
-
playback?.stdin?.write(pcm);
|
|
206
|
-
} catch {
|
|
207
|
-
playback = null;
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
clearPlayback() {
|
|
211
|
-
try {
|
|
212
|
-
playback?.kill("SIGTERM");
|
|
213
|
-
} catch {
|
|
214
|
-
}
|
|
215
|
-
playback = null;
|
|
216
|
-
},
|
|
217
|
-
close() {
|
|
218
|
-
try {
|
|
219
|
-
capture?.kill("SIGTERM");
|
|
220
|
-
} catch {
|
|
221
|
-
}
|
|
222
|
-
try {
|
|
223
|
-
playback?.kill("SIGTERM");
|
|
224
|
-
} catch {
|
|
225
|
-
}
|
|
226
|
-
capture = null;
|
|
227
|
-
playback = null;
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
async function createPorcupineWakeWord(opts) {
|
|
233
|
-
if (!opts.accessKey) throw new Error("wake-word needs PICOVOICE_ACCESS_KEY (free at console.picovoice.ai).");
|
|
234
|
-
let Porcupine, BuiltinKeyword, PvRecorder;
|
|
235
|
-
try {
|
|
236
|
-
({ Porcupine, BuiltinKeyword } = await import('@picovoice/porcupine-node'));
|
|
237
|
-
({ PvRecorder } = await import('@picovoice/pvrecorder-node'));
|
|
238
|
-
} catch {
|
|
239
|
-
throw new Error("wake-word needs the Picovoice modules: `yarn add @picovoice/porcupine-node @picovoice/pvrecorder-node`.");
|
|
240
|
-
}
|
|
241
|
-
const keywords = opts.keywordPath ? [opts.keywordPath] : [opts.builtinKeyword || BuiltinKeyword.PORCUPINE];
|
|
242
|
-
const sensitivities = [opts.sensitivity ?? 0.5];
|
|
243
|
-
const porcupine = new Porcupine(opts.accessKey, keywords, sensitivities);
|
|
244
|
-
const recorder = new PvRecorder(porcupine.frameLength, opts.deviceIndex ?? -1);
|
|
245
|
-
let running = false;
|
|
246
|
-
return {
|
|
247
|
-
start(onWake) {
|
|
248
|
-
if (running) return;
|
|
249
|
-
running = true;
|
|
250
|
-
recorder.start();
|
|
251
|
-
(async () => {
|
|
252
|
-
while (running) {
|
|
253
|
-
let frame;
|
|
254
|
-
try {
|
|
255
|
-
frame = await recorder.read();
|
|
256
|
-
} catch {
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
if (!running) break;
|
|
260
|
-
if (porcupine.process(frame) >= 0) onWake();
|
|
261
|
-
}
|
|
262
|
-
})();
|
|
263
|
-
},
|
|
264
|
-
stop() {
|
|
265
|
-
running = false;
|
|
266
|
-
try {
|
|
267
|
-
recorder.stop();
|
|
268
|
-
} catch {
|
|
269
|
-
}
|
|
270
|
-
try {
|
|
271
|
-
recorder.release?.();
|
|
272
|
-
} catch {
|
|
273
|
-
}
|
|
274
|
-
try {
|
|
275
|
-
porcupine.release?.();
|
|
276
|
-
} catch {
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
async function runWiseVoiceCli(opts = {}) {
|
|
283
|
-
const resolved = resolveModel({ provider: "openai" }, process.env);
|
|
284
|
-
const mis = describeMisconfiguration(resolved);
|
|
285
|
-
if (mis || !resolved.apiKey) {
|
|
286
|
-
console.error(`\u2717 ${mis || "No OpenAI API key on this machine."}
|
|
287
|
-
Configure it: svamp wise-agent auth use-openai <KEY> (or set OPENAI_API_KEY in ~/.svamp/.env)`);
|
|
288
|
-
process.exit(1);
|
|
289
|
-
}
|
|
290
|
-
if (!soxAvailable()) {
|
|
291
|
-
console.error("\u2717 headless voice needs `sox` for the mic/speaker bridge.\n macOS: brew install sox Debian/Ubuntu: sudo apt install sox");
|
|
292
|
-
process.exit(1);
|
|
293
|
-
}
|
|
294
|
-
const deps = buildMachineDeps({}, { cwd: process.env.HOME });
|
|
295
|
-
const { tools, sessionUpdate } = await initMachineVoiceSession({ deps, role: "admin", voice: opts.voice });
|
|
296
|
-
const instructions = sessionUpdate.session.instructions;
|
|
297
|
-
let wakeWord;
|
|
298
|
-
if (opts.wakeKeywordPath) {
|
|
299
|
-
try {
|
|
300
|
-
wakeWord = await createPorcupineWakeWord({ accessKey: process.env.PICOVOICE_ACCESS_KEY || "", keywordPath: opts.wakeKeywordPath });
|
|
301
|
-
} catch (e) {
|
|
302
|
-
console.error(`\u2717 wake-word: ${e.message}`);
|
|
303
|
-
process.exit(1);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
const audio = createSoxAudioAdapter();
|
|
307
|
-
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)"}`);
|
|
308
|
-
const loop = runHeadlessVoice({
|
|
309
|
-
apiKey: resolved.apiKey,
|
|
310
|
-
baseUrl: resolved.baseUrl,
|
|
311
|
-
config: { instructions, tools, voice: opts.voice, model: opts.model || resolved.model },
|
|
312
|
-
audio,
|
|
313
|
-
wakeWord,
|
|
314
|
-
onTool: (t) => console.log(` \u21B3 ${t.name}: ${t.output.slice(0, 120).replace(/\n/g, " ")}`),
|
|
315
|
-
onError: (e) => console.error(` ! ${e.message}`)
|
|
316
|
-
});
|
|
317
|
-
const shutdown = () => {
|
|
318
|
-
console.log("\nstopping\u2026");
|
|
319
|
-
try {
|
|
320
|
-
loop.stop();
|
|
321
|
-
} catch {
|
|
322
|
-
}
|
|
323
|
-
try {
|
|
324
|
-
audio.close();
|
|
325
|
-
} catch {
|
|
326
|
-
}
|
|
327
|
-
process.exit(0);
|
|
328
|
-
};
|
|
329
|
-
process.on("SIGINT", shutdown);
|
|
330
|
-
process.on("SIGTERM", shutdown);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
export { runWiseVoiceCli };
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { createServer } from 'node:http';
|
|
2
|
-
|
|
3
|
-
async function findOwner(deps, channelId) {
|
|
4
|
-
let fallback;
|
|
5
|
-
for (const sid of deps.getSessionIds()) {
|
|
6
|
-
const rpc = deps.getSessionRPCHandlers(sid);
|
|
7
|
-
if (!rpc) continue;
|
|
8
|
-
try {
|
|
9
|
-
if (rpc.channelOwns) {
|
|
10
|
-
const r = await rpc.channelOwns(channelId);
|
|
11
|
-
if (!r?.owned) continue;
|
|
12
|
-
if (r.boundSession) {
|
|
13
|
-
const bound = deps.getSessionRPCHandlers(r.boundSession);
|
|
14
|
-
if (bound) return bound;
|
|
15
|
-
}
|
|
16
|
-
fallback = fallback || rpc;
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
if (rpc.channelList) {
|
|
20
|
-
const r = await rpc.channelList();
|
|
21
|
-
if ((r?.channels || []).some((c) => c.id === channelId)) return rpc;
|
|
22
|
-
}
|
|
23
|
-
} catch {
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return fallback;
|
|
27
|
-
}
|
|
28
|
-
function createChannelHttpServer(deps) {
|
|
29
|
-
return createServer((req, res) => {
|
|
30
|
-
const u = new URL(req.url || "/", "http://localhost");
|
|
31
|
-
const json = (code, obj) => {
|
|
32
|
-
res.writeHead(code, { "content-type": "application/json" }).end(JSON.stringify(obj));
|
|
33
|
-
};
|
|
34
|
-
(async () => {
|
|
35
|
-
if (u.pathname === "/" || u.pathname === "/health") {
|
|
36
|
-
res.writeHead(200).end("channels ok");
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (u.pathname === "/channels") {
|
|
40
|
-
const out = [];
|
|
41
|
-
for (const sid of deps.getSessionIds()) {
|
|
42
|
-
const rpc2 = deps.getSessionRPCHandlers(sid);
|
|
43
|
-
if (!rpc2?.channelList) continue;
|
|
44
|
-
try {
|
|
45
|
-
const r = await rpc2.channelList();
|
|
46
|
-
for (const c of r?.channels || []) out.push(c);
|
|
47
|
-
} catch {
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
json(200, out);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
let m = u.pathname.match(/^\/channel\/([\w.-]+)\/skill\.md$/);
|
|
54
|
-
if (m) {
|
|
55
|
-
const rpc2 = await findOwner(deps, m[1]);
|
|
56
|
-
if (!rpc2?.channelDescribe) {
|
|
57
|
-
res.writeHead(404).end("not found");
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const d = await rpc2.channelDescribe(m[1]);
|
|
61
|
-
if (d?.error) {
|
|
62
|
-
res.writeHead(404).end("not found");
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
res.writeHead(200, { "content-type": "text/markdown" }).end(d.skill?.body || "");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const keyOf = () => (req.headers.authorization || "").replace(/^Bearer\s+/i, "") || u.searchParams.get("key") || void 0;
|
|
69
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)\/receive$/);
|
|
70
|
-
if (m) {
|
|
71
|
-
const rpc2 = await findOwner(deps, m[1]);
|
|
72
|
-
if (!rpc2?.channelReceive) {
|
|
73
|
-
json(404, { error: "channel not found" });
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
const out = await rpc2.channelReceive({
|
|
77
|
-
channel: m[1],
|
|
78
|
-
key: keyOf(),
|
|
79
|
-
from: u.searchParams.get("from") || void 0,
|
|
80
|
-
cursor: Number(u.searchParams.get("cursor") || 0),
|
|
81
|
-
correlationId: u.searchParams.get("correlationId") || void 0,
|
|
82
|
-
wait: u.searchParams.get("wait") != null ? Number(u.searchParams.get("wait")) : void 0
|
|
83
|
-
});
|
|
84
|
-
json(out?.error ? out.error === "channel not found" ? 404 : 401 : 200, out);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)\/events$/);
|
|
88
|
-
if (m) {
|
|
89
|
-
const rpc2 = await findOwner(deps, m[1]);
|
|
90
|
-
if (!rpc2?.channelReceive) {
|
|
91
|
-
res.writeHead(404).end("not found");
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const key = keyOf();
|
|
95
|
-
const from = u.searchParams.get("from") || void 0;
|
|
96
|
-
let cursor = Number(u.searchParams.get("cursor") || 0);
|
|
97
|
-
res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", connection: "keep-alive", "x-accel-buffering": "no" });
|
|
98
|
-
res.write(": connected\n\n");
|
|
99
|
-
let closed = false;
|
|
100
|
-
req.on("close", () => {
|
|
101
|
-
closed = true;
|
|
102
|
-
});
|
|
103
|
-
while (!closed) {
|
|
104
|
-
const out = await rpc2.channelReceive({ channel: m[1], key, from, cursor, wait: 25 });
|
|
105
|
-
if (out?.error) {
|
|
106
|
-
res.write(`event: error
|
|
107
|
-
data: ${JSON.stringify({ error: out.error })}
|
|
108
|
-
|
|
109
|
-
`);
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
for (const reply of out.replies || []) res.write(`data: ${JSON.stringify(reply)}
|
|
113
|
-
|
|
114
|
-
`);
|
|
115
|
-
cursor = out.cursor ?? cursor;
|
|
116
|
-
if (!(out.replies || []).length) res.write(": keepalive\n\n");
|
|
117
|
-
}
|
|
118
|
-
try {
|
|
119
|
-
res.end();
|
|
120
|
-
} catch {
|
|
121
|
-
}
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)\/profile$/);
|
|
125
|
-
if (m) {
|
|
126
|
-
const rpc2 = await findOwner(deps, m[1]);
|
|
127
|
-
if (!rpc2?.channelGetProfile) {
|
|
128
|
-
json(404, { error: "channel not found" });
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const out = await rpc2.channelGetProfile({ channel: m[1], key: keyOf(), from: u.searchParams.get("from") || void 0 });
|
|
132
|
-
json(out?.error ? out.error === "channel not found" ? 404 : 401 : 200, out);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)\/activity$/);
|
|
136
|
-
if (m) {
|
|
137
|
-
const cid = m[1];
|
|
138
|
-
const rpc2 = await findOwner(deps, cid);
|
|
139
|
-
if (!rpc2?.recordMeetingActivity) {
|
|
140
|
-
json(404, { error: "channel not found" });
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
let chunks2 = "";
|
|
144
|
-
req.on("data", (d) => {
|
|
145
|
-
chunks2 += d;
|
|
146
|
-
if (chunks2.length > 64 * 1024) req.destroy();
|
|
147
|
-
});
|
|
148
|
-
req.on("end", async () => {
|
|
149
|
-
let body = {};
|
|
150
|
-
try {
|
|
151
|
-
body = chunks2 ? JSON.parse(chunks2) : {};
|
|
152
|
-
} catch {
|
|
153
|
-
}
|
|
154
|
-
try {
|
|
155
|
-
const out = await rpc2.recordMeetingActivity({ channel: cid, key: keyOf(), from: body.from, kind: body.kind, speaker: body.speaker, text: body.text });
|
|
156
|
-
json(out?.error ? out.error === "channel not found" ? 404 : 401 : 200, out);
|
|
157
|
-
} catch (e) {
|
|
158
|
-
json(500, { error: e?.message || String(e) });
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)\/upload$/);
|
|
164
|
-
if (m) {
|
|
165
|
-
const cid = m[1];
|
|
166
|
-
const rpc2 = await findOwner(deps, cid);
|
|
167
|
-
if (!rpc2?.channelUpload) {
|
|
168
|
-
json(404, { error: "channel not found" });
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
let chunks2 = "";
|
|
172
|
-
req.on("data", (d) => {
|
|
173
|
-
chunks2 += d;
|
|
174
|
-
if (chunks2.length > 40 * 1024 * 1024) req.destroy();
|
|
175
|
-
});
|
|
176
|
-
req.on("end", async () => {
|
|
177
|
-
let body = {};
|
|
178
|
-
try {
|
|
179
|
-
body = chunks2 ? JSON.parse(chunks2) : {};
|
|
180
|
-
} catch {
|
|
181
|
-
json(400, { error: "invalid JSON body" });
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
try {
|
|
185
|
-
const out = await rpc2.channelUpload({
|
|
186
|
-
channel: cid,
|
|
187
|
-
key: keyOf(),
|
|
188
|
-
from: body.from,
|
|
189
|
-
session: body.session,
|
|
190
|
-
filename: body.filename,
|
|
191
|
-
content_base64: body.content_base64 ?? body.contentBase64,
|
|
192
|
-
content_type: body.content_type ?? body.contentType
|
|
193
|
-
});
|
|
194
|
-
json(out?.error ? out.error === "channel not found" ? 404 : 400 : 200, out);
|
|
195
|
-
} catch (e) {
|
|
196
|
-
json(500, { error: e?.message || String(e) });
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)\/tool$/);
|
|
202
|
-
if (m) {
|
|
203
|
-
const cid = m[1];
|
|
204
|
-
const rpc2 = await findOwner(deps, cid);
|
|
205
|
-
if (!rpc2?.channelExecTool) {
|
|
206
|
-
json(404, { error: "channel not found" });
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
let chunks2 = "";
|
|
210
|
-
req.on("data", (d) => {
|
|
211
|
-
chunks2 += d;
|
|
212
|
-
if (chunks2.length > 2e6) req.destroy();
|
|
213
|
-
});
|
|
214
|
-
req.on("end", async () => {
|
|
215
|
-
let body = {};
|
|
216
|
-
try {
|
|
217
|
-
body = chunks2 ? JSON.parse(chunks2) : {};
|
|
218
|
-
} catch {
|
|
219
|
-
}
|
|
220
|
-
try {
|
|
221
|
-
const out = await rpc2.channelExecTool({ channel: cid, key: keyOf(), from: body.from, name: body.name, args: body.args });
|
|
222
|
-
json(out?.error ? out.error === "channel not found" ? 404 : 400 : 200, out);
|
|
223
|
-
} catch (e) {
|
|
224
|
-
json(500, { error: e?.message || String(e) });
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
m = u.pathname.match(/^\/channel\/([\w.-]+)$/);
|
|
230
|
-
if (!m) {
|
|
231
|
-
json(404, { error: "not found" });
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
const channelId = m[1];
|
|
235
|
-
const rpc = await findOwner(deps, channelId);
|
|
236
|
-
if (!rpc?.channelSend) {
|
|
237
|
-
json(404, { error: "channel not found" });
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
if (req.method === "GET" && !u.searchParams.get("message")) {
|
|
241
|
-
const d = await rpc.channelDescribe(channelId);
|
|
242
|
-
json(200, d);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
let chunks = "";
|
|
246
|
-
req.on("data", (d) => {
|
|
247
|
-
chunks += d;
|
|
248
|
-
if (chunks.length > 1e6) req.destroy();
|
|
249
|
-
});
|
|
250
|
-
req.on("end", async () => {
|
|
251
|
-
let body = {};
|
|
252
|
-
try {
|
|
253
|
-
body = chunks ? JSON.parse(chunks) : {};
|
|
254
|
-
} catch {
|
|
255
|
-
}
|
|
256
|
-
const key = (req.headers.authorization || "").replace(/^Bearer\s+/i, "") || u.searchParams.get("key") || void 0;
|
|
257
|
-
const message = body.message ?? u.searchParams.get("message") ?? "";
|
|
258
|
-
const from = body.from ?? u.searchParams.get("from") ?? void 0;
|
|
259
|
-
const session = body.session ?? u.searchParams.get("session") ?? void 0;
|
|
260
|
-
try {
|
|
261
|
-
const out = await rpc.channelSend({ channel: channelId, message, from, key, session });
|
|
262
|
-
json(out?.error ? 400 : 200, out);
|
|
263
|
-
} catch (e) {
|
|
264
|
-
json(500, { error: e?.message || String(e) });
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
})().catch((e) => {
|
|
268
|
-
try {
|
|
269
|
-
json(500, { error: e?.message || String(e) });
|
|
270
|
-
} catch {
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
export { createChannelHttpServer };
|
package/dist/index.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-C-9ZtEi4.mjs';
|
|
2
|
-
import 'os';
|
|
3
|
-
import 'fs/promises';
|
|
4
|
-
import 'fs';
|
|
5
|
-
import 'path';
|
|
6
|
-
import 'url';
|
|
7
|
-
import 'child_process';
|
|
8
|
-
import 'crypto';
|
|
9
|
-
import 'node:crypto';
|
|
10
|
-
import 'node:fs';
|
|
11
|
-
import 'node:child_process';
|
|
12
|
-
import 'util';
|
|
13
|
-
import 'node:path';
|
|
14
|
-
import 'node:events';
|
|
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';
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
var name = "svamp-cli";
|
|
2
|
-
var version = "0.2.224";
|
|
3
|
-
var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
|
|
4
|
-
var author = "Amun AI AB";
|
|
5
|
-
var license = "SEE LICENSE IN LICENSE";
|
|
6
|
-
var type = "module";
|
|
7
|
-
var bin = {
|
|
8
|
-
svamp: "./bin/svamp.mjs"
|
|
9
|
-
};
|
|
10
|
-
var files = [
|
|
11
|
-
"dist",
|
|
12
|
-
"bin"
|
|
13
|
-
];
|
|
14
|
-
var main = "./dist/index.mjs";
|
|
15
|
-
var exports$1 = {
|
|
16
|
-
".": "./dist/index.mjs",
|
|
17
|
-
"./cli": "./dist/cli.mjs"
|
|
18
|
-
};
|
|
19
|
-
var scripts = {
|
|
20
|
-
build: "rm -rf dist bin/skills bin/commands && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/crew bin/skills/crew && cp -r ../../commands bin/commands && tsc --noEmit && pkgroll",
|
|
21
|
-
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.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-sharing-notify-sync.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-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-btw-proxy-env.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.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-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-store.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-issue-pause.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-workflow-scheduler.mjs && npx tsx test/test-workflow-runs.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.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 && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.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-hotreload-seam.mjs && npx tsx test/test-hot-reload.mjs && npx tsx test/test-hot-reload-live.mjs && npx tsx test/test-session-core.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-channel-upload.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs && npx tsx test/test-crew-verdict-routing.mjs && npx tsx test/test-crew-standalone.mjs && npx tsx test/test-session-links.mjs && npx tsx test/test-issue-loop-pause-guard.mjs",
|
|
23
|
-
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
24
|
-
dev: "tsx src/cli.ts",
|
|
25
|
-
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|
|
26
|
-
"test:e2e": "node --no-warnings test/e2e-session-tests.mjs",
|
|
27
|
-
"test:frpc": "npx tsx test/test-frpc-e2e.mjs"
|
|
28
|
-
};
|
|
29
|
-
var dependencies = {
|
|
30
|
-
"@agentclientprotocol/sdk": "^0.14.1",
|
|
31
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
32
|
-
"hypha-rpc": "0.21.42",
|
|
33
|
-
"node-pty": "1.2.0-beta.11",
|
|
34
|
-
ws: "^8.18.0",
|
|
35
|
-
yaml: "^2.8.2",
|
|
36
|
-
zod: "^3.24.4"
|
|
37
|
-
};
|
|
38
|
-
var devDependencies = {
|
|
39
|
-
"@types/node": ">=20",
|
|
40
|
-
"@types/ws": "^8.5.14",
|
|
41
|
-
pkgroll: "^2.14.2",
|
|
42
|
-
tsx: "^4.20.6",
|
|
43
|
-
typescript: "5.9.3"
|
|
44
|
-
};
|
|
45
|
-
var packageManager = "yarn@1.22.22";
|
|
46
|
-
var _package = {
|
|
47
|
-
name: name,
|
|
48
|
-
version: version,
|
|
49
|
-
description: description,
|
|
50
|
-
author: author,
|
|
51
|
-
license: license,
|
|
52
|
-
type: type,
|
|
53
|
-
bin: bin,
|
|
54
|
-
files: files,
|
|
55
|
-
main: main,
|
|
56
|
-
exports: exports$1,
|
|
57
|
-
scripts: scripts,
|
|
58
|
-
dependencies: dependencies,
|
|
59
|
-
devDependencies: devDependencies,
|
|
60
|
-
packageManager: packageManager
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export { author, bin, _package as default, dependencies, description, devDependencies, exports$1 as exports, files, license, main, name, packageManager, scripts, type, version };
|