svamp-cli 0.1.73 → 0.1.74

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.
@@ -1,6 +1,7 @@
1
1
  import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
3
  import os from 'node:os';
4
+ import 'node:crypto';
4
5
 
5
6
  const SVAMP_HOME = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
6
7
  function getConfigPath(sessionId) {
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { b as stopDaemon, s as startDaemon, d as daemonStatus } from './run-DWTcdCOS.mjs';
1
+ import { b as stopDaemon, s as startDaemon, d as daemonStatus } from './run-6QgabuQN.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -109,7 +109,7 @@ async function main() {
109
109
  const { handleServiceCommand } = await import('./commands-BLjcT1Vl.mjs');
110
110
  await handleServiceCommand();
111
111
  } else if (subcommand === "process" || subcommand === "proc") {
112
- const { processCommand } = await import('./commands-CPy4F-7w.mjs');
112
+ const { processCommand } = await import('./commands-dKkUOvUb.mjs');
113
113
  let machineId;
114
114
  const processArgs = args.slice(1);
115
115
  const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
@@ -127,7 +127,7 @@ async function main() {
127
127
  } else if (!subcommand || subcommand === "start") {
128
128
  await handleInteractiveCommand();
129
129
  } else if (subcommand === "--version" || subcommand === "-v") {
130
- const pkg = await import('./package-BAXhI1Iz.mjs').catch(() => ({ default: { version: "unknown" } }));
130
+ const pkg = await import('./package-CCjeil_X.mjs').catch(() => ({ default: { version: "unknown" } }));
131
131
  console.log(`svamp version: ${pkg.default.version}`);
132
132
  } else {
133
133
  console.error(`Unknown command: ${subcommand}`);
@@ -136,7 +136,7 @@ async function main() {
136
136
  }
137
137
  }
138
138
  async function handleInteractiveCommand() {
139
- const { runInteractive } = await import('./run-C2UwUIgR.mjs');
139
+ const { runInteractive } = await import('./run-BgwhZgkT.mjs');
140
140
  const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
141
141
  let directory = process.cwd();
142
142
  let resumeSessionId;
@@ -181,7 +181,7 @@ async function handleAgentCommand() {
181
181
  return;
182
182
  }
183
183
  if (agentArgs[0] === "list") {
184
- const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-DWTcdCOS.mjs').then(function (n) { return n.i; });
184
+ const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-6QgabuQN.mjs').then(function (n) { return n.i; });
185
185
  console.log("Known agents:");
186
186
  for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
187
187
  console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
@@ -193,7 +193,7 @@ async function handleAgentCommand() {
193
193
  console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
194
194
  return;
195
195
  }
196
- const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-DWTcdCOS.mjs').then(function (n) { return n.i; });
196
+ const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-6QgabuQN.mjs').then(function (n) { return n.i; });
197
197
  let cwd = process.cwd();
198
198
  const filteredArgs = [];
199
199
  for (let i = 0; i < agentArgs.length; i++) {
@@ -217,12 +217,12 @@ async function handleAgentCommand() {
217
217
  console.log(`Starting ${config.agentName} agent in ${cwd}...`);
218
218
  let backend;
219
219
  if (KNOWN_MCP_AGENTS[config.agentName]) {
220
- const { CodexMcpBackend } = await import('./run-DWTcdCOS.mjs').then(function (n) { return n.j; });
220
+ const { CodexMcpBackend } = await import('./run-6QgabuQN.mjs').then(function (n) { return n.j; });
221
221
  backend = new CodexMcpBackend({ cwd, log: logFn });
222
222
  } else {
223
- const { AcpBackend } = await import('./run-DWTcdCOS.mjs').then(function (n) { return n.h; });
224
- const { GeminiTransport } = await import('./run-DWTcdCOS.mjs').then(function (n) { return n.G; });
225
- const { DefaultTransport } = await import('./run-DWTcdCOS.mjs').then(function (n) { return n.D; });
223
+ const { AcpBackend } = await import('./run-6QgabuQN.mjs').then(function (n) { return n.h; });
224
+ const { GeminiTransport } = await import('./run-6QgabuQN.mjs').then(function (n) { return n.G; });
225
+ const { DefaultTransport } = await import('./run-6QgabuQN.mjs').then(function (n) { return n.D; });
226
226
  const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
227
227
  backend = new AcpBackend({
228
228
  agentName: config.agentName,
@@ -340,7 +340,7 @@ async function handleSessionCommand() {
340
340
  printSessionHelp();
341
341
  return;
342
342
  }
343
- const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionQueueAdd, sessionQueueList, sessionQueueClear } = await import('./commands-gghG16ZB.mjs');
343
+ const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionQueueAdd, sessionQueueList, sessionQueueClear, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-ClMc3nSg.mjs');
344
344
  const parseFlagStr = (flag, shortFlag) => {
345
345
  for (let i = 1; i < sessionArgs.length; i++) {
346
346
  if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
@@ -400,7 +400,7 @@ async function handleSessionCommand() {
400
400
  allowDomain.push(sessionArgs[++i]);
401
401
  }
402
402
  }
403
- const { parseShareArg } = await import('./commands-gghG16ZB.mjs');
403
+ const { parseShareArg } = await import('./commands-ClMc3nSg.mjs');
404
404
  const shareEntries = share.map((s) => parseShareArg(s));
405
405
  await sessionSpawn(agent, dir, targetMachineId, {
406
406
  message,
@@ -484,7 +484,7 @@ async function handleSessionCommand() {
484
484
  console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
485
485
  process.exit(1);
486
486
  }
487
- const { sessionApprove } = await import('./commands-gghG16ZB.mjs');
487
+ const { sessionApprove } = await import('./commands-ClMc3nSg.mjs');
488
488
  const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
489
489
  await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
490
490
  json: hasFlag("--json")
@@ -494,7 +494,7 @@ async function handleSessionCommand() {
494
494
  console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
495
495
  process.exit(1);
496
496
  }
497
- const { sessionDeny } = await import('./commands-gghG16ZB.mjs');
497
+ const { sessionDeny } = await import('./commands-ClMc3nSg.mjs');
498
498
  const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
499
499
  await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
500
500
  json: hasFlag("--json")
@@ -530,7 +530,7 @@ async function handleSessionCommand() {
530
530
  console.error("Usage: svamp session set-title <title>");
531
531
  process.exit(1);
532
532
  }
533
- const { sessionSetTitle } = await import('./agentCommands-C6iGblcL.mjs');
533
+ const { sessionSetTitle } = await import('./agentCommands-7GGmL2zY.mjs');
534
534
  await sessionSetTitle(title);
535
535
  } else if (sessionSubcommand === "set-link") {
536
536
  const url = sessionArgs[1];
@@ -539,7 +539,7 @@ async function handleSessionCommand() {
539
539
  process.exit(1);
540
540
  }
541
541
  const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
542
- const { sessionSetLink } = await import('./agentCommands-C6iGblcL.mjs');
542
+ const { sessionSetLink } = await import('./agentCommands-7GGmL2zY.mjs');
543
543
  await sessionSetLink(url, label);
544
544
  } else if (sessionSubcommand === "notify") {
545
545
  const message = sessionArgs[1];
@@ -548,7 +548,7 @@ async function handleSessionCommand() {
548
548
  process.exit(1);
549
549
  }
550
550
  const level = parseFlagStr("--level") || "info";
551
- const { sessionNotify } = await import('./agentCommands-C6iGblcL.mjs');
551
+ const { sessionNotify } = await import('./agentCommands-7GGmL2zY.mjs');
552
552
  await sessionNotify(message, level);
553
553
  } else if (sessionSubcommand === "broadcast") {
554
554
  const action = sessionArgs[1];
@@ -556,7 +556,7 @@ async function handleSessionCommand() {
556
556
  console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
557
557
  process.exit(1);
558
558
  }
559
- const { sessionBroadcast } = await import('./agentCommands-C6iGblcL.mjs');
559
+ const { sessionBroadcast } = await import('./agentCommands-7GGmL2zY.mjs');
560
560
  await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
561
561
  } else if (sessionSubcommand === "queue") {
562
562
  const queueSubcmd = sessionArgs[1];
@@ -582,6 +582,82 @@ async function handleSessionCommand() {
582
582
  console.error("Usage: svamp session queue <add|list|clear> <session-id> [args]");
583
583
  process.exit(1);
584
584
  }
585
+ } else if (sessionSubcommand === "inbox") {
586
+ const inboxSubcmd = sessionArgs[1];
587
+ if (inboxSubcmd === "send") {
588
+ const targetId = sessionArgs[2];
589
+ if (!targetId) {
590
+ console.error('Usage: svamp session inbox send <target-session-id> --subject "..." --body "..."');
591
+ process.exit(1);
592
+ }
593
+ const ccStr = parseFlagStr("--cc");
594
+ await sessionInboxSend(targetId, targetMachineId, {
595
+ subject: parseFlagStr("--subject") || "",
596
+ body: parseFlagStr("--body") || "",
597
+ urgency: parseFlagStr("--urgency") || "normal",
598
+ replyTo: parseFlagStr("--reply-to"),
599
+ cc: ccStr ? ccStr.split(",").map((s) => s.trim()).filter(Boolean) : void 0,
600
+ wait: hasFlag("--wait"),
601
+ timeout: parseFlagInt("--timeout"),
602
+ json: hasFlag("--json")
603
+ });
604
+ } else if (inboxSubcmd === "list" || inboxSubcmd === "ls") {
605
+ const targetId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : process.env.SVAMP_SESSION_ID;
606
+ if (!targetId) {
607
+ console.error("Usage: svamp session inbox list [session-id] [--unread] [--limit N] [--json]");
608
+ process.exit(1);
609
+ }
610
+ await sessionInboxList(targetId, targetMachineId, {
611
+ unread: hasFlag("--unread"),
612
+ limit: parseFlagInt("--limit"),
613
+ json: hasFlag("--json")
614
+ });
615
+ } else if (inboxSubcmd === "read") {
616
+ const targetId = sessionArgs[2];
617
+ const msgId = sessionArgs[3];
618
+ if (!targetId || !msgId) {
619
+ console.error("Usage: svamp session inbox read <session-id> <message-id>");
620
+ process.exit(1);
621
+ }
622
+ await sessionInboxRead(targetId, msgId, targetMachineId, {
623
+ json: hasFlag("--json")
624
+ });
625
+ } else if (inboxSubcmd === "reply") {
626
+ let targetId;
627
+ let msgId;
628
+ if (sessionArgs[3] && !sessionArgs[3].startsWith("--")) {
629
+ targetId = sessionArgs[2];
630
+ msgId = sessionArgs[3];
631
+ } else if (sessionArgs[2] && !sessionArgs[2].startsWith("--")) {
632
+ targetId = process.env.SVAMP_SESSION_ID;
633
+ msgId = sessionArgs[2];
634
+ }
635
+ if (!targetId || !msgId) {
636
+ console.error('Usage: svamp session inbox reply [session-id] <message-id> --body "..."');
637
+ process.exit(1);
638
+ }
639
+ await sessionInboxReply(targetId, msgId, targetMachineId, {
640
+ body: parseFlagStr("--body") || "",
641
+ urgency: parseFlagStr("--urgency") || "normal",
642
+ wait: hasFlag("--wait"),
643
+ json: hasFlag("--json")
644
+ });
645
+ } else if (inboxSubcmd === "clear") {
646
+ const targetId = sessionArgs[2];
647
+ if (!targetId) {
648
+ console.error("Usage: svamp session inbox clear <session-id> [--all]");
649
+ process.exit(1);
650
+ }
651
+ const msgId = sessionArgs[3] && !sessionArgs[3].startsWith("--") ? sessionArgs[3] : void 0;
652
+ await sessionInboxClear(targetId, targetMachineId, {
653
+ messageId: msgId,
654
+ all: hasFlag("--all"),
655
+ json: hasFlag("--json")
656
+ });
657
+ } else {
658
+ console.error("Usage: svamp session inbox <send|list|read|reply|clear> [args]");
659
+ process.exit(1);
660
+ }
585
661
  } else {
586
662
  console.error(`Unknown session command: ${sessionSubcommand}`);
587
663
  printSessionHelp();
@@ -597,7 +673,7 @@ async function handleMachineCommand() {
597
673
  return;
598
674
  }
599
675
  if (machineSubcommand === "share") {
600
- const { machineShare } = await import('./commands-gghG16ZB.mjs');
676
+ const { machineShare } = await import('./commands-ClMc3nSg.mjs');
601
677
  let machineId;
602
678
  const shareArgs = [];
603
679
  for (let i = 1; i < machineArgs.length; i++) {
@@ -627,7 +703,7 @@ async function handleMachineCommand() {
627
703
  }
628
704
  await machineShare(machineId, { add, remove, list, configPath, showConfig });
629
705
  } else if (machineSubcommand === "exec") {
630
- const { machineExec } = await import('./commands-gghG16ZB.mjs');
706
+ const { machineExec } = await import('./commands-ClMc3nSg.mjs');
631
707
  let machineId;
632
708
  let cwd;
633
709
  const cmdParts = [];
@@ -647,7 +723,7 @@ async function handleMachineCommand() {
647
723
  }
648
724
  await machineExec(machineId, command, cwd);
649
725
  } else if (machineSubcommand === "info") {
650
- const { machineInfo } = await import('./commands-gghG16ZB.mjs');
726
+ const { machineInfo } = await import('./commands-ClMc3nSg.mjs');
651
727
  let machineId;
652
728
  for (let i = 1; i < machineArgs.length; i++) {
653
729
  if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
@@ -667,10 +743,10 @@ async function handleMachineCommand() {
667
743
  level = machineArgs[++i];
668
744
  }
669
745
  }
670
- const { machineNotify } = await import('./agentCommands-C6iGblcL.mjs');
746
+ const { machineNotify } = await import('./agentCommands-7GGmL2zY.mjs');
671
747
  await machineNotify(message, level);
672
748
  } else if (machineSubcommand === "ls") {
673
- const { machineLs } = await import('./commands-gghG16ZB.mjs');
749
+ const { machineLs } = await import('./commands-ClMc3nSg.mjs');
674
750
  let machineId;
675
751
  let showHidden = false;
676
752
  let path;
@@ -1160,10 +1236,17 @@ COMMANDS:
1160
1236
  ralph-cancel <id> Cancel loop
1161
1237
  ralph-status <id> Show loop status
1162
1238
 
1163
- Message Queue:
1164
- queue add <id> "<message>" Queue a message for later
1165
- queue list <id> List queued messages
1166
- queue clear <id> Clear queue
1239
+ Inbox:
1240
+ inbox send <target> --subject "..." --body "..." Send inbox message
1241
+ inbox list [session-id] [--unread] [--json] List inbox messages
1242
+ inbox read <session-id> <message-id> Read a message
1243
+ inbox reply [session-id] <message-id> --body "..." Reply to a message
1244
+ inbox clear <session-id> [--all] Clear inbox
1245
+
1246
+ Queue (deprecated, use inbox):
1247
+ queue add <id> "<message>" Queue a message (alias for inbox send)
1248
+ queue list <id> List messages (alias for inbox list)
1249
+ queue clear <id> Clear messages (alias for inbox clear)
1167
1250
 
1168
1251
  SPAWN OPTIONS:
1169
1252
  -d, --directory <path> Working directory (REQUIRED for meaningful work)
@@ -1,8 +1,9 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { execSync } from 'node:child_process';
3
+ import { randomUUID } from 'node:crypto';
3
4
  import { resolve, join } from 'node:path';
4
5
  import os from 'node:os';
5
- import { l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha } from './run-DWTcdCOS.mjs';
6
+ import { l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha } from './run-6QgabuQN.mjs';
6
7
  import 'os';
7
8
  import 'fs/promises';
8
9
  import 'fs';
@@ -10,7 +11,6 @@ import 'path';
10
11
  import 'url';
11
12
  import 'child_process';
12
13
  import 'crypto';
13
- import 'node:crypto';
14
14
  import '@agentclientprotocol/sdk';
15
15
  import '@modelcontextprotocol/sdk/client/index.js';
16
16
  import '@modelcontextprotocol/sdk/client/stdio.js';
@@ -1713,71 +1713,207 @@ async function sessionQueueAdd(sessionIdPartial, message, machineId) {
1713
1713
  const match = resolveSessionId(sessions, sessionIdPartial);
1714
1714
  const fullId = match.sessionId;
1715
1715
  const svc = await server.getService(`svamp-session-${fullId}`);
1716
- const { metadata, version } = await svc.getMetadata();
1717
- const existingQueue = metadata?.messageQueue || [];
1718
1716
  const newMsg = {
1719
- id: `cli-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1720
- text: message,
1721
- createdAt: Date.now()
1717
+ messageId: `msg-${randomUUID()}`,
1718
+ body: message,
1719
+ timestamp: Date.now(),
1720
+ read: false
1722
1721
  };
1723
- const updatedQueue = [...existingQueue, newMsg];
1724
- const updatedMetadata = { ...metadata, messageQueue: updatedQueue };
1725
- const result = await svc.updateMetadata(updatedMetadata, version);
1726
- if (result.result !== "success") {
1727
- console.error(`Failed to add to queue: ${result.result}`);
1728
- process.exit(1);
1729
- }
1730
- console.log(`Message queued on session ${fullId.slice(0, 8)} (${updatedQueue.length} total)`);
1722
+ await svc.sendInboxMessage(newMsg);
1723
+ console.log(`Message queued on session ${fullId.slice(0, 8)}`);
1731
1724
  } finally {
1732
1725
  await server.disconnect();
1733
1726
  }
1734
1727
  }
1735
1728
  async function sessionQueueList(sessionIdPartial, machineId) {
1729
+ return sessionInboxList(sessionIdPartial, machineId);
1730
+ }
1731
+ async function sessionQueueClear(sessionIdPartial, machineId) {
1732
+ return sessionInboxClear(sessionIdPartial, machineId);
1733
+ }
1734
+ async function sessionInboxSend(targetSessionId, machineId, opts) {
1735
+ if (!opts?.subject || !opts?.body) {
1736
+ console.error('Usage: svamp session inbox send <target-session-id> --subject "..." --body "..."');
1737
+ process.exit(1);
1738
+ }
1739
+ const { server, machine } = await connectAndGetMachine(machineId);
1740
+ try {
1741
+ const sessions = await machine.listSessions();
1742
+ const match = resolveSessionId(sessions, targetSessionId);
1743
+ const fullTargetId = match.sessionId;
1744
+ const senderSessionId = process.env.SVAMP_SESSION_ID || "cli";
1745
+ const senderEmail = process.env.USER_EMAIL || process.env.USER || os.userInfo().username;
1746
+ const from = senderSessionId === "cli" ? `user:${senderEmail}` : `agent:${senderSessionId}`;
1747
+ const message = {
1748
+ messageId: `msg-${randomUUID()}`,
1749
+ from,
1750
+ fromSession: senderSessionId,
1751
+ to: fullTargetId,
1752
+ subject: opts.subject,
1753
+ body: opts.body,
1754
+ urgency: opts.urgency || "normal",
1755
+ replyTo: opts.replyTo,
1756
+ cc: opts.cc,
1757
+ timestamp: Date.now(),
1758
+ read: false,
1759
+ threadId: opts.replyTo ? void 0 : void 0
1760
+ // will be set by reply logic
1761
+ };
1762
+ const svc = await server.getService(`svamp-session-${fullTargetId}`);
1763
+ const result = await svc.sendInboxMessage(message);
1764
+ if (opts.wait) {
1765
+ const timeoutMs = (opts.timeout || 300) * 1e3;
1766
+ await waitForBusyThenIdle(server, fullTargetId, timeoutMs);
1767
+ }
1768
+ if (opts.json) {
1769
+ console.log(formatJson({
1770
+ messageId: message.messageId,
1771
+ targetSessionId: fullTargetId,
1772
+ subject: opts.subject,
1773
+ urgency: message.urgency,
1774
+ delivered: result.delivered
1775
+ }));
1776
+ } else {
1777
+ console.log(`Inbox message sent to session ${fullTargetId.slice(0, 8)} [${message.urgency}]: "${opts.subject}"`);
1778
+ }
1779
+ } finally {
1780
+ await server.disconnect();
1781
+ }
1782
+ }
1783
+ async function sessionInboxList(sessionIdPartial, machineId, opts) {
1736
1784
  const { server, machine } = await connectAndGetMachine(machineId);
1737
1785
  try {
1738
1786
  const sessions = await machine.listSessions();
1739
1787
  const match = resolveSessionId(sessions, sessionIdPartial);
1740
1788
  const fullId = match.sessionId;
1741
1789
  const svc = await server.getService(`svamp-session-${fullId}`);
1742
- const { metadata } = await svc.getMetadata();
1743
- const queue = metadata?.messageQueue || [];
1744
- if (queue.length === 0) {
1745
- console.log("Queue is empty.");
1746
- return;
1747
- }
1748
- console.log(`Queue for session ${fullId.slice(0, 8)} (${queue.length} messages):`);
1749
- for (let i = 0; i < queue.length; i++) {
1750
- const msg = queue[i];
1751
- const time = new Date(msg.createdAt).toLocaleTimeString();
1752
- console.log(` ${i + 1}. [${time}] ${msg.text.slice(0, 80)}${msg.text.length > 80 ? "..." : ""}`);
1790
+ const result = await svc.getInbox({
1791
+ unreadOnly: opts?.unread || false,
1792
+ limit: opts?.limit || 50
1793
+ });
1794
+ if (opts?.json) ; else {
1795
+ const msgs = result.messages || [];
1796
+ if (msgs.length === 0) {
1797
+ console.log("Inbox is empty.");
1798
+ return;
1799
+ }
1800
+ console.log(`Inbox for session ${fullId.slice(0, 8)} (${msgs.length} message(s), ${result.total} total):
1801
+ `);
1802
+ for (const msg of msgs) {
1803
+ const readMark = msg.read ? " " : "*";
1804
+ const date = new Date(msg.timestamp).toLocaleString();
1805
+ console.log(`${readMark} [${msg.messageId.slice(0, 12)}] ${date}`);
1806
+ console.log(` From: ${msg.from} | Subject: ${msg.subject} | Urgency: ${msg.urgency}`);
1807
+ if (msg.replyTo) console.log(` Reply-To: ${msg.replyTo.slice(0, 12)}`);
1808
+ console.log(` ${msg.body.slice(0, 120)}${msg.body.length > 120 ? "..." : ""}`);
1809
+ console.log();
1810
+ }
1753
1811
  }
1754
1812
  } finally {
1755
1813
  await server.disconnect();
1756
1814
  }
1757
1815
  }
1758
- async function sessionQueueClear(sessionIdPartial, machineId) {
1816
+ async function sessionInboxRead(sessionIdPartial, messageId, machineId, opts) {
1759
1817
  const { server, machine } = await connectAndGetMachine(machineId);
1760
1818
  try {
1761
1819
  const sessions = await machine.listSessions();
1762
1820
  const match = resolveSessionId(sessions, sessionIdPartial);
1763
1821
  const fullId = match.sessionId;
1764
1822
  const svc = await server.getService(`svamp-session-${fullId}`);
1765
- const { metadata, version } = await svc.getMetadata();
1766
- const count = (metadata?.messageQueue || []).length;
1767
- if (count === 0) {
1768
- console.log("Queue is already empty.");
1769
- return;
1823
+ const result = await svc.getInbox({});
1824
+ const msg = (result.messages || []).find(
1825
+ (m) => m.messageId === messageId || m.messageId.startsWith(messageId)
1826
+ );
1827
+ if (!msg) {
1828
+ console.error(`Message ${messageId} not found in inbox.`);
1829
+ process.exit(1);
1770
1830
  }
1771
- const updatedMetadata = { ...metadata, messageQueue: void 0 };
1772
- const result = await svc.updateMetadata(updatedMetadata, version);
1773
- if (result.result !== "success") {
1774
- console.error(`Failed to clear queue: ${result.result}`);
1831
+ await svc.markInboxRead([msg.messageId]);
1832
+ if (opts?.json) {
1833
+ console.log(formatJson(msg));
1834
+ } else {
1835
+ console.log(`Message-ID: ${msg.messageId}`);
1836
+ console.log(`From: ${msg.from}`);
1837
+ console.log(`From-Session: ${msg.fromSession}`);
1838
+ console.log(`Subject: ${msg.subject}`);
1839
+ console.log(`Urgency: ${msg.urgency}`);
1840
+ console.log(`Date: ${new Date(msg.timestamp).toLocaleString()}`);
1841
+ if (msg.replyTo) console.log(`Reply-To: ${msg.replyTo}`);
1842
+ if (msg.cc?.length) console.log(`CC: ${msg.cc.join(", ")}`);
1843
+ console.log(`---`);
1844
+ console.log(msg.body);
1845
+ }
1846
+ } finally {
1847
+ await server.disconnect();
1848
+ }
1849
+ }
1850
+ async function sessionInboxReply(sessionIdPartial, messageId, machineId, opts) {
1851
+ if (!opts?.body) {
1852
+ console.error('Usage: svamp session inbox reply <session-id> <message-id> --body "..."');
1853
+ process.exit(1);
1854
+ }
1855
+ const { server, machine } = await connectAndGetMachine(machineId);
1856
+ try {
1857
+ const sessions = await machine.listSessions();
1858
+ const match = resolveSessionId(sessions, sessionIdPartial);
1859
+ const fullId = match.sessionId;
1860
+ const svc = await server.getService(`svamp-session-${fullId}`);
1861
+ const inboxResult = await svc.getInbox({});
1862
+ const originalMsg = (inboxResult.messages || []).find(
1863
+ (m) => m.messageId === messageId || m.messageId.startsWith(messageId)
1864
+ );
1865
+ if (!originalMsg) {
1866
+ console.error(`Message ${messageId} not found in inbox. Cannot reply.`);
1775
1867
  process.exit(1);
1776
1868
  }
1777
- console.log(`Cleared ${count} message(s) from queue on session ${fullId.slice(0, 8)}`);
1869
+ const senderSessionId = process.env.SVAMP_SESSION_ID || fullId;
1870
+ const senderEmail = process.env.USER_EMAIL || process.env.USER || os.userInfo().username;
1871
+ const from = senderSessionId === "cli" ? `user:${senderEmail}` : `agent:${senderSessionId}`;
1872
+ const reply = {
1873
+ messageId: `msg-${randomUUID()}`,
1874
+ from,
1875
+ fromSession: senderSessionId,
1876
+ to: originalMsg.fromSession,
1877
+ subject: `Re: ${originalMsg.subject}`,
1878
+ body: opts.body,
1879
+ urgency: opts.urgency || "normal",
1880
+ replyTo: originalMsg.messageId,
1881
+ threadId: originalMsg.threadId || originalMsg.messageId,
1882
+ timestamp: Date.now(),
1883
+ read: false
1884
+ };
1885
+ const targetSvc = await server.getService(`svamp-session-${originalMsg.fromSession}`);
1886
+ const result = await targetSvc.sendInboxMessage(reply);
1887
+ if (opts.json) {
1888
+ console.log(formatJson({
1889
+ messageId: reply.messageId,
1890
+ targetSessionId: originalMsg.fromSession,
1891
+ subject: reply.subject,
1892
+ urgency: reply.urgency,
1893
+ delivered: result.delivered
1894
+ }));
1895
+ } else {
1896
+ console.log(`Reply sent to session ${originalMsg.fromSession.slice(0, 8)}: "${reply.subject}"`);
1897
+ }
1898
+ } finally {
1899
+ await server.disconnect();
1900
+ }
1901
+ }
1902
+ async function sessionInboxClear(sessionIdPartial, machineId, opts) {
1903
+ const { server, machine } = await connectAndGetMachine(machineId);
1904
+ try {
1905
+ const sessions = await machine.listSessions();
1906
+ const match = resolveSessionId(sessions, sessionIdPartial);
1907
+ const fullId = match.sessionId;
1908
+ const svc = await server.getService(`svamp-session-${fullId}`);
1909
+ const messageIds = opts?.messageId ? [opts.messageId] : void 0;
1910
+ const result = await svc.clearInbox(messageIds);
1911
+ if (opts?.json) ; else {
1912
+ console.log(`Cleared ${result.removed} message(s) from inbox on session ${fullId.slice(0, 8)}`);
1913
+ }
1778
1914
  } finally {
1779
1915
  await server.disconnect();
1780
1916
  }
1781
1917
  }
1782
1918
 
1783
- export { connectAndGetMachine, createWorktree, generateWorktreeName, machineExec, machineInfo, machineLs, machineShare, parseShareArg, renderMessage, resolveSessionId, sessionApprove, sessionAttach, sessionDeny, sessionInfo, sessionList, sessionMachines, sessionMessages, sessionQueueAdd, sessionQueueClear, sessionQueueList, sessionRalphCancel, sessionRalphStart, sessionRalphStatus, sessionSend, sessionShare, sessionSpawn, sessionStop, sessionWait };
1919
+ export { connectAndGetMachine, createWorktree, generateWorktreeName, machineExec, machineInfo, machineLs, machineShare, parseShareArg, renderMessage, resolveSessionId, sessionApprove, sessionAttach, sessionDeny, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionMachines, sessionMessages, sessionQueueAdd, sessionQueueClear, sessionQueueList, sessionRalphCancel, sessionRalphStart, sessionRalphStatus, sessionSend, sessionShare, sessionSpawn, sessionStop, sessionWait };
@@ -1,17 +1,17 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-gghG16ZB.mjs';
3
+ import { connectAndGetMachine } from './commands-ClMc3nSg.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:child_process';
6
+ import 'node:crypto';
6
7
  import 'node:path';
7
8
  import 'node:os';
8
- import './run-DWTcdCOS.mjs';
9
+ import './run-6QgabuQN.mjs';
9
10
  import 'os';
10
11
  import 'fs/promises';
11
12
  import 'url';
12
13
  import 'child_process';
13
14
  import 'crypto';
14
- import 'node:crypto';
15
15
  import '@agentclientprotocol/sdk';
16
16
  import '@modelcontextprotocol/sdk/client/index.js';
17
17
  import '@modelcontextprotocol/sdk/client/stdio.js';
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-DWTcdCOS.mjs';
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-6QgabuQN.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.73";
2
+ var version = "0.1.74";
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";
@@ -871,6 +871,27 @@ async function registerMachineService(server, machineId, metadata, daemonState,
871
871
  };
872
872
  }
873
873
 
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
+ }
874
895
  function loadMessages(messagesDir, sessionId) {
875
896
  const filePath = join$1(messagesDir, "messages.jsonl");
876
897
  if (!existsSync(filePath)) return [];
@@ -1247,6 +1268,24 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
1247
1268
  });
1248
1269
  return await callbacks.onUpdateSecurityContext(newSecurityContext);
1249
1270
  },
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
+ },
1250
1289
  /** Apply a new system prompt and restart the agent process */
1251
1290
  applySystemPrompt: async (prompt, context) => {
1252
1291
  authorizeRequest(context, metadata.sharing, "admin");
@@ -1255,6 +1294,86 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
1255
1294
  }
1256
1295
  return await callbacks.onApplySystemPrompt(prompt);
1257
1296
  },
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
+ },
1258
1377
  // ── Listener Registration ──
1259
1378
  registerListener: async (callback, context) => {
1260
1379
  authorizeRequest(context, metadata.sharing, "view");
@@ -4852,15 +4971,16 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
4852
4971
  const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
4853
4972
  const prompt = buildRalphPrompt(state.task, state);
4854
4973
  const ralphSysPrompt = buildRalphSystemPrompt(state, progressRelPath);
4855
- const existingQueue = getMetadata().messageQueue || [];
4974
+ const existingInbox = getMetadata().inbox || [];
4856
4975
  setMetadata((m) => ({
4857
4976
  ...m,
4858
4977
  ralphLoop,
4859
- messageQueue: [...existingQueue, {
4860
- id: randomUUID$1(),
4861
- text: prompt,
4978
+ inbox: [...existingInbox, {
4979
+ messageId: randomUUID$1(),
4980
+ body: prompt,
4862
4981
  displayText: state.task,
4863
- createdAt: Date.now(),
4982
+ timestamp: Date.now(),
4983
+ read: false,
4864
4984
  ralphSystemPrompt: ralphSysPrompt
4865
4985
  }]
4866
4986
  }));
@@ -5528,7 +5648,8 @@ async function startDaemon(options) {
5528
5648
  }
5529
5649
  });
5530
5650
  }, buildIsolationConfig2 = function(dir) {
5531
- if (!options2.forceIsolation && !sessionMetadata.sharing?.enabled) return null;
5651
+ const forceIsolation = sessionMetadata.forceIsolation ?? options2.forceIsolation;
5652
+ if (!forceIsolation && !sessionMetadata.sharing?.enabled) return null;
5532
5653
  const method = isolationCapabilities.preferred;
5533
5654
  if (!method) return null;
5534
5655
  const detail = isolationCapabilities.details[method];
@@ -5569,6 +5690,7 @@ async function startDaemon(options) {
5569
5690
  lifecycleState: resumeSessionId ? "idle" : "starting",
5570
5691
  sharing: options2.sharing,
5571
5692
  securityContext: options2.securityContext,
5693
+ forceIsolation: options2.forceIsolation || void 0,
5572
5694
  tags: options2.tags,
5573
5695
  parentSessionId: options2.parentSessionId,
5574
5696
  ...options2.parentSessionId && (() => {
@@ -5644,7 +5766,8 @@ async function startDaemon(options) {
5644
5766
  startupNonJsonLines = [];
5645
5767
  startupRetryMessage = initialMessage;
5646
5768
  let rawPermissionMode = effectiveMeta.permissionMode || agentConfig.default_permission_mode || currentPermissionMode;
5647
- if (options2.forceIsolation || sessionMetadata.sharing?.enabled) {
5769
+ const forceIsolation = sessionMetadata.forceIsolation ?? options2.forceIsolation;
5770
+ if (forceIsolation || sessionMetadata.sharing?.enabled) {
5648
5771
  rawPermissionMode = rawPermissionMode === "default" ? "auto-approve-all" : rawPermissionMode;
5649
5772
  }
5650
5773
  if (sessionMetadata.ralphLoop?.active) {
@@ -5681,7 +5804,7 @@ async function startDaemon(options) {
5681
5804
  if (wrapped.cleanupFiles) isolationCleanupFiles = wrapped.cleanupFiles;
5682
5805
  sessionMetadata = { ...sessionMetadata, isolationMethod: isoConfig.method };
5683
5806
  logger.log(`[Session ${sessionId}] Isolation: ${isoConfig.method} (binary: ${isoConfig.binaryPath})`);
5684
- } else if (options2.forceIsolation || sessionMetadata.sharing?.enabled) {
5807
+ } else if (forceIsolation || sessionMetadata.sharing?.enabled) {
5685
5808
  logger.log(`[Session ${sessionId}] WARNING: No isolation runtime (nono/docker/podman) available. Session is NOT sandboxed.`);
5686
5809
  sessionMetadata = { ...sessionMetadata, isolationMethod: void 0 };
5687
5810
  } else {
@@ -5906,7 +6029,7 @@ async function startDaemon(options) {
5906
6029
  logger.log(`[Session ${sessionId}] ${taskInfo}`);
5907
6030
  sessionService.pushMessage({ type: "session_event", message: taskInfo }, "session");
5908
6031
  }
5909
- const queueLen = sessionMetadata.messageQueue?.length ?? 0;
6032
+ const queueLen = sessionMetadata.inbox?.filter((m) => !m.read)?.length ?? 0;
5910
6033
  if (msg.is_error) {
5911
6034
  const rlStateForError = readRalphState(getRalphStateFilePath(directory, sessionId));
5912
6035
  if (rlStateForError) {
@@ -6211,7 +6334,7 @@ The automated loop has finished. Review the progress above and let me know if yo
6211
6334
  return;
6212
6335
  }
6213
6336
  }
6214
- const queueLen = sessionMetadata.messageQueue?.length ?? 0;
6337
+ const queueLen = sessionMetadata.inbox?.filter((m) => !m.read)?.length ?? 0;
6215
6338
  if (queueLen > 0 && claudeResumeId && !trackedSession.stopped) {
6216
6339
  signalProcessing(false);
6217
6340
  setTimeout(() => processMessageQueueRef?.(), 200);
@@ -6322,10 +6445,10 @@ The automated loop has finished. Review the progress above and let me know if yo
6322
6445
  }
6323
6446
  if (isKillingClaude || isRestartingClaude || isSwitchingMode) {
6324
6447
  logger.log(`[Session ${sessionId}] Message received while restarting Claude, queuing to prevent loss`);
6325
- const existingQueue = sessionMetadata.messageQueue || [];
6448
+ const existingInbox = sessionMetadata.inbox || [];
6326
6449
  sessionMetadata = {
6327
6450
  ...sessionMetadata,
6328
- messageQueue: [...existingQueue, { id: randomUUID$1(), text, createdAt: Date.now() }]
6451
+ inbox: [...existingInbox, { messageId: randomUUID$1(), body: text, timestamp: Date.now(), read: false }]
6329
6452
  };
6330
6453
  sessionService.updateMetadata(sessionMetadata);
6331
6454
  signalProcessing(false);
@@ -6360,7 +6483,7 @@ The automated loop has finished. Review the progress above and let me know if yo
6360
6483
  }
6361
6484
  signalProcessing(false);
6362
6485
  sessionWasProcessing = false;
6363
- const queueLen = sessionMetadata.messageQueue?.length ?? 0;
6486
+ const queueLen = sessionMetadata.inbox?.filter((m) => !m.read)?.length ?? 0;
6364
6487
  const abortMsg = queueLen > 0 ? `Aborted by user. ${queueLen} queued message(s) will be processed next.` : "Aborted by user";
6365
6488
  sessionService.pushMessage(
6366
6489
  { type: "message", message: abortMsg },
@@ -6442,6 +6565,24 @@ The automated loop has finished. Review the progress above and let me know if yo
6442
6565
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
6443
6566
  return await restartClaudeHandler();
6444
6567
  },
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
+ },
6445
6586
  onSharingUpdate: (newSharing) => {
6446
6587
  logger.log(`[Session ${sessionId}] Sharing config updated \u2014 persisting to disk`);
6447
6588
  sessionMetadata = { ...sessionMetadata, sharing: newSharing };
@@ -6464,14 +6605,72 @@ The automated loop has finished. Review the progress above and let me know if yo
6464
6605
  lastSpawnMeta = { ...lastSpawnMeta, appendSystemPrompt: prompt };
6465
6606
  return await restartClaudeHandler();
6466
6607
  },
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
+ },
6467
6651
  onKillSession: () => {
6468
6652
  logger.log(`[Session ${sessionId}] Kill session requested`);
6469
6653
  stopSession(sessionId);
6470
6654
  },
6471
6655
  onMetadataUpdate: (newMeta) => {
6472
6656
  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
+ }
6473
6669
  sessionMetadata = {
6474
6670
  ...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 } : {},
6475
6674
  // Daemon drives lifecycleState — don't let frontend overwrite with stale value
6476
6675
  lifecycleState: sessionMetadata.lifecycleState,
6477
6676
  // Preserve claudeSessionId set by 'system init' (frontend may not have it)
@@ -6487,8 +6686,11 @@ The automated loop has finished. Review the progress above and let me know if yo
6487
6686
  if (prevRalphLoop && !newMeta.ralphLoop) {
6488
6687
  sessionService.updateMetadata(sessionMetadata);
6489
6688
  }
6490
- const queue = newMeta.messageQueue;
6491
- if (queue && queue.length > 0 && !sessionWasProcessing && !trackedSession.stopped) {
6689
+ if (legacyQueue && legacyQueue.length > 0) {
6690
+ sessionService.updateMetadata(sessionMetadata);
6691
+ }
6692
+ const unreadInbox = sessionMetadata.inbox?.filter((m) => !m.read);
6693
+ if (unreadInbox && unreadInbox.length > 0 && !sessionWasProcessing && !trackedSession.stopped) {
6492
6694
  setTimeout(() => {
6493
6695
  processMessageQueueRef?.();
6494
6696
  }, 200);
@@ -6611,16 +6813,18 @@ The automated loop has finished. Review the progress above and let me know if yo
6611
6813
  if (trackedSession?.stopped) return;
6612
6814
  if (isKillingClaude) return;
6613
6815
  if (isRestartingClaude || isSwitchingMode) return;
6614
- const queue = sessionMetadata.messageQueue;
6615
- if (queue && queue.length > 0) {
6616
- const next = queue[0];
6617
- const remaining = queue.slice(1);
6618
- sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0 };
6816
+ const inbox = sessionMetadata.inbox;
6817
+ const unreadIdx = inbox?.findIndex((m) => !m.read) ?? -1;
6818
+ if (inbox && unreadIdx >= 0) {
6819
+ const next = inbox[unreadIdx];
6820
+ const updatedInbox = inbox.map((m, i) => i === unreadIdx ? { ...m, read: true } : m);
6821
+ sessionMetadata = { ...sessionMetadata, inbox: updatedInbox };
6619
6822
  sessionService.updateMetadata(sessionMetadata);
6620
- logger.log(`[Session ${sessionId}] Processing queued message: "${next.text.slice(0, 50)}..."`);
6823
+ const deliverText = isStructuredMessage(next) ? formatInboxMessageXml(next) : next.body;
6824
+ logger.log(`[Session ${sessionId}] Processing inbox message: "${next.body.slice(0, 50)}..."`);
6621
6825
  sessionWasProcessing = true;
6622
6826
  signalProcessing(true);
6623
- sessionService.pushMessage(next.displayText || next.text, "user");
6827
+ sessionService.pushMessage(next.displayText || next.body, "user");
6624
6828
  userMessagePending = true;
6625
6829
  turnInitiatedByUser = true;
6626
6830
  const queueMeta = next.ralphSystemPrompt ? { appendSystemPrompt: next.ralphSystemPrompt } : void 0;
@@ -6642,7 +6846,7 @@ The automated loop has finished. Review the progress above and let me know if yo
6642
6846
  if (trackedSession?.stopped) return;
6643
6847
  if (isRestartingClaude || isSwitchingMode) return;
6644
6848
  claudeResumeId = void 0;
6645
- spawnClaude(next.text, queueMeta);
6849
+ spawnClaude(deliverText, queueMeta);
6646
6850
  } catch (err) {
6647
6851
  logger.log(`[Session ${sessionId}] Error in fresh Ralph queue processing: ${err.message}`);
6648
6852
  isKillingClaude = false;
@@ -6653,11 +6857,11 @@ The automated loop has finished. Review the progress above and let me know if yo
6653
6857
  } else {
6654
6858
  try {
6655
6859
  if (!claudeProcess || claudeProcess.exitCode !== null) {
6656
- spawnClaude(next.text, queueMeta);
6860
+ spawnClaude(deliverText, queueMeta);
6657
6861
  } else {
6658
6862
  const stdinMsg = JSON.stringify({
6659
6863
  type: "user",
6660
- message: { role: "user", content: next.text }
6864
+ message: { role: "user", content: deliverText }
6661
6865
  });
6662
6866
  claudeProcess.stdin?.write(stdinMsg + "\n");
6663
6867
  }
@@ -6790,20 +6994,20 @@ The automated loop has finished. Review the progress above and let me know if yo
6790
6994
  }
6791
6995
  if (!acpBackendReady) {
6792
6996
  logger.log(`[${agentName} Session ${sessionId}] Backend not ready \u2014 queuing message`);
6793
- const existingQueue = sessionMetadata.messageQueue || [];
6997
+ const existingInbox = sessionMetadata.inbox || [];
6794
6998
  sessionMetadata = {
6795
6999
  ...sessionMetadata,
6796
- messageQueue: [...existingQueue, { id: randomUUID$1(), text, createdAt: Date.now() }]
7000
+ inbox: [...existingInbox, { messageId: randomUUID$1(), body: text, timestamp: Date.now(), read: false }]
6797
7001
  };
6798
7002
  sessionService.updateMetadata(sessionMetadata);
6799
7003
  return;
6800
7004
  }
6801
7005
  if (sessionMetadata.lifecycleState === "running") {
6802
7006
  logger.log(`[${agentName} Session ${sessionId}] Agent busy \u2014 queuing message`);
6803
- const existingQueue = sessionMetadata.messageQueue || [];
7007
+ const existingInbox = sessionMetadata.inbox || [];
6804
7008
  sessionMetadata = {
6805
7009
  ...sessionMetadata,
6806
- messageQueue: [...existingQueue, { id: randomUUID$1(), text, createdAt: Date.now() }]
7010
+ inbox: [...existingInbox, { messageId: randomUUID$1(), body: text, timestamp: Date.now(), read: false }]
6807
7011
  };
6808
7012
  sessionService.updateMetadata(sessionMetadata);
6809
7013
  return;
@@ -6860,6 +7064,10 @@ The automated loop has finished. Review the progress above and let me know if yo
6860
7064
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
6861
7065
  return { success: false, message: "Security context updates with restart are not yet supported for this agent type." };
6862
7066
  },
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
+ },
6863
7071
  onSharingUpdate: (newSharing) => {
6864
7072
  logger.log(`[${agentName} Session ${sessionId}] Sharing config updated \u2014 persisting in-memory`);
6865
7073
  sessionMetadata = { ...sessionMetadata, sharing: newSharing };
@@ -6867,14 +7075,59 @@ The automated loop has finished. Review the progress above and let me know if yo
6867
7075
  onApplySystemPrompt: async () => {
6868
7076
  return { success: false, message: "System prompt updates with restart are not yet supported for this agent type." };
6869
7077
  },
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
+ },
6870
7108
  onKillSession: () => {
6871
7109
  logger.log(`[${agentName} Session ${sessionId}] Kill session requested`);
6872
7110
  stopSession(sessionId);
6873
7111
  },
6874
7112
  onMetadataUpdate: (newMeta) => {
6875
7113
  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
+ }
6876
7126
  sessionMetadata = {
6877
7127
  ...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 } : {},
6878
7131
  // Daemon drives lifecycleState — don't let frontend overwrite with stale value
6879
7132
  lifecycleState: sessionMetadata.lifecycleState,
6880
7133
  ...sessionMetadata.summary && !newMeta.summary ? { summary: sessionMetadata.summary } : {},
@@ -6888,17 +7141,24 @@ The automated loop has finished. Review the progress above and let me know if yo
6888
7141
  if (prevRalphLoop && !newMeta.ralphLoop) {
6889
7142
  sessionService.updateMetadata(sessionMetadata);
6890
7143
  }
7144
+ if (legacyQueue && legacyQueue.length > 0) {
7145
+ sessionService.updateMetadata(sessionMetadata);
7146
+ }
6891
7147
  if (acpStopped) return;
6892
- const queue = newMeta.messageQueue;
6893
- if (queue && queue.length > 0 && sessionMetadata.lifecycleState === "idle") {
6894
- const next = queue[0];
6895
- const remaining = queue.slice(1);
6896
- sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
7148
+ const unreadInbox = sessionMetadata.inbox?.filter((m) => !m.read);
7149
+ if (unreadInbox && unreadInbox.length > 0 && sessionMetadata.lifecycleState === "idle") {
7150
+ const next = unreadInbox[0];
7151
+ sessionMetadata = {
7152
+ ...sessionMetadata,
7153
+ inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
7154
+ lifecycleState: "running"
7155
+ };
6897
7156
  sessionService.updateMetadata(sessionMetadata);
6898
- logger.log(`[Session ${sessionId}] Processing queued message from metadata update: "${next.text.slice(0, 50)}..."`);
7157
+ const deliverText = isStructuredMessage(next) ? formatInboxMessageXml(next) : next.body;
7158
+ logger.log(`[Session ${sessionId}] Processing inbox message from metadata update: "${next.body.slice(0, 50)}..."`);
6899
7159
  sessionService.sendKeepAlive(true);
6900
- agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
6901
- logger.error(`[Session ${sessionId}] Error processing queued message: ${err.message}`);
7160
+ agentBackend.sendPrompt(sessionId, deliverText).catch((err) => {
7161
+ logger.error(`[Session ${sessionId}] Error processing inbox message: ${err.message}`);
6902
7162
  if (!acpStopped) {
6903
7163
  sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
6904
7164
  sessionService.updateMetadata(sessionMetadata);
@@ -7015,16 +7275,20 @@ The automated loop has finished. Review the progress above and let me know if yo
7015
7275
  () => {
7016
7276
  if (acpStopped) return;
7017
7277
  if (insideOnTurnEnd) return;
7018
- const queue = sessionMetadata.messageQueue;
7019
- if (queue && queue.length > 0 && sessionMetadata.lifecycleState === "idle") {
7020
- const next = queue[0];
7021
- const remaining = queue.slice(1);
7022
- sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
7278
+ const unreadInbox = sessionMetadata.inbox?.filter((m) => !m.read);
7279
+ if (unreadInbox && unreadInbox.length > 0 && sessionMetadata.lifecycleState === "idle") {
7280
+ const next = unreadInbox[0];
7281
+ sessionMetadata = {
7282
+ ...sessionMetadata,
7283
+ inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
7284
+ lifecycleState: "running"
7285
+ };
7023
7286
  sessionService.updateMetadata(sessionMetadata);
7024
- logger.log(`[Session ${sessionId}] Processing queued message (ACP ralph activation): "${next.text.slice(0, 50)}..."`);
7287
+ const deliverText = isStructuredMessage(next) ? formatInboxMessageXml(next) : next.body;
7288
+ logger.log(`[Session ${sessionId}] Processing inbox message (ACP ralph activation): "${next.body.slice(0, 50)}..."`);
7025
7289
  sessionService.sendKeepAlive(true);
7026
- agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
7027
- logger.error(`[Session ${sessionId}] Error processing queued message: ${err.message}`);
7290
+ agentBackend.sendPrompt(sessionId, deliverText).catch((err) => {
7291
+ logger.error(`[Session ${sessionId}] Error processing inbox message: ${err.message}`);
7028
7292
  if (!acpStopped) {
7029
7293
  sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
7030
7294
  sessionService.updateMetadata(sessionMetadata);
@@ -7038,7 +7302,7 @@ The automated loop has finished. Review the progress above and let me know if yo
7038
7302
  const writeSvampConfigPatchAcp = svampConfigChecker.writeConfig;
7039
7303
  const permissionHandler = new HyphaPermissionHandler(shouldAutoAllow2, logger.log);
7040
7304
  let agentIsoConfig;
7041
- if ((options2.forceIsolation || sessionMetadata.sharing?.enabled) && isolationCapabilities.preferred) {
7305
+ if (((sessionMetadata.forceIsolation ?? options2.forceIsolation) || sessionMetadata.sharing?.enabled) && isolationCapabilities.preferred) {
7042
7306
  const method = isolationCapabilities.preferred;
7043
7307
  const detail = isolationCapabilities.details[method];
7044
7308
  if (detail.found && detail.verified !== false) {
@@ -7106,17 +7370,21 @@ The automated loop has finished. Review the progress above and let me know if yo
7106
7370
  logger.log(`[${agentName} Session ${sessionId}] ${reason}`);
7107
7371
  sessionService.pushMessage({ type: "message", message: reason }, "event");
7108
7372
  } else {
7109
- const pendingQueue = sessionMetadata.messageQueue;
7110
- if (pendingQueue && pendingQueue.length > 0) {
7111
- const next = pendingQueue[0];
7112
- const remaining = pendingQueue.slice(1);
7113
- sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
7373
+ const pendingInbox = sessionMetadata.inbox?.filter((m) => !m.read);
7374
+ if (pendingInbox && pendingInbox.length > 0) {
7375
+ const next = pendingInbox[0];
7376
+ sessionMetadata = {
7377
+ ...sessionMetadata,
7378
+ inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
7379
+ lifecycleState: "running"
7380
+ };
7114
7381
  sessionService.updateMetadata(sessionMetadata);
7115
7382
  sessionService.sendKeepAlive(true);
7116
- sessionService.pushMessage(next.displayText || next.text, "user");
7117
- logger.log(`[${agentName} Session ${sessionId}] Processing queued message (priority over Ralph advance): "${next.text.slice(0, 50)}..."`);
7118
- agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
7119
- logger.error(`[${agentName} Session ${sessionId}] Error processing queued message (Ralph): ${err.message}`);
7383
+ const deliverText = isStructuredMessage(next) ? formatInboxMessageXml(next) : next.body;
7384
+ sessionService.pushMessage(next.displayText || next.body, "user");
7385
+ logger.log(`[${agentName} Session ${sessionId}] Processing inbox message (priority over Ralph advance): "${next.body.slice(0, 50)}..."`);
7386
+ agentBackend.sendPrompt(sessionId, deliverText).catch((err) => {
7387
+ logger.error(`[${agentName} Session ${sessionId}] Error processing inbox message (Ralph): ${err.message}`);
7120
7388
  if (!acpStopped) {
7121
7389
  sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
7122
7390
  sessionService.updateMetadata(sessionMetadata);
@@ -7183,17 +7451,21 @@ The automated loop has finished. Review the progress above and let me know if yo
7183
7451
  return;
7184
7452
  }
7185
7453
  }
7186
- const queue = sessionMetadata.messageQueue;
7187
- if (queue && queue.length > 0) {
7188
- const next = queue[0];
7189
- const remaining = queue.slice(1);
7190
- sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
7454
+ const unreadInboxItems = sessionMetadata.inbox?.filter((m) => !m.read);
7455
+ if (unreadInboxItems && unreadInboxItems.length > 0) {
7456
+ const next = unreadInboxItems[0];
7457
+ sessionMetadata = {
7458
+ ...sessionMetadata,
7459
+ inbox: (sessionMetadata.inbox || []).map((m) => m.messageId === next.messageId ? { ...m, read: true } : m),
7460
+ lifecycleState: "running"
7461
+ };
7191
7462
  sessionService.updateMetadata(sessionMetadata);
7192
7463
  sessionService.sendKeepAlive(true);
7193
- logger.log(`[Session ${sessionId}] Processing queued message: "${next.text.slice(0, 50)}..."`);
7194
- sessionService.pushMessage(next.displayText || next.text, "user");
7195
- agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
7196
- logger.error(`[Session ${sessionId}] Error processing queued message: ${err.message}`);
7464
+ const deliverText = isStructuredMessage(next) ? formatInboxMessageXml(next) : next.body;
7465
+ logger.log(`[Session ${sessionId}] Processing inbox message: "${next.body.slice(0, 50)}..."`);
7466
+ sessionService.pushMessage(next.displayText || next.body, "user");
7467
+ agentBackend.sendPrompt(sessionId, deliverText).catch((err) => {
7468
+ logger.error(`[Session ${sessionId}] Error processing inbox message: ${err.message}`);
7197
7469
  if (!acpStopped) {
7198
7470
  sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
7199
7471
  sessionService.updateMetadata(sessionMetadata);
@@ -7404,7 +7676,7 @@ The automated loop has finished. Review the progress above and let me know if yo
7404
7676
  // Restore sharing & security context from persisted metadata
7405
7677
  sharing: persisted.metadata?.sharing,
7406
7678
  securityContext: persisted.metadata?.securityContext,
7407
- forceIsolation: !!persisted.metadata?.isolationMethod,
7679
+ forceIsolation: persisted.metadata?.forceIsolation ?? !!persisted.metadata?.isolationMethod,
7408
7680
  // Block queue processing until auto-continue completes
7409
7681
  wasProcessing: persisted.wasProcessing && !!persisted.claudeResumeId && !isOrphaned
7410
7682
  });
@@ -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-DWTcdCOS.mjs';
5
+ import { c as connectToHypha, a as registerSessionService } from './run-6QgabuQN.mjs';
6
6
  import { createServer } from 'node:http';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svamp-cli",
3
- "version": "0.1.73",
3
+ "version": "0.1.74",
4
4
  "description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
5
5
  "author": "Amun AI AB",
6
6
  "license": "SEE LICENSE IN LICENSE",