svamp-cli 0.2.253 → 0.2.254

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.
Files changed (24) hide show
  1. package/dist/{agentCommands-DYoNzX4K.mjs → agentCommands-Dtd2mICX.mjs} +5 -5
  2. package/dist/{auth-D0nW0Gyj.mjs → auth-C5b7_Wpo.mjs} +1 -1
  3. package/dist/cli.mjs +70 -62
  4. package/dist/{commands-YPQSZ4Qx.mjs → commands-Bz3xxhDd.mjs} +23 -2
  5. package/dist/{commands-CfDWN8Ej.mjs → commands-CTwhZ-Sj.mjs} +2 -2
  6. package/dist/{commands-CvWkQB_c.mjs → commands-Ch_nKvnk.mjs} +1 -1
  7. package/dist/{commands-_Tr8pO3_.mjs → commands-D8gpDICH.mjs} +2 -2
  8. package/dist/{commands-C3YGnWyy.mjs → commands-DH1pGrZe.mjs} +1 -1
  9. package/dist/{commands-B9wShol7.mjs → commands-DI-5Eder.mjs} +1 -1
  10. package/dist/{commands-EhQiKpwu.mjs → commands-rLFKP45k.mjs} +6 -6
  11. package/dist/{fleet-Ndfbo8Ni.mjs → fleet-u7T-s_4u.mjs} +1 -1
  12. package/dist/{frpc-CLQB-GM1.mjs → frpc-BBkDE65f.mjs} +1 -1
  13. package/dist/{headlessCli-CbCWVR81.mjs → headlessCli-D7JwS_Bf.mjs} +2 -2
  14. package/dist/index.mjs +1 -1
  15. package/dist/{package-BTW_-LFn.mjs → package-QKAEHd-5.mjs} +1 -1
  16. package/dist/{rpc-0HSLhpCb.mjs → rpc-CMS1F7Qu.mjs} +1 -1
  17. package/dist/{rpc-BB-AxQa_.mjs → rpc-DTU-aE0V.mjs} +1 -1
  18. package/dist/{run-BtWV7xhR.mjs → run-BJYwPKDR.mjs} +1 -1
  19. package/dist/{run-hYUl-Fln.mjs → run-BqqMOMZN.mjs} +147 -23
  20. package/dist/{scheduler-DaFydJPf.mjs → scheduler-B92Z_kox.mjs} +1 -1
  21. package/dist/{serveCommands-BgtRllaY.mjs → serveCommands-BEJg71HK.mjs} +5 -5
  22. package/dist/{serveManager-BK5OjhXU.mjs → serveManager-BBRgdCJp.mjs} +2 -2
  23. package/dist/{sideband-C0qzprWp.mjs → sideband-c7SyYkOC.mjs} +1 -1
  24. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync } from '
2
2
  import { join, dirname } from 'node:path';
3
3
  import os from 'node:os';
4
4
  import { requireNotSandboxed } from './sandboxDetect-DNTcbgWD.mjs';
5
- import { k as shortId } from './run-hYUl-Fln.mjs';
5
+ import { k as shortId } from './run-BqqMOMZN.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -97,7 +97,7 @@ async function sessionSetTitle(title) {
97
97
  }
98
98
  async function sessionSetProjectDescription(description) {
99
99
  const dir = process.cwd();
100
- const { projectName, writeProjectInfo, sanitizeDescription, projectInfoPath } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.al; });
100
+ const { projectName, writeProjectInfo, sanitizeDescription, projectInfoPath } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.al; });
101
101
  const desc = sanitizeDescription(description, 240);
102
102
  if (!desc) {
103
103
  console.error("Project description is empty.");
@@ -344,7 +344,7 @@ async function sessionBroadcast(action, args) {
344
344
  console.log(`Broadcast sent: ${action}`);
345
345
  }
346
346
  async function connectToMachineService() {
347
- const { connectAndGetMachine } = await import('./commands-YPQSZ4Qx.mjs');
347
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.mjs');
348
348
  return connectAndGetMachine();
349
349
  }
350
350
  function buildInboxMessage(args) {
@@ -422,7 +422,7 @@ async function inboxSend(targetSessionId, opts) {
422
422
  console.error("Message body is required.");
423
423
  process.exit(1);
424
424
  }
425
- const { connectAndResolveSession } = await import('./commands-YPQSZ4Qx.mjs');
425
+ const { connectAndResolveSession } = await import('./commands-Bz3xxhDd.mjs');
426
426
  let server;
427
427
  try {
428
428
  const { targetId, messageId } = await inboxSendCore(
@@ -476,7 +476,7 @@ async function inboxReply(messageId, body) {
476
476
  console.error("SVAMP_SESSION_ID not set. This command must be run inside a Svamp session.");
477
477
  process.exit(1);
478
478
  }
479
- const { connectAndResolveSession } = await import('./commands-YPQSZ4Qx.mjs');
479
+ const { connectAndResolveSession } = await import('./commands-Bz3xxhDd.mjs');
480
480
  const { server: localServer, machine: localMachine } = await connectToMachineService();
481
481
  let localDisconnected = false;
482
482
  const disconnectLocal = async () => {
@@ -1,4 +1,4 @@
1
- import { a1 as resolveModel } from './run-hYUl-Fln.mjs';
1
+ import { a1 as resolveModel } from './run-BqqMOMZN.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { e as clearStopMarker, f as stopMarkerExists, s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-hYUl-Fln.mjs';
1
+ import { e as clearStopMarker, f as stopMarkerExists, s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-BqqMOMZN.mjs';
2
2
  import { ensureSupervisorViaServiceManager, LAUNCHD_LABEL } from './serviceManager-hlOVxkhW.mjs';
3
3
  import 'os';
4
4
  import 'fs/promises';
@@ -35,7 +35,7 @@ const subcommand = args[0];
35
35
  let daemonSubcommand = args[1];
36
36
  async function main() {
37
37
  try {
38
- const { getLoadedConfig } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ar; });
38
+ const { getLoadedConfig } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ar; });
39
39
  getLoadedConfig();
40
40
  } catch {
41
41
  }
@@ -54,7 +54,7 @@ async function main() {
54
54
  }
55
55
  const whenIdle = args.includes("--when-idle");
56
56
  const force = args.includes("--force");
57
- const mod = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.at; });
57
+ const mod = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.at; });
58
58
  if (whenIdle && !force) {
59
59
  if (mod.isDaemonAlive()) {
60
60
  mod.writePendingRestart({ reason: "svamp daemon restart --when-idle" });
@@ -355,7 +355,7 @@ async function main() {
355
355
  console.error("svamp service: Service commands are not available in sandboxed sessions.");
356
356
  process.exit(1);
357
357
  }
358
- const { handleServiceCommand } = await import('./commands-EhQiKpwu.mjs');
358
+ const { handleServiceCommand } = await import('./commands-rLFKP45k.mjs');
359
359
  await handleServiceCommand();
360
360
  } else if (subcommand === "serve") {
361
361
  const { isSandboxed: isSandboxedServe } = await import('./sandboxDetect-DNTcbgWD.mjs');
@@ -363,7 +363,7 @@ async function main() {
363
363
  console.error("svamp serve: Serve commands are not available in sandboxed sessions.");
364
364
  process.exit(1);
365
365
  }
366
- const { handleServeCommand } = await import('./serveCommands-BgtRllaY.mjs');
366
+ const { handleServeCommand } = await import('./serveCommands-BEJg71HK.mjs');
367
367
  await handleServeCommand();
368
368
  process.exit(0);
369
369
  } else if (subcommand === "process" || subcommand === "proc") {
@@ -372,7 +372,7 @@ async function main() {
372
372
  console.error("svamp process: Process commands are not available in sandboxed sessions.");
373
373
  process.exit(1);
374
374
  }
375
- const { processCommand } = await import('./commands-_Tr8pO3_.mjs');
375
+ const { processCommand } = await import('./commands-D8gpDICH.mjs');
376
376
  let machineId;
377
377
  const processArgs = args.slice(1);
378
378
  const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
@@ -386,18 +386,18 @@ async function main() {
386
386
  }), machineId);
387
387
  process.exit(0);
388
388
  } else if (subcommand === "issue" || subcommand === "issues") {
389
- const { issueCommand } = await import('./commands-C3YGnWyy.mjs');
389
+ const { issueCommand } = await import('./commands-DH1pGrZe.mjs');
390
390
  await issueCommand(args.slice(1));
391
391
  process.exit(0);
392
392
  } else if (subcommand === "workflow" || subcommand === "workflows") {
393
- const { workflowCommand } = await import('./commands-B9wShol7.mjs');
393
+ const { workflowCommand } = await import('./commands-DI-5Eder.mjs');
394
394
  await workflowCommand(args.slice(1));
395
395
  process.exit(0);
396
396
  } else if (subcommand === "wise-agent" || subcommand === "wise") {
397
397
  await handleWiseAgentCommand(args.slice(1));
398
398
  process.exit(0);
399
399
  } else if (subcommand === "feature" || subcommand === "crew") {
400
- const { crewCommand } = await import('./commands-CfDWN8Ej.mjs');
400
+ const { crewCommand } = await import('./commands-CTwhZ-Sj.mjs');
401
401
  await crewCommand(args.slice(1));
402
402
  process.exit(0);
403
403
  } else if (subcommand === "--help" || subcommand === "-h") {
@@ -405,7 +405,7 @@ async function main() {
405
405
  } else if (!subcommand || subcommand === "start") {
406
406
  await handleInteractiveCommand();
407
407
  } else if (subcommand === "--version" || subcommand === "-v") {
408
- const pkg = await import('./package-BTW_-LFn.mjs').catch(() => ({ default: { version: "unknown" } }));
408
+ const pkg = await import('./package-QKAEHd-5.mjs').catch(() => ({ default: { version: "unknown" } }));
409
409
  console.log(`svamp version: ${pkg.default.version}`);
410
410
  } else {
411
411
  console.error(`Unknown command: ${subcommand}`);
@@ -414,7 +414,7 @@ async function main() {
414
414
  }
415
415
  }
416
416
  async function handleInteractiveCommand() {
417
- const { runInteractive } = await import('./run-BtWV7xhR.mjs');
417
+ const { runInteractive } = await import('./run-BJYwPKDR.mjs');
418
418
  const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
419
419
  let directory = process.cwd();
420
420
  let resumeSessionId;
@@ -459,7 +459,7 @@ async function handleAgentCommand() {
459
459
  return;
460
460
  }
461
461
  if (agentArgs[0] === "list") {
462
- const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ao; });
462
+ const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ao; });
463
463
  console.log("Known agents:");
