svamp-cli 0.2.67 → 0.2.70

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.
@@ -148,7 +148,7 @@ async function sessionBroadcast(action, args) {
148
148
  console.log(`Broadcast sent: ${action}`);
149
149
  }
150
150
  async function connectToMachineService() {
151
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
151
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
152
152
  return connectAndGetMachine();
153
153
  }
154
154
  async function inboxSend(targetSessionId, opts) {
@@ -165,7 +165,7 @@ async function inboxSend(targetSessionId, opts) {
165
165
  }
166
166
  const { server, machine } = await connectToMachineService();
167
167
  try {
168
- const { resolveSessionId } = await import('./commands-BO8gl_-u.mjs');
168
+ const { resolveSessionId } = await import('./commands-BMOelGYC.mjs');
169
169
  const sessions = await machine.listSessions();
170
170
  const match = resolveSessionId(sessions, targetSessionId);
171
171
  const fullTargetId = match.sessionId;
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-DZq12r28.mjs';
1
+ import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-BqAe7GgA.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -44,7 +44,7 @@ async function main() {
44
44
  console.error(`svamp daemon restart: ${err.message || err}`);
45
45
  process.exit(1);
46
46
  }
47
- const { restartDaemon } = await import('./run-DZq12r28.mjs').then(function (n) { return n.u; });
47
+ const { restartDaemon } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.u; });
48
48
  await restartDaemon();
49
49
  process.exit(0);
50
50
  }
@@ -280,7 +280,7 @@ async function main() {
280
280
  console.error("svamp service: Service commands are not available in sandboxed sessions.");
281
281
  process.exit(1);
282
282
  }
283
- const { handleServiceCommand } = await import('./commands-B6yUtg85.mjs');
283
+ const { handleServiceCommand } = await import('./commands-CdGLuwtQ.mjs');
284
284
  await handleServiceCommand();
285
285
  } else if (subcommand === "serve") {
286
286
  const { isSandboxed: isSandboxedServe } = await import('./sandboxDetect-DNTcbgWD.mjs');
@@ -288,7 +288,7 @@ async function main() {
288
288
  console.error("svamp serve: Serve commands are not available in sandboxed sessions.");
289
289
  process.exit(1);
290
290
  }
291
- const { handleServeCommand } = await import('./serveCommands-B-Ij7oce.mjs');
291
+ const { handleServeCommand } = await import('./serveCommands-DpKi_PuD.mjs');
292
292
  await handleServeCommand();
293
293
  process.exit(0);
294
294
  } else if (subcommand === "process" || subcommand === "proc") {
@@ -297,7 +297,7 @@ async function main() {
297
297
  console.error("svamp process: Process commands are not available in sandboxed sessions.");
298
298
  process.exit(1);
299
299
  }
300
- const { processCommand } = await import('./commands-D7A1aWC1.mjs');
300
+ const { processCommand } = await import('./commands-CB03m9-Z.mjs');
301
301
  let machineId;
302
302
  const processArgs = args.slice(1);
303
303
  const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
@@ -315,7 +315,7 @@ async function main() {
315
315
  } else if (!subcommand || subcommand === "start") {
316
316
  await handleInteractiveCommand();
317
317
  } else if (subcommand === "--version" || subcommand === "-v") {
318
- const pkg = await import('./package-wAsRM-Wx.mjs').catch(() => ({ default: { version: "unknown" } }));
318
+ const pkg = await import('./package-Cw40xKCx.mjs').catch(() => ({ default: { version: "unknown" } }));
319
319
  console.log(`svamp version: ${pkg.default.version}`);
320
320
  } else {
321
321
  console.error(`Unknown command: ${subcommand}`);
@@ -324,7 +324,7 @@ async function main() {
324
324
  }
325
325
  }
326
326
  async function handleInteractiveCommand() {
327
- const { runInteractive } = await import('./run-B4a6wAxf.mjs');
327
+ const { runInteractive } = await import('./run-Di-48dsY.mjs');
328
328
  const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
329
329
  let directory = process.cwd();
330
330
  let resumeSessionId;
@@ -369,7 +369,7 @@ async function handleAgentCommand() {
369
369
  return;
370
370
  }
371
371
  if (agentArgs[0] === "list") {
372
- const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-DZq12r28.mjs').then(function (n) { return n.p; });
372
+ const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.p; });
373
373
  console.log("Known agents:");
374
374
  for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
375
375
  console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
@@ -381,7 +381,7 @@ async function handleAgentCommand() {
381
381
  console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
382
382
  return;
383
383
  }
384
- const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-DZq12r28.mjs').then(function (n) { return n.p; });
384
+ const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.p; });
385
385
  let cwd = process.cwd();
386
386
  const filteredArgs = [];
387
387
  for (let i = 0; i < agentArgs.length; i++) {
@@ -405,12 +405,12 @@ async function handleAgentCommand() {
405
405
  console.log(`Starting ${config.agentName} agent in ${cwd}...`);
406
406
  let backend;
407
407
  if (KNOWN_MCP_AGENTS[config.agentName]) {
408
- const { CodexMcpBackend } = await import('./run-DZq12r28.mjs').then(function (n) { return n.q; });
408
+ const { CodexMcpBackend } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.q; });
409
409
  backend = new CodexMcpBackend({ cwd, log: logFn });
410
410
  } else {
411
- const { AcpBackend } = await import('./run-DZq12r28.mjs').then(function (n) { return n.o; });
412
- const { GeminiTransport } = await import('./run-DZq12r28.mjs').then(function (n) { return n.G; });
413
- const { DefaultTransport } = await import('./run-DZq12r28.mjs').then(function (n) { return n.D; });
411
+ const { AcpBackend } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.o; });
412
+ const { GeminiTransport } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.G; });
413
+ const { DefaultTransport } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.D; });
414
414
  const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
