svamp-cli 0.1.74 → 0.1.75
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-7GGmL2zY.mjs → agentCommands-C6iGblcL.mjs} +0 -1
- package/dist/cli.mjs +27 -110
- package/dist/{commands-dKkUOvUb.mjs → commands-Dq8WSqvt.mjs} +3 -3
- package/dist/{commands-ClMc3nSg.mjs → commands-a7p1jW-t.mjs} +38 -174
- package/dist/index.mjs +1 -1
- package/dist/{package-CCjeil_X.mjs → package-BFnad6d1.mjs} +2 -1
- package/dist/{run-BgwhZgkT.mjs → run-Dy5lxT3M.mjs} +1 -1
- package/dist/{run-6QgabuQN.mjs → run-lhAjX4NB.mjs} +193 -337
- package/package.json +2 -1
|
@@ -294,6 +294,33 @@ function applySecurityContext(baseConfig, context) {
|
|
|
294
294
|
return config;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
const terminalSessions = /* @__PURE__ */ new Map();
|
|
298
|
+
let ptyModule = null;
|
|
299
|
+
async function getPtyModule() {
|
|
300
|
+
if (!ptyModule) {
|
|
301
|
+
try {
|
|
302
|
+
ptyModule = await import('node-pty');
|
|
303
|
+
} catch {
|
|
304
|
+
throw new Error("node-pty is not available. Install it with: npm install node-pty");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return ptyModule;
|
|
308
|
+
}
|
|
309
|
+
function generateTerminalId() {
|
|
310
|
+
return `term-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
311
|
+
}
|
|
312
|
+
const ALLOWED_CONTROL_CHARS = /* @__PURE__ */ new Set([7, 8, 9, 10, 11, 12, 13, 27]);
|
|
313
|
+
function filterForXterm(text) {
|
|
314
|
+
if (!text) return text;
|
|
315
|
+
let result = "";
|
|
316
|
+
for (let i = 0; i < text.length; i++) {
|
|
317
|
+
const code = text.charCodeAt(i);
|
|
318
|
+
if (code >= 32 && code <= 126 || ALLOWED_CONTROL_CHARS.has(code) || code > 127) {
|
|
319
|
+
result += text[i];
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
297
324
|
function getMachineMetadataPath(svampHomeDir) {
|
|
298
325
|
return join(svampHomeDir, "machine-metadata.json");
|
|
299
326
|
}
|
|
@@ -667,6 +694,107 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
667
694
|
});
|
|
668
695
|
});
|
|
669
696
|
},
|
|
697
|
+
// ── Terminal PTY RPC ──────────────────────────────────────────────
|
|
698
|
+
/** Start a new terminal PTY session. Returns { sessionId, cols, rows }. */
|
|
699
|
+
terminalStart: async (params = {}, context) => {
|
|
700
|
+
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
701
|
+
const pty = await getPtyModule();
|
|
702
|
+
const { homedir: getHomedir } = await import('os');
|
|
703
|
+
const cols = params.cols || 80;
|
|
704
|
+
const rows = params.rows || 24;
|
|
705
|
+
const cwd = params.cwd || getHomedir();
|
|
706
|
+
const shell = params.shell || process.env.SHELL || "bash";
|
|
707
|
+
const sessionId = generateTerminalId();
|
|
708
|
+
const ptyProcess = pty.spawn(shell, [], {
|
|
709
|
+
name: "xterm-256color",
|
|
710
|
+
cols,
|
|
711
|
+
rows,
|
|
712
|
+
cwd,
|
|
713
|
+
env: { ...process.env, TERM: "xterm-256color" }
|
|
714
|
+
});
|
|
715
|
+
const session = {
|
|
716
|
+
id: sessionId,
|
|
717
|
+
pty: ptyProcess,
|
|
718
|
+
listeners: [],
|
|
719
|
+
cols,
|
|
720
|
+
rows,
|
|
721
|
+
createdAt: Date.now(),
|
|
722
|
+
cwd
|
|
723
|
+
};
|
|
724
|
+
terminalSessions.set(sessionId, session);
|
|
725
|
+
ptyProcess.onData((data) => {
|
|
726
|
+
const filtered = filterForXterm(data);
|
|
727
|
+
if (!filtered) return;
|
|
728
|
+
const update = { type: "output", content: filtered, sessionId };
|
|
729
|
+
for (const listener of session.listeners) {
|
|
730
|
+
try {
|
|
731
|
+
listener(update);
|
|
732
|
+
} catch {
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
ptyProcess.onExit(({ exitCode, signal }) => {
|
|
737
|
+
const update = { type: "exit", content: "", sessionId, exitCode, signal };
|
|
738
|
+
for (const listener of session.listeners) {
|
|
739
|
+
try {
|
|
740
|
+
listener(update);
|
|
741
|
+
} catch {
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
terminalSessions.delete(sessionId);
|
|
745
|
+
});
|
|
746
|
+
return { sessionId, cols, rows };
|
|
747
|
+
},
|
|
748
|
+
/** Write data (keystrokes) to a terminal session. */
|
|
749
|
+
terminalWrite: async (params, context) => {
|
|
750
|
+
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
751
|
+
const session = terminalSessions.get(params.sessionId);
|
|
752
|
+
if (!session) throw new Error(`Terminal session ${params.sessionId} not found`);
|
|
753
|
+
session.pty.write(params.data);
|
|
754
|
+
return { success: true };
|
|
755
|
+
},
|
|
756
|
+
/** Resize a terminal session. */
|
|
757
|
+
terminalResize: async (params, context) => {
|
|
758
|
+
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
759
|
+
const session = terminalSessions.get(params.sessionId);
|
|
760
|
+
if (!session) throw new Error(`Terminal session ${params.sessionId} not found`);
|
|
761
|
+
session.pty.resize(params.cols, params.rows);
|
|
762
|
+
session.cols = params.cols;
|
|
763
|
+
session.rows = params.rows;
|
|
764
|
+
return { success: true };
|
|
765
|
+
},
|
|
766
|
+
/**
|
|
767
|
+
* Attach to a terminal session for real-time output streaming.
|
|
768
|
+
* The onData callback receives { type: 'output'|'exit', content, sessionId }.
|
|
769
|
+
*/
|
|
770
|
+
terminalAttach: async (params, context) => {
|
|
771
|
+
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
772
|
+
const session = terminalSessions.get(params.sessionId);
|
|
773
|
+
if (!session) throw new Error(`Terminal session ${params.sessionId} not found`);
|
|
774
|
+
if (typeof params.onData !== "function") throw new Error("onData callback is required");
|
|
775
|
+
session.listeners.push(params.onData);
|
|
776
|
+
return { success: true, cols: session.cols, rows: session.rows };
|
|
777
|
+
},
|
|
778
|
+
/** Stop (kill) a terminal session. */
|
|
779
|
+
terminalStop: async (params, context) => {
|
|
780
|
+
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
781
|
+
const session = terminalSessions.get(params.sessionId);
|
|
782
|
+
if (!session) throw new Error(`Terminal session ${params.sessionId} not found`);
|
|
783
|
+
session.pty.kill();
|
|
784
|
+
terminalSessions.delete(params.sessionId);
|
|
785
|
+
return { success: true };
|
|
786
|
+
},
|
|
787
|
+
/** List active terminal sessions. */
|
|
788
|
+
terminalList: async (context) => {
|
|
789
|
+
authorizeRequest(context, currentMetadata.sharing, "view");
|
|
790
|
+
return Array.from(terminalSessions.values()).map((s) => ({
|
|
791
|
+
sessionId: s.id,
|
|
792
|
+
cols: s.cols,
|
|
793
|
+
rows: s.rows,
|
|
794
|
+
cwd: s.cwd,
|
|
795
|
+
createdAt: s.createdAt
|
|
796
|
+
}));
|
|
797
|
+
},
|
|
670
798
|
// Machine-level directory listing (read-only, view role)
|
|
671
799
|
listDirectory: async (path, options, context) => {
|
|
672
800
|
authorizeRequest(context, currentMetadata.sharing, "view");
|
|
@@ -871,27 +999,6 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
871
999
|
};
|
|
872
1000
|
}
|
|
873
1001
|
|
|
874
|
-
function isStructuredMessage(msg) {
|
|
875
|
-
return !!(msg.from && msg.subject);
|
|
876
|
-
}
|
|
877
|
-
function formatInboxMessageXml(msg) {
|
|
878
|
-
if (!isStructuredMessage(msg)) return msg.body;
|
|
879
|
-
const attrs = [
|
|
880
|
-
`message-id="${msg.messageId}"`,
|
|
881
|
-
`from="${msg.from}"`,
|
|
882
|
-
`from-session="${msg.fromSession || ""}"`,
|
|
883
|
-
`to="${msg.to || ""}"`,
|
|
884
|
-
`subject="${msg.subject}"`,
|
|
885
|
-
`urgency="${msg.urgency || "normal"}"`,
|
|
886
|
-
`timestamp="${msg.timestamp}"`
|
|
887
|
-
];
|
|
888
|
-
if (msg.replyTo) attrs.push(`reply-to="${msg.replyTo}"`);
|
|
889
|
-
if (msg.cc && msg.cc.length > 0) attrs.push(`cc="${msg.cc.join(",")}"`);
|
|
890
|
-
if (msg.threadId) attrs.push(`thread-id="${msg.threadId}"`);
|
|
891
|
-
return `<svamp-message ${attrs.join(" ")}>
|
|
892
|
-
${msg.body}
|
|
893
|
-
</svamp-message>`;
|
|
894
|
-
}
|
|
895
1002
|
function loadMessages(messagesDir, sessionId) {
|
|
896
1003
|
const filePath = join$1(messagesDir, "messages.jsonl");
|
|
897
1004
|
if (!existsSync(filePath)) return [];
|
|
@@ -1268,24 +1375,6 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
1268
1375
|
});
|
|
1269
1376
|
return await callbacks.onUpdateSecurityContext(newSecurityContext);
|
|
1270
1377
|
},
|
|
1271
|
-
/** Toggle isolation (nono/docker/podman) on or off — triggers agent restart */
|
|
1272
|
-
updateIsolation: async (enabled, context) => {
|
|
1273
|
-
authorizeRequest(context, metadata.sharing, "admin");
|
|
1274
|
-
if (metadata.sharing && context?.user?.email && metadata.sharing.owner && context.user.email.toLowerCase() !== metadata.sharing.owner.toLowerCase()) {
|
|
1275
|
-
throw new Error("Only the session owner can change isolation settings");
|
|
1276
|
-
}
|
|
1277
|
-
if (!callbacks.onUpdateIsolation) {
|
|
1278
|
-
throw new Error("Isolation updates are not supported for this session");
|
|
1279
|
-
}
|
|
1280
|
-
metadata = { ...metadata, forceIsolation: enabled };
|
|
1281
|
-
metadataVersion++;
|
|
1282
|
-
notifyListeners({
|
|
1283
|
-
type: "update-session",
|
|
1284
|
-
sessionId,
|
|
1285
|
-
metadata: { value: metadata, version: metadataVersion }
|
|
1286
|
-
});
|
|
1287
|
-
return await callbacks.onUpdateIsolation(enabled);
|
|
1288
|
-
},
|
|
1289
1378
|
/** Apply a new system prompt and restart the agent process */
|
|
1290
1379
|
applySystemPrompt: async (prompt, context) => {
|
|
1291
1380
|
authorizeRequest(context, metadata.sharing, "admin");
|
|
@@ -1294,86 +1383,6 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
1294
1383
|
}
|
|
1295
1384
|
return await callbacks.onApplySystemPrompt(prompt);
|
|
1296
1385
|
},
|
|
1297
|
-
// ── Inbox Messaging ──
|
|
1298
|
-
sendInboxMessage: async (message, context) => {
|
|
1299
|
-
authorizeRequest(context, metadata.sharing, "interact");
|
|
1300
|
-
if (!message.messageId || !message.body) {
|
|
1301
|
-
throw new Error("Inbox message requires messageId and body");
|
|
1302
|
-
}
|
|
1303
|
-
const inbox = (metadata.inbox || []).slice();
|
|
1304
|
-
inbox.push({ ...message, read: false });
|
|
1305
|
-
if (inbox.length > 100) {
|
|
1306
|
-
const readIdx = inbox.findIndex((m) => m.read);
|
|
1307
|
-
if (readIdx >= 0) {
|
|
1308
|
-
inbox.splice(readIdx, 1);
|
|
1309
|
-
} else {
|
|
1310
|
-
inbox.shift();
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
|
-
metadata = { ...metadata, inbox };
|
|
1314
|
-
metadataVersion++;
|
|
1315
|
-
notifyListeners({
|
|
1316
|
-
type: "update-session",
|
|
1317
|
-
sessionId,
|
|
1318
|
-
metadata: { value: metadata, version: metadataVersion }
|
|
1319
|
-
});
|
|
1320
|
-
callbacks.onInboxMessage?.(message);
|
|
1321
|
-
return { messageId: message.messageId, delivered: true };
|
|
1322
|
-
},
|
|
1323
|
-
getInbox: async (opts, context) => {
|
|
1324
|
-
authorizeRequest(context, metadata.sharing, "view");
|
|
1325
|
-
let inbox = metadata.inbox || [];
|
|
1326
|
-
if (opts?.unreadOnly) {
|
|
1327
|
-
inbox = inbox.filter((m) => !m.read);
|
|
1328
|
-
}
|
|
1329
|
-
if (opts?.limit && opts.limit > 0) {
|
|
1330
|
-
inbox = inbox.slice(-opts.limit);
|
|
1331
|
-
}
|
|
1332
|
-
return { messages: inbox, total: (metadata.inbox || []).length };
|
|
1333
|
-
},
|
|
1334
|
-
markInboxRead: async (messageIds, context) => {
|
|
1335
|
-
authorizeRequest(context, metadata.sharing, "interact");
|
|
1336
|
-
let updated = 0;
|
|
1337
|
-
const inbox = (metadata.inbox || []).map((m) => {
|
|
1338
|
-
if (messageIds.includes(m.messageId) && !m.read) {
|
|
1339
|
-
updated++;
|
|
1340
|
-
return { ...m, read: true };
|
|
1341
|
-
}
|
|
1342
|
-
return m;
|
|
1343
|
-
});
|
|
1344
|
-
if (updated > 0) {
|
|
1345
|
-
metadata = { ...metadata, inbox };
|
|
1346
|
-
metadataVersion++;
|
|
1347
|
-
notifyListeners({
|
|
1348
|
-
type: "update-session",
|
|
1349
|
-
sessionId,
|
|
1350
|
-
metadata: { value: metadata, version: metadataVersion }
|
|
1351
|
-
});
|
|
1352
|
-
}
|
|
1353
|
-
return { updated };
|
|
1354
|
-
},
|
|
1355
|
-
clearInbox: async (messageIds, context) => {
|
|
1356
|
-
authorizeRequest(context, metadata.sharing, "interact");
|
|
1357
|
-
const currentInbox = metadata.inbox || [];
|
|
1358
|
-
let removed;
|
|
1359
|
-
if (messageIds && messageIds.length > 0) {
|
|
1360
|
-
const newInbox = currentInbox.filter((m) => !messageIds.includes(m.messageId));
|
|
1361
|
-
removed = currentInbox.length - newInbox.length;
|
|
1362
|
-
metadata = { ...metadata, inbox: newInbox.length > 0 ? newInbox : void 0 };
|
|
1363
|
-
} else {
|
|
1364
|
-
removed = currentInbox.length;
|
|
1365
|
-
metadata = { ...metadata, inbox: void 0 };
|
|
1366
|
-
}
|
|
1367
|
-
if (removed > 0) {
|
|
1368
|
-
metadataVersion++;
|
|
1369
|
-
notifyListeners({
|
|
1370
|
-
type: "update-session",
|
|
1371
|
-
sessionId,
|
|
1372
|
-
metadata: { value: metadata, version: metadataVersion }
|
|
1373
|
-
});
|
|
1374
|
-
}
|
|
1375
|
-
return { removed };
|
|
1376
|
-
},
|
|
1377
1386
|
// ── Listener Registration ──
|
|
1378
1387
|
registerListener: async (callback, context) => {
|
|
1379
1388
|
authorizeRequest(context, metadata.sharing, "view");
|
|
@@ -4971,16 +4980,15 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
|
|
|
4971
4980
|
const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
|
|
4972
4981
|
const prompt = buildRalphPrompt(state.task, state);
|
|
4973
4982
|
const ralphSysPrompt = buildRalphSystemPrompt(state, progressRelPath);
|
|
4974
|
-
const
|
|
4983
|
+
const existingQueue = getMetadata().messageQueue || [];
|
|
4975
4984
|
setMetadata((m) => ({
|
|
4976
4985
|
...m,
|
|
4977
4986
|
ralphLoop,
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4987
|
+
messageQueue: [...existingQueue, {
|
|
4988
|
+
id: randomUUID$1(),
|
|
4989
|
+
text: prompt,
|
|
4981
4990
|
displayText: state.task,
|
|
4982
|
-
|
|
4983
|
-
read: false,
|
|
4991
|
+
createdAt: Date.now(),
|
|
4984
4992
|
ralphSystemPrompt: ralphSysPrompt
|
|
4985
4993
|
}]
|
|
4986
4994
|
}));
|
|
@@ -5648,8 +5656,7 @@ async function startDaemon(options) {
|
|
|
5648
5656
|
}
|
|
5649
5657
|
});
|
|
5650
5658
|
}, buildIsolationConfig2 = function(dir) {
|
|
5651
|
-
|
|
5652
|
-
if (!forceIsolation && !sessionMetadata.sharing?.enabled) return null;
|
|
5659
|
+
if (!options2.forceIsolation && !sessionMetadata.sharing?.enabled) return null;
|
|
5653
5660
|
const method = isolationCapabilities.preferred;
|
|
5654
5661
|
if (!method) return null;
|
|
5655
5662
|
const detail = isolationCapabilities.details[method];
|
|
@@ -5690,7 +5697,6 @@ async function startDaemon(options) {
|
|
|
5690
5697
|
lifecycleState: resumeSessionId ? "idle" : "starting",
|
|
5691
5698
|
sharing: options2.sharing,
|
|
5692
5699
|
securityContext: options2.securityContext,
|
|
5693
|
-
forceIsolation: options2.forceIsolation || void 0,
|
|
5694
5700
|
tags: options2.tags,
|
|
5695
5701
|
parentSessionId: options2.parentSessionId,
|
|
5696
5702
|
...options2.parentSessionId && (() => {
|
|
@@ -5766,8 +5772,7 @@ async function startDaemon(options) {
|
|
|
5766
5772
|
startupNonJsonLines = [];
|
|
5767
5773
|
startupRetryMessage = initialMessage;
|
|
5768
5774
|
let rawPermissionMode = effectiveMeta.permissionMode || agentConfig.default_permission_mode || currentPermissionMode;
|
|
5769
|
-
|
|
5770
|
-
if (forceIsolation || sessionMetadata.sharing?.enabled) {
|
|
5775
|
+
if (options2.forceIsolation || sessionMetadata.sharing?.enabled) {
|
|
5771
5776
|
rawPermissionMode = rawPermissionMode === "default" ? "auto-approve-all" : rawPermissionMode;
|
|
5772
5777
|
}
|
|
5773
5778
|
if (sessionMetadata.ralphLoop?.active) {
|
|
@@ -5804,7 +5809,7 @@ async function startDaemon(options) {
|
|
|
5804
5809
|
if (wrapped.cleanupFiles) isolationCleanupFiles = wrapped.cleanupFiles;
|
|
5805
5810
|
sessionMetadata = { ...sessionMetadata, isolationMethod: isoConfig.method };
|
|
5806
5811
|
logger.log(`[Session ${sessionId}] Isolation: ${isoConfig.method} (binary: ${isoConfig.binaryPath})`);
|
|
5807
|
-
} else if (forceIsolation || sessionMetadata.sharing?.enabled) {
|
|
5812
|
+
} else if (options2.forceIsolation || sessionMetadata.sharing?.enabled) {
|
|
5808
5813
|
logger.log(`[Session ${sessionId}] WARNING: No isolation runtime (nono/docker/podman) available. Session is NOT sandboxed.`);
|
|
5809
5814
|
sessionMetadata = { ...sessionMetadata, isolationMethod: void 0 };
|
|
5810
5815
|
} else {
|
|
@@ -6029,7 +6034,7 @@ async function startDaemon(options) {
|
|
|
6029
6034
|
logger.log(`[Session ${sessionId}] ${taskInfo}`);
|
|
6030
6035
|
sessionService.pushMessage({ type: "session_event", message: taskInfo }, "session");
|
|
6031
6036
|
}
|
|
6032
|
-
const queueLen = sessionMetadata.
|
|
6037
|
+
const queueLen = sessionMetadata.messageQueue?.length ?? 0;
|
|
6033
6038
|
if (msg.is_error) {
|
|
6034
6039
|
const rlStateForError = readRalphState(getRalphStateFilePath(directory, sessionId));
|
|
6035
6040
|
if (rlStateForError) {
|
|
@@ -6334,7 +6339,7 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6334
6339
|
return;
|
|
6335
6340
|
}
|
|
6336
6341
|
}
|
|
6337
|
-
const queueLen = sessionMetadata.
|
|
6342
|
+
const queueLen = sessionMetadata.messageQueue?.length ?? 0;
|
|
6338
6343
|
if (queueLen > 0 && claudeResumeId && !trackedSession.stopped) {
|
|
6339
6344
|
signalProcessing(false);
|
|
6340
6345
|
setTimeout(() => processMessageQueueRef?.(), 200);
|
|
@@ -6445,10 +6450,10 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6445
6450
|
}
|
|
6446
6451
|
if (isKillingClaude || isRestartingClaude || isSwitchingMode) {
|
|
6447
6452
|
logger.log(`[Session ${sessionId}] Message received while restarting Claude, queuing to prevent loss`);
|
|
6448
|
-
const
|
|
6453
|
+
const existingQueue = sessionMetadata.messageQueue || [];
|
|
6449
6454
|
sessionMetadata = {
|
|
6450
6455
|
...sessionMetadata,
|
|
6451
|
-
|
|
6456
|
+
messageQueue: [...existingQueue, { id: randomUUID$1(), text, createdAt: Date.now() }]
|
|
6452
6457
|
};
|
|
6453
6458
|
sessionService.updateMetadata(sessionMetadata);
|
|
6454
6459
|
signalProcessing(false);
|
|
@@ -6483,7 +6488,7 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6483
6488
|
}
|
|
6484
6489
|
signalProcessing(false);
|
|
6485
6490
|
sessionWasProcessing = false;
|
|
6486
|
-
const queueLen = sessionMetadata.
|
|
6491
|
+
const queueLen = sessionMetadata.messageQueue?.length ?? 0;
|
|
6487
6492
|
const abortMsg = queueLen > 0 ? `Aborted by user. ${queueLen} queued message(s) will be processed next.` : "Aborted by user";
|
|
6488
6493
|
sessionService.pushMessage(
|
|
6489
6494
|
{ type: "message", message: abortMsg },
|
|
@@ -6565,24 +6570,6 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6565
6570
|
sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
|
|
6566
6571
|
return await restartClaudeHandler();
|
|
6567
6572
|
},
|
|
6568
|
-
onUpdateIsolation: async (enabled) => {
|
|
6569
|
-
logger.log(`[Session ${sessionId}] Isolation ${enabled ? "enabled" : "disabled"} \u2014 restarting agent`);
|
|
6570
|
-
sessionMetadata = { ...sessionMetadata, forceIsolation: enabled };
|
|
6571
|
-
if (!trackedSession.stopped) {
|
|
6572
|
-
saveSession({
|
|
6573
|
-
sessionId,
|
|
6574
|
-
directory,
|
|
6575
|
-
claudeResumeId,
|
|
6576
|
-
permissionMode: currentPermissionMode,
|
|
6577
|
-
spawnMeta: lastSpawnMeta,
|
|
6578
|
-
metadata: sessionMetadata,
|
|
6579
|
-
createdAt: Date.now(),
|
|
6580
|
-
machineId,
|
|
6581
|
-
wasProcessing: sessionWasProcessing
|
|
6582
|
-
});
|
|
6583
|
-
}
|
|
6584
|
-
return await restartClaudeHandler();
|
|
6585
|
-
},
|
|
6586
6573
|
onSharingUpdate: (newSharing) => {
|
|
6587
6574
|
logger.log(`[Session ${sessionId}] Sharing config updated \u2014 persisting to disk`);
|
|
6588
6575
|
sessionMetadata = { ...sessionMetadata, sharing: newSharing };
|
|
@@ -6605,72 +6592,14 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6605
6592
|
lastSpawnMeta = { ...lastSpawnMeta, appendSystemPrompt: prompt };
|
|
6606
6593
|
return await restartClaudeHandler();
|
|
6607
6594
|
},
|
|
6608
|
-
onInboxMessage: (message) => {
|
|
6609
|
-
const xmlText = formatInboxMessageXml(message);
|
|
6610
|
-
if (message.urgency === "urgent") {
|
|
6611
|
-
logger.log(`[Session ${sessionId}] Urgent inbox message from ${message.from}: ${message.subject}`);
|
|
6612
|
-
const text = xmlText;
|
|
6613
|
-
if (sessionWasProcessing) {
|
|
6614
|
-
const existingInbox = sessionMetadata.inbox || [];
|
|
6615
|
-
sessionMetadata = { ...sessionMetadata, inbox: [{ messageId: message.messageId, body: text, displayText: `[Inbox] ${message.subject}`, timestamp: Date.now(), read: false, from: message.from, fromSession: message.fromSession, subject: message.subject, urgency: "urgent" }, ...existingInbox] };
|
|
6616
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
6617
|
-
} else {
|
|
6618
|
-
sessionWasProcessing = true;
|
|
6619
|
-
signalProcessing(true);
|
|
6620
|
-
sessionService.pushMessage(`[Inbox] ${message.subject}`, "user");
|
|
6621
|
-
userMessagePending = true;
|
|
6622
|
-
turnInitiatedByUser = true;
|
|
6623
|
-
try {
|
|
6624
|
-
if (!claudeProcess || claudeProcess.exitCode !== null) {
|
|
6625
|
-
spawnClaude(text);
|
|
6626
|
-
} else {
|
|
6627
|
-
const stdinMsg = JSON.stringify({
|
|
6628
|
-
type: "user",
|
|
6629
|
-
message: { role: "user", content: text }
|
|
6630
|
-
});
|
|
6631
|
-
claudeProcess.stdin?.write(stdinMsg + "\n");
|
|
6632
|
-
}
|
|
6633
|
-
} catch (err) {
|
|
6634
|
-
logger.log(`[Session ${sessionId}] Error injecting urgent inbox message: ${err.message}`);
|
|
6635
|
-
sessionWasProcessing = false;
|
|
6636
|
-
signalProcessing(false);
|
|
6637
|
-
}
|
|
6638
|
-
}
|
|
6639
|
-
const inbox = (sessionMetadata.inbox || []).map(
|
|
6640
|
-
(m) => m.messageId === message.messageId ? { ...m, read: true } : m
|
|
6641
|
-
);
|
|
6642
|
-
sessionMetadata = { ...sessionMetadata, inbox };
|
|
6643
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
6644
|
-
} else {
|
|
6645
|
-
logger.log(`[Session ${sessionId}] Normal inbox message from ${message.from}: ${message.subject}`);
|
|
6646
|
-
if (!sessionWasProcessing && !trackedSession.stopped) {
|
|
6647
|
-
setTimeout(() => processMessageQueueRef?.(), 200);
|
|
6648
|
-
}
|
|
6649
|
-
}
|
|
6650
|
-
},
|
|
6651
6595
|
onKillSession: () => {
|
|
6652
6596
|
logger.log(`[Session ${sessionId}] Kill session requested`);
|
|
6653
6597
|
stopSession(sessionId);
|
|
6654
6598
|
},
|
|
6655
6599
|
onMetadataUpdate: (newMeta) => {
|
|
6656
6600
|
const prevRalphLoop = sessionMetadata.ralphLoop;
|
|
6657
|
-
const legacyQueue = newMeta.messageQueue;
|
|
6658
|
-
let migratedInbox = newMeta.inbox || [];
|
|
6659
|
-
if (legacyQueue && legacyQueue.length > 0) {
|
|
6660
|
-
const converted = legacyQueue.map((q) => ({
|
|
6661
|
-
messageId: q.id,
|
|
6662
|
-
body: q.text,
|
|
6663
|
-
displayText: q.displayText,
|
|
6664
|
-
timestamp: q.createdAt,
|
|
6665
|
-
read: false
|
|
6666
|
-
}));
|
|
6667
|
-
migratedInbox = [...migratedInbox || [], ...converted];
|
|
6668
|
-
}
|
|
6669
6601
|
sessionMetadata = {
|
|
6670
6602
|
...newMeta,
|
|
6671
|
-
inbox: migratedInbox.length > 0 ? migratedInbox : newMeta.inbox,
|
|
6672
|
-
// Clear legacy messageQueue — daemon uses inbox only
|
|
6673
|
-
...legacyQueue && legacyQueue.length > 0 ? { messageQueue: void 0 } : {},
|
|
6674
6603
|
// Daemon drives lifecycleState — don't let frontend overwrite with stale value
|
|
6675
6604
|
lifecycleState: sessionMetadata.lifecycleState,
|
|
6676
6605
|
// Preserve claudeSessionId set by 'system init' (frontend may not have it)
|
|
@@ -6686,11 +6615,8 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6686
6615
|
if (prevRalphLoop && !newMeta.ralphLoop) {
|
|
6687
6616
|
sessionService.updateMetadata(sessionMetadata);
|
|
6688
6617
|
}
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
}
|
|
6692
|
-
const unreadInbox = sessionMetadata.inbox?.filter((m) => !m.read);
|
|
6693
|
-
if (unreadInbox && unreadInbox.length > 0 && !sessionWasProcessing && !trackedSession.stopped) {
|
|
6618
|
+
const queue = newMeta.messageQueue;
|
|
6619
|
+
if (queue && queue.length > 0 && !sessionWasProcessing && !trackedSession.stopped) {
|
|
6694
6620
|
setTimeout(() => {
|
|
6695
6621
|
processMessageQueueRef?.();
|
|
6696
6622
|
}, 200);
|
|
@@ -6813,18 +6739,16 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6813
6739
|
if (trackedSession?.stopped) return;
|
|
6814
6740
|
if (isKillingClaude) return;
|
|
6815
6741
|
if (isRestartingClaude || isSwitchingMode) return;
|
|
6816
|
-
const
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
const
|
|
6820
|
-
|
|
6821
|
-
sessionMetadata = { ...sessionMetadata, inbox: updatedInbox };
|
|
6742
|
+
const queue = sessionMetadata.messageQueue;
|
|
6743
|
+
if (queue && queue.length > 0) {
|
|
6744
|
+
const next = queue[0];
|
|
6745
|
+
const remaining = queue.slice(1);
|
|
6746
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0 };
|
|
6822
6747
|
sessionService.updateMetadata(sessionMetadata);
|
|
6823
|
-
|
|
6824
|
-
logger.log(`[Session ${sessionId}] Processing inbox message: "${next.body.slice(0, 50)}..."`);
|
|
6748
|
+
logger.log(`[Session ${sessionId}] Processing queued message: "${next.text.slice(0, 50)}..."`);
|
|
6825
6749
|
sessionWasProcessing = true;
|
|
6826
6750
|
signalProcessing(true);
|
|
6827
|
-
sessionService.pushMessage(next.displayText || next.
|
|
6751
|
+
sessionService.pushMessage(next.displayText || next.text, "user");
|
|
6828
6752
|
userMessagePending = true;
|
|
6829
6753
|
turnInitiatedByUser = true;
|
|
6830
6754
|
const queueMeta = next.ralphSystemPrompt ? { appendSystemPrompt: next.ralphSystemPrompt } : void 0;
|
|
@@ -6846,7 +6770,7 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6846
6770
|
if (trackedSession?.stopped) return;
|
|
6847
6771
|
if (isRestartingClaude || isSwitchingMode) return;
|
|
6848
6772
|
claudeResumeId = void 0;
|
|
6849
|
-
spawnClaude(
|
|
6773
|
+
spawnClaude(next.text, queueMeta);
|
|
6850
6774
|
} catch (err) {
|
|
6851
6775
|
logger.log(`[Session ${sessionId}] Error in fresh Ralph queue processing: ${err.message}`);
|
|
6852
6776
|
isKillingClaude = false;
|
|
@@ -6857,11 +6781,11 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6857
6781
|
} else {
|
|
6858
6782
|
try {
|
|
6859
6783
|
if (!claudeProcess || claudeProcess.exitCode !== null) {
|
|
6860
|
-
spawnClaude(
|
|
6784
|
+
spawnClaude(next.text, queueMeta);
|
|
6861
6785
|
} else {
|
|
6862
6786
|
const stdinMsg = JSON.stringify({
|
|
6863
6787
|
type: "user",
|
|
6864
|
-
message: { role: "user", content:
|
|
6788
|
+
message: { role: "user", content: next.text }
|
|
6865
6789
|
});
|
|
6866
6790
|
claudeProcess.stdin?.write(stdinMsg + "\n");
|
|
6867
6791
|
}
|
|
@@ -6994,20 +6918,20 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
6994
6918
|
}
|
|
6995
6919
|
if (!acpBackendReady) {
|
|
6996
6920
|
logger.log(`[${agentName} Session ${sessionId}] Backend not ready \u2014 queuing message`);
|
|
6997
|
-
const
|
|
6921
|
+
const existingQueue = sessionMetadata.messageQueue || [];
|
|
6998
6922
|
sessionMetadata = {
|
|
6999
6923
|
...sessionMetadata,
|
|
7000
|
-
|
|
6924
|
+
messageQueue: [...existingQueue, { id: randomUUID$1(), text, createdAt: Date.now() }]
|
|
7001
6925
|
};
|
|
7002
6926
|
sessionService.updateMetadata(sessionMetadata);
|
|
7003
6927
|
return;
|
|
7004
6928
|
}
|
|
7005
6929
|
if (sessionMetadata.lifecycleState === "running") {
|
|
7006
6930
|
logger.log(`[${agentName} Session ${sessionId}] Agent busy \u2014 queuing message`);
|
|
7007
|
-
const
|
|
6931
|
+
const existingQueue = sessionMetadata.messageQueue || [];
|
|
7008
6932
|
sessionMetadata = {
|
|
7009
6933
|
...sessionMetadata,
|
|
7010
|
-
|
|
6934
|
+
messageQueue: [...existingQueue, { id: randomUUID$1(), text, createdAt: Date.now() }]
|
|
7011
6935
|
};
|
|
7012
6936
|
sessionService.updateMetadata(sessionMetadata);
|
|
7013
6937
|
return;
|
|
@@ -7064,10 +6988,6 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7064
6988
|
sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
|
|
7065
6989
|
return { success: false, message: "Security context updates with restart are not yet supported for this agent type." };
|
|
7066
6990
|
},
|
|
7067
|
-
onUpdateIsolation: async (enabled) => {
|
|
7068
|
-
sessionMetadata = { ...sessionMetadata, forceIsolation: enabled };
|
|
7069
|
-
return { success: false, message: "Isolation changes with restart are not yet supported for this agent type." };
|
|
7070
|
-
},
|
|
7071
6991
|
onSharingUpdate: (newSharing) => {
|
|
7072
6992
|
logger.log(`[${agentName} Session ${sessionId}] Sharing config updated \u2014 persisting in-memory`);
|
|
7073
6993
|
sessionMetadata = { ...sessionMetadata, sharing: newSharing };
|
|
@@ -7075,59 +6995,14 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7075
6995
|
onApplySystemPrompt: async () => {
|
|
7076
6996
|
return { success: false, message: "System prompt updates with restart are not yet supported for this agent type." };
|
|
7077
6997
|
},
|
|
7078
|
-
onInboxMessage: (message) => {
|
|
7079
|
-
const xmlText = formatInboxMessageXml(message);
|
|
7080
|
-
if (message.urgency === "urgent") {
|
|
7081
|
-
logger.log(`[${agentName} Session ${sessionId}] Urgent inbox message from ${message.from}: ${message.subject}`);
|
|
7082
|
-
if (sessionMetadata.lifecycleState === "running" || !acpBackendReady) {
|
|
7083
|
-
const existingInbox = sessionMetadata.inbox || [];
|
|
7084
|
-
sessionMetadata = { ...sessionMetadata, inbox: [{ messageId: message.messageId, body: xmlText, displayText: `[Inbox] ${message.subject}`, timestamp: Date.now(), read: false, from: message.from, fromSession: message.fromSession, subject: message.subject, urgency: "urgent" }, ...existingInbox] };
|
|
7085
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
7086
|
-
} else {
|
|
7087
|
-
sessionMetadata = { ...sessionMetadata, lifecycleState: "running" };
|
|
7088
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
7089
|
-
sessionService.pushMessage(`[Inbox] ${message.subject}`, "user");
|
|
7090
|
-
agentBackend.sendPrompt(sessionId, xmlText).catch((err) => {
|
|
7091
|
-
logger.error(`[${agentName} Session ${sessionId}] Error sending urgent inbox: ${err.message}`);
|
|
7092
|
-
if (!acpStopped) {
|
|
7093
|
-
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
7094
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
7095
|
-
sessionService.sendSessionEnd();
|
|
7096
|
-
}
|
|
7097
|
-
});
|
|
7098
|
-
}
|
|
7099
|
-
const inbox = (sessionMetadata.inbox || []).map(
|
|
7100
|
-
(m) => m.messageId === message.messageId ? { ...m, read: true } : m
|
|
7101
|
-
);
|
|
7102
|
-
sessionMetadata = { ...sessionMetadata, inbox };
|
|
7103
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
7104
|
-
} else {
|
|
7105
|
-
logger.log(`[${agentName} Session ${sessionId}] Normal inbox message from ${message.from}: ${message.subject}`);
|
|
7106
|
-
}
|
|
7107
|
-
},
|
|
7108
6998
|
onKillSession: () => {
|
|
7109
6999
|
logger.log(`[${agentName} Session ${sessionId}] Kill session requested`);
|
|
7110
7000
|
stopSession(sessionId);
|
|
7111
7001
|
},
|
|
7112
7002
|
onMetadataUpdate: (newMeta) => {
|
|
7113
7003
|
const prevRalphLoop = sessionMetadata.ralphLoop;
|
|
7114
|
-
const legacyQueue = newMeta.messageQueue;
|
|
7115
|
-
let migratedInbox = newMeta.inbox || [];
|
|
7116
|
-
if (legacyQueue && legacyQueue.length > 0) {
|
|
7117
|
-
const converted = legacyQueue.map((q) => ({
|
|
7118
|
-
messageId: q.id,
|
|
7119
|
-
body: q.text,
|
|
7120
|
-
displayText: q.displayText,
|
|
7121
|
-
timestamp: q.createdAt,
|
|
7122
|
-
read: false
|
|
7123
|
-
}));
|
|
7124
|
-
migratedInbox = [...migratedInbox || [], ...converted];
|
|
7125
|
-
}
|
|
7126
7004
|
sessionMetadata = {
|
|
7127
7005
|
...newMeta,
|
|
7128
|
-
inbox: migratedInbox.length > 0 ? migratedInbox : newMeta.inbox,
|
|
7129
|
-
// Clear legacy messageQueue — daemon uses inbox only
|
|
7130
|
-
...legacyQueue && legacyQueue.length > 0 ? { messageQueue: void 0 } : {},
|
|
7131
7006
|
// Daemon drives lifecycleState — don't let frontend overwrite with stale value
|
|
7132
7007
|
lifecycleState: sessionMetadata.lifecycleState,
|
|
7133
7008
|
...sessionMetadata.summary && !newMeta.summary ? { summary: sessionMetadata.summary } : {},
|
|
@@ -7141,24 +7016,17 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7141
7016
|
if (prevRalphLoop && !newMeta.ralphLoop) {
|
|
7142
7017
|
sessionService.updateMetadata(sessionMetadata);
|
|
7143
7018
|
}
|
|
7144
|
-
if (legacyQueue && legacyQueue.length > 0) {
|
|
7145
|
-
sessionService.updateMetadata(sessionMetadata);
|
|
7146
|
-
}
|
|
7147
7019
|
if (acpStopped) return;
|
|
7148
|
-
const
|
|
7149
|
-
if (
|
|
7150
|
-
const next =
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
|
|
7154
|
-
lifecycleState: "running"
|
|
7155
|
-
};
|
|
7020
|
+
const queue = newMeta.messageQueue;
|
|
7021
|
+
if (queue && queue.length > 0 && sessionMetadata.lifecycleState === "idle") {
|
|
7022
|
+
const next = queue[0];
|
|
7023
|
+
const remaining = queue.slice(1);
|
|
7024
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
|
|
7156
7025
|
sessionService.updateMetadata(sessionMetadata);
|
|
7157
|
-
|
|
7158
|
-
logger.log(`[Session ${sessionId}] Processing inbox message from metadata update: "${next.body.slice(0, 50)}..."`);
|
|
7026
|
+
logger.log(`[Session ${sessionId}] Processing queued message from metadata update: "${next.text.slice(0, 50)}..."`);
|
|
7159
7027
|
sessionService.sendKeepAlive(true);
|
|
7160
|
-
agentBackend.sendPrompt(sessionId,
|
|
7161
|
-
logger.error(`[Session ${sessionId}] Error processing
|
|
7028
|
+
agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
|
|
7029
|
+
logger.error(`[Session ${sessionId}] Error processing queued message: ${err.message}`);
|
|
7162
7030
|
if (!acpStopped) {
|
|
7163
7031
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
7164
7032
|
sessionService.updateMetadata(sessionMetadata);
|
|
@@ -7275,20 +7143,16 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7275
7143
|
() => {
|
|
7276
7144
|
if (acpStopped) return;
|
|
7277
7145
|
if (insideOnTurnEnd) return;
|
|
7278
|
-
const
|
|
7279
|
-
if (
|
|
7280
|
-
const next =
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
|
|
7284
|
-
lifecycleState: "running"
|
|
7285
|
-
};
|
|
7146
|
+
const queue = sessionMetadata.messageQueue;
|
|
7147
|
+
if (queue && queue.length > 0 && sessionMetadata.lifecycleState === "idle") {
|
|
7148
|
+
const next = queue[0];
|
|
7149
|
+
const remaining = queue.slice(1);
|
|
7150
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
|
|
7286
7151
|
sessionService.updateMetadata(sessionMetadata);
|
|
7287
|
-
|
|
7288
|
-
logger.log(`[Session ${sessionId}] Processing inbox message (ACP ralph activation): "${next.body.slice(0, 50)}..."`);
|
|
7152
|
+
logger.log(`[Session ${sessionId}] Processing queued message (ACP ralph activation): "${next.text.slice(0, 50)}..."`);
|
|
7289
7153
|
sessionService.sendKeepAlive(true);
|
|
7290
|
-
agentBackend.sendPrompt(sessionId,
|
|
7291
|
-
logger.error(`[Session ${sessionId}] Error processing
|
|
7154
|
+
agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
|
|
7155
|
+
logger.error(`[Session ${sessionId}] Error processing queued message: ${err.message}`);
|
|
7292
7156
|
if (!acpStopped) {
|
|
7293
7157
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
7294
7158
|
sessionService.updateMetadata(sessionMetadata);
|
|
@@ -7302,7 +7166,7 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7302
7166
|
const writeSvampConfigPatchAcp = svampConfigChecker.writeConfig;
|
|
7303
7167
|
const permissionHandler = new HyphaPermissionHandler(shouldAutoAllow2, logger.log);
|
|
7304
7168
|
let agentIsoConfig;
|
|
7305
|
-
if ((
|
|
7169
|
+
if ((options2.forceIsolation || sessionMetadata.sharing?.enabled) && isolationCapabilities.preferred) {
|
|
7306
7170
|
const method = isolationCapabilities.preferred;
|
|
7307
7171
|
const detail = isolationCapabilities.details[method];
|
|
7308
7172
|
if (detail.found && detail.verified !== false) {
|
|
@@ -7370,21 +7234,17 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7370
7234
|
logger.log(`[${agentName} Session ${sessionId}] ${reason}`);
|
|
7371
7235
|
sessionService.pushMessage({ type: "message", message: reason }, "event");
|
|
7372
7236
|
} else {
|
|
7373
|
-
const
|
|
7374
|
-
if (
|
|
7375
|
-
const next =
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
|
|
7379
|
-
lifecycleState: "running"
|
|
7380
|
-
};
|
|
7237
|
+
const pendingQueue = sessionMetadata.messageQueue;
|
|
7238
|
+
if (pendingQueue && pendingQueue.length > 0) {
|
|
7239
|
+
const next = pendingQueue[0];
|
|
7240
|
+
const remaining = pendingQueue.slice(1);
|
|
7241
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
|
|
7381
7242
|
sessionService.updateMetadata(sessionMetadata);
|
|
7382
7243
|
sessionService.sendKeepAlive(true);
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
logger.error(`[${agentName} Session ${sessionId}] Error processing inbox message (Ralph): ${err.message}`);
|
|
7244
|
+
sessionService.pushMessage(next.displayText || next.text, "user");
|
|
7245
|
+
logger.log(`[${agentName} Session ${sessionId}] Processing queued message (priority over Ralph advance): "${next.text.slice(0, 50)}..."`);
|
|
7246
|
+
agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
|
|
7247
|
+
logger.error(`[${agentName} Session ${sessionId}] Error processing queued message (Ralph): ${err.message}`);
|
|
7388
7248
|
if (!acpStopped) {
|
|
7389
7249
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
7390
7250
|
sessionService.updateMetadata(sessionMetadata);
|
|
@@ -7451,21 +7311,17 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7451
7311
|
return;
|
|
7452
7312
|
}
|
|
7453
7313
|
}
|
|
7454
|
-
const
|
|
7455
|
-
if (
|
|
7456
|
-
const next =
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
|
|
7460
|
-
lifecycleState: "running"
|
|
7461
|
-
};
|
|
7314
|
+
const queue = sessionMetadata.messageQueue;
|
|
7315
|
+
if (queue && queue.length > 0) {
|
|
7316
|
+
const next = queue[0];
|
|
7317
|
+
const remaining = queue.slice(1);
|
|
7318
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
|
|
7462
7319
|
sessionService.updateMetadata(sessionMetadata);
|
|
7463
7320
|
sessionService.sendKeepAlive(true);
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
logger.error(`[Session ${sessionId}] Error processing inbox message: ${err.message}`);
|
|
7321
|
+
logger.log(`[Session ${sessionId}] Processing queued message: "${next.text.slice(0, 50)}..."`);
|
|
7322
|
+
sessionService.pushMessage(next.displayText || next.text, "user");
|
|
7323
|
+
agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
|
|
7324
|
+
logger.error(`[Session ${sessionId}] Error processing queued message: ${err.message}`);
|
|
7469
7325
|
if (!acpStopped) {
|
|
7470
7326
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
7471
7327
|
sessionService.updateMetadata(sessionMetadata);
|
|
@@ -7676,7 +7532,7 @@ The automated loop has finished. Review the progress above and let me know if yo
|
|
|
7676
7532
|
// Restore sharing & security context from persisted metadata
|
|
7677
7533
|
sharing: persisted.metadata?.sharing,
|
|
7678
7534
|
securityContext: persisted.metadata?.securityContext,
|
|
7679
|
-
forceIsolation:
|
|
7535
|
+
forceIsolation: !!persisted.metadata?.isolationMethod,
|
|
7680
7536
|
// Block queue processing until auto-continue completes
|
|
7681
7537
|
wasProcessing: persisted.wasProcessing && !!persisted.claudeResumeId && !isOrphaned
|
|
7682
7538
|
});
|