464
464
  for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
465
465
  console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
@@ -471,7 +471,7 @@ async function handleAgentCommand() {
471
471
  console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
472
472
  return;
473
473
  }
474
- const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ao; });
474
+ const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ao; });
475
475
  let cwd = process.cwd();
476
476
  const filteredArgs = [];
477
477
  for (let i = 0; i < agentArgs.length; i++) {
@@ -495,12 +495,12 @@ async function handleAgentCommand() {
495
495
  console.log(`Starting ${config.agentName} agent in ${cwd}...`);
496
496
  let backend;
497
497
  if (KNOWN_MCP_AGENTS[config.agentName]) {
498
- const { CodexMcpBackend } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ap; });
498
+ const { CodexMcpBackend } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ap; });
499
499
  backend = new CodexMcpBackend({ cwd, log: logFn });
500
500
  } else {
501
- const { AcpBackend } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.an; });
502
- const { GeminiTransport } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.aq; });
503
- const { DefaultTransport } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.am; });
501
+ const { AcpBackend } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.an; });
502
+ const { GeminiTransport } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.aq; });
503
+ const { DefaultTransport } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.am; });
504
504
  const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
505
505
  backend = new AcpBackend({
506
506
  agentName: config.agentName,
@@ -627,7 +627,7 @@ async function handleSessionCommand() {
627
627
  process.exit(1);
628
628
  }
629
629
  }
630
- const { sessionList, sessionWhoami, sessionSpawn, sessionArchive, sessionResume, sessionDelete, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionLoopStart, sessionLoopCancel, sessionLoopStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-YPQSZ4Qx.mjs');
630
+ const { sessionList, sessionWhoami, sessionSpawn, sessionArchive, sessionResume, sessionDelete, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionLoopStart, sessionLoopCancel, sessionLoopStatus, sessionLoopExtend, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-Bz3xxhDd.mjs');
631
631
  const parseFlagStr = (flag, shortFlag) => {
632
632
  for (let i = 1; i < sessionArgs.length; i++) {
633
633
  if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
@@ -695,7 +695,7 @@ async function handleSessionCommand() {
695
695
  allowDomain.push(sessionArgs[++i]);
696
696
  }
697
697
  }
698
- const { parseShareArg } = await import('./commands-YPQSZ4Qx.mjs');
698
+ const { parseShareArg } = await import('./commands-Bz3xxhDd.mjs');
699
699
  const shareEntries = share.map((s) => parseShareArg(s));
700
700
  await sessionSpawn(agent, dir, targetMachineId, {
701
701
  message,
@@ -785,7 +785,7 @@ async function handleSessionCommand() {
785
785
  console.error(" Rewinds history: rewrites the message + drops everything after it, then restarts Claude.");
786
786
  process.exit(1);
787
787
  }
788
- const { sessionEditMessage } = await import('./commands-YPQSZ4Qx.mjs');
788
+ const { sessionEditMessage } = await import('./commands-Bz3xxhDd.mjs');
789
789
  await sessionEditMessage(sessionArgs[1], sessionArgs[2], sessionArgs[3], targetMachineId);
790
790
  } else if (sessionSubcommand === "refine") {
791
791
  if (!sessionArgs[1] || !sessionArgs[2]) {
@@ -793,7 +793,7 @@ async function handleSessionCommand() {
793
793
  console.error(" Asks the agent to revise its latest reply in place (no extra round).");
794
794
  process.exit(1);
795
795
  }
796
- const { sessionRefineLastReply } = await import('./commands-YPQSZ4Qx.mjs');
796
+ const { sessionRefineLastReply } = await import('./commands-Bz3xxhDd.mjs');
797
797
  await sessionRefineLastReply(sessionArgs[1], sessionArgs[2], targetMachineId);
798
798
  } else if (sessionSubcommand === "undo-edit" || sessionSubcommand === "undo") {
799
799
  if (!sessionArgs[1]) {
@@ -801,7 +801,7 @@ async function handleSessionCommand() {
801
801
  console.error(" Reverts the most recent edit/refine, restoring the pre-edit history.");
802
802
  process.exit(1);
803
803
  }
804
- const { sessionUndoEdit } = await import('./commands-YPQSZ4Qx.mjs');
804
+ const { sessionUndoEdit } = await import('./commands-Bz3xxhDd.mjs');
805
805
  await sessionUndoEdit(sessionArgs[1], targetMachineId);
806
806
  } else if (sessionSubcommand === "query") {
807
807
  const dir = sessionArgs[1];
@@ -811,7 +811,7 @@ async function handleSessionCommand() {
811
811
  console.error(" Spawns a stateless Claude session in <directory>, sends <prompt>, prints the answer, then deletes the session.");
812
812
  process.exit(1);
813
813
  }
814
- const { sessionQuery } = await import('./commands-YPQSZ4Qx.mjs');
814
+ const { sessionQuery } = await import('./commands-Bz3xxhDd.mjs');
815
815
  await sessionQuery(dir, prompt, targetMachineId, {
816
816
  timeout: parseFlagInt("--timeout"),
817
817
  json: hasFlag("--json"),
@@ -844,7 +844,7 @@ async function handleSessionCommand() {
844
844
  console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
845
845
  process.exit(1);
846
846
  }
847
- const { sessionApprove } = await import('./commands-YPQSZ4Qx.mjs');
847
+ const { sessionApprove } = await import('./commands-Bz3xxhDd.mjs');
848
848
  const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
849
849
  await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
850
850
  json: hasFlag("--json")
@@ -854,7 +854,7 @@ async function handleSessionCommand() {
854
854
  console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
855
855
  process.exit(1);
856
856
  }
857
- const { sessionDeny } = await import('./commands-YPQSZ4Qx.mjs');
857
+ const { sessionDeny } = await import('./commands-Bz3xxhDd.mjs');
858
858
  const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
859
859
  await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
860
860
  json: hasFlag("--json")
@@ -893,13 +893,20 @@ async function handleSessionCommand() {
893
893
  process.exit(1);
894
894
  }
895
895
  await sessionLoopStatus(sessionArgs[1], targetMachineId);
896
+ } else if (sessionSubcommand === "loop-extend") {
897
+ const reason = parseFlagStr("--reason");
898
+ if (!sessionArgs[1] || !reason) {
899
+ console.error('Usage: svamp session loop-extend <session-id> --reason "<why more turns are needed>" [--turns N]');
900
+ process.exit(1);
901
+ }
902
+ await sessionLoopExtend(sessionArgs[1], reason, targetMachineId, parseFlagInt("--turns") ?? void 0);
896
903
  } else if (sessionSubcommand === "set-title") {
897
904
  const title = sessionArgs[1];
898
905
  if (!title) {
899
906
  console.error("Usage: svamp session set-title <title>");
900
907
  process.exit(1);
901
908
  }
902
- const { sessionSetTitle } = await import('./agentCommands-DYoNzX4K.mjs');
909
+ const { sessionSetTitle } = await import('./agentCommands-Dtd2mICX.mjs');
903
910
  await sessionSetTitle(title);
904
911
  } else if (sessionSubcommand === "set-project-description" || sessionSubcommand === "set-project") {
905
912
  const desc = sessionArgs.slice(1).filter((a) => !a.startsWith("--")).join(" ");
@@ -907,7 +914,7 @@ async function handleSessionCommand() {
907
914
  console.error("Usage: svamp session set-project-description <text>");
908
915
  process.exit(1);
909
916
  }
910
- const { sessionSetProjectDescription } = await import('./agentCommands-DYoNzX4K.mjs');
917
+ const { sessionSetProjectDescription } = await import('./agentCommands-Dtd2mICX.mjs');
911
918
  await sessionSetProjectDescription(desc);
912
919
  } else if (sessionSubcommand === "set-link") {
913
920
  const url = sessionArgs[1];
@@ -916,11 +923,11 @@ async function handleSessionCommand() {
916
923
  process.exit(1);
917
924
  }
918
925
  const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
919
- const { sessionSetLink } = await import('./agentCommands-DYoNzX4K.mjs');
926
+ const { sessionSetLink } = await import('./agentCommands-Dtd2mICX.mjs');
920
927
  await sessionSetLink(url, label);
921
928
  } else if (sessionSubcommand === "link") {
922
929
  const op = sessionArgs[1];
923
- const lm = await import('./agentCommands-DYoNzX4K.mjs');
930
+ const lm = await import('./agentCommands-Dtd2mICX.mjs');
924
931
  if (op === "add") {
925
932
  const url = sessionArgs[2];
926
933
  if (!url || url.startsWith("--")) {
@@ -955,7 +962,7 @@ async function handleSessionCommand() {
955
962
  process.exit(1);
956
963
  }
957
964
  const level = parseFlagStr("--level") || "info";
958
- const { sessionNotify } = await import('./agentCommands-DYoNzX4K.mjs');
965
+ const { sessionNotify } = await import('./agentCommands-Dtd2mICX.mjs');
959
966
  await sessionNotify(message, level);
960
967
  } else if (sessionSubcommand === "broadcast") {
961
968
  const action = sessionArgs[1];
@@ -963,7 +970,7 @@ async function handleSessionCommand() {
963
970
  console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
964
971
  process.exit(1);
965
972
  }
966
- const { sessionBroadcast } = await import('./agentCommands-DYoNzX4K.mjs');
973
+ const { sessionBroadcast } = await import('./agentCommands-Dtd2mICX.mjs');
967
974
  await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
968
975
  } else if (sessionSubcommand === "inbox") {
969
976
  const inboxSubcmd = sessionArgs[1];
@@ -974,7 +981,7 @@ async function handleSessionCommand() {
974
981
  process.exit(1);
975
982
  }
976
983
  if (agentSessionId) {
977
- const { inboxSend } = await import('./agentCommands-DYoNzX4K.mjs');
984
+ const { inboxSend } = await import('./agentCommands-Dtd2mICX.mjs');
978
985
  await inboxSend(sessionArgs[2], {
979
986
  body: sessionArgs[3],
980
987
  subject: parseFlagStr("--subject"),
@@ -989,7 +996,7 @@ async function handleSessionCommand() {
989
996
  }
990
997
  } else if (inboxSubcmd === "list" || inboxSubcmd === "ls") {
991
998
  if (agentSessionId && !sessionArgs[2]) {
992
- const { inboxList } = await import('./agentCommands-DYoNzX4K.mjs');
999
+ const { inboxList } = await import('./agentCommands-Dtd2mICX.mjs');
993
1000
  await inboxList({
994
1001
  unread: hasFlag("--unread"),
995
1002
  limit: parseFlagInt("--limit"),
@@ -1011,7 +1018,7 @@ async function handleSessionCommand() {
1011
1018
  process.exit(1);
1012
1019
  }
1013
1020
  if (agentSessionId && !sessionArgs[3]) {
1014
- const { inboxList } = await import('./agentCommands-DYoNzX4K.mjs');
1021
+ const { inboxList } = await import('./agentCommands-Dtd2mICX.mjs');
1015
1022
  await sessionInboxRead(agentSessionId, sessionArgs[2], targetMachineId);
1016
1023
  } else if (sessionArgs[3]) {
1017
1024
  await sessionInboxRead(sessionArgs[2], sessionArgs[3], targetMachineId);
@@ -1021,7 +1028,7 @@ async function handleSessionCommand() {
1021
1028
  }
1022
1029
  } else if (inboxSubcmd === "reply") {
1023
1030
  if (agentSessionId && sessionArgs[2] && sessionArgs[3] && !sessionArgs[4]) {
1024
- const { inboxReply } = await import('./agentCommands-DYoNzX4K.mjs');
1031
+ const { inboxReply } = await import('./agentCommands-Dtd2mICX.mjs');
1025
1032
  await inboxReply(sessionArgs[2], sessionArgs[3]);
1026
1033
  } else if (sessionArgs[2] && sessionArgs[3] && sessionArgs[4]) {
1027
1034
  await sessionInboxReply(sessionArgs[2], sessionArgs[3], sessionArgs[4], targetMachineId);
@@ -1059,7 +1066,7 @@ async function handleMachineCommand() {
1059
1066
  return;
1060
1067
  }
1061
1068
  if (machineSubcommand === "share") {
1062
- const { machineShare } = await import('./commands-YPQSZ4Qx.mjs');
1069
+ const { machineShare } = await import('./commands-Bz3xxhDd.mjs');
1063
1070
  let machineId;
1064
1071
  const shareArgs = [];
1065
1072
  for (let i = 1; i < machineArgs.length; i++) {
@@ -1110,14 +1117,14 @@ async function handleMachineCommand() {
1110
1117
  process.exit(1);
1111
1118
  }
1112
1119
  if (all) {
1113
- const { fleetExec } = await import('./fleet-Ndfbo8Ni.mjs');
1120
+ const { fleetExec } = await import('./fleet-u7T-s_4u.mjs');
1114
1121
  await fleetExec(command, { cwd });
1115
1122
  } else {
1116
- const { machineExec } = await import('./commands-YPQSZ4Qx.mjs');
1123
+ const { machineExec } = await import('./commands-Bz3xxhDd.mjs');
1117
1124
  await machineExec(machineId, command, cwd);
1118
1125
  }
1119
1126
  } else if (machineSubcommand === "info") {
1120
- const { machineInfo } = await import('./commands-YPQSZ4Qx.mjs');
1127
+ const { machineInfo } = await import('./commands-Bz3xxhDd.mjs');
1121
1128
  let machineId;
1122
1129
  for (let i = 1; i < machineArgs.length; i++) {
1123
1130
  if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
@@ -1137,10 +1144,10 @@ async function handleMachineCommand() {
1137
1144
  level = machineArgs[++i];
1138
1145
  }
1139
1146
  }
1140
- const { machineNotify } = await import('./agentCommands-DYoNzX4K.mjs');
1147
+ const { machineNotify } = await import('./agentCommands-Dtd2mICX.mjs');
1141
1148
  await machineNotify(message, level);
1142
1149
  } else if (machineSubcommand === "ls") {
1143
- const { machineLs } = await import('./commands-YPQSZ4Qx.mjs');
1150
+ const { machineLs } = await import('./commands-Bz3xxhDd.mjs');
1144
1151
  let machineId;
1145
1152
  let showHidden = false;
1146
1153
  let path;
@@ -1199,20 +1206,20 @@ Examples:
1199
1206
  };
1200
1207
  const hasFlag = (name) => fleetArgs.includes(`--${name}`);
1201
1208
  if (sub === "status") {
1202
- const { fleetStatus } = await import('./fleet-Ndfbo8Ni.mjs');
1209
+ const { fleetStatus } = await import('./fleet-u7T-s_4u.mjs');
1203
1210
  await fleetStatus();
1204
1211
  } else if (sub === "upgrade-claude") {
1205
- const { fleetUpgradeClaude } = await import('./fleet-Ndfbo8Ni.mjs');
1212
+ const { fleetUpgradeClaude } = await import('./fleet-u7T-s_4u.mjs');
1206
1213
  await fleetUpgradeClaude({ version: flag("version", "-v") });
1207
1214
  } else if (sub === "upgrade-svamp") {
1208
- const { fleetUpgradeSvamp } = await import('./fleet-Ndfbo8Ni.mjs');
1215
+ const { fleetUpgradeSvamp } = await import('./fleet-u7T-s_4u.mjs');
1209
1216
  await fleetUpgradeSvamp({ version: flag("version", "-v"), excludeSelf: hasFlag("exclude-self"), force: hasFlag("force") });
1210
1217
  } else if (sub === "daemon-restart") {
1211
- const { fleetDaemonRestart } = await import('./fleet-Ndfbo8Ni.mjs');
1218
+ const { fleetDaemonRestart } = await import('./fleet-u7T-s_4u.mjs');
1212
1219
  await fleetDaemonRestart({ graceful: !hasFlag("cleanup") });
1213
1220
  } else if (sub === "push-skill") {
1214
1221
  const name = fleetArgs[1];
1215
- const { fleetPushSkill } = await import('./fleet-Ndfbo8Ni.mjs');
1222
+ const { fleetPushSkill } = await import('./fleet-u7T-s_4u.mjs');
1216
1223
  await fleetPushSkill(name);
1217
1224
  } else {
1218
1225
  console.error(`Unknown fleet subcommand: ${sub}`);
@@ -1228,7 +1235,7 @@ async function handleSkillsCommand() {
1228
1235
  await printSkillsHelp();
1229
1236
  return;
1230
1237
  }
1231
- const { skillsFind, skillsInstall, skillsList, skillsRemove, skillsPublish } = await import('./commands-CvWkQB_c.mjs');
1238
+ const { skillsFind, skillsInstall, skillsList, skillsRemove, skillsPublish } = await import('./commands-Ch_nKvnk.mjs');
1232
1239
  if (skillsSubcommand === "find" || skillsSubcommand === "search") {
1233
1240
  const query = skillsArgs.slice(1).filter((a) => !a.startsWith("--")).join(" ");
1234
1241
  if (!query) {
@@ -1275,7 +1282,7 @@ async function loginToHypha() {
1275
1282
  process.exit(1);
1276
1283
  }
1277
1284
  const anchor = anchorArg.replace(/\/+$/, "");
1278
- const { loadInstanceConfig } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ar; });
1285
+ const { loadInstanceConfig } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ar; });
1279
1286
  let cfg = null;
1280
1287
  try {
1281
1288
  cfg = await loadInstanceConfig({ anchor, force: true });
@@ -1386,7 +1393,7 @@ async function logoutFromHypha() {
1386
1393
  } catch {
1387
1394
  }
1388
1395
  try {
1389
- const { clearInstanceConfigCache } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ar; });
1396
+ const { clearInstanceConfigCache } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ar; });
1390
1397
  clearInstanceConfigCache();
1391
1398
  } catch {
1392
1399
  }
@@ -1725,7 +1732,7 @@ async function applyClaudeAuthFlags(argv) {
1725
1732
  "--use-hypha-proxy, --use-claude-login, and --anthropic-base-url/--anthropic-api-key are mutually exclusive"
1726
1733
  );
1727
1734
  }
1728
- const mod = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ak; });
1735
+ const mod = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ak; });
1729
1736
  if (hasHypha) {
1730
1737
  let url;
1731
1738
  const hyphaIdx = argv.indexOf("--use-hypha-proxy");
@@ -1779,7 +1786,7 @@ async function applyDaemonShareFlag(argv) {
1779
1786
  }
1780
1787
  }
1781
1788
  if (collected.length === 0) return;
1782
- const { updateEnvFile } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ak; });
1789
+ const { updateEnvFile } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ak; });
1783
1790
  const seen = /* @__PURE__ */ new Set();
1784
1791
  const deduped = collected.filter((e) => {
1785
1792
  const k = e.toLowerCase();
@@ -1812,7 +1819,7 @@ async function handleWiseAgentCommand(rest) {
1812
1819
  }
1813
1820
  });
1814
1821
  const message = rest.slice(1).map((a, idx) => ({ a, idx: idx + 1 })).filter(({ a, idx }) => !a.startsWith("-") && !consumed.has(String(idx))).map(({ a }) => a).join(" ");
1815
- const { wiseAskCli } = await import('./commands-YPQSZ4Qx.mjs');
1822
+ const { wiseAskCli } = await import('./commands-Bz3xxhDd.mjs');
1816
1823
  await wiseAskCli(machineId, message, sessionId, { json });
1817
1824
  return;
1818
1825
  }
@@ -1824,7 +1831,7 @@ async function handleWiseAgentCommand(rest) {
1824
1831
  }
1825
1832
  return void 0;
1826
1833
  };
1827
- const { runWiseVoiceCli } = await import('./headlessCli-CbCWVR81.mjs');
1834
+ const { runWiseVoiceCli } = await import('./headlessCli-D7JwS_Bf.mjs');
1828
1835
  await runWiseVoiceCli({ voice: valueOf(["--voice"]), wakeKeywordPath: valueOf(["--wake"]), model: valueOf(["--model"]) });
1829
1836
  return;
1830
1837
  }
@@ -1842,7 +1849,7 @@ async function handleWiseAgentCommand(rest) {
1842
1849
  const mode = valueOf(["--mode"]);
1843
1850
  const mission = valueOf(["--mission"]);
1844
1851
  const url = rest.slice(1).find((a) => /^https?:\/\//.test(a)) || "";
1845
- const { wiseJoinMeetingCli } = await import('./commands-YPQSZ4Qx.mjs');
1852
+ const { wiseJoinMeetingCli } = await import('./commands-Bz3xxhDd.mjs');
1846
1853
  await wiseJoinMeetingCli(machineId, url, sessionId, { json, mode, mission });
1847
1854
  return;
1848
1855
  }
@@ -1854,7 +1861,7 @@ async function handleWiseAgentCommand(rest) {
1854
1861
  }
1855
1862
  return void 0;
1856
1863
  };
1857
- const { wiseLeaveMeetingCli } = await import('./commands-YPQSZ4Qx.mjs');
1864
+ const { wiseLeaveMeetingCli } = await import('./commands-Bz3xxhDd.mjs');
1858
1865
  await wiseLeaveMeetingCli(valueOf(["--machine", "-m"]), valueOf(["--session", "-s"]), { json: rest.includes("--json") });
1859
1866
  return;
1860
1867
  }
@@ -1878,7 +1885,7 @@ async function handleWiseAgentCommand(rest) {
1878
1885
  }
1879
1886
  });
1880
1887
  const text = rest.slice(1).map((a, idx) => ({ a, idx: idx + 1 })).filter(({ a, idx }) => !a.startsWith("-") && !consumed.has(String(idx))).map(({ a }) => a).join(" ");
1881
- const { wiseAnnounceCli } = await import('./commands-YPQSZ4Qx.mjs');
1888
+ const { wiseAnnounceCli } = await import('./commands-Bz3xxhDd.mjs');
1882
1889
  await wiseAnnounceCli(machineId, text, sessionId, { json });
1883
1890
  return;
1884
1891
  }
@@ -1890,7 +1897,7 @@ async function handleWiseAgentCommand(rest) {
1890
1897
  }
1891
1898
  return void 0;
1892
1899
  };
