svamp-cli 0.1.29 → 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 +8 -8
- package/dist/{commands-CgT3AgJ0.mjs → commands-78RHC879.mjs} +162 -55
- package/dist/index.mjs +1 -1
- package/dist/{package-DPXkSwHu.mjs → package-BtoCHVOd.mjs} +1 -1
- package/dist/{run-BCSNMhiz.mjs → run-dBWhjQRf.mjs} +66 -61
- package/package.json +1 -1
- package/dist/agent-cli.mjs +0 -453
- package/dist/commands-1CYZC6Xh.mjs +0 -481
- package/dist/commands-B1DcpgLW.mjs +0 -481
- package/dist/commands-BGmdgMAC.mjs +0 -485
- package/dist/commands-BOeSil-P.mjs +0 -459
- package/dist/commands-BU4GZQuH.mjs +0 -481
- package/dist/commands-Ba66PxtQ.mjs +0 -481
- package/dist/commands-C0-xqIIc.mjs +0 -481
- package/dist/commands-C7Qy5n6d.mjs +0 -481
- package/dist/commands-CKTIJoV0.mjs +0 -636
- package/dist/commands-CKpC8R9T.mjs +0 -481
- package/dist/commands-CNqOjR1y.mjs +0 -481
- package/dist/commands-CVKh1tWr.mjs +0 -485
- package/dist/commands-CYBblX73.mjs +0 -485
- package/dist/commands-CZBYmj16.mjs +0 -485
- package/dist/commands-CcWIvCA4.mjs +0 -481
- package/dist/commands-Cfwf-cQG.mjs +0 -481
- package/dist/commands-CtO1WRt4.mjs +0 -862
- package/dist/commands-DCNO2m66.mjs +0 -471
- package/dist/commands-DDB3y1L1.mjs +0 -611
- package/dist/commands-DRIFvhmC.mjs +0 -481
- package/dist/commands-DXmw2dzy.mjs +0 -481
- package/dist/commands-DkSvlKFF.mjs +0 -485
- package/dist/commands-DnDd4Sew.mjs +0 -481
- package/dist/commands-DnpnAFQW.mjs +0 -485
- package/dist/commands-Do-TVYFm.mjs +0 -481
- package/dist/commands-GEXri0yz.mjs +0 -484
- package/dist/commands-Kzm0_XNH.mjs +0 -481
- package/dist/commands-MQvNbIid.mjs +0 -481
- package/dist/commands-_uCC3U1U.mjs +0 -481
- package/dist/commands-y2WG29W9.mjs +0 -485
- package/dist/hyphaClient-DLkclazm.mjs +0 -39
- package/dist/package-ASJ9pMHk.mjs +0 -60
- package/dist/package-B2FOzHaM.mjs +0 -57
- package/dist/package-Bk_PFVA0.mjs +0 -57
- package/dist/package-Bnij-ZtR.mjs +0 -57
- package/dist/package-BtRbHfjz.mjs +0 -57
- package/dist/package-C5B0twb8.mjs +0 -57
- package/dist/package-CC5d8_0L.mjs +0 -57
- package/dist/package-CCJ045H0.mjs +0 -60
- package/dist/package-CKOQ5lA7.mjs +0 -57
- package/dist/package-CS219SXn.mjs +0 -57
- package/dist/package-Cd-9ktpd.mjs +0 -60
- package/dist/package-CgBD49cA.mjs +0 -57
- package/dist/package-CvnNnsm7.mjs +0 -60
- package/dist/package-DpqWz9Cr.mjs +0 -60
- package/dist/package-JqEt5Ib4.mjs +0 -57
- package/dist/package-k18Su1iE.mjs +0 -58
- package/dist/package-nzkXV1aM.mjs +0 -57
- package/dist/package-pNo6GC3a.mjs +0 -60
- package/dist/package-pZp14zKI.mjs +0 -57
- package/dist/run-4fyJcaRE.mjs +0 -3856
- package/dist/run-B6oqR83K.mjs +0 -4631
- package/dist/run-BI32lPRK.mjs +0 -3870
- package/dist/run-BQHneHfW.mjs +0 -3834
- package/dist/run-Bb4fyIWZ.mjs +0 -3812
- package/dist/run-BglwnB-A.mjs +0 -3889
- package/dist/run-BjVWuitO.mjs +0 -3919
- package/dist/run-BzUE-JUT.mjs +0 -3708
- package/dist/run-BzqS97Sx.mjs +0 -3666
- package/dist/run-C6snRxyh.mjs +0 -3826
- package/dist/run-C8CI8Ujj.mjs +0 -3693
- package/dist/run-CL-FS4Yc.mjs +0 -3933
- package/dist/run-CS1Z4GcM.mjs +0 -3786
- package/dist/run-CT7uizQo.mjs +0 -4492
- package/dist/run-CUIj4xbE.mjs +0 -4880
- package/dist/run-CW26vPqj.mjs +0 -3919
- package/dist/run-CkTufc0D.mjs +0 -3875
- package/dist/run-Cmostc0S.mjs +0 -3902
- package/dist/run-Cp3kKdzm.mjs +0 -3865
- package/dist/run-CuN6K7pN.mjs +0 -4824
- package/dist/run-D0bCTY72.mjs +0 -3816
- package/dist/run-D4N6FQON.mjs +0 -4673
- package/dist/run-D4dlA0jo.mjs +0 -4813
- package/dist/run-DMD0N00A.mjs +0 -4737
- package/dist/run-DMW8ibIw.mjs +0 -3958
- package/dist/run-DO52unxE.mjs +0 -3950
- package/dist/run-DQ5FOQ_c.mjs +0 -4788
- package/dist/run-DT7FgL8L.mjs +0 -4339
- package/dist/run-DYhBROuo.mjs +0 -3934
- package/dist/run-DZmxHj-e.mjs +0 -4774
- package/dist/run-DjfPjgOb.mjs +0 -3904
- package/dist/run-DlL4JALM.mjs +0 -4719
- package/dist/run-Dp2JPkGI.mjs +0 -3913
- package/dist/run-Dptna3Je.mjs +0 -3867
- package/dist/run-DwK3dfHd.mjs +0 -3875
- package/dist/run-M_SMt96j.mjs +0 -3913
- package/dist/run-MlpxQUPN.mjs +0 -3869
- package/dist/run-PuTIelbv.mjs +0 -3706
- package/dist/run-h37iSCUB.mjs +0 -3934
- package/dist/run-lpV0oguG.mjs +0 -3897
- package/dist/run-oHmTMcv8.mjs +0 -4721
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-
|
|
1
|
+
import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-dBWhjQRf.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -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}`);
|
|
@@ -104,7 +104,7 @@ async function handleAgentCommand() {
|
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
if (agentArgs[0] === "list") {
|
|
107
|
-
const { KNOWN_ACP_AGENTS } = await import('./run-
|
|
107
|
+
const { KNOWN_ACP_AGENTS } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.f; });
|
|
108
108
|
console.log("Known ACP agents:");
|
|
109
109
|
for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
|
|
110
110
|
console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")}`);
|
|
@@ -113,10 +113,10 @@ async function handleAgentCommand() {
|
|
|
113
113
|
console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
|
-
const { resolveAcpAgentConfig } = await import('./run-
|
|
117
|
-
const { AcpBackend } = await import('./run-
|
|
118
|
-
const { GeminiTransport } = await import('./run-
|
|
119
|
-
const { DefaultTransport } = await import('./run-
|
|
116
|
+
const { resolveAcpAgentConfig } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.f; });
|
|
117
|
+
const { AcpBackend } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.e; });
|
|
118
|
+
const { GeminiTransport } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.G; });
|
|
119
|
+
const { DefaultTransport } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.D; });
|
|
120
120
|
let cwd = process.cwd();
|
|
121
121
|
const filteredArgs = [];
|
|
122
122
|
for (let i = 0; i < agentArgs.length; i++) {
|
|
@@ -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) {
|
|
@@ -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-dBWhjQRf.mjs';
|
|
5
5
|
import 'os';
|
|
6
6
|
import 'fs/promises';
|
|
7
7
|
import 'fs';
|
|
@@ -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) {
|
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-dBWhjQRf.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -183,6 +183,11 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
183
183
|
});
|
|
184
184
|
return result;
|
|
185
185
|
},
|
|
186
|
+
// Restart agent process in a session (machine-level fallback)
|
|
187
|
+
restartSession: async (sessionId, context) => {
|
|
188
|
+
authorizeRequest(context, currentMetadata.sharing, "interact");
|
|
189
|
+
return await handlers.restartSession(sessionId);
|
|
190
|
+
},
|
|
186
191
|
// Stop the daemon
|
|
187
192
|
stopDaemon: async (context) => {
|
|
188
193
|
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
@@ -425,6 +430,8 @@ async function registerSessionService(server, sessionId, initialMetadata, initia
|
|
|
425
430
|
data.uuid = randomUUID();
|
|
426
431
|
}
|
|
427
432
|
wrappedContent = { role: "agent", content: { type: "output", data } };
|
|
433
|
+
} else if (role === "event") {
|
|
434
|
+
wrappedContent = { role: "agent", content: { type: "event", data: content } };
|
|
428
435
|
} else if (role === "session") {
|
|
429
436
|
wrappedContent = { role: "session", content: { type: "session", data: content } };
|
|
430
437
|
} else {
|
|
@@ -2262,15 +2269,15 @@ function bridgeAcpToSession(backend, sessionService, getMetadata, setMetadata, l
|
|
|
2262
2269
|
setMetadata((m) => ({ ...m, lifecycleState: "running" }));
|
|
2263
2270
|
} else if (msg.status === "error") {
|
|
2264
2271
|
flushText();
|
|
2265
|
-
sessionService.pushMessage(
|
|
2266
|
-
type: "
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
sessionService.
|
|
2272
|
+
sessionService.pushMessage(
|
|
2273
|
+
{ type: "message", message: `Agent process exited unexpectedly: ${msg.detail || "Unknown error"}` },
|
|
2274
|
+
"event"
|
|
2275
|
+
);
|
|
2276
|
+
sessionService.sendSessionEnd();
|
|
2270
2277
|
setMetadata((m) => ({ ...m, lifecycleState: "error" }));
|
|
2271
2278
|
} else if (msg.status === "stopped") {
|
|
2272
2279
|
flushText();
|
|
2273
|
-
sessionService.
|
|
2280
|
+
sessionService.sendSessionEnd();
|
|
2274
2281
|
setMetadata((m) => ({ ...m, lifecycleState: "stopped" }));
|
|
2275
2282
|
}
|
|
2276
2283
|
break;
|
|
@@ -3800,17 +3807,11 @@ async function startDaemon() {
|
|
|
3800
3807
|
logger.log(`[Session ${sessionId}] Claude PID: ${child.pid}, stdin: ${!!child.stdin}, stdout: ${!!child.stdout}, stderr: ${!!child.stderr}`);
|
|
3801
3808
|
child.on("error", (err) => {
|
|
3802
3809
|
logger.log(`[Session ${sessionId}] Claude process error: ${err.message}`);
|
|
3803
|
-
sessionService.pushMessage(
|
|
3804
|
-
type: "
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
Please ensure Claude Code CLI is installed on this machine. You can install it with:
|
|
3810
|
-
\`npm install -g @anthropic-ai/claude-code\``
|
|
3811
|
-
}]
|
|
3812
|
-
}, "agent");
|
|
3813
|
-
sessionService.sendKeepAlive(false);
|
|
3810
|
+
sessionService.pushMessage(
|
|
3811
|
+
{ type: "message", message: `Agent process exited unexpectedly: ${err.message}. Please ensure Claude Code CLI is installed.` },
|
|
3812
|
+
"event"
|
|
3813
|
+
);
|
|
3814
|
+
sessionService.sendSessionEnd();
|
|
3814
3815
|
});
|
|
3815
3816
|
let stdoutBuffer = "";
|
|
3816
3817
|
let lastErrorMessagePushed = false;
|
|
@@ -4014,20 +4015,15 @@ Please ensure Claude Code CLI is installed on this machine. You can install it w
|
|
|
4014
4015
|
}
|
|
4015
4016
|
pendingPermissions.clear();
|
|
4016
4017
|
if (code !== 0 && code !== null && !lastErrorMessagePushed) {
|
|
4017
|
-
sessionService.pushMessage(
|
|
4018
|
-
type: "
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
text: `Error: Claude process exited with code ${code}${signal ? ` (signal: ${signal})` : ""}.
|
|
4022
|
-
|
|
4023
|
-
This may indicate that Claude Code CLI is not properly installed or configured.`
|
|
4024
|
-
}]
|
|
4025
|
-
}, "agent");
|
|
4018
|
+
sessionService.pushMessage(
|
|
4019
|
+
{ type: "message", message: `Agent process exited unexpectedly (code ${code}${signal ? `, signal: ${signal}` : ""})` },
|
|
4020
|
+
"event"
|
|
4021
|
+
);
|
|
4026
4022
|
}
|
|
4027
4023
|
lastErrorMessagePushed = false;
|
|
4028
4024
|
sessionMetadata = { ...sessionMetadata, lifecycleState: claudeResumeId ? "idle" : "stopped" };
|
|
4029
4025
|
sessionService.updateMetadata(sessionMetadata);
|
|
4030
|
-
sessionService.
|
|
4026
|
+
sessionService.sendSessionEnd();
|
|
4031
4027
|
if (claudeResumeId && !trackedSession.stopped) {
|
|
4032
4028
|
saveSession({
|
|
4033
4029
|
sessionId,
|
|
@@ -4051,6 +4047,30 @@ This may indicate that Claude Code CLI is not properly installed or configured.`
|
|
|
4051
4047
|
}
|
|
4052
4048
|
return child;
|
|
4053
4049
|
};
|
|
4050
|
+
const restartClaudeHandler = async () => {
|
|
4051
|
+
logger.log(`[Session ${sessionId}] Restart Claude requested`);
|
|
4052
|
+
try {
|
|
4053
|
+
if (claudeProcess && claudeProcess.exitCode === null) {
|
|
4054
|
+
isKillingClaude = true;
|
|
4055
|
+
sessionMetadata = { ...sessionMetadata, lifecycleState: "restarting" };
|
|
4056
|
+
sessionService.updateMetadata(sessionMetadata);
|
|
4057
|
+
await killAndWaitForExit2(claudeProcess);
|
|
4058
|
+
isKillingClaude = false;
|
|
4059
|
+
}
|
|
4060
|
+
if (claudeResumeId) {
|
|
4061
|
+
spawnClaude(void 0, { permissionMode: currentPermissionMode });
|
|
4062
|
+
logger.log(`[Session ${sessionId}] Claude respawned with --resume ${claudeResumeId}`);
|
|
4063
|
+
return { success: true, message: "Claude process restarted successfully." };
|
|
4064
|
+
} else {
|
|
4065
|
+
logger.log(`[Session ${sessionId}] No resume ID \u2014 cannot restart`);
|
|
4066
|
+
return { success: false, message: "No session to resume. Send a message to start a new session." };
|
|
4067
|
+
}
|
|
4068
|
+
} catch (err) {
|
|
4069
|
+
isKillingClaude = false;
|
|
4070
|
+
logger.log(`[Session ${sessionId}] Restart failed: ${err.message}`);
|
|
4071
|
+
return { success: false, message: `Restart failed: ${err.message}` };
|
|
4072
|
+
}
|
|
4073
|
+
};
|
|
4054
4074
|
const sessionService = await registerSessionService(
|
|
4055
4075
|
server,
|
|
4056
4076
|
sessionId,
|
|
@@ -4148,30 +4168,7 @@ This may indicate that Claude Code CLI is not properly installed or configured.`
|
|
|
4148
4168
|
spawnClaude(void 0, { permissionMode: mode });
|
|
4149
4169
|
}
|
|
4150
4170
|
},
|
|
4151
|
-
onRestartClaude:
|
|
4152
|
-
logger.log(`[Session ${sessionId}] Restart Claude requested`);
|
|
4153
|
-
try {
|
|
4154
|
-
if (claudeProcess && claudeProcess.exitCode === null) {
|
|
4155
|
-
isKillingClaude = true;
|
|
4156
|
-
sessionMetadata = { ...sessionMetadata, lifecycleState: "restarting" };
|
|
4157
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
4158
|
-
await killAndWaitForExit2(claudeProcess);
|
|
4159
|
-
isKillingClaude = false;
|
|
4160
|
-
}
|
|
4161
|
-
if (claudeResumeId) {
|
|
4162
|
-
spawnClaude(void 0, { permissionMode: currentPermissionMode });
|
|
4163
|
-
logger.log(`[Session ${sessionId}] Claude respawned with --resume ${claudeResumeId}`);
|
|
4164
|
-
return { success: true, message: "Claude process restarted successfully." };
|
|
4165
|
-
} else {
|
|
4166
|
-
logger.log(`[Session ${sessionId}] No resume ID \u2014 cannot restart`);
|
|
4167
|
-
return { success: false, message: "No session to resume. Send a message to start a new session." };
|
|
4168
|
-
}
|
|
4169
|
-
} catch (err) {
|
|
4170
|
-
isKillingClaude = false;
|
|
4171
|
-
logger.log(`[Session ${sessionId}] Restart failed: ${err.message}`);
|
|
4172
|
-
return { success: false, message: `Restart failed: ${err.message}` };
|
|
4173
|
-
}
|
|
4174
|
-
},
|
|
4171
|
+
onRestartClaude: restartClaudeHandler,
|
|
4175
4172
|
onKillSession: () => {
|
|
4176
4173
|
logger.log(`[Session ${sessionId}] Kill session requested`);
|
|
4177
4174
|
stopSession(sessionId);
|
|
@@ -4284,6 +4281,7 @@ This may indicate that Claude Code CLI is not properly installed or configured.`
|
|
|
4284
4281
|
checkSvampConfig,
|
|
4285
4282
|
directory,
|
|
4286
4283
|
resumeSessionId: claudeResumeId,
|
|
4284
|
+
restartAgent: restartClaudeHandler,
|
|
4287
4285
|
get childProcess() {
|
|
4288
4286
|
return claudeProcess || void 0;
|
|
4289
4287
|
}
|
|
@@ -4585,16 +4583,11 @@ This may indicate that Claude Code CLI is not properly installed or configured.`
|
|
|
4585
4583
|
logger.log(`[Agent Session ${sessionId}] ${agentName} backend started, waiting for first message`);
|
|
4586
4584
|
}).catch((err) => {
|
|
4587
4585
|
logger.error(`[Agent Session ${sessionId}] Failed to start ${agentName}:`, err);
|
|
4588
|
-
sessionService.pushMessage(
|
|
4589
|
-
type: "
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
Please ensure the ${agentName} CLI is installed.`
|
|
4595
|
-
}]
|
|
4596
|
-
}, "agent");
|
|
4597
|
-
sessionService.sendKeepAlive(false);
|
|
4586
|
+
sessionService.pushMessage(
|
|
4587
|
+
{ type: "message", message: `Agent process exited unexpectedly: ${err.message}. Please ensure the ${agentName} CLI is installed.` },
|
|
4588
|
+
"event"
|
|
4589
|
+
);
|
|
4590
|
+
sessionService.sendSessionEnd();
|
|
4598
4591
|
});
|
|
4599
4592
|
return {
|
|
4600
4593
|
type: "success",
|
|
@@ -4631,6 +4624,17 @@ Please ensure the ${agentName} CLI is installed.`
|
|
|
4631
4624
|
logger.log(`Session ${sessionId} not found`);
|
|
4632
4625
|
return false;
|
|
4633
4626
|
};
|
|
4627
|
+
const restartSession = async (sessionId) => {
|
|
4628
|
+
for (const session of pidToTrackedSession.values()) {
|
|
4629
|
+
if (session.svampSessionId === sessionId && !session.stopped) {
|
|
4630
|
+
if (session.restartAgent) {
|
|
4631
|
+
return await session.restartAgent();
|
|
4632
|
+
}
|
|
4633
|
+
return { success: false, message: "This session does not support restart." };
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
return { success: false, message: `Session ${sessionId} not found or already stopped.` };
|
|
4637
|
+
};
|
|
4634
4638
|
let isolationCapabilities;
|
|
4635
4639
|
try {
|
|
4636
4640
|
isolationCapabilities = await detectIsolationCapabilities();
|
|
@@ -4663,6 +4667,7 @@ Please ensure the ${agentName} CLI is installed.`
|
|
|
4663
4667
|
{
|
|
4664
4668
|
spawnSession,
|
|
4665
4669
|
stopSession,
|
|
4670
|
+
restartSession,
|
|
4666
4671
|
requestShutdown: () => requestShutdown("hypha-app"),
|
|
4667
4672
|
getTrackedSessions: getCurrentChildren
|
|
4668
4673
|
}
|