svamp-cli 0.1.80 → 0.1.82
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-WLRw5gAP.mjs → agentCommands-DJQZraQK.mjs} +2 -2
- package/dist/cli.mjs +27 -27
- package/dist/{commands-C06J5fW3.mjs → commands-BkDj4wWg.mjs} +127 -79
- package/dist/{commands-CphOj2pR.mjs → commands-D6pOaahW.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{package-CSxyijZF.mjs → package-B9nxDOIr.mjs} +2 -2
- package/dist/{run-DsSVL5N4.mjs → run-Ceop6nDB.mjs} +1 -1
- package/dist/{run-Dm7UViwQ.mjs → run-RO50yndI.mjs} +92 -65
- package/package.json +2 -2
|
@@ -145,7 +145,7 @@ async function sessionBroadcast(action, args) {
|
|
|
145
145
|
console.log(`Broadcast sent: ${action}`);
|
|
146
146
|
}
|
|
147
147
|
async function connectToMachineService() {
|
|
148
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
148
|
+
const { connectAndGetMachine } = await import('./commands-BkDj4wWg.mjs');
|
|
149
149
|
return connectAndGetMachine();
|
|
150
150
|
}
|
|
151
151
|
async function inboxSend(targetSessionId, opts) {
|
|
@@ -161,7 +161,7 @@ async function inboxSend(targetSessionId, opts) {
|
|
|
161
161
|
}
|
|
162
162
|
const { server, machine } = await connectToMachineService();
|
|
163
163
|
try {
|
|
164
|
-
const { resolveSessionId } = await import('./commands-
|
|
164
|
+
const { resolveSessionId } = await import('./commands-BkDj4wWg.mjs');
|
|
165
165
|
const sessions = await machine.listSessions();
|
|
166
166
|
const match = resolveSessionId(sessions, targetSessionId);
|
|
167
167
|
const fullTargetId = match.sessionId;
|
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as stopDaemon, s as startDaemon, d as daemonStatus } from './run-
|
|
1
|
+
import { b as stopDaemon, s as startDaemon, d as daemonStatus } from './run-RO50yndI.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -211,7 +211,7 @@ async function main() {
|
|
|
211
211
|
const { handleServiceCommand } = await import('./commands-BYbuedOK.mjs');
|
|
212
212
|
await handleServiceCommand();
|
|
213
213
|
} else if (subcommand === "process" || subcommand === "proc") {
|
|
214
|
-
const { processCommand } = await import('./commands-
|
|
214
|
+
const { processCommand } = await import('./commands-D6pOaahW.mjs');
|
|
215
215
|
let machineId;
|
|
216
216
|
const processArgs = args.slice(1);
|
|
217
217
|
const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
|
|
@@ -229,7 +229,7 @@ async function main() {
|
|
|
229
229
|
} else if (!subcommand || subcommand === "start") {
|
|
230
230
|
await handleInteractiveCommand();
|
|
231
231
|
} else if (subcommand === "--version" || subcommand === "-v") {
|
|
232
|
-
const pkg = await import('./package-
|
|
232
|
+
const pkg = await import('./package-B9nxDOIr.mjs').catch(() => ({ default: { version: "unknown" } }));
|
|
233
233
|
console.log(`svamp version: ${pkg.default.version}`);
|
|
234
234
|
} else {
|
|
235
235
|
console.error(`Unknown command: ${subcommand}`);
|
|
@@ -238,7 +238,7 @@ async function main() {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
async function handleInteractiveCommand() {
|
|
241
|
-
const { runInteractive } = await import('./run-
|
|
241
|
+
const { runInteractive } = await import('./run-Ceop6nDB.mjs');
|
|
242
242
|
const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
|
|
243
243
|
let directory = process.cwd();
|
|
244
244
|
let resumeSessionId;
|
|
@@ -283,7 +283,7 @@ async function handleAgentCommand() {
|
|
|
283
283
|
return;
|
|
284
284
|
}
|
|
285
285
|
if (agentArgs[0] === "list") {
|
|
286
|
-
const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-
|
|
286
|
+
const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-RO50yndI.mjs').then(function (n) { return n.i; });
|
|
287
287
|
console.log("Known agents:");
|
|
288
288
|
for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
|
|
289
289
|
console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
|
|
@@ -295,7 +295,7 @@ async function handleAgentCommand() {
|
|
|
295
295
|
console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
|
|
296
296
|
return;
|
|
297
297
|
}
|
|
298
|
-
const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-
|
|
298
|
+
const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-RO50yndI.mjs').then(function (n) { return n.i; });
|
|
299
299
|
let cwd = process.cwd();
|
|
300
300
|
const filteredArgs = [];
|
|
301
301
|
for (let i = 0; i < agentArgs.length; i++) {
|
|
@@ -319,12 +319,12 @@ async function handleAgentCommand() {
|
|
|
319
319
|
console.log(`Starting ${config.agentName} agent in ${cwd}...`);
|
|
320
320
|
let backend;
|
|
321
321
|
if (KNOWN_MCP_AGENTS[config.agentName]) {
|
|
322
|
-
const { CodexMcpBackend } = await import('./run-
|
|
322
|
+
const { CodexMcpBackend } = await import('./run-RO50yndI.mjs').then(function (n) { return n.j; });
|
|
323
323
|
backend = new CodexMcpBackend({ cwd, log: logFn });
|
|
324
324
|
} else {
|
|
325
|
-
const { AcpBackend } = await import('./run-
|
|
326
|
-
const { GeminiTransport } = await import('./run-
|
|
327
|
-
const { DefaultTransport } = await import('./run-
|
|
325
|
+
const { AcpBackend } = await import('./run-RO50yndI.mjs').then(function (n) { return n.h; });
|
|
326
|
+
const { GeminiTransport } = await import('./run-RO50yndI.mjs').then(function (n) { return n.G; });
|
|
327
|
+
const { DefaultTransport } = await import('./run-RO50yndI.mjs').then(function (n) { return n.D; });
|
|
328
328
|
const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
|
|
329
329
|
backend = new AcpBackend({
|
|
330
330
|
agentName: config.agentName,
|
|
@@ -442,7 +442,7 @@ async function handleSessionCommand() {
|
|
|
442
442
|
printSessionHelp();
|
|
443
443
|
return;
|
|
444
444
|
}
|
|
445
|
-
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-
|
|
445
|
+
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-BkDj4wWg.mjs');
|
|
446
446
|
const parseFlagStr = (flag, shortFlag) => {
|
|
447
447
|
for (let i = 1; i < sessionArgs.length; i++) {
|
|
448
448
|
if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
|
|
@@ -502,7 +502,7 @@ async function handleSessionCommand() {
|
|
|
502
502
|
allowDomain.push(sessionArgs[++i]);
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
|
-
const { parseShareArg } = await import('./commands-
|
|
505
|
+
const { parseShareArg } = await import('./commands-BkDj4wWg.mjs');
|
|
506
506
|
const shareEntries = share.map((s) => parseShareArg(s));
|
|
507
507
|
await sessionSpawn(agent, dir, targetMachineId, {
|
|
508
508
|
message,
|
|
@@ -588,7 +588,7 @@ async function handleSessionCommand() {
|
|
|
588
588
|
console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
|
|
589
589
|
process.exit(1);
|
|
590
590
|
}
|
|
591
|
-
const { sessionApprove } = await import('./commands-
|
|
591
|
+
const { sessionApprove } = await import('./commands-BkDj4wWg.mjs');
|
|
592
592
|
const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
|
|
593
593
|
await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
|
|
594
594
|
json: hasFlag("--json")
|
|
@@ -598,7 +598,7 @@ async function handleSessionCommand() {
|
|
|
598
598
|
console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
|
|
599
599
|
process.exit(1);
|
|
600
600
|
}
|
|
601
|
-
const { sessionDeny } = await import('./commands-
|
|
601
|
+
const { sessionDeny } = await import('./commands-BkDj4wWg.mjs');
|
|
602
602
|
const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
|
|
603
603
|
await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
|
|
604
604
|
json: hasFlag("--json")
|
|
@@ -634,7 +634,7 @@ async function handleSessionCommand() {
|
|
|
634
634
|
console.error("Usage: svamp session set-title <title>");
|
|
635
635
|
process.exit(1);
|
|
636
636
|
}
|
|
637
|
-
const { sessionSetTitle } = await import('./agentCommands-
|
|
637
|
+
const { sessionSetTitle } = await import('./agentCommands-DJQZraQK.mjs');
|
|
638
638
|
await sessionSetTitle(title);
|
|
639
639
|
} else if (sessionSubcommand === "set-link") {
|
|
640
640
|
const url = sessionArgs[1];
|
|
@@ -643,7 +643,7 @@ async function handleSessionCommand() {
|
|
|
643
643
|
process.exit(1);
|
|
644
644
|
}
|
|
645
645
|
const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
|
|
646
|
-
const { sessionSetLink } = await import('./agentCommands-
|
|
646
|
+
const { sessionSetLink } = await import('./agentCommands-DJQZraQK.mjs');
|
|
647
647
|
await sessionSetLink(url, label);
|
|
648
648
|
} else if (sessionSubcommand === "notify") {
|
|
649
649
|
const message = sessionArgs[1];
|
|
@@ -652,7 +652,7 @@ async function handleSessionCommand() {
|
|
|
652
652
|
process.exit(1);
|
|
653
653
|
}
|
|
654
654
|
const level = parseFlagStr("--level") || "info";
|
|
655
|
-
const { sessionNotify } = await import('./agentCommands-
|
|
655
|
+
const { sessionNotify } = await import('./agentCommands-DJQZraQK.mjs');
|
|
656
656
|
await sessionNotify(message, level);
|
|
657
657
|
} else if (sessionSubcommand === "broadcast") {
|
|
658
658
|
const action = sessionArgs[1];
|
|
@@ -660,7 +660,7 @@ async function handleSessionCommand() {
|
|
|
660
660
|
console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
|
|
661
661
|
process.exit(1);
|
|
662
662
|
}
|
|
663
|
-
const { sessionBroadcast } = await import('./agentCommands-
|
|
663
|
+
const { sessionBroadcast } = await import('./agentCommands-DJQZraQK.mjs');
|
|
664
664
|
await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
|
|
665
665
|
} else if (sessionSubcommand === "inbox") {
|
|
666
666
|
const inboxSubcmd = sessionArgs[1];
|
|
@@ -671,7 +671,7 @@ async function handleSessionCommand() {
|
|
|
671
671
|
process.exit(1);
|
|
672
672
|
}
|
|
673
673
|
if (agentSessionId) {
|
|
674
|
-
const { inboxSend } = await import('./agentCommands-
|
|
674
|
+
const { inboxSend } = await import('./agentCommands-DJQZraQK.mjs');
|
|
675
675
|
await inboxSend(sessionArgs[2], {
|
|
676
676
|
body: sessionArgs[3],
|
|
677
677
|
subject: parseFlagStr("--subject"),
|
|
@@ -686,7 +686,7 @@ async function handleSessionCommand() {
|
|
|
686
686
|
}
|
|
687
687
|
} else if (inboxSubcmd === "list" || inboxSubcmd === "ls") {
|
|
688
688
|
if (agentSessionId && !sessionArgs[2]) {
|
|
689
|
-
const { inboxList } = await import('./agentCommands-
|
|
689
|
+
const { inboxList } = await import('./agentCommands-DJQZraQK.mjs');
|
|
690
690
|
await inboxList({
|
|
691
691
|
unread: hasFlag("--unread"),
|
|
692
692
|
limit: parseFlagInt("--limit"),
|
|
@@ -708,7 +708,7 @@ async function handleSessionCommand() {
|
|
|
708
708
|
process.exit(1);
|
|
709
709
|
}
|
|
710
710
|
if (agentSessionId && !sessionArgs[3]) {
|
|
711
|
-
const { inboxList } = await import('./agentCommands-
|
|
711
|
+
const { inboxList } = await import('./agentCommands-DJQZraQK.mjs');
|
|
712
712
|
await sessionInboxRead(agentSessionId, sessionArgs[2], targetMachineId);
|
|
713
713
|
} else if (sessionArgs[3]) {
|
|
714
714
|
await sessionInboxRead(sessionArgs[2], sessionArgs[3], targetMachineId);
|
|
@@ -718,7 +718,7 @@ async function handleSessionCommand() {
|
|
|
718
718
|
}
|
|
719
719
|
} else if (inboxSubcmd === "reply") {
|
|
720
720
|
if (agentSessionId && sessionArgs[2] && sessionArgs[3] && !sessionArgs[4]) {
|
|
721
|
-
const { inboxReply } = await import('./agentCommands-
|
|
721
|
+
const { inboxReply } = await import('./agentCommands-DJQZraQK.mjs');
|
|
722
722
|
await inboxReply(sessionArgs[2], sessionArgs[3]);
|
|
723
723
|
} else if (sessionArgs[2] && sessionArgs[3] && sessionArgs[4]) {
|
|
724
724
|
await sessionInboxReply(sessionArgs[2], sessionArgs[3], sessionArgs[4], targetMachineId);
|
|
@@ -754,7 +754,7 @@ async function handleMachineCommand() {
|
|
|
754
754
|
return;
|
|
755
755
|
}
|
|
756
756
|
if (machineSubcommand === "share") {
|
|
757
|
-
const { machineShare } = await import('./commands-
|
|
757
|
+
const { machineShare } = await import('./commands-BkDj4wWg.mjs');
|
|
758
758
|
let machineId;
|
|
759
759
|
const shareArgs = [];
|
|
760
760
|
for (let i = 1; i < machineArgs.length; i++) {
|
|
@@ -784,7 +784,7 @@ async function handleMachineCommand() {
|
|
|
784
784
|
}
|
|
785
785
|
await machineShare(machineId, { add, remove, list, configPath, showConfig });
|
|
786
786
|
} else if (machineSubcommand === "exec") {
|
|
787
|
-
const { machineExec } = await import('./commands-
|
|
787
|
+
const { machineExec } = await import('./commands-BkDj4wWg.mjs');
|
|
788
788
|
let machineId;
|
|
789
789
|
let cwd;
|
|
790
790
|
const cmdParts = [];
|
|
@@ -804,7 +804,7 @@ async function handleMachineCommand() {
|
|
|
804
804
|
}
|
|
805
805
|
await machineExec(machineId, command, cwd);
|
|
806
806
|
} else if (machineSubcommand === "info") {
|
|
807
|
-
const { machineInfo } = await import('./commands-
|
|
807
|
+
const { machineInfo } = await import('./commands-BkDj4wWg.mjs');
|
|
808
808
|
let machineId;
|
|
809
809
|
for (let i = 1; i < machineArgs.length; i++) {
|
|
810
810
|
if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
|
|
@@ -824,10 +824,10 @@ async function handleMachineCommand() {
|
|
|
824
824
|
level = machineArgs[++i];
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
|
-
const { machineNotify } = await import('./agentCommands-
|
|
827
|
+
const { machineNotify } = await import('./agentCommands-DJQZraQK.mjs');
|
|
828
828
|
await machineNotify(message, level);
|
|
829
829
|
} else if (machineSubcommand === "ls") {
|
|
830
|
-
const { machineLs } = await import('./commands-
|
|
830
|
+
const { machineLs } = await import('./commands-BkDj4wWg.mjs');
|
|
831
831
|
let machineId;
|
|
832
832
|
let showHidden = false;
|
|
833
833
|
let path;
|
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
|
-
import { l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha } from './run-
|
|
5
|
+
import { l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha } from './run-RO50yndI.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
8
8
|
import 'fs';
|
|
@@ -70,6 +70,58 @@ function formatJson(data) {
|
|
|
70
70
|
return JSON.stringify(data, null, 2);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
const SESSION_RPC_PARAMS = {
|
|
74
|
+
getMessages: ["afterSeq", "limit"],
|
|
75
|
+
sendMessage: ["content", "localId", "meta"],
|
|
76
|
+
getMetadata: [],
|
|
77
|
+
updateMetadata: ["newMetadata", "expectedVersion"],
|
|
78
|
+
updateConfig: ["patch"],
|
|
79
|
+
getAgentState: [],
|
|
80
|
+
updateAgentState: ["newState", "expectedVersion"],
|
|
81
|
+
abort: [],
|
|
82
|
+
permissionResponse: ["params"],
|
|
83
|
+
switchMode: ["mode"],
|
|
84
|
+
restartClaude: [],
|
|
85
|
+
killSession: [],
|
|
86
|
+
keepAlive: ["thinking", "mode"],
|
|
87
|
+
sessionEnd: [],
|
|
88
|
+
getActivityState: [],
|
|
89
|
+
readFile: ["path"],
|
|
90
|
+
writeFile: ["path", "content"],
|
|
91
|
+
listDirectory: ["path"],
|
|
92
|
+
bash: ["command", "cwd", "timeout"],
|
|
93
|
+
ripgrep: ["args", "cwd"],
|
|
94
|
+
getDirectoryTree: ["path", "maxDepth"],
|
|
95
|
+
getSharing: [],
|
|
96
|
+
getEffectiveRole: [],
|
|
97
|
+
updateSharing: ["newSharing"],
|
|
98
|
+
updateSecurityContext: ["newSecurityContext"],
|
|
99
|
+
applySystemPrompt: ["prompt"],
|
|
100
|
+
sendInboxMessage: ["message"],
|
|
101
|
+
getInbox: ["opts"],
|
|
102
|
+
markInboxRead: ["messageId"],
|
|
103
|
+
clearInbox: ["opts"],
|
|
104
|
+
registerListener: ["callback"]
|
|
105
|
+
};
|
|
106
|
+
function getSessionProxy(machine, sessionId) {
|
|
107
|
+
return new Proxy({}, {
|
|
108
|
+
get(_target, method) {
|
|
109
|
+
return (...args) => {
|
|
110
|
+
const paramNames = SESSION_RPC_PARAMS[method];
|
|
111
|
+
if (paramNames) {
|
|
112
|
+
const kwargs = {};
|
|
113
|
+
for (let i = 0; i < paramNames.length && i < args.length; i++) {
|
|
114
|
+
if (args[i] !== void 0) {
|
|
115
|
+
kwargs[paramNames[i]] = args[i];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return machine.sessionRPC(sessionId, method, kwargs);
|
|
119
|
+
}
|
|
120
|
+
return machine.sessionRPC(sessionId, method, {});
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
73
125
|
const SVAMP_HOME = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
|
|
74
126
|
const DAEMON_STATE_FILE = join(SVAMP_HOME, "daemon.state.json");
|
|
75
127
|
const ENV_FILE = join(SVAMP_HOME, ".env");
|
|
@@ -318,12 +370,11 @@ async function connectAndGetAllMachines() {
|
|
|
318
370
|
const machines = [];
|
|
319
371
|
try {
|
|
320
372
|
const services = await server.listServices({ query: { type: "svamp-machine" }, include_unlisted: true, _rkwargs: true });
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
373
|
+
const results = await Promise.allSettled(
|
|
374
|
+
services.map((svc) => server.getService(svc.id || svc.name))
|
|
375
|
+
);
|
|
376
|
+
for (const r of results) {
|
|
377
|
+
if (r.status === "fulfilled") machines.push(r.value);
|
|
327
378
|
}
|
|
328
379
|
} catch (err) {
|
|
329
380
|
restoreConsole();
|
|
@@ -402,34 +453,37 @@ async function sessionMachines() {
|
|
|
402
453
|
console.log("No machines found.");
|
|
403
454
|
return;
|
|
404
455
|
}
|
|
405
|
-
const machines =
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
456
|
+
const machines = await Promise.all(
|
|
457
|
+
services.map(async (svc) => {
|
|
458
|
+
const svcId = svc.id || svc.name;
|
|
459
|
+
try {
|
|
460
|
+
const machineSvc = await server.getService(svcId);
|
|
461
|
+
const [info, sessions] = await Promise.all([
|
|
462
|
+
machineSvc.getMachineInfo(),
|
|
463
|
+
machineSvc.listSessions()
|
|
464
|
+
]);
|
|
465
|
+
return {
|
|
466
|
+
serviceId: svcId,
|
|
467
|
+
machineId: info.machineId || svcId,
|
|
468
|
+
displayName: info.metadata?.displayName || info.metadata?.host || "-",
|
|
469
|
+
platform: info.metadata?.platform || "-",
|
|
470
|
+
host: info.metadata?.host || "-",
|
|
471
|
+
sessions: sessions.length,
|
|
472
|
+
status: info.daemonState?.status || "unknown"
|
|
473
|
+
};
|
|
474
|
+
} catch {
|
|
475
|
+
return {
|
|
476
|
+
serviceId: svcId,
|
|
477
|
+
machineId: svcId,
|
|
478
|
+
displayName: "-",
|
|
479
|
+
platform: "-",
|
|
480
|
+
host: "-",
|
|
481
|
+
sessions: -1,
|
|
482
|
+
status: "unreachable"
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
})
|
|
486
|
+
);
|
|
433
487
|
const header = `${"MACHINE ID".padEnd(20)} ${"NAME".padEnd(20)} ${"PLATFORM".padEnd(12)} ${"HOST".padEnd(25)} ${"SESSIONS".padEnd(10)} ${"STATUS"}`;
|
|
434
488
|
console.log(header);
|
|
435
489
|
console.log("-".repeat(header.length));
|
|
@@ -672,18 +726,23 @@ async function sessionList(machineId, opts) {
|
|
|
672
726
|
}
|
|
673
727
|
}
|
|
674
728
|
}
|
|
675
|
-
async function listSessionsFromMachines(
|
|
729
|
+
async function listSessionsFromMachines(_server, machines, opts) {
|
|
676
730
|
const allSessions = [];
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
const info = await
|
|
680
|
-
|
|
731
|
+
const machineResults = await Promise.allSettled(
|
|
732
|
+
machines.map(async (machine) => {
|
|
733
|
+
const [info, sessions] = await Promise.all([
|
|
734
|
+
machine.getMachineInfo(),
|
|
735
|
+
machine.listSessions()
|
|
736
|
+
]);
|
|
737
|
+
const host = info.metadata?.displayName || info.metadata?.host || info.machineId;
|
|
681
738
|
for (const s of sessions) {
|
|
682
|
-
s.machineHost =
|
|
739
|
+
s.machineHost = host;
|
|
683
740
|
}
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
|
|
741
|
+
return sessions;
|
|
742
|
+
})
|
|
743
|
+
);
|
|
744
|
+
for (const r of machineResults) {
|
|
745
|
+
if (r.status === "fulfilled") allSessions.push(...r.value);
|
|
687
746
|
}
|
|
688
747
|
const filtered = opts?.active ? allSessions.filter((s) => s.active) : allSessions;
|
|
689
748
|
if (filtered.length === 0) {
|
|
@@ -694,29 +753,16 @@ async function listSessionsFromMachines(server, machines, opts) {
|
|
|
694
753
|
}
|
|
695
754
|
return;
|
|
696
755
|
}
|
|
697
|
-
const enriched =
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
if (s.active) {
|
|
708
|
-
try {
|
|
709
|
-
const svc = await server.getService(`svamp-session-${s.sessionId}`);
|
|
710
|
-
const { metadata } = await svc.getMetadata();
|
|
711
|
-
flavor = metadata?.flavor || flavor;
|
|
712
|
-
name = metadata?.name || name;
|
|
713
|
-
path = metadata?.path || path;
|
|
714
|
-
host = metadata?.host || host;
|
|
715
|
-
} catch {
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
enriched.push({ ...s, flavor, name, path, host });
|
|
719
|
-
}
|
|
756
|
+
const enriched = filtered.map((s) => {
|
|
757
|
+
const m = s.metadata || {};
|
|
758
|
+
return {
|
|
759
|
+
...s,
|
|
760
|
+
flavor: m.flavor || "claude",
|
|
761
|
+
name: m.name || "",
|
|
762
|
+
path: m.path || s.directory || "",
|
|
763
|
+
host: m.host || s.machineHost || ""
|
|
764
|
+
};
|
|
765
|
+
});
|
|
720
766
|
if (opts?.json) {
|
|
721
767
|
console.log(formatJson(enriched.map((s) => ({
|
|
722
768
|
sessionId: s.sessionId,
|
|
@@ -874,12 +920,14 @@ async function sessionSpawn(agent, directory, machineId, opts) {
|
|
|
874
920
|
let effectiveParentSessionId = opts?.parentSessionId || process.env.SVAMP_SESSION_ID || void 0;
|
|
875
921
|
if (effectiveParentSessionId) {
|
|
876
922
|
try {
|
|
923
|
+
const sessions = await machine.listSessions();
|
|
877
924
|
if (opts?.parentSessionId) {
|
|
878
|
-
const sessions = await machine.listSessions();
|
|
879
925
|
const match = resolveSessionId(sessions, effectiveParentSessionId);
|
|
880
926
|
effectiveParentSessionId = match.sessionId;
|
|
927
|
+
} else {
|
|
928
|
+
const found = sessions.find((s) => s.sessionId === effectiveParentSessionId);
|
|
929
|
+
if (!found) throw new Error("not found");
|
|
881
930
|
}
|
|
882
|
-
await server.getService(`svamp-session-${effectiveParentSessionId}`);
|
|
883
931
|
} catch (err) {
|
|
884
932
|
const source = opts?.parentSessionId ? "--parent" : "SVAMP_SESSION_ID";
|
|
885
933
|
console.error(`Error: Parent session ${effectiveParentSessionId} not found (from ${source}).`);
|
|
@@ -921,7 +969,7 @@ async function sessionSpawn(agent, directory, machineId, opts) {
|
|
|
921
969
|
console.log(`\x1B[33m Use -p bypassPermissions to run without approval prompts.\x1B[0m`);
|
|
922
970
|
}
|
|
923
971
|
if (opts?.message && result.sessionId) {
|
|
924
|
-
const svc =
|
|
972
|
+
const svc = getSessionProxy(machine, result.sessionId);
|
|
925
973
|
const sendResult = await svc.sendMessage(
|
|
926
974
|
JSON.stringify({
|
|
927
975
|
role: "user",
|
|
@@ -972,7 +1020,7 @@ async function sessionInfo(sessionId, machineId, opts) {
|
|
|
972
1020
|
let metadata = {};
|
|
973
1021
|
let activity = {};
|
|
974
1022
|
try {
|
|
975
|
-
const svc =
|
|
1023
|
+
const svc = getSessionProxy(machine, fullId);
|
|
976
1024
|
const metaResult = await svc.getMetadata();
|
|
977
1025
|
metadata = metaResult.metadata || {};
|
|
978
1026
|
activity = await svc.getActivityState();
|
|
@@ -1012,7 +1060,7 @@ async function sessionMessages(sessionId, machineId, opts) {
|
|
|
1012
1060
|
const sessions = await machine.listSessions();
|
|
1013
1061
|
const match = resolveSessionId(sessions, sessionId);
|
|
1014
1062
|
const fullId = match.sessionId;
|
|
1015
|
-
const svc =
|
|
1063
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1016
1064
|
const afterSeq = opts?.after ?? 0;
|
|
1017
1065
|
const apiLimit = opts?.limit ?? 1e3;
|
|
1018
1066
|
const { messages } = await svc.getMessages(afterSeq, apiLimit);
|
|
@@ -1052,7 +1100,7 @@ async function sessionApprove(sessionId, requestId, machineId, opts) {
|
|
|
1052
1100
|
const sessions = await machine.listSessions();
|
|
1053
1101
|
const match = resolveSessionId(sessions, sessionId);
|
|
1054
1102
|
const fullId = match.sessionId;
|
|
1055
|
-
const svc =
|
|
1103
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1056
1104
|
if (requestId) {
|
|
1057
1105
|
const activity = await svc.getActivityState();
|
|
1058
1106
|
const pending = activity.pendingPermissions || [];
|
|
@@ -1101,7 +1149,7 @@ async function sessionDeny(sessionId, requestId, machineId, opts) {
|
|
|
1101
1149
|
const sessions = await machine.listSessions();
|
|
1102
1150
|
const match = resolveSessionId(sessions, sessionId);
|
|
1103
1151
|
const fullId = match.sessionId;
|
|
1104
|
-
const svc =
|
|
1152
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1105
1153
|
if (requestId) {
|
|
1106
1154
|
const activity = await svc.getActivityState();
|
|
1107
1155
|
const pending = activity.pendingPermissions || [];
|
|
@@ -1151,7 +1199,7 @@ async function sessionAttach(sessionId, machineId) {
|
|
|
1151
1199
|
const fullId = match.sessionId;
|
|
1152
1200
|
let svc;
|
|
1153
1201
|
try {
|
|
1154
|
-
svc =
|
|
1202
|
+
svc = getSessionProxy(machine, fullId);
|
|
1155
1203
|
} catch (err) {
|
|
1156
1204
|
console.error(`Could not find session service: ${err.message}`);
|
|
1157
1205
|
await server.disconnect();
|
|
@@ -1369,7 +1417,7 @@ async function sessionShare(sessionIdPartial, machineId, opts) {
|
|
|
1369
1417
|
const sessions = await machine.listSessions();
|
|
1370
1418
|
const match = resolveSessionId(sessions, sessionIdPartial);
|
|
1371
1419
|
const fullId = match.sessionId;
|
|
1372
|
-
const svc =
|
|
1420
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1373
1421
|
if (opts.list) {
|
|
1374
1422
|
const metaResult = await svc.getMetadata();
|
|
1375
1423
|
const sharing = metaResult.metadata?.sharing;
|
|
@@ -1638,7 +1686,7 @@ async function sessionRalphStart(sessionIdPartial, task, machineId, opts) {
|
|
|
1638
1686
|
const sessions = await machine.listSessions();
|
|
1639
1687
|
const match = resolveSessionId(sessions, sessionIdPartial);
|
|
1640
1688
|
const fullId = match.sessionId;
|
|
1641
|
-
const svc =
|
|
1689
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1642
1690
|
const { metadata } = await svc.getMetadata();
|
|
1643
1691
|
if (metadata?.ralphLoop?.active) {
|
|
1644
1692
|
console.error(`Ralph loop is already active (iteration ${metadata.ralphLoop.currentIteration}). Cancel it first with: svamp session ralph-cancel ${sessionIdPartial}`);
|
|
@@ -1672,7 +1720,7 @@ async function sessionRalphCancel(sessionIdPartial, machineId) {
|
|
|
1672
1720
|
const sessions = await machine.listSessions();
|
|
1673
1721
|
const match = resolveSessionId(sessions, sessionIdPartial);
|
|
1674
1722
|
const fullId = match.sessionId;
|
|
1675
|
-
const svc =
|
|
1723
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1676
1724
|
const { metadata } = await svc.getMetadata();
|
|
1677
1725
|
if (!metadata?.ralphLoop?.active) {
|
|
1678
1726
|
console.log("No active Ralph loop on this session.");
|
|
@@ -1691,7 +1739,7 @@ async function sessionRalphStatus(sessionIdPartial, machineId) {
|
|
|
1691
1739
|
const sessions = await machine.listSessions();
|
|
1692
1740
|
const match = resolveSessionId(sessions, sessionIdPartial);
|
|
1693
1741
|
const fullId = match.sessionId;
|
|
1694
|
-
const svc =
|
|
1742
|
+
const svc = getSessionProxy(machine, fullId);
|
|
1695
1743
|
const { metadata } = await svc.getMetadata();
|
|
1696
1744
|
const ralph = metadata?.ralphLoop;
|
|
1697
1745
|
if (!ralph || !ralph.active) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { writeFileSync, readFileSync } from 'fs';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import { connectAndGetMachine } from './commands-
|
|
3
|
+
import { connectAndGetMachine } from './commands-BkDj4wWg.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-RO50yndI.mjs';
|
|
9
9
|
import 'os';
|
|
10
10
|
import 'fs/promises';
|
|
11
11
|
import 'url';
|
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-RO50yndI.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "svamp-cli";
|
|
2
|
-
var version = "0.1.
|
|
2
|
+
var version = "0.1.82";
|
|
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 && tsc --noEmit && pkgroll",
|
|
21
21
|
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-authorize.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-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-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-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-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs",
|
|
22
|
+
test: "npx tsx test/test-authorize.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-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-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-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-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.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",
|
|
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { mkdirSync, writeFileSync, existsSync, unlinkSync, readFileSync, watch } from 'node:fs';
|
|
5
|
-
import { c as connectToHypha, a as registerSessionService } from './run-
|
|
5
|
+
import { c as connectToHypha, a as registerSessionService } from './run-RO50yndI.mjs';
|
|
6
6
|
import { createServer } from 'node:http';
|
|
7
7
|
import { spawn } from 'node:child_process';
|
|
8
8
|
import { createInterface } from 'node:readline';
|
|
@@ -294,6 +294,12 @@ function applySecurityContext(baseConfig, context) {
|
|
|
294
294
|
return config;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
function getParamNames(fn) {
|
|
298
|
+
const src = fn.toString();
|
|
299
|
+
const match = src.match(/^(?:async\s+)?(?:function\s*\w*)?\s*\(([^)]*)\)/);
|
|
300
|
+
if (!match) return [];
|
|
301
|
+
return match[1].split(",").map((p) => p.trim().replace(/\s*=.*$/, "").replace(/^\.\.\.\s*/, "")).filter(Boolean);
|
|
302
|
+
}
|
|
297
303
|
const terminalSessions = /* @__PURE__ */ new Map();
|
|
298
304
|
let ptyModule = null;
|
|
299
305
|
async function getPtyModule() {
|
|
@@ -439,7 +445,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
439
445
|
* This consolidates all session RPCs through the machine service,
|
|
440
446
|
* eliminating the need for per-session Hypha service registration.
|
|
441
447
|
*/
|
|
442
|
-
sessionRPC: async (sessionId, method,
|
|
448
|
+
sessionRPC: async (sessionId, method, kwargs, context) => {
|
|
443
449
|
authorizeRequest(context, currentMetadata.sharing, "view");
|
|
444
450
|
const rpc = handlers.getSessionRPCHandlers?.(sessionId);
|
|
445
451
|
if (!rpc) {
|
|
@@ -449,8 +455,11 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
449
455
|
if (typeof handler !== "function") {
|
|
450
456
|
throw new Error(`Unknown session method: ${method}`);
|
|
451
457
|
}
|
|
452
|
-
const
|
|
453
|
-
|
|
458
|
+
const paramNames = getParamNames(handler);
|
|
459
|
+
const callArgs = paramNames.map(
|
|
460
|
+
(name) => name === "context" ? context : kwargs?.[name] ?? void 0
|
|
461
|
+
);
|
|
462
|
+
return await handler(...callArgs);
|
|
454
463
|
},
|
|
455
464
|
/**
|
|
456
465
|
* Register a listener for a specific session's real-time updates.
|
|
@@ -836,6 +845,11 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
836
845
|
const session = terminalSessions.get(params.sessionId);
|
|
837
846
|
if (!session) throw new Error(`Terminal session ${params.sessionId} not found`);
|
|
838
847
|
const scrollback = session.outputBuffer.join("");
|
|
848
|
+
if (params.cols && params.rows) {
|
|
849
|
+
session.pty.resize(params.cols, params.rows);
|
|
850
|
+
session.cols = params.cols;
|
|
851
|
+
session.rows = params.rows;
|
|
852
|
+
}
|
|
839
853
|
return { sessionId: session.id, cols: session.cols, rows: session.rows, scrollback, exited: session.exited };
|
|
840
854
|
},
|
|
841
855
|
// Machine-level directory listing (read-only, view role)
|
|
@@ -1599,6 +1613,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
1599
1613
|
const store = {
|
|
1600
1614
|
serviceInfo: { id: `svamp-session-${sessionId}` },
|
|
1601
1615
|
pushMessage,
|
|
1616
|
+
getMetadata: () => ({ ...metadata }),
|
|
1602
1617
|
get _agentState() {
|
|
1603
1618
|
return agentState;
|
|
1604
1619
|
},
|
|
@@ -5572,8 +5587,7 @@ async function startDaemon(options) {
|
|
|
5572
5587
|
process.on("SIGUSR1", () => requestShutdown("os-signal-cleanup"));
|
|
5573
5588
|
process.on("uncaughtException", (error) => {
|
|
5574
5589
|
if (shutdownRequested) return;
|
|
5575
|
-
logger.error("Uncaught exception:", error);
|
|
5576
|
-
requestShutdown("exception", error.message);
|
|
5590
|
+
logger.error("Uncaught exception (non-fatal, daemon continues):", error);
|
|
5577
5591
|
});
|
|
5578
5592
|
const TRANSIENT_REJECTION_PATTERNS = [
|
|
5579
5593
|
"_rintf",
|
|
@@ -5604,8 +5618,12 @@ async function startDaemon(options) {
|
|
|
5604
5618
|
// Fetch API errors during reconnect
|
|
5605
5619
|
"already exists in the cache store",
|
|
5606
5620
|
// hypha-rpc: stale in-flight RPC calls after reconnect try to resolve with duplicate message keys
|
|
5607
|
-
"Failed to send the request when calling method"
|
|
5621
|
+
"Failed to send the request when calling method",
|
|
5608
5622
|
// hypha-rpc: RPC call failed after reconnect (often wraps the cache store error)
|
|
5623
|
+
"Rate limit",
|
|
5624
|
+
// Hypha server 429 rate limiting — transient, will resolve on its own
|
|
5625
|
+
"status 429"
|
|
5626
|
+
// HTTP 429 status code
|
|
5609
5627
|
];
|
|
5610
5628
|
let unhandledRejectionCount = 0;
|
|
5611
5629
|
let unhandledRejectionResetTimer = null;
|
|
@@ -5628,10 +5646,9 @@ async function startDaemon(options) {
|
|
|
5628
5646
|
}, UNHANDLED_REJECTION_WINDOW_MS);
|
|
5629
5647
|
}
|
|
5630
5648
|
if (unhandledRejectionCount >= UNHANDLED_REJECTION_THRESHOLD) {
|
|
5631
|
-
logger.log(`Too many unhandled rejections (${unhandledRejectionCount} in ${UNHANDLED_REJECTION_WINDOW_MS / 1e3}s),
|
|
5632
|
-
requestShutdown("exception", msg);
|
|
5649
|
+
logger.log(`Too many unhandled rejections (${unhandledRejectionCount} in ${UNHANDLED_REJECTION_WINDOW_MS / 1e3}s) \u2014 logging only, daemon continues`);
|
|
5633
5650
|
} else {
|
|
5634
|
-
logger.log(`Unhandled rejection ${unhandledRejectionCount}/${UNHANDLED_REJECTION_THRESHOLD}
|
|
5651
|
+
logger.log(`Unhandled rejection ${unhandledRejectionCount}/${UNHANDLED_REJECTION_THRESHOLD}: ${msg.slice(0, 200)}`);
|
|
5635
5652
|
}
|
|
5636
5653
|
});
|
|
5637
5654
|
if (isDaemonAlive()) {
|
|
@@ -5713,8 +5730,7 @@ async function startDaemon(options) {
|
|
|
5713
5730
|
});
|
|
5714
5731
|
logger.log(`Connected to Hypha (workspace: ${server.config.workspace})`);
|
|
5715
5732
|
server.on("disconnected", (reason) => {
|
|
5716
|
-
logger.log(`Hypha connection permanently lost: ${reason}
|
|
5717
|
-
requestShutdown("hypha-disconnected", String(reason));
|
|
5733
|
+
logger.log(`Hypha connection permanently lost: ${reason}. Daemon continues running \u2014 restart manually to reconnect.`);
|
|
5718
5734
|
});
|
|
5719
5735
|
const pidToTrackedSession = /* @__PURE__ */ new Map();
|
|
5720
5736
|
server.on("services_registered", () => {
|
|
@@ -5725,13 +5741,33 @@ async function startDaemon(options) {
|
|
|
5725
5741
|
}
|
|
5726
5742
|
});
|
|
5727
5743
|
const getCurrentChildren = () => {
|
|
5728
|
-
return Array.from(pidToTrackedSession.values()).map((s) =>
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5744
|
+
return Array.from(pidToTrackedSession.values()).map((s) => {
|
|
5745
|
+
const active = !s.stopped && s.hyphaService != null;
|
|
5746
|
+
let metadata;
|
|
5747
|
+
if (active && s.hyphaService) {
|
|
5748
|
+
try {
|
|
5749
|
+
const m = s.hyphaService.getMetadata();
|
|
5750
|
+
metadata = {
|
|
5751
|
+
flavor: m.flavor,
|
|
5752
|
+
name: m.name,
|
|
5753
|
+
path: m.path,
|
|
5754
|
+
host: m.host,
|
|
5755
|
+
lifecycleState: m.lifecycleState,
|
|
5756
|
+
parentSessionId: m.parentSessionId,
|
|
5757
|
+
tags: m.tags
|
|
5758
|
+
};
|
|
5759
|
+
} catch {
|
|
5760
|
+
}
|
|
5761
|
+
}
|
|
5762
|
+
return {
|
|
5763
|
+
sessionId: s.svampSessionId || `PID-${s.pid}`,
|
|
5764
|
+
pid: s.pid,
|
|
5765
|
+
startedBy: s.startedBy,
|
|
5766
|
+
directory: s.directory,
|
|
5767
|
+
active,
|
|
5768
|
+
metadata
|
|
5769
|
+
};
|
|
5770
|
+
});
|
|
5735
5771
|
};
|
|
5736
5772
|
let machineServiceRef = null;
|
|
5737
5773
|
const spawnSession = async (options2) => {
|
|
@@ -6767,6 +6803,10 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6767
6803
|
if (message.urgency === "urgent") {
|
|
6768
6804
|
const formatted = formatInboxMessageXml(message);
|
|
6769
6805
|
logger.log(`[Session ${sessionId}] Delivering urgent inbox message to agent`);
|
|
6806
|
+
sessionService.pushMessage(
|
|
6807
|
+
{ role: "user", content: { type: "text", text: formatted } },
|
|
6808
|
+
"user"
|
|
6809
|
+
);
|
|
6770
6810
|
if (!claudeProcess || claudeProcess.exitCode !== null) {
|
|
6771
6811
|
spawnClaude(formatted);
|
|
6772
6812
|
} else {
|
|
@@ -7191,6 +7231,10 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7191
7231
|
if (message.urgency === "urgent" && acpBackendReady) {
|
|
7192
7232
|
const formatted = formatInboxMessageXml(message);
|
|
7193
7233
|
logger.log(`[${agentName} Session ${sessionId}] Delivering urgent inbox message to agent`);
|
|
7234
|
+
sessionService.pushMessage(
|
|
7235
|
+
{ role: "user", content: { type: "text", text: formatted } },
|
|
7236
|
+
"user"
|
|
7237
|
+
);
|
|
7194
7238
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "running" };
|
|
7195
7239
|
sessionService.updateMetadata(sessionMetadata);
|
|
7196
7240
|
sessionService.sendKeepAlive(true);
|
|
@@ -7679,7 +7723,9 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7679
7723
|
spawnSession,
|
|
7680
7724
|
stopSession,
|
|
7681
7725
|
restartSession,
|
|
7682
|
-
requestShutdown: () =>
|
|
7726
|
+
requestShutdown: () => {
|
|
7727
|
+
logger.log("Shutdown requested via hypha-app (ignored \u2014 daemon never self-terminates)");
|
|
7728
|
+
},
|
|
7683
7729
|
getTrackedSessions: getCurrentChildren,
|
|
7684
7730
|
getSessionRPCHandlers: (sessionId) => {
|
|
7685
7731
|
for (const [, session] of pidToTrackedSession) {
|
|
@@ -7785,20 +7831,16 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7785
7831
|
for (const sessionId of sessionsToAutoContinue) {
|
|
7786
7832
|
setTimeout(async () => {
|
|
7787
7833
|
try {
|
|
7788
|
-
const
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
})
|
|
7799
|
-
),
|
|
7800
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("sendMessage timeout")), 3e4))
|
|
7801
|
-
]);
|
|
7834
|
+
const tracked = Array.from(pidToTrackedSession.values()).find((s) => s.svampSessionId === sessionId);
|
|
7835
|
+
const rpc = tracked?.sessionRPCHandlers;
|
|
7836
|
+
if (!rpc) throw new Error(`Session ${sessionId} RPC handlers not found`);
|
|
7837
|
+
await rpc.sendMessage(
|
|
7838
|
+
JSON.stringify({
|
|
7839
|
+
role: "user",
|
|
7840
|
+
content: { type: "text", text: 'The svamp daemon was restarted, which interrupted this session. Please continue where you left off. IMPORTANT: Do not run any command that would stop or restart the svamp daemon (e.g. "svamp daemon stop") \u2014 that would interrupt the session again.' },
|
|
7841
|
+
meta: { sentFrom: "svamp-daemon-auto-continue" }
|
|
7842
|
+
})
|
|
7843
|
+
);
|
|
7802
7844
|
logger.log(`Auto-continued session ${sessionId}`);
|
|
7803
7845
|
} catch (err) {
|
|
7804
7846
|
logger.log(`Failed to auto-continue session ${sessionId}: ${err.message}`);
|
|
@@ -7812,10 +7854,12 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7812
7854
|
logger.log(`Resuming Ralph loop for ${sessionsToRalphResume.length} session(s)...`);
|
|
7813
7855
|
for (const { sessionId, directory: sessDir } of sessionsToRalphResume) {
|
|
7814
7856
|
try {
|
|
7815
|
-
const
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7857
|
+
const tracked = Array.from(pidToTrackedSession.values()).find((s) => s.svampSessionId === sessionId);
|
|
7858
|
+
const rpc = tracked?.sessionRPCHandlers;
|
|
7859
|
+
if (!rpc) {
|
|
7860
|
+
logger.log(`Session ${sessionId} RPC handlers not found for Ralph resume`);
|
|
7861
|
+
continue;
|
|
7862
|
+
}
|
|
7819
7863
|
const rlState = readRalphState(getRalphStateFilePath(sessDir, sessionId));
|
|
7820
7864
|
if (!rlState) continue;
|
|
7821
7865
|
const initDelayMs = 2e3;
|
|
@@ -7836,20 +7880,17 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7836
7880
|
const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
|
|
7837
7881
|
const prompt = buildRalphPrompt(currentState.task, currentState);
|
|
7838
7882
|
const ralphSysPrompt = buildRalphSystemPrompt(currentState, progressRelPath);
|
|
7839
|
-
await
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
),
|
|
7851
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("sendMessage timeout")), 3e4))
|
|
7852
|
-
]);
|
|
7883
|
+
await rpc.sendMessage(
|
|
7884
|
+
JSON.stringify({
|
|
7885
|
+
role: "user",
|
|
7886
|
+
content: { type: "text", text: prompt },
|
|
7887
|
+
meta: {
|
|
7888
|
+
sentFrom: "svamp-daemon-ralph-resume",
|
|
7889
|
+
appendSystemPrompt: ralphSysPrompt,
|
|
7890
|
+
...isFreshMode ? { ralphFreshContext: true } : {}
|
|
7891
|
+
}
|
|
7892
|
+
})
|
|
7893
|
+
);
|
|
7853
7894
|
logger.log(`Resumed Ralph loop for session ${sessionId} at iteration ${currentState.iteration} (${isFreshMode ? "fresh" : "continue"})`);
|
|
7854
7895
|
} catch (err) {
|
|
7855
7896
|
logger.log(`Failed to resume Ralph loop for session ${sessionId}: ${err.message}`);
|
|
@@ -7913,20 +7954,6 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7913
7954
|
}
|
|
7914
7955
|
} catch {
|
|
7915
7956
|
}
|
|
7916
|
-
try {
|
|
7917
|
-
const installedVersion = readPackageVersion();
|
|
7918
|
-
if (installedVersion !== "unknown" && installedVersion !== DAEMON_VERSION) {
|
|
7919
|
-
const supervised2 = process.env.SVAMP_SUPERVISED === "1";
|
|
7920
|
-
if (supervised2) {
|
|
7921
|
-
logger.log(`svamp-cli version changed on disk: ${DAEMON_VERSION} \u2192 ${installedVersion}. Exiting for launchd restart...`);
|
|
7922
|
-
requestShutdown("version-update", `Updated ${DAEMON_VERSION} \u2192 ${installedVersion}`);
|
|
7923
|
-
return;
|
|
7924
|
-
} else {
|
|
7925
|
-
logger.log(`svamp-cli version changed on disk: ${DAEMON_VERSION} \u2192 ${installedVersion}. Run 'svamp daemon stop && svamp daemon start' to apply the update.`);
|
|
7926
|
-
}
|
|
7927
|
-
}
|
|
7928
|
-
} catch {
|
|
7929
|
-
}
|
|
7930
7957
|
for (const [key, session] of pidToTrackedSession) {
|
|
7931
7958
|
const child = session.childProcess;
|
|
7932
7959
|
if (child && child.pid) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svamp-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.82",
|
|
4
4
|
"description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
|
|
5
5
|
"author": "Amun AI AB",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "rm -rf dist && tsc --noEmit && pkgroll",
|
|
22
22
|
"typecheck": "tsc --noEmit",
|
|
23
|
-
"test": "npx tsx test/test-authorize.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-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-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-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-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs",
|
|
23
|
+
"test": "npx tsx test/test-authorize.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-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-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-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-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs",
|
|
24
24
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
25
25
|
"dev": "tsx src/cli.ts",
|
|
26
26
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|