1893
- const { wiseMeetingsCli } = await import('./commands-YPQSZ4Qx.mjs');
1900
+ const { wiseMeetingsCli } = await import('./commands-Bz3xxhDd.mjs');
1894
1901
  await wiseMeetingsCli(valueOf(["--machine", "-m"]), { json: rest.includes("--json") });
1895
1902
  return;
1896
1903
  }
@@ -1940,7 +1947,7 @@ If none is set, hitting a WISE Agent channel returns a clear "not configured" er
1940
1947
  return;
1941
1948
  }
1942
1949
  const authArgs = rest.slice(1);
1943
- const mod = await import('./auth-D0nW0Gyj.mjs');
1950
+ const mod = await import('./auth-C5b7_Wpo.mjs');
1944
1951
  let action;
1945
1952
  try {
1946
1953
  action = mod.parseWiseAgentAuthArgs(authArgs);
@@ -1950,7 +1957,7 @@ If none is set, hitting a WISE Agent channel returns a clear "not configured" er
1950
1957
  return;
1951
1958
  }
1952
1959
  if (action) {
1953
- const { updateEnvFile } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ak; });
1960
+ const { updateEnvFile } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ak; });
1954
1961
  const updates = mod.buildWiseAgentEnvUpdates(action);
1955
1962
  updateEnvFile(updates);