415
415
  backend = new AcpBackend({
416
416
  agentName: config.agentName,
@@ -537,7 +537,7 @@ async function handleSessionCommand() {
537
537
  process.exit(1);
538
538
  }
539
539
  }
540
- const { sessionList, sessionSpawn, sessionArchive, sessionResume, sessionDelete, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-BO8gl_-u.mjs');
540
+ const { sessionList, sessionSpawn, sessionArchive, sessionResume, sessionDelete, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-BMOelGYC.mjs');
541
541
  const parseFlagStr = (flag, shortFlag) => {
542
542
  for (let i = 1; i < sessionArgs.length; i++) {
543
543
  if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
@@ -573,7 +573,13 @@ async function handleSessionCommand() {
573
573
  const wait = hasFlag("--wait");
574
574
  const worktree = hasFlag("--worktree");
575
575
  const isolate = hasFlag("--isolate");
576
- const permissionMode = parseFlagStr("--permission-mode") || parseFlagStr("-p");
576
+ let permissionMode = parseFlagStr("--permission-mode") || parseFlagStr("-p");
577
+ if (!permissionMode && hasFlag("--require-approval")) {
578
+ permissionMode = "default";
579
+ }
580
+ if (!permissionMode) {
581
+ permissionMode = "bypassPermissions";
582
+ }
577
583
  const securityContextPath = parseFlagStr("--security-context");
578
584
  const denyNetwork = hasFlag("--deny-network");
579
585
  const parentSessionId = parseFlagStr("--parent");
@@ -597,7 +603,7 @@ async function handleSessionCommand() {
597
603
  allowDomain.push(sessionArgs[++i]);
598
604
  }
599
605
  }
600
- const { parseShareArg } = await import('./commands-BO8gl_-u.mjs');
606
+ const { parseShareArg } = await import('./commands-BMOelGYC.mjs');
601
607
  const shareEntries = share.map((s) => parseShareArg(s));
602
608
  await sessionSpawn(agent, dir, targetMachineId, {
603
609
  message,
@@ -660,16 +666,35 @@ async function handleSessionCommand() {
660
666
  await sessionAttach(sessionArgs[1], targetMachineId);
661
667
  } else if (sessionSubcommand === "send") {
662
668
  if (!sessionArgs[1] || !sessionArgs[2]) {
663
- console.error('Usage: svamp session send <session-id> <message> [--subject "..."] [--urgency urgent|normal] [--wait] [--timeout N] [--json]');
669
+ console.error('Usage: svamp session send <session-id> <message> [--subject "..."] [--urgency urgent|normal] [--wait] [--response] [--btw] [--require-approval] [--timeout N] [--json]');
664
670
  process.exit(1);
665
671
  }
666
672
  await sessionSend(sessionArgs[1], sessionArgs[2], targetMachineId, {
667
673
  wait: hasFlag("--wait"),
674
+ response: hasFlag("--response"),
675
+ btw: hasFlag("--btw"),
676
+ requireApproval: hasFlag("--require-approval"),
668
677
  timeout: parseFlagInt("--timeout"),
669
678
  json: hasFlag("--json"),
670
679
  subject: parseFlagStr("--subject"),
671
680
  urgency: parseFlagStr("--urgency")
672
681
  });
682
+ } else if (sessionSubcommand === "query") {
683
+ const dir = sessionArgs[1];
684
+ const prompt = sessionArgs[2];
685
+ if (!dir || !prompt) {
686
+ console.error("Usage: svamp session query <directory> <prompt> [--timeout N] [--keep] [--json] [--permission-mode MODE] [--tag NAME]");
687
+ console.error(" Spawns a stateless Claude session in <directory>, sends <prompt>, prints the answer, then deletes the session.");
688
+ process.exit(1);
689
+ }
690
+ const { sessionQuery } = await import('./commands-BMOelGYC.mjs');
691
+ await sessionQuery(dir, prompt, targetMachineId, {
692
+ timeout: parseFlagInt("--timeout"),
693
+ json: hasFlag("--json"),
694
+ keep: hasFlag("--keep"),
695
+ permissionMode: parseFlagStr("--permission-mode"),
696
+ tag: parseFlagStr("--tag")
697
+ });
673
698
  } else if (sessionSubcommand === "wait") {
674
699
  if (!sessionArgs[1]) {
675
700
  console.error("Usage: svamp session wait <session-id> [--timeout N] [--json]");
@@ -695,7 +720,7 @@ async function handleSessionCommand() {
695
720
  console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
696
721
  process.exit(1);
697
722
  }
698
- const { sessionApprove } = await import('./commands-BO8gl_-u.mjs');
723
+ const { sessionApprove } = await import('./commands-BMOelGYC.mjs');
699
724
  const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
700
725
  await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
701
726
  json: hasFlag("--json")
@@ -705,7 +730,7 @@ async function handleSessionCommand() {
705
730
  console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
706
731
  process.exit(1);
707
732
  }
708
- const { sessionDeny } = await import('./commands-BO8gl_-u.mjs');
733
+ const { sessionDeny } = await import('./commands-BMOelGYC.mjs');
709
734
  const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
710
735
  await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
711
736
  json: hasFlag("--json")
@@ -741,7 +766,7 @@ async function handleSessionCommand() {
741
766
  console.error("Usage: svamp session set-title <title>");
742
767
  process.exit(1);
743
768
  }
744
- const { sessionSetTitle } = await import('./agentCommands-CVmNxFdC.mjs');
769
+ const { sessionSetTitle } = await import('./agentCommands-BaQIO1T2.mjs');
745
770
  await sessionSetTitle(title);
746
771
  } else if (sessionSubcommand === "set-link") {
747
772
  const url = sessionArgs[1];
@@ -750,7 +775,7 @@ async function handleSessionCommand() {
750
775
  process.exit(1);
751
776
  }
752
777
  const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
753
- const { sessionSetLink } = await import('./agentCommands-CVmNxFdC.mjs');
778
+ const { sessionSetLink } = await import('./agentCommands-BaQIO1T2.mjs');
754
779
  await sessionSetLink(url, label);
755
780
  } else if (sessionSubcommand === "notify") {
756
781
  const message = sessionArgs[1];
@@ -759,7 +784,7 @@ async function handleSessionCommand() {
759
784
  process.exit(1);
760
785
  }
761
786
  const level = parseFlagStr("--level") || "info";
762
- const { sessionNotify } = await import('./agentCommands-CVmNxFdC.mjs');
787
+ const { sessionNotify } = await import('./agentCommands-BaQIO1T2.mjs');
763
788
  await sessionNotify(message, level);
764
789
  } else if (sessionSubcommand === "broadcast") {
765
790
  const action = sessionArgs[1];
@@ -767,7 +792,7 @@ async function handleSessionCommand() {
767
792
  console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
768
793
  process.exit(1);
769
794
  }
770
- const { sessionBroadcast } = await import('./agentCommands-CVmNxFdC.mjs');
795
+ const { sessionBroadcast } = await import('./agentCommands-BaQIO1T2.mjs');
771
796
  await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
772
797
  } else if (sessionSubcommand === "inbox") {
773
798
  const inboxSubcmd = sessionArgs[1];
@@ -778,7 +803,7 @@ async function handleSessionCommand() {
778
803
  process.exit(1);
779
804
  }
780
805
  if (agentSessionId) {
781
- const { inboxSend } = await import('./agentCommands-CVmNxFdC.mjs');
806
+ const { inboxSend } = await import('./agentCommands-BaQIO1T2.mjs');
782
807
  await inboxSend(sessionArgs[2], {
783
808
  body: sessionArgs[3],
784
809
  subject: parseFlagStr("--subject"),
@@ -793,7 +818,7 @@ async function handleSessionCommand() {
793
818
  }
794
819
  } else if (inboxSubcmd === "list" || inboxSubcmd === "ls") {
795
820
  if (agentSessionId && !sessionArgs[2]) {
796
- const { inboxList } = await import('./agentCommands-CVmNxFdC.mjs');
821
+ const { inboxList } = await import('./agentCommands-BaQIO1T2.mjs');
797
822
  await inboxList({
798
823
  unread: hasFlag("--unread"),
799
824
  limit: parseFlagInt("--limit"),
@@ -815,7 +840,7 @@ async function handleSessionCommand() {
815
840
  process.exit(1);
816
841
  }
817
842
  if (agentSessionId && !sessionArgs[3]) {
818
- const { inboxList } = await import('./agentCommands-CVmNxFdC.mjs');
843
+ const { inboxList } = await import('./agentCommands-BaQIO1T2.mjs');
819
844
  await sessionInboxRead(agentSessionId, sessionArgs[2], targetMachineId);
820
845
  } else if (sessionArgs[3]) {
821
846
  await sessionInboxRead(sessionArgs[2], sessionArgs[3], targetMachineId);
@@ -825,7 +850,7 @@ async function handleSessionCommand() {
825
850
  }
826
851
  } else if (inboxSubcmd === "reply") {
827
852
  if (agentSessionId && sessionArgs[2] && sessionArgs[3] && !sessionArgs[4]) {
828
- const { inboxReply } = await import('./agentCommands-CVmNxFdC.mjs');
853
+ const { inboxReply } = await import('./agentCommands-BaQIO1T2.mjs');
829
854
  await inboxReply(sessionArgs[2], sessionArgs[3]);
830
855
  } else if (sessionArgs[2] && sessionArgs[3] && sessionArgs[4]) {
831
856
  await sessionInboxReply(sessionArgs[2], sessionArgs[3], sessionArgs[4], targetMachineId);
@@ -861,7 +886,7 @@ async function handleMachineCommand() {
861
886
  return;
862
887
  }
863
888
  if (machineSubcommand === "share") {
864
- const { machineShare } = await import('./commands-BO8gl_-u.mjs');
889
+ const { machineShare } = await import('./commands-BMOelGYC.mjs');
865
890
  let machineId;
866
891
  const shareArgs = [];
867
892
  for (let i = 1; i < machineArgs.length; i++) {
@@ -891,7 +916,7 @@ async function handleMachineCommand() {
891
916
  }
892
917
  await machineShare(machineId, { add, remove, list, configPath, showConfig });
893
918
  } else if (machineSubcommand === "exec") {
894
- const { machineExec } = await import('./commands-BO8gl_-u.mjs');
919
+ const { machineExec } = await import('./commands-BMOelGYC.mjs');
895
920
  let machineId;
896
921
  let cwd;
897
922
  const cmdParts = [];
@@ -911,7 +936,7 @@ async function handleMachineCommand() {
911
936
  }
912
937
  await machineExec(machineId, command, cwd);
913
938
  } else if (machineSubcommand === "info") {
914
- const { machineInfo } = await import('./commands-BO8gl_-u.mjs');
939
+ const { machineInfo } = await import('./commands-BMOelGYC.mjs');
915
940
  let machineId;
916
941
  for (let i = 1; i < machineArgs.length; i++) {
917
942
  if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
@@ -931,10 +956,10 @@ async function handleMachineCommand() {
931
956
  level = machineArgs[++i];
932
957
  }
933
958
  }
934
- const { machineNotify } = await import('./agentCommands-CVmNxFdC.mjs');
959
+ const { machineNotify } = await import('./agentCommands-BaQIO1T2.mjs');
935
960
  await machineNotify(message, level);
936
961
  } else if (machineSubcommand === "ls") {
937
- const { machineLs } = await import('./commands-BO8gl_-u.mjs');
962
+ const { machineLs } = await import('./commands-BMOelGYC.mjs');
938
963
  let machineId;
939
964
  let showHidden = false;
940
965
  let path;
@@ -1307,12 +1332,12 @@ function printHelp() {
1307
1332
  console.log(`
1308
1333
  svamp \u2014 AI workspace on Hypha Cloud
1309
1334
 
1310
- Quick start \u2014 spawn an agent to do a task (use -p bypassPermissions to run autonomously):
1311
- svamp session spawn claude -d ./project -p bypassPermissions --message "fix tests" --wait
1335
+ Quick start \u2014 spawn an agent to do a task (autonomous by default):
1336
+ svamp session spawn claude -d ./project --message "fix tests" --wait
1312
1337
 
1313
- Note: without -p bypassPermissions the agent PAUSES waiting for human approval of each
1314
- tool use. This will cause it to hang in automated/agent contexts. Use bypassPermissions
1315
- for autonomous work, or "default" only when a human is actively watching.
1338
+ Note: as of 0.2.69 spawn defaults to permission mode "bypassPermissions" so the
1339
+ child agent doesn't get stuck on tool-approval prompts. Pass --require-approval
1340
+ (or -p default / -p acceptEdits) when you want a human to gate tool use.
1316
1341
 
1317
1342
  Commands:
1318
1343
  svamp Start interactive Claude session (synced to cloud)
@@ -1324,7 +1349,8 @@ Commands:
1324
1349
 
1325
1350
  Session management (requires daemon running):
1326
1351
  svamp session spawn <agent> [opts] Spawn a new agent session (agents: claude, gemini, codex)
1327
- svamp session send <id> <message> Send message to a session (--wait to block until done)
1352
+ svamp session send <id> <message> Send message to a session (--wait, --response, --btw)
1353
+ svamp session query <dir> <prompt> Stateless one-shot: spawn \u2192 ask \u2192 answer \u2192 delete
1328
1354
  svamp session wait <id> Wait for agent to become idle
1329
1355
  svamp session messages <id> Show message history (--last N, --json, --raw)
1330
1356
  svamp session info <id> Show session status & pending permissions
@@ -1403,7 +1429,7 @@ async function applyClaudeAuthFlags(argv) {
1403
1429
  "--use-hypha-proxy, --use-claude-login, and --anthropic-base-url/--anthropic-api-key are mutually exclusive"
1404
1430
  );
1405
1431
  }
1406
- const mod = await import('./run-DZq12r28.mjs').then(function (n) { return n.t; });
1432
+ const mod = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.t; });
1407
1433
  if (hasHypha) {
1408
1434
  mod.setClaudeAuthHyphaProxy();
1409
1435
  console.log("Claude auth configured: hypha-proxy (uses HYPHA_TOKEN live at each spawn).");
@@ -1441,7 +1467,7 @@ async function applyDaemonShareFlag(argv) {
1441
1467
  }
1442
1468
  }
1443
1469
  if (collected.length === 0) return;
1444
- const { updateEnvFile } = await import('./run-DZq12r28.mjs').then(function (n) { return n.t; });
1470
+ const { updateEnvFile } = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.t; });
1445
1471
  const seen = /* @__PURE__ */ new Set();
1446
1472
  const deduped = collected.filter((e) => {
1447
1473
  const k = e.toLowerCase();
@@ -1454,7 +1480,7 @@ async function applyDaemonShareFlag(argv) {
1454
1480
  }
1455
1481
  async function handleDaemonAuthCommand(argv) {
1456
1482
  const sub = (argv[0] || "status").toLowerCase();
1457
- const mod = await import('./run-DZq12r28.mjs').then(function (n) { return n.t; });
1483
+ const mod = await import('./run-BqAe7GgA.mjs').then(function (n) { return n.t; });
1458
1484
  if (sub === "--help" || sub === "-h" || sub === "help") {
1459
1485
  console.log(`
1460
1486
  svamp daemon auth \u2014 Configure how Claude subprocesses authenticate
@@ -1520,9 +1546,8 @@ svamp session \u2014 Spawn and manage AI agent sessions
1520
1546
 
1521
1547
  QUICK START \u2014 Spawn a session, give it a task, get results:
1522
1548
 
1523
- # One-liner: spawn agent, send task, wait for completion
1524
- svamp session spawn claude -d ./my-project -p bypassPermissions \\
1525
- --message "fix the failing tests" --wait
1549
+ # One-liner: spawn agent, send task, wait for completion (autonomous by default)
1550
+ svamp session spawn claude -d ./my-project --message "fix the failing tests" --wait
1526
1551
 
1527
1552
  # The command prints the session ID (e.g., "abc12345-..."). Use it to:
1528
1553
  svamp session messages abc1 --last 10 # read output (prefix match on ID)
@@ -1553,8 +1578,24 @@ COMMANDS:
1553
1578
  info <id> [--json] Show status & pending permissions
1554
1579
 
1555
1580
  Communicate:
1556
- send <id> <message> [--wait] [--timeout N] [--json]
1557
- Send a message to a running session
1581
+ send <id> <message> [--wait] [--response] [--btw] [--require-approval] [--timeout N] [--json]
1582
+ Send a message to a running session.
1583
+ --wait block until the agent goes idle
1584
+ --response block AND print the agent's
1585
+ text answer (implies --wait)
1586
+ --btw side-channel one-shot query via
1587
+ /btw \u2014 does NOT touch the
1588
+ running session's context window
1589
+ --require-approval do NOT pre-flight the target to
1590
+ bypassPermissions. Without this,
1591
+ send with --wait/--response auto-
1592
+ ensures bypass so the agent does
1593
+ not stall on tool prompts.
1594
+ query <directory> <prompt> [--timeout N] [--keep] [--json] [--permission-mode MODE] [--tag NAME]
1595
+ Stateless one-shot: spawn fresh Claude in
1596
+ <directory>, send <prompt>, print answer,
1597
+ delete the session. No existing session is
1598
+ affected. Use for reproducible Q&A.
1558
1599
  messages <id> [--last N] [--json] Read message history (alias: msgs)
1559
1600
  wait <id> [--timeout N] [--json] Wait for agent to become idle
1560
1601
  attach <id> Attach interactive terminal (stdin/stdout)
@@ -1583,7 +1624,9 @@ COMMANDS:
1583
1624
 
1584
1625
  SPAWN OPTIONS:
1585
1626
  -d, --directory <path> Working directory (REQUIRED for meaningful work)
1586
- -p, --permission-mode <mode> Permission mode (see below). Default: "default"
1627
+ -p, --permission-mode <mode> Permission mode (see below). Default: "bypassPermissions"
1628
+ --require-approval Opt into human-in-the-loop approval (alias for -p default).
1629
+ Without this flag, the agent runs autonomously.
1587
1630
  --message <msg> Send this message to the agent immediately after spawn
1588
1631
  --wait Block until agent finishes (idle). Combine with --message
1589
1632
  for fire-and-forget: spawn \u2192 task \u2192 wait \u2192 done.
@@ -1593,15 +1636,14 @@ SPAWN OPTIONS:
1593
1636
  --parent <sessionId> Set parent session (auto-set from SVAMP_SESSION_ID env)
1594
1637
 
1595
1638
  PERMISSION MODES:
1639
+ bypassPermissions \u2605 Default. Auto-approve everything. No prompts, no pauses.
1640
+ Right choice for automation, CI, agent-spawning-agent.
1641
+ acceptEdits Auto-approve file edits. Still pauses for bash & dangerous tools.
1596
1642
  default \u26A0 Agent PAUSES and waits for human approval before each tool use.
1597
1643
  The agent will be stuck (exit code 2) until you run approve/deny.
1598
- DO NOT use default mode in automated pipelines \u2014 the agent will hang.
1599
- acceptEdits Auto-approve file edits. Still pauses for bash & dangerous tools.
1600
- bypassPermissions Auto-approve everything. No prompts, no pauses. Fully autonomous.
1601
- Use this for automation, CI, or when spawning from another agent.
1644
+ Use only when a human is actively watching the session.
1602
1645
 
1603
- \u26A1 For agents/scripts: ALWAYS pass -p bypassPermissions unless you have a human
1604
- monitoring the session who can approve/deny tool requests in real time.
1646
+ Tip: pass --require-approval (or -p default) when you want a human gate.
1605
1647
 
1606
1648
  PERMISSION WORKFLOW (only relevant for "default" and "acceptEdits" modes):
1607
1649
  1. svamp session wait <id> --json \u2192 exit code 2 means permission pending
@@ -1652,32 +1694,32 @@ ID MATCHING:
1652
1694
  EXAMPLES:
1653
1695
 
1654
1696
  # === Common: Spawn agent to do a task and wait ===
1655
- svamp session spawn claude -d ./my-project -p bypassPermissions \\
1697
+ # Default is bypassPermissions \u2014 no -p flag needed for autonomous runs.
1698
+ svamp session spawn claude -d ./my-project \\
1656
1699
  --message "fix all TypeScript errors, run tsc to verify" --wait
1657
1700
 
1658
1701
  # === Multi-step: Spawn, then send messages interactively ===
1659
- ID=$(svamp session spawn claude -d ./proj -p bypassPermissions)
1702
+ ID=$(svamp session spawn claude -d ./proj)
1660
1703
  svamp session send $ID "first, read the README" --wait
1661
1704
  svamp session send $ID "now implement the feature described there" --wait
1662
1705
  svamp session messages $ID --last 20
1663
1706
 
1664
1707
  # === Spawn child session from another agent (e.g., in a bash tool) ===
1665
- # Use -p bypassPermissions so the child doesn't get stuck on approvals.
1666
- # Use --wait so your script blocks until the child finishes.
1667
- svamp session spawn claude -d /tmp/test-project -p bypassPermissions \\
1708
+ # bypassPermissions is the default; --wait blocks until done.
1709
+ svamp session spawn claude -d /tmp/test-project \\
1668
1710
  --message "run the test suite and report results" --wait
1669
- # Then read the child's output:
1670
1711
  svamp session messages <child-id> --last 5
1671
1712
 
1672
- # === Monitor with permissions (default mode) ===
1673
- svamp session spawn claude -d ./proj --message "refactor auth module"
1713
+ # === Human-in-the-loop: require approval for every tool ===
1714
+ svamp session spawn claude -d ./proj --require-approval \\
1715
+ --message "refactor auth module"
1674
1716
  svamp session wait abc1 --json # exit code 2 = permission pending
1675
1717
  svamp session approve abc1 # approve all pending
1676
1718
  svamp session wait abc1 # wait for completion
1677
1719
 
1678
1720
  # === Spawn on a remote machine ===
1679
1721
  svamp session spawn claude -d /workspace -m my-cloud-box \\
1680
- -p bypassPermissions --message "deploy to staging" --wait
1722
+ --message "deploy to staging" --wait
1681
1723
 
1682
1724
  # === Isolated session with network restrictions ===
1683
1725
  svamp session spawn claude -d /tmp/sandbox --isolate --deny-network
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from 'node:fs';
2
2
  import { execSync } from 'node:child_process';
3
3
  import { resolve, join } from 'node:path';
4
4
  import os from 'node:os';
5
- import { n as normalizeAllowedUser, l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha, i as buildSessionShareUrl, j as buildMachineShareUrl } from './run-DZq12r28.mjs';
5
+ import { n as normalizeAllowedUser, l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha, i as buildSessionShareUrl, j as buildMachineShareUrl } from './run-BqAe7GgA.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -73,7 +73,10 @@ function formatJson(data) {
73
73
 
74
74
  const SESSION_RPC_PARAMS = {
75
75
  getMessages: ["afterSeq", "limit"],
76
+ getMessageCount: [],
77
+ getLatestMessages: ["beforeSeq", "limit"],
76
78
  sendMessage: ["content", "localId", "meta"],
79
+ btw: ["question"],
77
80
  getMetadata: [],
78
81
  updateMetadata: ["newMetadata", "expectedVersion"],
79
82
  updateConfig: ["patch"],
@@ -97,6 +100,7 @@ const SESSION_RPC_PARAMS = {
97
100
  getEffectiveRole: [],
98
101
  updateSharing: ["newSharing"],
99
102
  updateSecurityContext: ["newSecurityContext"],
103
+ setClaudeChrome: ["enabled"],
100
104
  applySystemPrompt: ["prompt"],
101
105
  sendInboxMessage: ["message"],
102
106
  getInbox: ["opts"],
@@ -1001,10 +1005,10 @@ async function sessionSpawn(agent, directory, machineId, opts) {
1001
1005
  if (result.type === "success") {
1002
1006
  console.log(`Session started: ${result.sessionId}`);
1003
1007
  if (result.message) console.log(` ${result.message}`);
1004
- const effectivePermMode = opts?.permissionMode || "default";
1005
- if (effectivePermMode !== "bypassPermissions") {
1006
- console.log(`\x1B[33m\u26A0 Permission mode: ${effectivePermMode}. Agent may pause for tool approval.\x1B[0m`);
1007
- console.log(`\x1B[33m Use -p bypassPermissions to run without approval prompts.\x1B[0m`);
1008
+ const explicitPermMode = opts?.permissionMode;
1009
+ if (explicitPermMode && explicitPermMode !== "bypassPermissions") {
1010
+ console.log(`\x1B[33m\u26A0 Permission mode: ${explicitPermMode}. Agent will pause for tool approval.\x1B[0m`);
1011
+ console.log(`\x1B[33m Use \`svamp session approve <id>\` to unblock, or drop the flag to run autonomously.\x1B[0m`);
1008
1012
  }
1009
1013
  if (opts?.message && result.sessionId) {
1010
1014
  const svc = getSessionProxy(machine, result.sessionId);
@@ -1357,63 +1361,356 @@ async function sessionAttach(sessionId, machineId) {
1357
1361
  process.exit(0);
1358
1362
  });
1359
1363
  }
1364
+ async function snapshotLatestSeq(machine, fullId) {
1365
+ try {
1366
+ const r = await machine.sessionRPC(fullId, "getMessageCount", {});
1367
+ return Math.max(0, Number(r?.latestSeq ?? 0));
1368
+ } catch {
1369
+ try {
1370
+ const r = await machine.sessionRPC(fullId, "getLatestMessages", { limit: 1 });
1371
+ const msgs = r?.messages || [];
1372
+ return msgs.length > 0 ? Number(msgs[msgs.length - 1].seq || 0) : 0;
1373
+ } catch {
1374
+ return 0;
1375
+ }
1376
+ }
1377
+ }
1378
+ async function collectAssistantResponse(machine, fullId, afterSeq) {
1379
+ const pageLimit = 500;
1380
+ let cursor = afterSeq;
1381
+ const collected = [];
1382
+ const seqs = [];
1383
+ for (let i = 0; i < 20; i++) {
1384
+ const { messages, hasMore } = await machine.sessionRPC(
1385
+ fullId,
1386
+ "getMessages",
1387
+ { afterSeq: cursor, limit: pageLimit }
1388
+ );
1389
+ if (!messages || messages.length === 0) break;
1390
+ for (const msg of messages) {
1391
+ const role = msg?.content?.role;
1392
+ if (role === "agent" || role === "assistant") {
1393
+ const data = msg.content?.content?.data || msg.content?.content;
1394
+ if (!data) continue;
1395
+ let blocks = null;
1396
+ if (data.type === "assistant") {
1397
+ const b = data.message?.content || data.content;
1398
+ blocks = Array.isArray(b) ? b : null;
1399
+ } else if (data.type === "output" && data.data?.type === "assistant") {
1400
+ const b = data.data.message?.content || data.data.content;
1401
+ blocks = Array.isArray(b) ? b : null;
1402
+ }
1403
+ if (blocks) {
1404
+ for (const block of blocks) {
1405
+ if (block.type === "text" && typeof block.text === "string" && block.text) {
1406
+ collected.push(block.text);
1407
+ if (!seqs.includes(msg.seq)) seqs.push(msg.seq);
1408
+ }
1409
+ }
1410
+ } else if (data.type === "result" && typeof data.result === "string" && data.result) {
1411
+ collected.push(data.result);
1412
+ if (!seqs.includes(msg.seq)) seqs.push(msg.seq);
1413
+ } else if (data.type === "output" && data.data?.type === "result" && typeof data.data.result === "string" && data.data.result) {
1414
+ collected.push(data.data.result);
1415
+ if (!seqs.includes(msg.seq)) seqs.push(msg.seq);
1416
+ }
1417
+ }
1418
+ cursor = Math.max(cursor, Number(msg.seq || 0));
1419
+ }
1420
+ if (!hasMore) break;
1421
+ }
1422
+ return { text: collected.join("\n").trim(), messageSeqs: seqs };
1423
+ }
1424
+ function validateSendOptions(opts) {
1425
+ if (!opts?.btw) return [];
1426
+ const incompatible = [];
1427
+ if (opts.subject) incompatible.push("--subject");
1428
+ if (opts.urgency) incompatible.push("--urgency");
1429
+ if (opts.wait) incompatible.push("--wait");
1430
+ if (opts.response) incompatible.push("--response");
1431
+ return incompatible;
1432
+ }
1433
+ async function sendCore(machine, fullId, message, opts) {
1434
+ if (opts?.btw) {
1435
+ const btwResult = await machine.sessionRPC(fullId, "btw", { question: message });
1436
+ if (!btwResult?.success) {
1437
+ return {
1438
+ sessionId: fullId,
1439
+ mode: "btw",
1440
+ sent: false,
1441
+ waited: false,
1442
+ status: "error",
1443
+ error: btwResult?.error || "btw failed"
1444
+ };
1445
+ }
1446
+ return {
1447
+ sessionId: fullId,
1448
+ mode: "btw",
1449
+ sent: true,
1450
+ waited: true,
1451
+ status: "idle",
1452
+ response: String(btwResult.answer || "")
1453
+ };
1454
+ }
1455
+ const wantResponse = !!opts?.response;
1456
+ const shouldWait = !!opts?.wait || wantResponse;
1457
+ let bypassEnsured = false;
1458
+ if (shouldWait && !opts?.requireApproval) {
1459
+ try {
1460
+ await machine.sessionRPC(fullId, "switchMode", { mode: "bypassPermissions" });
1461
+ bypassEnsured = true;
1462
+ } catch {
1463
+ }
1464
+ }
1465
+ const preSeq = wantResponse ? await snapshotLatestSeq(machine, fullId) : 0;
1466
+ const { randomUUID } = await import('node:crypto');
1467
+ const inboxMessage = {
1468
+ messageId: randomUUID(),
1469
+ body: message,
1470
+ timestamp: Date.now(),
1471
+ read: false,
1472
+ from: `cli:${os.userInfo().username}`,
1473
+ to: fullId,
1474
+ subject: opts?.subject,
1475
+ urgency: opts?.urgency || "urgent"
1476
+ };
1477
+ const result = await machine.sessionRPC(fullId, "sendInboxMessage", { message: inboxMessage });
1478
+ let waitResult;
1479
+ if (shouldWait) {
1480
+ const timeoutMs = (opts?.timeout || 300) * 1e3;
1481
+ waitResult = await waitForBusyThenIdle(machine, fullId, timeoutMs);
1482
+ }
1483
+ if (waitResult?.pendingPermissions?.length) {
1484
+ return {
1485
+ sessionId: fullId,
1486
+ mode: "send",
1487
+ sent: true,
1488
+ messageId: result.messageId,
1489
+ waited: true,
1490
+ status: "permission-pending",
1491
+ pendingPermissions: waitResult.pendingPermissions,
1492
+ bypassEnsured
1493
+ };
1494
+ }
1495
+ let response;
1496
+ if (wantResponse) {
1497
+ response = await collectAssistantResponse(machine, fullId, preSeq);
1498
+ }
1499
+ return {
1500
+ sessionId: fullId,
1501
+ mode: "send",
1502
+ sent: true,
1503
+ messageId: result.messageId,
1504
+ waited: shouldWait,
1505
+ status: shouldWait ? "idle" : "sent",
1506
+ bypassEnsured,
1507
+ ...wantResponse && response ? { response: response.text, responseSeqs: response.messageSeqs } : {}
1508
+ };
1509
+ }
1360
1510
  async function sessionSend(sessionId, message, machineId, opts) {
1511
+ const incompatible = validateSendOptions(opts);
1512
+ if (incompatible.length) {
1513
+ console.error(`Error: --btw is incompatible with: ${incompatible.join(", ")}`);
1514
+ console.error(" --btw runs as a one-shot forked query that returns the answer directly.");
1515
+ process.exit(1);
1516
+ }
1361
1517
  const { server, machine, fullId } = await connectAndResolveSession(sessionId, machineId);
1362
1518
  try {
1363
- const { randomUUID } = await import('node:crypto');
1364
- const inboxMessage = {
1365
- messageId: randomUUID(),
1366
- body: message,
1367
- timestamp: Date.now(),
1368
- read: false,
1369
- from: `cli:${os.userInfo().username}`,
1370
- to: fullId,
1371
- subject: opts?.subject,
1372
- urgency: opts?.urgency || "urgent"
1373
- };
1374
- const result = await machine.sessionRPC(fullId, "sendInboxMessage", { message: inboxMessage });
1375
- let waitResult;
1376
- if (opts?.wait) {
1377
- const timeoutMs = (opts.timeout || 300) * 1e3;
1378
- waitResult = await waitForBusyThenIdle(machine, fullId, timeoutMs);
1519
+ const r = await sendCore(machine, fullId, message, opts);
1520
+ if (r.mode === "btw") {
1521
+ if (r.status === "error") {
1522
+ if (opts?.json) {
1523
+ console.log(formatJson({
1524
+ sessionId: r.sessionId,
1525
+ mode: "btw",
1526
+ message,
1527
+ success: false,
1528
+ error: r.error
1529
+ }));
1530
+ } else {
1531
+ console.error(`btw failed: ${r.error || "unknown error"}`);
1532
+ }
1533
+ process.exitCode = 1;
1534
+ return;
1535
+ }
1536
+ if (opts?.json) {
1537
+ console.log(formatJson({
1538
+ sessionId: r.sessionId,
1539
+ mode: "btw",
1540
+ message,
1541
+ success: true,
1542
+ response: r.response || ""
1543
+ }));
1544
+ } else if (r.response) {
1545
+ console.log(r.response);
1546
+ }
1547
+ return;
1379
1548
  }
1380
- if (waitResult?.pendingPermissions?.length) {
1549
+ if (r.status === "permission-pending") {
1381
1550
  if (opts?.json) {
1382
1551
  console.log(formatJson({
1383
- sessionId: fullId,
1552
+ sessionId: r.sessionId,
1384
1553
  message,
1385
1554
  sent: true,
1386
- messageId: result.messageId,
1555
+ messageId: r.messageId,
1387
1556
  status: "permission-pending",
1388
- pendingPermissions: waitResult.pendingPermissions
1557
+ pendingPermissions: r.pendingPermissions
1389
1558
  }));
1390
1559
  } else {
1391
- console.log(`Message sent to session ${fullId.slice(0, 8)} (id: ${result.messageId.slice(0, 8)})`);
1560
+ console.log(`Message sent to session ${r.sessionId.slice(0, 8)} (id: ${(r.messageId || "").slice(0, 8)})`);
1392
1561
  console.log("Agent is waiting for permission approval:");
1393
- for (const p of waitResult.pendingPermissions) {
1562
+ for (const p of r.pendingPermissions || []) {
1394
1563
  const argsStr = JSON.stringify(p.arguments || {}).slice(0, 120);
1395
1564
  console.log(` [${p.id.slice(0, 8)}] ${p.tool}(${argsStr})`);
1396
1565
  }
1397
1566
  console.log(`
1398
- Use: svamp session approve ${fullId.slice(0, 8)}`);
1567
+ Use: svamp session approve ${r.sessionId.slice(0, 8)}`);
1399
1568
  }
1400
1569
  process.exitCode = 2;
1401
- } else if (opts?.json) {
1570
+ return;
1571
+ }
1572
+ if (opts?.json) {
1402
1573
  console.log(formatJson({
1403
- sessionId: fullId,
1574
+ sessionId: r.sessionId,
1404
1575
  message,
1405
1576
  sent: true,
1406
- messageId: result.messageId,
1407
- waited: !!opts.wait,
1408
- status: opts.wait ? "idle" : "sent"
1577
+ messageId: r.messageId,
1578
+ waited: r.waited,
1579
+ status: r.status,
1580
+ ...r.bypassEnsured ? { bypassEnsured: true } : {},
1581
+ ...opts.response ? { response: r.response || "", responseSeqs: r.responseSeqs || [] } : {}
1409
1582
  }));
1410
1583
  } else {
1411
- console.log(`Message sent to session ${fullId.slice(0, 8)} (id: ${result.messageId.slice(0, 8)})`);
1412
- if (opts?.wait) {
1584
+ console.log(`Message sent to session ${r.sessionId.slice(0, 8)} (id: ${(r.messageId || "").slice(0, 8)})`);
1585
+ if (r.waited) {
1413
1586
  console.log("Agent is idle.");
1414
1587
  }
1588
+ if (opts?.response) {
1589
+ if (r.response) {
1590
+ console.log("");
1591
+ console.log(r.response);
1592
+ } else {
1593
+ console.log("(no text response captured)");
1594
+ }
1595
+ }
1596
+ }
1597
+ } finally {
1598
+ await server.disconnect();
1599
+ }
1600
+ }
1601
+ async function queryCore(machine, directory, prompt, opts) {
1602
+ const absDir = resolve(directory);
1603
+ const spawnOpts = {
1604
+ directory: absDir,
1605
+ agent: "claude",
1606
+ permissionMode: opts?.permissionMode || "bypassPermissions",
1607
+ tags: opts?.tag ? [opts.tag] : ["svamp-query"]
1608
+ };
1609
+ const spawn = await machine.spawnSession(spawnOpts);
1610
+ if (spawn.type !== "success" || !spawn.sessionId) {
1611
+ return {
1612
+ sessionId: "",
1613
+ mode: "query",
1614
+ sent: false,
1615
+ waited: false,
1616
+ status: "error",
1617
+ error: spawn.errorMessage || `spawn returned type=${spawn.type}`,
1618
+ directory: absDir
1619
+ };
1620
+ }
1621
+ const spawnedId = spawn.sessionId;
1622
+ const svc = getSessionProxy(machine, spawnedId);
1623
+ await svc.sendMessage(
1624
+ JSON.stringify({
1625
+ role: "user",
1626
+ content: { type: "text", text: prompt },
1627
+ meta: { sentFrom: "svamp-cli-query" }
1628
+ })
1629
+ );
1630
+ const timeoutMs = (opts?.timeout || 300) * 1e3;
1631
+ const waitResult = await waitForBusyThenIdle(machine, spawnedId, timeoutMs);
1632
+ if (waitResult.pendingPermissions?.length) {
1633
+ return {
1634
+ sessionId: spawnedId,
1635
+ mode: "query",
1636
+ sent: true,
1637
+ waited: true,
1638
+ status: "permission-pending",
1639
+ pendingPermissions: waitResult.pendingPermissions,
1640
+ error: `Agent paused for tool approval (${waitResult.pendingPermissions.length} pending). Pass --permission-mode bypassPermissions or approve the request manually.`,
1641
+ directory: absDir
1642
+ };
1643
+ }
1644
+ const response = await collectAssistantResponse(machine, spawnedId, 0);
1645
+ return {
1646
+ sessionId: spawnedId,
1647
+ mode: "query",
1648
+ sent: true,
1649
+ waited: true,
1650
+ status: "idle",
1651
+ response: response.text,
1652
+ responseSeqs: response.messageSeqs,
1653
+ directory: absDir
1654
+ };
1655
+ }
1656
+ async function sessionQuery(directory, prompt, machineId, opts) {
1657
+ const { server, machine } = await connectAndGetMachine(machineId);
1658
+ let spawnedId;
1659
+ try {
1660
+ const r = await queryCore(machine, directory, prompt, opts);
1661
+ spawnedId = r.sessionId || void 0;
1662
+ if (r.status === "error") {
1663
+ if (opts?.json) {
1664
+ console.log(formatJson({
1665
+ success: false,
1666
+ error: r.error,
1667
+ directory: r.directory
1668
+ }));
1669
+ } else {
1670
+ console.error(`Failed to spawn query session: ${r.error}`);
1671
+ }
1672
+ process.exitCode = 1;
1673
+ return;
1674
+ }
1675
+ if (r.status === "permission-pending") {
1676
+ if (opts?.json) {
1677
+ console.log(formatJson({
1678
+ success: false,
1679
+ sessionId: r.sessionId,
1680
+ directory: r.directory,
1681
+ error: r.error,
1682
+ pendingPermissions: r.pendingPermissions
1683
+ }));
1684
+ } else {
1685
+ console.error(r.error);
1686
+ }
1687
+ process.exitCode = 2;
1688
+ return;
1689
+ }
1690
+ if (opts?.json) {
1691
+ console.log(formatJson({
1692
+ success: true,
1693
+ sessionId: r.sessionId,
1694
+ directory: r.directory,
1695
+ prompt,
1696
+ response: r.response || "",
1697
+ responseSeqs: r.responseSeqs || []
1698
+ }));
1699
+ } else {
1700
+ if (r.response) {
1701
+ console.log(r.response);
1702
+ } else {
1703
+ console.log("(no text response captured)");
1704
+ }
1415
1705
  }
1416
1706
  } finally {
1707
+ if (spawnedId && !opts?.keep) {
1708
+ try {
1709
+ await machine.deleteSession(spawnedId);
1710
+ } catch (err) {
1711
+ console.error(`Warning: failed to delete query session ${spawnedId}: ${err?.message || err}`);
1712
+ }
1713
+ }
1417
1714
  await server.disconnect();
1418
1715
  }
1419
1716
  }
@@ -1924,4 +2221,4 @@ async function sessionInboxClear(sessionIdPartial, machineId, opts) {
1924
2221
  }
1925
2222
  }
1926
2223
 
1927
- export { connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, machineExec, machineInfo, machineLs, machineShare, parseShareArg, renderMessage, resolveSessionId, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionMachines, sessionMessages, sessionRalphCancel, sessionRalphStart, sessionRalphStatus, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionWait };
2224
+ export { collectAssistantResponse, connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, machineExec, machineInfo, machineLs, machineShare, parseShareArg, queryCore, renderMessage, resolveSessionId, sendCore, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionMachines, sessionMessages, sessionQuery, sessionRalphCancel, sessionRalphStart, sessionRalphStatus, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionWait, snapshotLatestSeq, validateSendOptions };
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-BO8gl_-u.mjs';
3
+ import { connectAndGetMachine } from './commands-BMOelGYC.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:child_process';
6
6
  import 'node:path';
7
7
  import 'node:os';
8
- import './run-DZq12r28.mjs';
8
+ import './run-BqAe7GgA.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
@@ -68,7 +68,7 @@ async function serviceExpose(args) {
68
68
  });
69
69
  return;
70
70
  }
71
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
71
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
72
72
  const { server, machine } = await connectAndGetMachine();
73
73
  try {
74
74
  const status = await machine.tunnelStart({
@@ -132,7 +132,7 @@ async function serviceServe(args) {
132
132
  }
133
133
  async function serviceList(_args) {
134
134
  try {
135
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
135
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
136
136
  const { server, machine } = await connectAndGetMachine();
137
137
  try {
138
138
  const tunnels = await machine.tunnelList({});
@@ -161,7 +161,7 @@ async function serviceDelete(args) {
161
161
  process.exit(1);
162
162
  }
163
163
  try {
164
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
164
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
165
165
  const { server, machine } = await connectAndGetMachine();
166
166
  try {
167
167
  await machine.tunnelStop({ name });
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-DZq12r28.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-BqAe7GgA.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.2.67";
2
+ var version = "0.2.70";
3
3
  var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
4
4
  var author = "Amun AI AB";
5
5
  var license = "SEE LICENSE IN LICENSE";
@@ -19,12 +19,11 @@ var exports$1 = {
19
19
  var scripts = {
20
20
  build: "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && tsc --noEmit && pkgroll",
21
21
  typecheck: "tsc --noEmit",
22
- test: "npx tsx test/test-context-window.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only",
22
+ test: "npx tsx test/test-context-window.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only",
23
23
  "test:hypha": "node --no-warnings test/test-hypha-service.mjs",
24
24
  dev: "tsx src/cli.ts",
25
25
  "dev:daemon": "tsx src/cli.ts daemon start-sync",
26
26
  "test:e2e": "node --no-warnings test/e2e-session-tests.mjs",
27
- "test:archive-resume": "node --no-warnings test/test-session-archive-resume.mjs",
28
27
  "test:frpc": "npx tsx test/test-frpc-e2e.mjs"
29
28
  };
30
29
  var dependencies = {
@@ -1140,9 +1140,10 @@ async function registerMachineService(server, machineId, metadata, daemonState,
1140
1140
  const { join: join2, resolve } = await import('path');
1141
1141
  const { homedir } = await import('os');
1142
1142
  const targetPath = resolve(path || homedir());
1143
+ const effectiveRole = getEffectiveRole(context, currentMetadata.sharing);
1143
1144
  const home = homedir();
1144
- const isOwner = !currentMetadata.sharing?.enabled || context?.user?.email && currentMetadata.sharing.owner && context.user.email.toLowerCase() === currentMetadata.sharing.owner.toLowerCase();
1145
- if (!isOwner && targetPath !== home && !targetPath.startsWith(home + "/")) {
1145
+ const restrictedToHome = effectiveRole === "view";
1146
+ if (restrictedToHome && targetPath !== home && !targetPath.startsWith(home + "/")) {
1146
1147
  throw new Error(`Access denied: path must be within ${home}`);
1147
1148
  }
1148
1149
  const showHidden = options?.showHidden ?? false;
@@ -2116,6 +2117,22 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
2116
2117
  });
2117
2118
  return await callbacks.onUpdateSecurityContext(resolvedContext);
2118
2119
  },
2120
+ /** Toggle the Claude --chrome flag and restart the agent process.
2121
+ * Admin tier (owner or admin-shared user) can perform this. */
2122
+ setClaudeChrome: async (enabled, context) => {
2123
+ authorizeRequest(context, metadata.sharing, "admin");
2124
+ if (!callbacks.onSetClaudeChrome) {
2125
+ throw new Error("Chrome integration toggle is not supported for this session");
2126
+ }
2127
+ metadata = { ...metadata, claudeChrome: !!enabled };
2128
+ metadataVersion++;
2129
+ notifyListeners({
2130
+ type: "update-session",
2131
+ sessionId,
2132
+ metadata: { value: metadata, version: metadataVersion }
2133
+ });
2134
+ return await callbacks.onSetClaudeChrome(!!enabled);
2135
+ },
2119
2136
  /** Apply a new system prompt and restart the agent process */
2120
2137
  applySystemPrompt: async (prompt, context) => {
2121
2138
  authorizeRequest(context, metadata.sharing, "admin");
@@ -2248,6 +2265,8 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
2248
2265
  claudeSessionId,
2249
2266
  "--fork-session",
2250
2267
  "--no-session-persistence",
2268
+ "--permission-mode",
2269
+ "bypassPermissions",
2251
2270
  "--output-format",
2252
2271
  "json",
2253
2272
  "--max-turns",
@@ -5737,6 +5756,19 @@ btn.addEventListener('click', async () => {
5737
5756
  return;
5738
5757
  }
5739
5758
 
5759
+ // Open the popup SYNCHRONOUSLY inside the click handler so the browser's
5760
+ // popup blocker treats it as user-initiated. The hypha SDK awaits a
5761
+ // network round-trip before invoking login_callback, by which time the
5762
+ // user-gesture flag has cleared and any window.open() call is silently
5763
+ // blocked \u2014 especially inside sandboxed iframes (canvas, artifact view).
5764
+ // We point it at about:blank first and rewrite the URL once we have it.
5765
+ const popup = window.open('about:blank', '_blank');
5766
+ if (!popup) {
5767
+ setError('Popup was blocked by the browser. Please allow popups for this site and retry.');
5768
+ return;
5769
+ }
5770
+ try { popup.document.write('<html><body style="font-family:system-ui;padding:24px;color:#656d76">Opening Hypha sign-in\u2026</body></html>'); } catch (e) {}
5771
+
5740
5772
  btn.disabled = true;
5741
5773
  statusEl.textContent = 'Opening Hypha sign-in\u2026';
5742
5774
 
@@ -5745,10 +5777,8 @@ btn.addEventListener('click', async () => {
5745
5777
  server_url: hyphaServer,
5746
5778
  login_callback: (context) => {
5747
5779
  statusEl.textContent = 'Waiting for you to sign in\u2026';
5748
- // Open the login URL in a new tab. Called synchronously from
5749
- // inside the SDK's login() after the user's button click, so
5750
- // popup blockers generally allow it.
5751
- window.open(context.login_url, '_blank');
5780
+ try { popup.location.href = context.login_url; }
5781
+ catch (e) { window.open(context.login_url, '_blank'); }
5752
5782
  },
5753
5783
  });
5754
5784
 
@@ -5758,9 +5788,11 @@ btn.addEventListener('click', async () => {
5758
5788
  const secure = location.protocol === 'https:' ? '; Secure' : '';
5759
5789
  document.cookie = cookieName + '=' + token + '; path=/; SameSite=Lax' + secure;
5760
5790
 
5791
+ try { popup.close(); } catch (e) {}
5761
5792
  statusEl.innerHTML = '<span class="ok">Signed in. Redirecting\u2026</span>';
5762
5793
  setTimeout(() => { window.location.replace(redirectUrl); }, 300);
5763
5794
  } catch (err) {
5795
+ try { popup.close(); } catch (e) {}
5764
5796
  setError('Login failed: ' + (err && err.message ? err.message : err));
5765
5797
  }
5766
5798
  });
@@ -7816,7 +7848,7 @@ async function startDaemon(options) {
7816
7848
  const list = loadExposedTunnels().filter((t) => t.name !== name);
7817
7849
  saveExposedTunnels(list);
7818
7850
  }
7819
- const { ServeManager } = await import('./serveManager-D4f3wiSO.mjs');
7851
+ const { ServeManager } = await import('./serveManager-Dy4afaLH.mjs');
7820
7852
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
7821
7853
  ensureAutoInstalledSkills(logger).catch(() => {
7822
7854
  });
@@ -8010,13 +8042,14 @@ async function startDaemon(options) {
8010
8042
  const parentTracked = Array.from(pidToTrackedSession.values()).find((t) => t.svampSessionId === options2.parentSessionId);
8011
8043
  return parentTracked?.directory ? { parentSessionPath: parentTracked.directory } : {};
8012
8044
  })(),
8013
- ...options2.injectPlatformGuidance !== void 0 && { injectPlatformGuidance: options2.injectPlatformGuidance }
8045
+ ...options2.injectPlatformGuidance !== void 0 && { injectPlatformGuidance: options2.injectPlatformGuidance },
8046
+ ...options2.claudeChrome !== void 0 && { claudeChrome: options2.claudeChrome }
8014
8047
  };
8015
8048
  let claudeProcess = null;
8016
8049
  const allPersisted = loadPersistedSessions();
8017
8050
  const persisted = allPersisted.find((p) => p.sessionId === sessionId) || (resumeSessionId ? allPersisted.find((p) => p.claudeResumeId === resumeSessionId) : void 0);
8018
8051
  let claudeResumeId = persisted?.claudeResumeId || (resumeSessionId || void 0);
8019
- let currentPermissionMode = options2.permissionMode || persisted?.permissionMode || "default";
8052
+ let currentPermissionMode = options2.permissionMode || persisted?.permissionMode || "bypassPermissions";
8020
8053
  const sessionCreatedAt = persisted?.createdAt || Date.now();
8021
8054
  let lastSpawnMeta = persisted?.spawnMeta || {};
8022
8055
  let sessionWasProcessing = !!options2.wasProcessing;
@@ -8172,6 +8205,13 @@ async function startDaemon(options) {
8172
8205
  if (model) args.push("--model", model);
8173
8206
  if (appendSystemPrompt) args.push("--append-system-prompt", appendSystemPrompt);
8174
8207
  if (claudeResumeId) args.push("--resume", claudeResumeId);
8208
+ if (sessionMetadata.claudeChrome) {
8209
+ if (shouldIsolateSession()) {
8210
+ logger.log(`[Session ${sessionId}] claudeChrome=true but session is isolated; skipping --chrome (Chrome IPC not reachable from sandbox)`);
8211
+ } else {
8212
+ args.push("--chrome");
8213
+ }
8214
+ }
8175
8215
  if (!hookSettings) {
8176
8216
  try {
8177
8217
  hookSettings = generateHookSettings({ id: sessionId });
@@ -8988,6 +9028,11 @@ The automated loop has finished. Review the progress above and let me know if yo
8988
9028
  claudeResumeId,
8989
9029
  "--fork-session",
8990
9030
  "--no-session-persistence",
9031
+ // /btw is non-interactive; without bypass the
9032
+ // forked Claude pauses on tool prompts and the
9033
+ // user just sees a hanging side-channel.
9034
+ "--permission-mode",
9035
+ "bypassPermissions",
8991
9036
  "--output-format",
8992
9037
  "stream-json",
8993
9038
  "--verbose"
@@ -9122,6 +9167,9 @@ The automated loop has finished. Review the progress above and let me know if yo
9122
9167
  },
9123
9168
  onSwitchMode: async (mode) => {
9124
9169
  const normalizedMode = toClaudePermissionMode(mode);
9170
+ if (currentPermissionMode === normalizedMode) {
9171
+ return;
9172
+ }
9125
9173
  logger.log(`[Session ${sessionId}] Switch mode: ${mode}${mode !== normalizedMode ? ` \u2192 ${normalizedMode}` : ""}`);
9126
9174
  if (isRestartingClaude || isSwitchingMode) {
9127
9175
  logger.log(`[Session ${sessionId}] Switch mode deferred \u2014 restart/switch already in progress`);
@@ -9148,6 +9196,24 @@ The automated loop has finished. Review the progress above and let me know if yo
9148
9196
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
9149
9197
  return await restartClaudeHandler();
9150
9198
  },
9199
+ onSetClaudeChrome: async (enabled) => {
9200
+ logger.log(`[Session ${sessionId}] Chrome integration ${enabled ? "enabled" : "disabled"} \u2014 restarting agent`);
9201
+ sessionMetadata = { ...sessionMetadata, claudeChrome: enabled };
9202
+ if (claudeResumeId && !trackedSession.stopped) {
9203
+ saveSession({
9204
+ sessionId,
9205
+ directory,
9206
+ claudeResumeId,
9207
+ permissionMode: currentPermissionMode,
9208
+ spawnMeta: lastSpawnMeta,
9209
+ metadata: sessionMetadata,
9210
+ createdAt: sessionCreatedAt,
9211
+ machineId,
9212
+ wasProcessing: sessionWasProcessing
9213
+ });
9214
+ }
9215
+ return await restartClaudeHandler();
9216
+ },
9151
9217
  onSharingUpdate: (newSharing) => {
9152
9218
  logger.log(`[Session ${sessionId}] Sharing config updated \u2014 persisting to disk`);
9153
9219
  const oldSharing = sessionMetadata.sharing;
@@ -9190,7 +9256,6 @@ The automated loop has finished. Review the progress above and let me know if yo
9190
9256
  if (trackedSession?.stopped) return;
9191
9257
  logger.log(`[Session ${sessionId}] Inbox message received (urgency: ${message.urgency || "normal"}, from: ${message.from || "unknown"})`);
9192
9258
  const formatted = formatInboxMessageXml(message);
9193
- sessionService.markInboxRead(message.messageId);
9194
9259
  if (message.urgency === "urgent") {
9195
9260
  logger.log(`[Session ${sessionId}] Delivering urgent inbox message to agent`);
9196
9261
  sessionService.pushMessage(formatted, "user");
@@ -9540,7 +9605,7 @@ The automated loop has finished. Review the progress above and let me know if yo
9540
9605
  tags: options2.tags,
9541
9606
  parentSessionId: options2.parentSessionId
9542
9607
  };
9543
- let currentPermissionMode = options2.permissionMode || "default";
9608
+ let currentPermissionMode = options2.permissionMode || "bypassPermissions";
9544
9609
  const allowedTools = /* @__PURE__ */ new Set();
9545
9610
  const allowedBashLiterals = /* @__PURE__ */ new Set();
9546
9611
  const allowedBashPrefixes = /* @__PURE__ */ new Set();
@@ -9634,6 +9699,7 @@ The automated loop has finished. Review the progress above and let me know if yo
9634
9699
  agentBackend.respondToPermission?.(requestId, params.approved);
9635
9700
  },
9636
9701
  onSwitchMode: (mode) => {
9702
+ if (currentPermissionMode === mode) return;
9637
9703
  logger.log(`[${agentName} Session ${sessionId}] Switch mode: ${mode}`);
9638
9704
  currentPermissionMode = mode;
9639
9705
  },
@@ -9661,7 +9727,6 @@ The automated loop has finished. Review the progress above and let me know if yo
9661
9727
  if (acpStopped) return;
9662
9728
  logger.log(`[${agentName} Session ${sessionId}] Inbox message received (urgency: ${message.urgency || "normal"}, from: ${message.from || "unknown"})`);
9663
9729
  const formatted = formatInboxMessageXml(message);
9664
- sessionService.markInboxRead(message.messageId);
9665
9730
  if (message.urgency === "urgent" && acpBackendReady) {
9666
9731
  logger.log(`[${agentName} Session ${sessionId}] Delivering urgent inbox message to agent`);
9667
9732
  sessionService.pushMessage(formatted, "user");
@@ -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 { resolve, join } from 'node:path';
4
4
  import { existsSync, readFileSync, watch } from 'node:fs';
5
- import { c as connectToHypha, a as registerSessionService, k as generateHookSettings } from './run-DZq12r28.mjs';
5
+ import { c as connectToHypha, a as registerSessionService, k as generateHookSettings } from './run-BqAe7GgA.mjs';
6
6
  import { createServer } from 'node:http';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';
@@ -54,7 +54,7 @@ async function handleServeCommand() {
54
54
  }
55
55
  }
56
56
  async function serveAdd(args, machineId) {
57
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
57
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
58
58
  const pos = positionalArgs(args);
59
59
  const name = pos[0];
60
60
  if (!name) {
@@ -93,7 +93,7 @@ async function serveAdd(args, machineId) {
93
93
  }
94
94
  }
95
95
  async function serveApply(args, machineId) {
96
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
97
97
  const fs = await import('fs');
98
98
  const yaml = await import('yaml');
99
99
  const file = positionalArgs(args)[0];
@@ -182,7 +182,7 @@ async function serveApply(args, machineId) {
182
182
  }
183
183
  }
184
184
  async function serveRemove(args, machineId) {
185
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
185
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
186
186
  const pos = positionalArgs(args);
187
187
  const name = pos[0];
188
188
  if (!name) {
@@ -202,7 +202,7 @@ async function serveRemove(args, machineId) {
202
202
  }
203
203
  }
204
204
  async function serveList(args, machineId) {
205
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
205
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
206
206
  const all = hasFlag(args, "--all", "-a");
207
207
  const json = hasFlag(args, "--json");
208
208
  const sessionId = getFlag(args, "--session");
@@ -235,7 +235,7 @@ async function serveList(args, machineId) {
235
235
  }
236
236
  }
237
237
  async function serveInfo(machineId) {
238
- const { connectAndGetMachine } = await import('./commands-BO8gl_-u.mjs');
238
+ const { connectAndGetMachine } = await import('./commands-BMOelGYC.mjs');
239
239
  const { machine, server } = await connectAndGetMachine(machineId);
240
240
  try {
241
241
  const info = await machine.serveInfo();
@@ -4,7 +4,7 @@ import * as fs from 'fs';
4
4
  import * as http from 'http';
5
5
  import * as net from 'net';
6
6
  import * as path from 'path';
7
- import { S as ServeAuth, h as hasCookieToken } from './run-DZq12r28.mjs';
7
+ import { S as ServeAuth, h as hasCookieToken } from './run-BqAe7GgA.mjs';
8
8
  import 'os';
9
9
  import 'fs/promises';
10
10
  import 'url';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svamp-cli",
3
- "version": "0.2.67",
3
+ "version": "0.2.70",
4
4
  "description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
5
5
  "author": "Amun AI AB",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -20,12 +20,11 @@
20
20
  "scripts": {
21
21
  "build": "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && tsc --noEmit && pkgroll",
22
22
  "typecheck": "tsc --noEmit",
23
- "test": "npx tsx test/test-context-window.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only",
23
+ "test": "npx tsx test/test-context-window.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only",
24
24
  "test:hypha": "node --no-warnings test/test-hypha-service.mjs",
25
25
  "dev": "tsx src/cli.ts",
26
26
  "dev:daemon": "tsx src/cli.ts daemon start-sync",
27
27
  "test:e2e": "node --no-warnings test/e2e-session-tests.mjs",
28
- "test:archive-resume": "node --no-warnings test/test-session-archive-resume.mjs",
29
28
  "test:frpc": "npx tsx test/test-frpc-e2e.mjs"
30
29
  },
31
30
  "dependencies": {