svamp-cli 0.1.30 → 0.1.31
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/cli.mjs +2 -2
- package/dist/{commands-C5pW2VmI.mjs → commands-78RHC879.mjs} +161 -54
- package/dist/{package-CKOQ5lA7.mjs → package-BtoCHVOd.mjs} +1 -1
- package/package.json +1 -1
- package/dist/commands-B2xQb9u7.mjs +0 -862
- package/dist/commands-CtO1WRt4.mjs +0 -862
- package/dist/commands-TZkNivgV.mjs +0 -862
- package/dist/run-BCSNMhiz.mjs +0 -4972
- package/dist/run-CtCTd6if.mjs +0 -4958
- package/dist/run-Cxdc5Zmw.mjs +0 -4976
package/dist/cli.mjs
CHANGED
|
@@ -89,7 +89,7 @@ async function main() {
|
|
|
89
89
|
} else if (subcommand === "--help" || subcommand === "-h" || !subcommand) {
|
|
90
90
|
printHelp();
|
|
91
91
|
} else if (subcommand === "--version" || subcommand === "-v") {
|
|
92
|
-
const pkg = await import('./package-
|
|
92
|
+
const pkg = await import('./package-BtoCHVOd.mjs').catch(() => ({ default: { version: "unknown" } }));
|
|
93
93
|
console.log(`svamp version: ${pkg.default.version}`);
|
|
94
94
|
} else {
|
|
95
95
|
console.error(`Unknown command: ${subcommand}`);
|
|
@@ -255,7 +255,7 @@ async function handleSessionCommand() {
|
|
|
255
255
|
printSessionHelp();
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
258
|
-
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait } = await import('./commands-
|
|
258
|
+
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait } = await import('./commands-78RHC879.mjs');
|
|
259
259
|
const parseFlagStr = (flag, shortFlag) => {
|
|
260
260
|
for (let i = 1; i < sessionArgs.length; i++) {
|
|
261
261
|
if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
|
|
@@ -186,7 +186,15 @@ async function connectAndGetMachine(machineId) {
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
} else {
|
|
189
|
-
|
|
189
|
+
if (state.machineId) {
|
|
190
|
+
const localMatch = services.find((s) => {
|
|
191
|
+
const id = s.id || s.name || "";
|
|
192
|
+
return id.includes(state.machineId);
|
|
193
|
+
});
|
|
194
|
+
selectedService = localMatch || services[0];
|
|
195
|
+
} else {
|
|
196
|
+
selectedService = services[0];
|
|
197
|
+
}
|
|
190
198
|
}
|
|
191
199
|
const svcId = selectedService.id || selectedService.name;
|
|
192
200
|
machine = await server.getService(svcId);
|
|
@@ -199,6 +207,81 @@ async function connectAndGetMachine(machineId) {
|
|
|
199
207
|
restoreConsole();
|
|
200
208
|
return { server, machine };
|
|
201
209
|
}
|
|
210
|
+
async function connectAndGetAllMachines() {
|
|
211
|
+
loadDotEnv();
|
|
212
|
+
const state = readDaemonState();
|
|
213
|
+
if (!state || !isDaemonAlive(state)) {
|
|
214
|
+
console.error('Daemon is not running. Start it with "svamp daemon start".');
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
const serverUrl = process.env.HYPHA_SERVER_URL || state.hyphaServerUrl;
|
|
218
|
+
const token = process.env.HYPHA_TOKEN;
|
|
219
|
+
if (!serverUrl) {
|
|
220
|
+
console.error('No Hypha server URL. Run "svamp login <url>" first.');
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
const origLog = console.log;
|
|
224
|
+
const origWarn = console.warn;
|
|
225
|
+
const origInfo = console.info;
|
|
226
|
+
const origError = console.error;
|
|
227
|
+
const stdoutWrite = process.stdout.write.bind(process.stdout);
|
|
228
|
+
const stderrWrite = process.stderr.write.bind(process.stderr);
|
|
229
|
+
const isHyphaLog = (chunk) => typeof chunk === "string" && (chunk.includes("WebSocket connection") || chunk.includes("Connection established") || chunk.includes("registering service built-in") || chunk.includes("registered service") || chunk.includes("registered all") || chunk.includes("Subscribing to client_") || chunk.includes("subscribed to client_") || chunk.includes("subscribe to client_") || chunk.includes("Cleaning up all sessions") || chunk.includes("WebSocket connection disconnected") || chunk.includes("local RPC disconnection") || chunk.includes("Timeout registering service") || chunk.includes("Failed to subscribe to client_disconnected") || chunk.includes("Timeout subscribing to client_disconnected"));
|
|
230
|
+
console.log = () => {
|
|
231
|
+
};
|
|
232
|
+
console.warn = () => {
|
|
233
|
+
};
|
|
234
|
+
console.info = () => {
|
|
235
|
+
};
|
|
236
|
+
console.error = (...args) => {
|
|
237
|
+
if (!args.some((a) => isHyphaLog(a))) origError(...args);
|
|
238
|
+
};
|
|
239
|
+
process.stdout.write = (chunk, ...args) => {
|
|
240
|
+
if (isHyphaLog(chunk)) return true;
|
|
241
|
+
return stdoutWrite(chunk, ...args);
|
|
242
|
+
};
|
|
243
|
+
process.stderr.write = (chunk, ...args) => {
|
|
244
|
+
if (isHyphaLog(chunk)) return true;
|
|
245
|
+
return stderrWrite(chunk, ...args);
|
|
246
|
+
};
|
|
247
|
+
const restoreConsole = () => {
|
|
248
|
+
console.log = origLog;
|
|
249
|
+
console.warn = origWarn;
|
|
250
|
+
console.info = origInfo;
|
|
251
|
+
console.error = origError;
|
|
252
|
+
};
|
|
253
|
+
let server;
|
|
254
|
+
try {
|
|
255
|
+
server = await connectToHypha({ serverUrl, token, name: "svamp-session-cli" });
|
|
256
|
+
} catch (err) {
|
|
257
|
+
restoreConsole();
|
|
258
|
+
console.error(`Failed to connect to Hypha: ${err.message}`);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
const machines = [];
|
|
262
|
+
try {
|
|
263
|
+
const services = await server.listServices({ type: "svamp-machine" });
|
|
264
|
+
for (const svc of services) {
|
|
265
|
+
try {
|
|
266
|
+
const svcId = svc.id || svc.name;
|
|
267
|
+
machines.push(await server.getService(svcId));
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
} catch (err) {
|
|
272
|
+
restoreConsole();
|
|
273
|
+
console.error(`Failed to discover machine services: ${err.message}`);
|
|
274
|
+
await server.disconnect();
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
restoreConsole();
|
|
278
|
+
if (machines.length === 0) {
|
|
279
|
+
console.error("No machine service found. Is the daemon registered on Hypha?");
|
|
280
|
+
await server.disconnect();
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
return { server, machines };
|
|
284
|
+
}
|
|
202
285
|
async function sessionMachines() {
|
|
203
286
|
loadDotEnv();
|
|
204
287
|
const state = readDaemonState();
|
|
@@ -497,66 +580,90 @@ async function waitForBusyThenIdle(server, sessionId, timeoutMs = 3e5, busyTimeo
|
|
|
497
580
|
throw new Error("Timeout waiting for agent to become idle");
|
|
498
581
|
}
|
|
499
582
|
async function sessionList(machineId, opts) {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
console.log(formatJson([]));
|
|
507
|
-
} else {
|
|
508
|
-
console.log("No active sessions.");
|
|
509
|
-
}
|
|
510
|
-
return;
|
|
583
|
+
if (machineId) {
|
|
584
|
+
const { server, machine } = await connectAndGetMachine(machineId);
|
|
585
|
+
try {
|
|
586
|
+
await listSessionsFromMachines(server, [machine], opts);
|
|
587
|
+
} finally {
|
|
588
|
+
await server.disconnect();
|
|
511
589
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
host = metadata?.host || "";
|
|
530
|
-
} catch {
|
|
531
|
-
}
|
|
590
|
+
} else {
|
|
591
|
+
const { server, machines } = await connectAndGetAllMachines();
|
|
592
|
+
try {
|
|
593
|
+
await listSessionsFromMachines(server, machines, opts);
|
|
594
|
+
} finally {
|
|
595
|
+
await server.disconnect();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
async function listSessionsFromMachines(server, machines, opts) {
|
|
600
|
+
const allSessions = [];
|
|
601
|
+
for (const machine of machines) {
|
|
602
|
+
try {
|
|
603
|
+
const info = await machine.getMachineInfo();
|
|
604
|
+
const sessions = await machine.listSessions();
|
|
605
|
+
for (const s of sessions) {
|
|
606
|
+
s.machineHost = info.metadata?.displayName || info.metadata?.host || info.machineId;
|
|
532
607
|
}
|
|
533
|
-
|
|
608
|
+
allSessions.push(...sessions);
|
|
609
|
+
} catch {
|
|
534
610
|
}
|
|
611
|
+
}
|
|
612
|
+
const filtered = opts?.active ? allSessions.filter((s) => s.active) : allSessions;
|
|
613
|
+
if (filtered.length === 0) {
|
|
535
614
|
if (opts?.json) {
|
|
536
|
-
console.log(formatJson(
|
|
537
|
-
sessionId: s.sessionId,
|
|
538
|
-
agent: s.flavor,
|
|
539
|
-
name: s.name,
|
|
540
|
-
path: s.path,
|
|
541
|
-
host: s.host,
|
|
542
|
-
active: s.active,
|
|
543
|
-
directory: s.directory
|
|
544
|
-
}))));
|
|
615
|
+
console.log(formatJson([]));
|
|
545
616
|
} else {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
617
|
+
console.log("No active sessions.");
|
|
618
|
+
}
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
const enriched = [];
|
|
622
|
+
for (const s of filtered) {
|
|
623
|
+
let flavor = "claude";
|
|
624
|
+
let name = "";
|
|
625
|
+
let path = s.directory || "";
|
|
626
|
+
let host = s.machineHost || "";
|
|
627
|
+
if (s.metadata) {
|
|
628
|
+
flavor = s.metadata.flavor || "claude";
|
|
629
|
+
name = s.metadata.name || "";
|
|
630
|
+
}
|
|
631
|
+
if (s.active) {
|
|
632
|
+
try {
|
|
633
|
+
const svc = await server.getService(`svamp-session-${s.sessionId}`);
|
|
634
|
+
const { metadata } = await svc.getMetadata();
|
|
635
|
+
flavor = metadata?.flavor || flavor;
|
|
636
|
+
name = metadata?.name || name;
|
|
637
|
+
path = metadata?.path || path;
|
|
638
|
+
host = metadata?.host || host;
|
|
639
|
+
} catch {
|
|
556
640
|
}
|
|
557
641
|
}
|
|
558
|
-
|
|
559
|
-
|
|
642
|
+
enriched.push({ ...s, flavor, name, path, host });
|
|
643
|
+
}
|
|
644
|
+
if (opts?.json) {
|
|
645
|
+
console.log(formatJson(enriched.map((s) => ({
|
|
646
|
+
sessionId: s.sessionId,
|
|
647
|
+
agent: s.flavor,
|
|
648
|
+
name: s.name,
|
|
649
|
+
path: s.path,
|
|
650
|
+
host: s.host,
|
|
651
|
+
active: s.active,
|
|
652
|
+
directory: s.directory
|
|
653
|
+
}))));
|
|
654
|
+
} else {
|
|
655
|
+
const header = `${"ID".padEnd(10)} ${"AGENT".padEnd(10)} ${"STATUS".padEnd(9)} ${"NAME".padEnd(25)} ${"MACHINE".padEnd(18)} ${"DIRECTORY".padEnd(35)}`;
|
|
656
|
+
console.log(header);
|
|
657
|
+
console.log("-".repeat(header.length));
|
|
658
|
+
for (const s of enriched) {
|
|
659
|
+
const id = s.sessionId.slice(0, 8);
|
|
660
|
+
const agent = (s.flavor || "claude").padEnd(10);
|
|
661
|
+
const status = s.active ? "\x1B[32mactive\x1B[0m " : "\x1B[90minactive\x1B[0m";
|
|
662
|
+
const name = truncate(s.name || "-", 25).padEnd(25);
|
|
663
|
+
const machine = truncate(s.host || "-", 16).padEnd(18);
|
|
664
|
+
const dir = truncate(s.directory || "-", 33).padEnd(35);
|
|
665
|
+
console.log(`${id.padEnd(10)} ${agent} ${status} ${name} ${machine} ${dir}`);
|
|
666
|
+
}
|
|
560
667
|
}
|
|
561
668
|
}
|
|
562
669
|
async function sessionSpawn(agent, directory, machineId, opts) {
|