1956
1963
  for (const [k, v] of Object.entries(updates)) {
@@ -1964,7 +1971,7 @@ If none is set, hitting a WISE Agent channel returns a clear "not configured" er
1964
1971
  }
1965
1972
  async function handleDaemonAuthCommand(argv) {
1966
1973
  const sub = (argv[0] || "status").toLowerCase();
1967
- const mod = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.ak; });
1974
+ const mod = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.ak; });
1968
1975
  if (sub === "--help" || sub === "-h" || sub === "help") {
1969
1976
  console.log(`
1970
1977
  svamp daemon auth \u2014 Configure how Claude subprocesses authenticate
@@ -2129,7 +2136,8 @@ COMMANDS:
2129
2136
  HOT-PLUG onto the running session (no kickoff).
2130
2137
  opts: --oracle "cmd" --agent --parent <id> --max N
2131
2138
  loop-cancel <id> Cancel the loop / release the gate
2132
- loop-status <id> Show loop phase + iteration
2139
+ loop-status <id> Show loop phase + iteration + extensions
2140
+ loop-extend <id> --reason "<why>" Extend the SOFT cap (+turns, bounded) with a reason
2133
2141
 
2134
2142
  Inbox:
2135
2143
  inbox send <id> "<body>" [opts] Send a message to session inbox
@@ -2283,7 +2291,7 @@ Examples:
2283
2291
  async function printSkillsHelp() {
2284
2292
  let browseUrl = "<HYPHA_SERVER_URL>/<workspace>/artifacts/marketplace (set HYPHA_SERVER_URL)";
2285
2293
  try {
2286
- const { getArtifactBaseUrl, getSkillsCollectionName } = await import('./run-hYUl-Fln.mjs').then(function (n) { return n.as; });
2294
+ const { getArtifactBaseUrl, getSkillsCollectionName } = await import('./run-BqqMOMZN.mjs').then(function (n) { return n.as; });
2287
2295
  browseUrl = `${getArtifactBaseUrl()}/${getSkillsCollectionName()}`;
2288
2296
  } catch {
2289
2297
  }
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { execSync } from 'node:child_process';
3
3
  import { basename, resolve, join, isAbsolute } from 'node:path';
4
4
  import os from 'node:os';
5
- import { a2 as formatHandle, a3 as normalizeAllowedUser, a4 as loadSecurityContextConfig, a5 as resolveSecurityContext, a6 as buildSecurityContextFromFlags, a7 as mergeSecurityContexts, c as connectToHypha, a8 as buildSessionShareUrl, a9 as computeOutboundHop, k as shortId, aa as registerAwaitingReply, ab as buildMachineShareUrl, ac as parseHandle, ad as handleMatchesMetadata } from './run-hYUl-Fln.mjs';
5
+ import { a2 as formatHandle, a3 as normalizeAllowedUser, a4 as loadSecurityContextConfig, a5 as resolveSecurityContext, a6 as buildSecurityContextFromFlags, a7 as mergeSecurityContexts, c as connectToHypha, a8 as buildSessionShareUrl, a9 as computeOutboundHop, k as shortId, aa as registerAwaitingReply, ab as buildMachineShareUrl, ac as parseHandle, ad as handleMatchesMetadata } from './run-BqqMOMZN.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -2566,6 +2566,19 @@ async function sessionLoopCancel(sessionIdPartial, machineId) {
2566
2566
  await server.disconnect();
2567
2567
  }
2568
2568
  }
2569
+ async function sessionLoopExtend(sessionIdPartial, reason, machineId, grantedTurns) {
2570
+ const { server, machine, fullId } = await connectAndResolveSession(sessionIdPartial, machineId);
2571
+ try {
2572
+ const svc = getSessionProxy(machine, fullId);
2573
+ await svc.updateConfig({
2574
+ loop: { extend: { reason, ...grantedTurns != null ? { grantedTurns } : {} } }
2575
+ });
2576
+ console.log(`\u{1F501} Requested loop extension on session ${fullId.slice(0, 8)} \u2014 reason: ${reason.slice(0, 120)}${reason.length > 120 ? "\u2026" : ""}`);
2577
+ console.log(` (bounded by SVAMP_LOOP_MAX_EXTENSIONS; raises only the soft iteration cap, never the hard cost ceiling. Check: svamp session loop-status ${fullId.slice(0, 8)})`);
2578
+ } finally {
2579
+ await server.disconnect();
2580
+ }
2581
+ }
2569
2582
  async function sessionLoopStatus(sessionIdPartial, machineId) {
2570
2583
  const { server, machine, fullId } = await connectAndResolveSession(sessionIdPartial, machineId);
2571
2584
  try {
@@ -2602,6 +2615,14 @@ async function sessionLoopStatus(sessionIdPartial, machineId) {
2602
2615
  console.log(` Evaluator: ${verdict ? `${verdict.verdict}${verdict.reason ? ` \u2014 ${verdict.reason}` : ""}` : "on (no verdict yet)"}`);
2603
2616
  }
2604
2617
  if (state.gave_up_reason) console.log(` Gave up: ${state.gave_up_reason}`);
2618
+ if (Array.isArray(state.extensions) && state.extensions.length) {
2619
+ const totalTurns = state.extensions.reduce((s, e) => s + (Number.isFinite(e?.grantedTurns) && e.grantedTurns > 0 ? Math.floor(e.grantedTurns) : 0), 0);
2620
+ console.log(` Extensions: ${state.extensions.length} (+${totalTurns} turns)`);
2621
+ for (const e of state.extensions) {
2622
+ const when = Number.isFinite(e?.ts) ? new Date(e.ts).toISOString() : "";
2623
+ console.log(` \u2022 +${e?.grantedTurns ?? 0} turns${when ? ` @ ${when}` : ""} \u2014 ${String(e?.reason || "").slice(0, 160)}`);
2624
+ }
2625
+ }
2605
2626
  if (state.started_at) console.log(` Started at: ${state.started_at}`);
2606
2627
  } finally {
2607
2628
  await server.disconnect();
@@ -2768,4 +2789,4 @@ async function sessionInboxClear(sessionIdPartial, machineId, opts) {
2768
2789
  }
2769
2790
  }
2770
2791
 
2771
- export { collectAssistantResponse, connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, isSelfBtw, machineExec, machineInfo, machineLs, machineShare, parseShareArg, queryCore, renderMessage, resolveSessionId, sendCore, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionEditMessage, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionLoopCancel, sessionLoopStart, sessionLoopStatus, sessionMachines, sessionMessages, sessionQuery, sessionRefineLastReply, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionUndoEdit, sessionWait, sessionWhoami, snapshotLatestSeq, validateSendOptions, wiseAnnounceCli, wiseAskCli, wiseJoinMeetingCli, wiseLeaveMeetingCli, wiseMeetingsCli };
2792
+ export { collectAssistantResponse, connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, isSelfBtw, machineExec, machineInfo, machineLs, machineShare, parseShareArg, queryCore, renderMessage, resolveSessionId, sendCore, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionEditMessage, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionLoopCancel, sessionLoopExtend, sessionLoopStart, sessionLoopStatus, sessionMachines, sessionMessages, sessionQuery, sessionRefineLastReply, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionUndoEdit, sessionWait, sessionWhoami, snapshotLatestSeq, validateSendOptions, wiseAnnounceCli, wiseAskCli, wiseJoinMeetingCli, wiseLeaveMeetingCli, wiseMeetingsCli };
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
- import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-YPQSZ4Qx.mjs';
3
+ import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-Bz3xxhDd.mjs';
4
4
  import { execSync } from 'node:child_process';
5
- import { u as updateIssue, t as addComment, v as addIssue, k as shortId } from './run-hYUl-Fln.mjs';
5
+ import { u as updateIssue, t as addComment, v as addIssue, k as shortId } from './run-BqqMOMZN.mjs';
6
6
  import 'node:os';
7
7
  import 'os';
8
8
  import 'fs/promises';
@@ -1,7 +1,7 @@
1
1
  import os from 'os';
2
2
  import fs__default from 'fs';
3
3
  import { resolve, join, relative } from 'path';
4
- import { T as parseFrontmatter, U as getSkillsServer, V as getSkillsWorkspaceName, W as getSkillsCollectionName, X as fetchWithTimeout, Y as searchSkills, Z as SKILLS_DIR, _ as getSkillInfo, $ as downloadSkillFile, a0 as listSkillFiles } from './run-hYUl-Fln.mjs';
4
+ import { T as parseFrontmatter, U as getSkillsServer, V as getSkillsWorkspaceName, W as getSkillsCollectionName, X as fetchWithTimeout, Y as searchSkills, Z as SKILLS_DIR, _ as getSkillInfo, $ as downloadSkillFile, a0 as listSkillFiles } from './run-BqqMOMZN.mjs';
5
5
  import 'fs/promises';
6
6
  import 'url';
7
7
  import 'child_process';
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-YPQSZ4Qx.mjs';
3
+ import { connectAndGetMachine } from './commands-Bz3xxhDd.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-hYUl-Fln.mjs';
8
+ import './run-BqqMOMZN.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
@@ -1,7 +1,7 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
- import { n as resolveProjectRoot, x as searchIssues, w as listIssues, p as resumeIssue, q as pauseIssue, t as addComment, u as updateIssue, o as getIssue, y as isVisibleTo, L as summarize, v as addIssue } from './run-hYUl-Fln.mjs';
4
+ import { n as resolveProjectRoot, x as searchIssues, w as listIssues, p as resumeIssue, q as pauseIssue, t as addComment, u as updateIssue, o as getIssue, y as isVisibleTo, L as summarize, v as addIssue } from './run-BqqMOMZN.mjs';
5
5
  import 'os';
6
6
  import 'fs/promises';
7
7
  import 'fs';
@@ -1,5 +1,5 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { n as resolveProjectRoot, M as workflowSteps, D as setWorkflowEnabled, I as isWorkflowEnabled, E as removeWorkflow, B as getWorkflow, H as listWorkflows, F as saveWorkflow, G as rawWorkflow } from './run-hYUl-Fln.mjs';
2
+ import { n as resolveProjectRoot, M as workflowSteps, D as setWorkflowEnabled, I as isWorkflowEnabled, E as removeWorkflow, B as getWorkflow, H as listWorkflows, F as saveWorkflow, G as rawWorkflow } from './run-BqqMOMZN.mjs';
3
3
  import 'os';
4
4
  import 'fs/promises';
5
5
  import 'fs';
@@ -58,7 +58,7 @@ async function serviceExpose(args) {
58
58
  process.exit(1);
59
59
  }
60
60
  if (foreground) {
61
- const { runFrpcTunnel } = await import('./frpc-CLQB-GM1.mjs');
61
+ const { runFrpcTunnel } = await import('./frpc-BBkDE65f.mjs');
62
62
  await runFrpcTunnel(name, ports, void 0, {
63
63
  group,
64
64
  groupKey,
@@ -68,7 +68,7 @@ async function serviceExpose(args) {
68
68
  });
69
69
  return;
70
70
  }
71
- const { connectAndGetMachine } = await import('./commands-YPQSZ4Qx.mjs');
71
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.mjs');
72
72
  const { server, machine } = await connectAndGetMachine();
73
73
  try {
74
74
  const status = await machine.tunnelStart({
@@ -90,7 +90,7 @@ async function serviceExpose(args) {
90
90
  console.log(` port ${port}: ${url}`);
91
91
  }
92
92
  if (process.env.SVAMP_SESSION_ID) {
93
- const { autoAddSessionLink } = await import('./agentCommands-DYoNzX4K.mjs');
93
+ const { autoAddSessionLink } = await import('./agentCommands-Dtd2mICX.mjs');
94
94
  let added = 0;
95
95
  for (const [port, url] of urlEntries) {
96
96
  const label = urlEntries.length > 1 ? `${name}:${port}` : name;
@@ -136,7 +136,7 @@ async function serviceServe(args) {
136
136
  };
137
137
  process.on("SIGINT", cleanup);
138
138
  process.on("SIGTERM", cleanup);
139
- const { runFrpcTunnel } = await import('./frpc-CLQB-GM1.mjs');
139
+ const { runFrpcTunnel } = await import('./frpc-BBkDE65f.mjs');
140
140
  await runFrpcTunnel(name, [caddyPort]);
141
141
  } catch (err) {
142
142
  console.error(`Error serving directory: ${err.message}`);
@@ -145,7 +145,7 @@ async function serviceServe(args) {
145
145
  }
146
146
  async function serviceList(_args) {
147
147
  try {
148
- const { connectAndGetMachine } = await import('./commands-YPQSZ4Qx.mjs');
148
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.mjs');
149
149
  const { server, machine } = await connectAndGetMachine();
150
150
  try {
151
151
  const tunnels = await machine.tunnelList({});
@@ -185,7 +185,7 @@ async function serviceDelete(args) {
185
185
  process.exit(1);
186
186
  }
187
187
  try {
188
- const { connectAndGetMachine } = await import('./commands-YPQSZ4Qx.mjs');
188
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.mjs');
189
189
  const { server, machine } = await connectAndGetMachine();
190
190
  try {
191
191
  await machine.tunnelStop({ name });
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import os from 'node:os';
4
- import { c as connectToHypha } from './run-hYUl-Fln.mjs';
4
+ import { c as connectToHypha } from './run-BqqMOMZN.mjs';
5
5
  import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-DuLXaoGP.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
@@ -4,7 +4,7 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
4
4
  import { join } from 'path';
5
5
  import { homedir, platform, arch } from 'os';
6
6
  import { randomUUID, createHash } from 'crypto';
7
- import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-hYUl-Fln.mjs';
7
+ import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-BqqMOMZN.mjs';
8
8
  import 'fs/promises';
9
9
  import 'url';
10
10
  import 'node:crypto';
@@ -1,5 +1,5 @@
1
- import { a1 as resolveModel, ae as describeMisconfiguration, af as buildMachineDeps } from './run-hYUl-Fln.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-C0qzprWp.mjs';
1
+ import { a1 as resolveModel, ae as describeMisconfiguration, af as buildMachineDeps } from './run-BqqMOMZN.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-c7SyYkOC.mjs';
3
3
  import { WebSocket } from 'ws';
4
4
  import { execSync, spawn } from 'child_process';
5
5
  import 'os';
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-hYUl-Fln.mjs';
1
+ export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-BqqMOMZN.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.253";
2
+ var version = "0.2.254";
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";
@@ -1,4 +1,4 @@
1
- import { n as resolveProjectRoot, u as updateIssue, o as getIssue, p as resumeIssue, q as pauseIssue, t as addComment, v as addIssue, w as listIssues, x as searchIssues, y as isVisibleTo } from './run-hYUl-Fln.mjs';
1
+ import { n as resolveProjectRoot, u as updateIssue, o as getIssue, p as resumeIssue, q as pauseIssue, t as addComment, v as addIssue, w as listIssues, x as searchIssues, y as isVisibleTo } from './run-BqqMOMZN.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,4 +1,4 @@
1
- import { n as resolveProjectRoot, z as getRun, A as listRuns, B as getWorkflow, C as runWorkflow, D as setWorkflowEnabled, E as removeWorkflow, F as saveWorkflow, G as rawWorkflow, H as listWorkflows } from './run-hYUl-Fln.mjs';
1
+ import { n as resolveProjectRoot, z as getRun, A as listRuns, B as getWorkflow, C as runWorkflow, D as setWorkflowEnabled, E as removeWorkflow, F as saveWorkflow, G as rawWorkflow, H as listWorkflows } from './run-BqqMOMZN.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,4 +1,4 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { ag as applyClaudeProxyEnv, ah as composeSessionId, ai as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, aj as generateHookSettings } from './run-hYUl-Fln.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { ag as applyClaudeProxyEnv, ah as composeSessionId, ai as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, aj as generateHookSettings } from './run-BqqMOMZN.mjs';
2
2
  import os from 'node:os';
3
3
  import { resolve, join } from 'node:path';
4
4
  import { existsSync, readFileSync, watch } from 'node:fs';
@@ -2985,7 +2985,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2985
2985
  const tunnels = handlers.tunnels;
2986
2986
  if (!tunnels) throw new Error("Tunnel management not available");
2987
2987
  if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
2988
- const { FrpcTunnel } = await import('./frpc-CLQB-GM1.mjs');
2988
+ const { FrpcTunnel } = await import('./frpc-BBkDE65f.mjs');
2989
2989
  const tunnel = new FrpcTunnel({
2990
2990
  name: params.name,
2991
2991
  ports: params.ports,
@@ -3452,7 +3452,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3452
3452
  }
3453
3453
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
3454
3454
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
3455
- const { toolsForRole } = await import('./sideband-C0qzprWp.mjs');
3455
+ const { toolsForRole } = await import('./sideband-c7SyYkOC.mjs');
3456
3456
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
3457
3457
  return fmt(r2);
3458
3458
  }
@@ -3551,7 +3551,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3551
3551
  if (r.error || !r.sender) return { error: r.error || "unauthorized" };
3552
3552
  const callId = "call_" + Math.random().toString(16).slice(2, 12);
3553
3553
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
3554
- const { queryCore } = await import('./commands-YPQSZ4Qx.mjs');
3554
+ const { queryCore } = await import('./commands-Bz3xxhDd.mjs');
3555
3555
  const timeout = c.reply?.timeout_sec || 120;
3556
3556
  let result;
3557
3557
  try {
@@ -11542,6 +11542,53 @@ function computeSoftTurnCap(hardMax, cadence) {
11542
11542
  const chunks = Math.ceil(hardMax / c);
11543
11543
  return Math.ceil(hardMax / chunks);
11544
11544
  }
11545
+ const DEFAULT_LOOP_MAX_EXTENSIONS = 3;
11546
+ const DEFAULT_LOOP_EXTENSION_TURNS = 25;
11547
+ function resolveMaxExtensions(envValue) {
11548
+ const n = Number(envValue);
11549
+ if (Number.isFinite(n) && n >= 0) return Math.floor(n);
11550
+ return DEFAULT_LOOP_MAX_EXTENSIONS;
11551
+ }
11552
+ function resolveExtensionTurns(envValue) {
11553
+ const n = Number(envValue);
11554
+ if (Number.isFinite(n) && n >= 1) return Math.floor(n);
11555
+ return DEFAULT_LOOP_EXTENSION_TURNS;
11556
+ }
11557
+ function grantedExtensionCount(extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENSIONS) {
11558
+ if (!Array.isArray(extensions)) return 0;
11559
+ const cap = Number.isFinite(maxExtensions) && maxExtensions >= 0 ? Math.floor(maxExtensions) : DEFAULT_LOOP_MAX_EXTENSIONS;
11560
+ return Math.min(extensions.filter((e) => e && typeof e === "object").length, cap);
11561
+ }
11562
+ function extensionTurns(extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENSIONS) {
11563
+ if (!Array.isArray(extensions)) return 0;
11564
+ const cap = Number.isFinite(maxExtensions) && maxExtensions >= 0 ? Math.floor(maxExtensions) : DEFAULT_LOOP_MAX_EXTENSIONS;
11565
+ return extensions.slice(0, cap).reduce((s, e) => {
11566
+ const g = e && Number.isFinite(e.grantedTurns) && e.grantedTurns > 0 ? Math.floor(e.grantedTurns) : 0;
11567
+ return s + g;
11568
+ }, 0);
11569
+ }
11570
+ function effectiveSoftCap(baseMax, extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENSIONS) {
11571
+ if (typeof baseMax !== "number" || !Number.isFinite(baseMax) || baseMax <= 0 || baseMax >= UNBOUNDED_LOOP_ITERATIONS) return baseMax;
11572
+ return baseMax + extensionTurns(extensions, maxExtensions);
11573
+ }
11574
+ function grantLoopExtension(prior, o) {
11575
+ const max = Number.isFinite(o.maxExtensions) && o.maxExtensions >= 0 ? Math.floor(o.maxExtensions) : DEFAULT_LOOP_MAX_EXTENSIONS;
11576
+ const base = Array.isArray(prior) ? prior.filter((e) => e && typeof e === "object") : [];
11577
+ if (base.length >= max) return { granted: false, used: base.length, max };
11578
+ const extension = {
11579
+ reason: (o.reason || "").trim().slice(0, 500) || "(no reason given)",
11580
+ ts: o.ts,
11581
+ grantedTurns: Number.isFinite(o.grantedTurns) && o.grantedTurns > 0 ? Math.floor(o.grantedTurns) : DEFAULT_LOOP_EXTENSION_TURNS
11582
+ };
11583
+ return { granted: true, extension, extensions: [...base, extension], used: base.length + 1, max };
11584
+ }
11585
+ function summarizeExtensions(extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENSIONS) {
11586
+ const n = grantedExtensionCount(extensions, maxExtensions);
11587
+ if (n === 0) return "";
11588
+ const turns = extensionTurns(extensions, maxExtensions);
11589
+ const reasons = extensions.slice(0, maxExtensions).map((e) => (e.reason || "").trim()).filter(Boolean).join("; ").slice(0, 300);
11590
+ return `${n} extension${n === 1 ? "" : "s"} granted (+${turns} turns)${reasons ? `: ${reasons}` : ""}`;
11591
+ }
11545
11592
  const DEFAULT_LOOP_STUCK_CHECKPOINTS = 3;
11546
11593
  const DEFAULT_LOOP_MAX_AUTORESUMES = Number.POSITIVE_INFINITY;
11547
11594
  const PROGRESS_HISTORY_CAP = 12;
@@ -12916,8 +12963,45 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
12916
12963
  }
12917
12964
  const task = cfg && typeof cfg.task === "string" && cfg.task.trim() ? cfg.task.trim() : void 0;
12918
12965
  const until = cfg && typeof cfg.until === "string" && cfg.until.trim() ? cfg.until.trim() : cfg && typeof cfg.criteria === "string" && cfg.criteria.trim() ? cfg.criteria.trim() : void 0;
12919
- const onlyLimit = cfg && typeof cfg === "object" && !task && !until && (typeof cfg.max_iterations === "number" || typeof cfg.max_rounds === "number" || cfg.budget);
12920
- if (onlyLimit) {
12966
+ const extendReq = cfg && typeof cfg === "object" && cfg.extend && typeof cfg.extend === "object" ? cfg.extend : null;
12967
+ const onlyLimit = cfg && typeof cfg === "object" && !task && !until && !extendReq && (typeof cfg.max_iterations === "number" || typeof cfg.max_rounds === "number" || cfg.budget);
12968
+ if (extendReq) {
12969
+ const existing = readLoopState(directory, sessionId);
12970
+ if (!existing) {
12971
+ sessionService.pushMessage({ type: "message", message: 'No loop to extend \u2014 start one with: svamp session loop <id> "<task>" --until "<criteria>" --max N', level: "warning" }, "event");
12972
+ } else {
12973
+ const maxExtensions = resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS);
12974
+ const grantTurns = typeof extendReq.grantedTurns === "number" && extendReq.grantedTurns > 0 ? Math.floor(extendReq.grantedTurns) : resolveExtensionTurns(process.env.SVAMP_LOOP_EXTENSION_TURNS);
12975
+ const grant = grantLoopExtension(existing.extensions, {
12976
+ reason: typeof extendReq.reason === "string" ? extendReq.reason : "",
12977
+ ts: Date.now(),
12978
+ grantedTurns: grantTurns,
12979
+ maxExtensions
12980
+ });
12981
+ if (!grant.granted) {
12982
+ sessionService.pushMessage({ type: "message", message: `\u{1F6D1} Extension refused \u2014 this loop already used all ${grant.max} allowed extension${grant.max === 1 ? "" : "s"} (${grant.used}/${grant.max}). A hard cap is a hard cap; do the remaining work or raise the limit manually: svamp session loop-resume ${sessionId} --max <N>`, level: "warning" }, "event");
12983
+ logger.log(`[svampConfig] loop-extend refused (bounded ${grant.used}/${grant.max})`);
12984
+ } else {
12985
+ const wasStopped = existing.active === false || existing.phase === "done" || existing.phase === "gave_up" || existing.phase === "cancelled";
12986
+ try {
12987
+ const sp = join$1(getLoopDir(directory, sessionId), "loop-state.json");
12988
+ atomicWriteLoopState(sp, {
12989
+ ...existing,
12990
+ extensions: grant.extensions,
12991
+ ...wasStopped ? { active: true, phase: "continue", iteration: 0, completed_at: void 0, gave_up_reason: void 0, stall_hinted: false, resumed_at: Date.now() } : {}
12992
+ });
12993
+ } catch {
12994
+ }
12995
+ if (wasStopped) {
12996
+ const eq = getMetadata().messageQueue || [];
12997
+ setMetadata((m) => ({ ...m, messageQueue: [...eq, { id: randomUUID$1(), text: loopResumeMessage(directory, sessionId), displayText: "\u{1F501} Resuming loop (extended)", createdAt: Date.now() }] }));
12998
+ onLoopActivated?.();
12999
+ }
13000
+ sessionService.pushMessage({ type: "message", message: `\u{1F501} Loop extended (+${grant.extension.grantedTurns} turns, ${grant.used}/${grant.max} used)${wasStopped ? " \u2014 resuming" : ""}. Reason: ${grant.extension.reason}`, level: "warning" }, "event");
13001
+ logger.log(`[svampConfig] loop-extend granted (+${grant.extension.grantedTurns}, ${grant.used}/${grant.max}, resumed=${wasStopped}): ${grant.extension.reason}`);
13002
+ }
13003
+ }
13004
+ } else if (onlyLimit) {
12921
13005
  const existing = readLoopState(directory, sessionId);
12922
13006
  if (!existing) {
12923
13007
  sessionService.pushMessage({ type: "message", message: 'No loop to modify \u2014 start one with: svamp session loop <id> "<task>" --until "<criteria>" --max N', level: "warning" }, "event");
@@ -13449,7 +13533,7 @@ async function startDaemon(options) {
13449
13533
  try {
13450
13534
  const dir = loadSessionIndex()[sessionId]?.directory;
13451
13535
  if (!dir) return;
13452
- const { reconcileServiceLinks } = await import('./agentCommands-DYoNzX4K.mjs');
13536
+ const { reconcileServiceLinks } = await import('./agentCommands-Dtd2mICX.mjs');
13453
13537
  const configPath = getSvampConfigPath(dir, sessionId);
13454
13538
  const config = readSvampConfig(configPath);
13455
13539
  const entries = Array.from(urls.entries());
@@ -13467,7 +13551,7 @@ async function startDaemon(options) {
13467
13551
  }
13468
13552
  }
13469
13553
  async function createExposedTunnel(spec) {
13470
- const { FrpcTunnel } = await import('./frpc-CLQB-GM1.mjs');
13554
+ const { FrpcTunnel } = await import('./frpc-BBkDE65f.mjs');
13471
13555
  const tunnel = new FrpcTunnel({
13472
13556
  name: spec.name,
13473
13557
  ports: spec.ports,
@@ -13487,7 +13571,7 @@ async function startDaemon(options) {
13487
13571
  return tunnel;
13488
13572
  }
13489
13573
  const tunnelRecreateState = /* @__PURE__ */ new Map();
13490
- const { ServeManager } = await import('./serveManager-BK5OjhXU.mjs');
13574
+ const { ServeManager } = await import('./serveManager-BBRgdCJp.mjs');
13491
13575
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
13492
13576
  ensureAutoInstalledSkills(logger).catch(() => {
13493
13577
  });
@@ -14172,6 +14256,7 @@ ${parts.join("\n")}`);
14172
14256
  const ledger = ls.ledger;
14173
14257
  const budget = ls.budget;
14174
14258
  const progress_history = ls.progress_history;
14259
+ const extensions = ls.extensions;
14175
14260
  if (result.action === "rekick") {
14176
14261
  const cond = ls.task || "";
14177
14262
  writeGoalLoopState(directory, sessionId, {
@@ -14188,7 +14273,8 @@ ${parts.join("\n")}`);
14188
14273
  holds: holds + 1,
14189
14274
  ledger,
14190
14275
  progress_history,
14191
- auto_resumes: ls.auto_resumes
14276
+ auto_resumes: ls.auto_resumes,
14277
+ extensions
14192
14278
  });
14193
14279
  const guidance = result.guidance.replace(/\s+/g, " ").slice(0, 1200);
14194
14280
  sessionService.pushMessage({ type: "message", message: `\u{1F501} Loop not done \u2014 independent review: ${result.reason}`, level: "warning" }, "event");
@@ -14200,7 +14286,9 @@ ${parts.join("\n")}`);
14200
14286
  progressHistory: progress_history || [],
14201
14287
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
14202
14288
  autoResumes: typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0,
14203
- maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES),
14289
+ // #0320: extensions also raise a FINITE auto-resume cap (one extra resume each). With
14290
+ // the unbounded #0319 default this is a no-op (Infinity + n = Infinity).
14291
+ maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS)),
14204
14292
  stuckReason: result.reason
14205
14293
  });
14206
14294
  if (decision.action === "continue") {
@@ -14222,7 +14310,8 @@ ${parts.join("\n")}`);
14222
14310
  holds: decision.kind === "progress" ? 0 : holds,
14223
14311
  ledger,
14224
14312
  progress_history,
14225
- auto_resumes: nextAuto
14313
+ auto_resumes: nextAuto,
14314
+ extensions
14226
14315
  });
14227
14316
  const label = decision.kind === "autoresume" ? "\u{1F501} Auto-resuming stalled loop" : "\u{1F501} Loop still progressing";
14228
14317
  sessionService.pushMessage({ type: "message", message: `${label} \u2014 ${decision.reason}` }, "event");
@@ -14231,12 +14320,12 @@ ${parts.join("\n")}`);
14231
14320
  enqueueLoopMessage(push, label);
14232
14321
  if (!trackedSession.stopped) setTimeout(() => processMessageQueueRef?.(), 200);
14233
14322
  } else {
14234
- writeGoalLoopState(directory, sessionId, { active: false, phase: "gave_up", completed_at: Date.now(), gave_up_reason: decision.reason, holds, ledger, progress_history, auto_resumes: ls.auto_resumes });
14323
+ writeGoalLoopState(directory, sessionId, { active: false, phase: "gave_up", completed_at: Date.now(), gave_up_reason: decision.reason, holds, ledger, progress_history, auto_resumes: ls.auto_resumes, extensions });
14235
14324
  logger.log(`[Session ${sessionId}] [loop-persist] stuck-stop: ${decision.reason}`);
14236
14325
  checkSvampConfig?.();
14237
14326
  }
14238
14327
  } else {
14239
- writeGoalLoopState(directory, sessionId, { active: false, phase: "done", completed_at: Date.now(), holds, ledger, progress_history, auto_resumes: ls.auto_resumes });
14328
+ writeGoalLoopState(directory, sessionId, { active: false, phase: "done", completed_at: Date.now(), holds, ledger, progress_history, auto_resumes: ls.auto_resumes, extensions });
14240
14329
  checkSvampConfig?.();
14241
14330
  }
14242
14331
  } catch (e) {
@@ -14705,7 +14794,9 @@ ${parts.join("\n")}`);
14705
14794
  });
14706
14795
  ls.ledger = ledger;
14707
14796
  const startedAt = typeof ls.started_at === "number" ? ls.started_at : typeof ls.resumed_at === "number" ? ls.resumed_at : void 0;
14708
- const budgetCheck = process.env.SVAMP_LOOP_BUDGET === "0" ? { exceeded: false, kind: void 0 } : checkLoopBudget(ledger, { max_iterations: ls.max_iterations, ...ls.budget || {} }, now, startedAt);
14797
+ const maxExt = resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS);
14798
+ const effMaxIters = effectiveSoftCap(ls.max_iterations, ls.extensions, maxExt);
14799
+ const budgetCheck = process.env.SVAMP_LOOP_BUDGET === "0" ? { exceeded: false, kind: void 0 } : checkLoopBudget(ledger, { max_iterations: effMaxIters, ...ls.budget || {} }, now, startedAt);
14709
14800
  const pending = safeBacklogPendingCount(resolveProjectRoot(directory), sessionId);
14710
14801
  const prog = updateLoopProgress(ls, pending, now);
14711
14802
  ls.progress_history = prog.progress_history;
@@ -14722,7 +14813,9 @@ ${parts.join("\n")}`);
14722
14813
  progress_history: prog.progress_history,
14723
14814
  auto_resumes: prog.auto_resumes
14724
14815
  });
14725
- const detail = iterStop ? `${budgetCheck.reason} (hard iteration ceiling \u2014 will not auto-resume). Resume & extend with: svamp session loop-resume ${sessionId} --max <N>` : `${budgetCheck.reason} (hard cost ceiling \u2014 will not auto-resume). Resume & extend with: svamp session loop-resume ${sessionId} --max <N>`;
14816
+ const extNote = summarizeExtensions(ls.extensions, maxExt);
14817
+ const resumeHint = iterStop ? `Extend with a reason: svamp session loop-extend ${sessionId} --reason "<why>" \xB7 or set a new cap: svamp session loop-resume ${sessionId} --max <N>` : `Resume & extend with: svamp session loop-resume ${sessionId} --max <N>`;
14818
+ const detail = `${budgetCheck.reason} (hard ${iterStop ? "iteration ceiling" : "cost ceiling"} \u2014 will not auto-resume)${extNote ? ` [${extNote}]` : ""}. ${resumeHint}`;
14726
14819
  sessionService.pushMessage({ type: "message", message: `\u{1F6D1} Loop stopped \u2014 ${detail}`, level: "warning" }, "event");
14727
14820
  checkSvampConfig?.();
14728
14821
  } else if (process.env.SVAMP_LOOP_VERIFY === "0") {
@@ -15512,6 +15605,19 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15512
15605
  }
15513
15606
  signalProcessing(true);
15514
15607
  sessionWasProcessing = true;
15608
+ if (claudeResumeId && !trackedSession?.stopped) {
15609
+ saveSession({
15610
+ sessionId,
15611
+ directory,
15612
+ claudeResumeId,
15613
+ permissionMode: currentPermissionMode,
15614
+ spawnMeta: lastSpawnMeta,
15615
+ metadata: sessionMetadata,
15616
+ createdAt: sessionCreatedAt,
15617
+ machineId,
15618
+ wasProcessing: true
15619
+ });
15620
+ }
15515
15621
  } else {
15516
15622
  logger.log(`[Session ${sessionId}] Queuing inbox message for idle processing`);
15517
15623
  const existingQueue = sessionMetadata.messageQueue || [];
@@ -15581,11 +15687,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15581
15687
  });
15582
15688
  },
15583
15689
  onIssue: async (params) => {
15584
- const { issueRpc } = await import('./rpc-0HSLhpCb.mjs');
15690
+ const { issueRpc } = await import('./rpc-CMS1F7Qu.mjs');
15585
15691
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
15586
15692
  },
15587
15693
  onWorkflow: async (params) => {
15588
- const { workflowRpc } = await import('./rpc-BB-AxQa_.mjs');
15694
+ const { workflowRpc } = await import('./rpc-DTU-aE0V.mjs');
15589
15695
  return workflowRpc(params?.cwd || directory, params || {});
15590
15696
  },
15591
15697
  onRipgrep: async (args, cwd) => {
@@ -15724,6 +15830,19 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15724
15830
  message: { role: "user", content: next.text }
15725
15831
  });
15726
15832
  claudeProcess.stdin?.write(stdinMsg + "\n");
15833
+ if (claudeResumeId && !trackedSession?.stopped) {
15834
+ saveSession({
15835
+ sessionId,
15836
+ directory,
15837
+ claudeResumeId,
15838
+ permissionMode: currentPermissionMode,
15839
+ spawnMeta: lastSpawnMeta,
15840
+ metadata: sessionMetadata,
15841
+ createdAt: sessionCreatedAt,
15842
+ machineId,
15843
+ wasProcessing: true
15844
+ });
15845
+ }
15727
15846
  }
15728
15847
  } catch (err) {
15729
15848
  logger.log(`[Session ${sessionId}] Error in processMessageQueue spawn: ${err.message}`);
@@ -16121,11 +16240,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
16121
16240
  });
16122
16241
  },
16123
16242
  onIssue: async (params) => {
16124
- const { issueRpc } = await import('./rpc-0HSLhpCb.mjs');
16243
+ const { issueRpc } = await import('./rpc-CMS1F7Qu.mjs');
16125
16244
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
16126
16245
  },
16127
16246
  onWorkflow: async (params) => {
16128
- const { workflowRpc } = await import('./rpc-BB-AxQa_.mjs');
16247
+ const { workflowRpc } = await import('./rpc-DTU-aE0V.mjs');
16129
16248
  return workflowRpc(params?.cwd || directory, params || {});
16130
16249
  },
16131
16250
  onRipgrep: async (args, cwd) => {
@@ -16338,7 +16457,9 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
16338
16457
  return { ok: pending.length === 0, output: pending.length ? `${pending.length} pending: ${pending.map((i) => "#" + i.id).join(" ")}` : "No pending issues." };
16339
16458
  };
16340
16459
  try {
16341
- const budgetCheck = process.env.SVAMP_LOOP_BUDGET === "0" ? { exceeded: false, kind: void 0 } : checkLoopBudget(ledger, { max_iterations: ls.max_iterations, ...ls.budget || {} }, now, startedAt);
16460
+ const acpMaxExt = resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS);
16461
+ const acpEffMax = effectiveSoftCap(ls.max_iterations, ls.extensions, acpMaxExt);
16462
+ const budgetCheck = process.env.SVAMP_LOOP_BUDGET === "0" ? { exceeded: false, kind: void 0 } : checkLoopBudget(ledger, { max_iterations: acpEffMax, ...ls.budget || {} }, now, startedAt);
16342
16463
  const acpPending = safeBacklogPendingCount(projectRoot, sessionId);
16343
16464
  const acpProg = updateLoopProgress(ls, acpPending, now);
16344
16465
  ls.progress_history = acpProg.progress_history;
@@ -16346,7 +16467,9 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
16346
16467
  if (budgetCheck.exceeded && isHardBudgetStop(budgetCheck.kind)) {
16347
16468
  const iterStop = !isCostCeiling(budgetCheck.kind);
16348
16469
  writeGoalLoopState(directory, sessionId, { ...ls, active: false, phase: "gave_up", completed_at: now, gave_up_reason: `resource budget exhausted \u2014 ${budgetCheck.reason}`, ledger });
16349
- sessionService.pushMessage({ type: "message", message: `\u{1F6D1} Loop stopped \u2014 ${budgetCheck.reason} (hard ${iterStop ? "iteration ceiling" : "cost ceiling"} \u2014 will not auto-resume). Resume & extend with: svamp session loop-resume ${sessionId} --max <N>`, level: "warning" }, "event");
16470
+ const acpExtNote = summarizeExtensions(ls.extensions, acpMaxExt);
16471
+ const acpResumeHint = iterStop ? `Extend with a reason: svamp session loop-extend ${sessionId} --reason "<why>" \xB7 or set a new cap: svamp session loop-resume ${sessionId} --max <N>` : `Resume & extend with: svamp session loop-resume ${sessionId} --max <N>`;
16472
+ sessionService.pushMessage({ type: "message", message: `\u{1F6D1} Loop stopped \u2014 ${budgetCheck.reason} (hard ${iterStop ? "iteration ceiling" : "cost ceiling"} \u2014 will not auto-resume)${acpExtNote ? ` [${acpExtNote}]` : ""}. ${acpResumeHint}`, level: "warning" }, "event");
16350
16473
  checkSvampConfig?.();
16351
16474
  return;
16352
16475
  }
@@ -16383,7 +16506,8 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
16383
16506
  progressHistory: ls.progress_history || [],
16384
16507
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
16385
16508
  autoResumes: typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0,
16386
- maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES),
16509
+ // #0320: extensions also raise a FINITE auto-resume cap (no-op under the unbounded default).
16510
+ maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, acpMaxExt),
16387
16511
  stuckReason: result.reason
16388
16512
  });
16389
16513
  if (decision.action === "continue") {
@@ -17084,7 +17208,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
17084
17208
  const PING_TIMEOUT_MS = 15e3;
17085
17209
  const POST_RECONNECT_GRACE_MS = 2e4;
17086
17210
  const RECONNECT_JITTER_MS = 2500;
17087
- const { WorkflowScheduler } = await import('./scheduler-DaFydJPf.mjs');
17211
+ const { WorkflowScheduler } = await import('./scheduler-B92Z_kox.mjs');
17088
17212
  const workflowScheduler = new WorkflowScheduler({
17089
17213
  projectRoots: () => {
17090
17214
  const dirs = /* @__PURE__ */ new Set();
@@ -1,4 +1,4 @@
1
- import { n as resolveProjectRoot, H as listWorkflows, I as isWorkflowEnabled, J as workflowCrons, C as runWorkflow, K as cronMatches } from './run-hYUl-Fln.mjs';
1
+ import { n as resolveProjectRoot, H as listWorkflows, I as isWorkflowEnabled, J as workflowCrons, C as runWorkflow, K as cronMatches } from './run-BqqMOMZN.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -54,7 +54,7 @@ async function handleServeCommand() {
54
54
  }
55
55
  }
56
56
  async function serveAdd(args, machineId) {
57
- const { connectAndGetMachine } = await import('./commands-YPQSZ4Qx.mjs');
57
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.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-YPQSZ4Qx.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.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-YPQSZ4Qx.mjs');
185
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.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-YPQSZ4Qx.mjs');
205
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.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-YPQSZ4Qx.mjs');
238
+ const { connectAndGetMachine } = await import('./commands-Bz3xxhDd.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 { l as getHyphaServerUrl, S as ServeAuth, m as hasCookieToken } from './run-hYUl-Fln.mjs';
7
+ import { l as getHyphaServerUrl, S as ServeAuth, m as hasCookieToken } from './run-BqqMOMZN.mjs';
8
8
  import 'os';
9
9
  import 'fs/promises';
10
10
  import 'url';
@@ -751,7 +751,7 @@ class ServeManager {
751
751
  const mount = this.mounts.get(mountName);
752
752
  const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
753
753
  try {
754
- const { FrpcTunnel } = await import('./frpc-CLQB-GM1.mjs');
754
+ const { FrpcTunnel } = await import('./frpc-BBkDE65f.mjs');
755
755
  let tunnel;
756
756
  tunnel = new FrpcTunnel({
757
757
  name: tunnelName,
@@ -1,4 +1,4 @@
1
- import { R as READ_ONLY_TOOLS, N as loadMachineContext, O as buildMachineInstructions, P as machineToolsForRole, Q as buildMachineTools } from './run-hYUl-Fln.mjs';
1
+ import { R as READ_ONLY_TOOLS, N as loadMachineContext, O as buildMachineInstructions, P as machineToolsForRole, Q as buildMachineTools } from './run-BqqMOMZN.mjs';
2
2
  import 'node:child_process';
3
3
  import 'os';
4
4
  import 'fs/promises';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svamp-cli",
3
- "version": "0.2.253",
3
+ "version": "0.2.254",
4
4
  "description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
5
5
  "author": "Amun AI AB",
6
6
  "license": "SEE LICENSE IN LICENSE",