svamp-cli 0.2.128 → 0.2.130

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.
@@ -2677,7 +2677,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2677
2677
  const tunnels = handlers.tunnels;
2678
2678
  if (!tunnels) throw new Error("Tunnel management not available");
2679
2679
  if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
2680
- const { FrpcTunnel } = await import('./frpc-CWyoLax7.mjs');
2680
+ const { FrpcTunnel } = await import('./frpc-DrfDPPux.mjs');
2681
2681
  const tunnel = new FrpcTunnel({
2682
2682
  name: params.name,
2683
2683
  ports: params.ports,
@@ -2686,6 +2686,10 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2686
2686
  healthCheckType: params.healthCheckType,
2687
2687
  healthCheckPath: params.healthCheckPath,
2688
2688
  healthCheckInterval: params.healthCheckInterval,
2689
+ // Poll frpc's loopback admin API for backend-agnostic
2690
+ // ghost/stuck-proxy detection (the daemon health loop recreates
2691
+ // on persistent failure).
2692
+ adminStatus: true,
2689
2693
  onError: (err) => console.error(`[FRPC] ${params.name}: ${err.message}`),
2690
2694
  onConnect: () => console.log(`[FRPC] ${params.name}: connected`),
2691
2695
  onDisconnect: () => console.log(`[FRPC] ${params.name}: disconnected, will auto-reconnect`)
@@ -2718,14 +2722,47 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2718
2722
  handlers.forgetExposedTunnel?.(params.name);
2719
2723
  return { name: params.name, stopped: true };
2720
2724
  },
2721
- /** List active tunnels with health status. */
2725
+ /**
2726
+ * List the full CONFIGURED set of daemon-managed tunnels with a
2727
+ * derived per-tunnel `state`, not just the ones currently live. The
2728
+ * configured set comes from the persisted specs (survives restarts +
2729
+ * mid-recreate gaps); each is joined with its live FrpcTunnel status
2730
+ * if present. A tunnel that's persisted but not live (failed restore,
2731
+ * recreating) shows up as `reconnecting` instead of silently vanishing.
2732
+ */
2722
2733
  tunnelList: async (context) => {
2723
2734
  authorizeRequest(context, currentMetadata.sharing, "view");
2724
2735
  const tunnels = handlers.tunnels;
2725
2736
  if (!tunnels) return [];
2726
- return Array.from(tunnels.entries()).map(([, tunnel]) => ({
2727
- ...tunnel.status
2728
- }));
2737
+ const specs = handlers.listExposedTunnels?.() ?? [];
2738
+ const seen = /* @__PURE__ */ new Set();
2739
+ const rows = [];
2740
+ const stateOf = (s) => {
2741
+ if (!s) return "reconnecting";
2742
+ if (s.probe && !s.probe.ok) return "failed";
2743
+ if (s.connected) return "connected";
2744
+ return s.restartAttempts > 0 ? "reconnecting" : "failed";
2745
+ };
2746
+ for (const spec of specs) {
2747
+ seen.add(spec.name);
2748
+ const tunnel = tunnels.get(spec.name);
2749
+ const status = tunnel ? tunnel.status : null;
2750
+ rows.push({
2751
+ name: spec.name,
2752
+ ports: spec.ports,
2753
+ group: spec.group,
2754
+ configured: true,
2755
+ live: !!tunnel,
2756
+ state: stateOf(status),
2757
+ ...status ?? {}
2758
+ });
2759
+ }
2760
+ for (const [name, tunnel] of tunnels) {
2761
+ if (seen.has(name)) continue;
2762
+ const status = tunnel.status;
2763
+ rows.push({ ...status, name, configured: false, live: true, state: stateOf(status) });
2764
+ }
2765
+ return rows;
2729
2766
  },
2730
2767
  // ── Shared static file server ────────────────────────────────────
2731
2768
  /** Add a mount to the shared static file server. */
@@ -2938,7 +2975,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
2938
2975
  }
2939
2976
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
2940
2977
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
2941
- const { toolsForRole } = await import('./sideband-D5F6XGss.mjs');
2978
+ const { toolsForRole } = await import('./sideband-Bk7iN3dp.mjs');
2942
2979
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
2943
2980
  return fmt(r2);
2944
2981
  }
@@ -3037,7 +3074,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3037
3074
  if (r.error || !r.sender) return { error: r.error || "unauthorized" };
3038
3075
  const callId = "call_" + Math.random().toString(16).slice(2, 12);
3039
3076
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
3040
- const { queryCore } = await import('./commands-BVx72l2K.mjs');
3077
+ const { queryCore } = await import('./commands-QGaI-ukW.mjs');
3041
3078
  const timeout = c.reply?.timeout_sec || 120;
3042
3079
  let result;
3043
3080
  try {
@@ -3519,9 +3556,20 @@ function patchStoredText(msg, newText) {
3519
3556
  return true;
3520
3557
  }
3521
3558
  if (data?.type === "assistant" && Array.isArray(data?.message?.content)) {
3522
- const textBlocks = data.message.content.filter((b) => b && b.type === "text" && typeof b.text === "string");
3523
- if (textBlocks.length === 1) {
3559
+ const content = data.message.content;
3560
+ const isText = (b) => b && b.type === "text" && typeof b.text === "string";
3561
+ const textBlocks = content.filter(isText);
3562
+ if (textBlocks.length >= 1) {
3524
3563
  textBlocks[0].text = newText;
3564
+ let seen = false;
3565
+ data.message.content = content.filter((b) => {
3566
+ if (!isText(b)) return true;
3567
+ if (!seen) {
3568
+ seen = true;
3569
+ return true;
3570
+ }
3571
+ return false;
3572
+ });
3525
3573
  return true;
3526
3574
  }
3527
3575
  }
@@ -7734,11 +7782,21 @@ function applyTranscriptEdit(file, index, newText) {
7734
7782
  if (target.type === "assistant") {
7735
7783
  const content = target?.message?.content;
7736
7784
  if (!Array.isArray(content)) return { ok: false, reason: "assistant content is not a block array" };
7737
- const textBlocks = content.filter((b) => b && b.type === "text" && typeof b.text === "string");
7738
- if (textBlocks.length !== 1) {
7739
- return { ok: false, reason: `expected exactly 1 text block, found ${textBlocks.length}` };
7785
+ const isText = (b) => b && b.type === "text" && typeof b.text === "string";
7786
+ const textBlocks = content.filter(isText);
7787
+ if (textBlocks.length === 0) {
7788
+ return { ok: false, reason: "expected at least 1 text block, found 0" };
7740
7789
  }
7741
7790
  textBlocks[0].text = newText;
7791
+ let seen = false;
7792
+ target.message.content = content.filter((b) => {
7793
+ if (!isText(b)) return true;
7794
+ if (!seen) {
7795
+ seen = true;
7796
+ return true;
7797
+ }
7798
+ return false;
7799
+ });
7742
7800
  } else if (target.type === "user") {
7743
7801
  if (typeof target?.message?.content !== "string") {
7744
7802
  return { ok: false, reason: "user content is not a string" };
@@ -10804,15 +10862,32 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
10804
10862
  loopChecker();
10805
10863
  };
10806
10864
  const writeConfig = (patch) => {
10807
- if ("loop" in patch) {
10808
- const lp = patch.loop;
10809
- if (lp && typeof lp === "object" && typeof lp.task === "string" && lp.task.trim()) {
10810
- const oracle = typeof lp.oracle === "string" && lp.oracle.trim() ? lp.oracle.trim() : void 0;
10811
- const maxIterations = typeof lp.max_iterations === "number" ? lp.max_iterations : 20;
10812
- const evaluator = lp.evaluator !== false;
10865
+ const _gateKey = "loop" in patch ? "loop" : "supervisor" in patch ? "supervisor" : null;
10866
+ if (_gateKey) {
10867
+ let cfg = patch[_gateKey];
10868
+ if (_gateKey === "supervisor" && cfg && typeof cfg === "object") {
10869
+ const j = Array.isArray(cfg.judges) ? cfg.judges : [];
10870
+ const oj = j.find((x) => x?.type === "oracle");
10871
+ const pj = j.find((x) => x?.type === "parent");
10872
+ cfg = {
10873
+ // legacy supervisor = hot-plug (no task); criteria → until.
10874
+ until: cfg.criteria,
10875
+ oracle: (oj && typeof oj.cmd === "string" ? oj.cmd : void 0) || cfg.oracle,
10876
+ evaluator: j.length === 0 || j.some((x) => x?.type === "agent"),
10877
+ parent: pj?.parent || cfg.parent,
10878
+ max_iterations: cfg.max_rounds
10879
+ };
10880
+ }
10881
+ const task = cfg && typeof cfg.task === "string" && cfg.task.trim() ? cfg.task.trim() : void 0;
10882
+ 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;
10883
+ if (cfg && typeof cfg === "object" && (task || until)) {
10884
+ const oracle = typeof cfg.oracle === "string" && cfg.oracle.trim() ? cfg.oracle.trim() : void 0;
10885
+ const evaluator = cfg.evaluator !== false;
10886
+ const maxIterations = typeof cfg.max_iterations === "number" ? cfg.max_iterations : typeof cfg.max_rounds === "number" ? cfg.max_rounds : 20;
10813
10887
  const ok = initLoop(directory, {
10814
- task: lp.task.trim(),
10815
- criteria: typeof lp.criteria === "string" && lp.criteria.trim() ? lp.criteria.trim() : void 0,
10888
+ task: task || until,
10889
+ // LOOP.md goal = the task, or the until-criteria when hot-plugging
10890
+ criteria: until,
10816
10891
  oracle,
10817
10892
  maxIterations,
10818
10893
  evaluator,
@@ -10820,24 +10895,23 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
10820
10895
  });
10821
10896
  if (ok) {
10822
10897
  const existingQueue = getMetadata().messageQueue || [];
10823
- const kickoff = "Begin the loop. Read LOOP.md and work on the task until the exit conditions are met. Do not stop early \u2014 an independent Stop gate will re-check before the loop can end.";
10824
- setMetadata((m) => ({
10825
- ...m,
10826
- messageQueue: [...existingQueue, {
10827
- id: randomUUID$1(),
10828
- text: kickoff,
10829
- // Compact chat badge; full task lives in LOOP.md. Show an ellipsis
10830
- // when truncated so it's clear the preview is shortened, not the task.
10831
- displayText: `\u{1F501} Loop started: ${lp.task.trim().slice(0, 100)}${lp.task.trim().length > 100 ? "\u2026" : ""}`,
10832
- createdAt: Date.now()
10833
- }]
10834
- }));
10898
+ if (task) {
10899
+ const kickoff = "Begin the loop. Read LOOP.md and work on the task until the exit conditions are met. Do not stop early \u2014 an independent Stop gate will re-check before the loop can end.";
10900
+ setMetadata((m) => ({ ...m, messageQueue: [...existingQueue, { id: randomUUID$1(), text: kickoff, displayText: `\u{1F501} Loop started: ${task.slice(0, 100)}${task.length > 100 ? "\u2026" : ""}`, createdAt: Date.now() }] }));
10901
+ } else {
10902
+ const idle = getMetadata().lifecycleState === "idle";
10903
+ if (idle) {
10904
+ const nudge = `A loop gate is now active. Keep working until this is met: ${until}
10905
+ Or verify and finish \u2014 an independent Stop gate re-checks before you can stop.`;
10906
+ setMetadata((m) => ({ ...m, messageQueue: [...existingQueue, { id: randomUUID$1(), text: nudge, displayText: `\u{1F501} Loop until: ${until.slice(0, 100)}${until.length > 100 ? "\u2026" : ""}`, createdAt: Date.now() }] }));
10907
+ }
10908
+ }
10909
+ onLoopActivated?.();
10835
10910
  sessionService.pushMessage(
10836
- { type: "message", message: `\u{1F501} Loop started \u2014 iterating until done (oracle: ${oracle || "none"}, evaluator ${evaluator ? "on" : "off"}, max ${maxIterations}).` },
10911
+ { type: "message", message: `\u{1F501} Loop active \u2014 ${task ? "iterating on the task" : "gating current work"} (until: ${until || "done"}, oracle: ${oracle || "none"}, evaluator ${evaluator ? "on" : "off"}, max ${maxIterations}).` },
10837
10912
  "event"
10838
10913
  );
10839
- logger.log(`[svampConfig] Loop started: "${lp.task.trim().slice(0, 50)}..."`);
10840
- onLoopActivated?.();
10914
+ logger.log(`[svampConfig] Loop active (${task ? "kickoff" : "hot-plug"}): until="${(until || task || "").slice(0, 50)}"`);
10841
10915
  } else {
10842
10916
  sessionService.pushMessage(
10843
10917
  { type: "message", message: "Failed to start loop \u2014 the loop skill could not be located. Reinstall with: svamp skills install loop --force", level: "error" },
@@ -10850,54 +10924,7 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
10850
10924
  sessionService.pushMessage({ type: "message", message: "Loop cancelled." }, "event");
10851
10925
  logger.log(`[svampConfig] Loop cancelled`);
10852
10926
  }
10853
- const { loop: _, ...restPatch } = patch;
10854
- patch = restPatch;
10855
- }
10856
- if ("supervisor" in patch) {
10857
- const sup = patch.supervisor;
10858
- if (sup && typeof sup === "object" && typeof sup.criteria === "string" && sup.criteria.trim()) {
10859
- const criteria = sup.criteria.trim();
10860
- const judges = Array.isArray(sup.judges) ? sup.judges : [];
10861
- const oracleJudge = judges.find((j) => j?.type === "oracle");
10862
- const oracle = oracleJudge && typeof oracleJudge.cmd === "string" && oracleJudge.cmd.trim() ? oracleJudge.cmd.trim() : typeof sup.oracle === "string" && sup.oracle.trim() ? sup.oracle.trim() : void 0;
10863
- const hasAgentJudge = judges.length === 0 || judges.some((j) => j?.type === "agent");
10864
- const maxRounds = typeof sup.max_rounds === "number" ? sup.max_rounds : 20;
10865
- const ok = initLoop(directory, {
10866
- task: criteria,
10867
- // P1: criteria seeds LOOP.md as the goal (skill carries it as config.criteria in #30)
10868
- criteria,
10869
- oracle,
10870
- maxIterations: maxRounds,
10871
- evaluator: hasAgentJudge,
10872
- sessionId
10873
- });
10874
- if (ok) {
10875
- const judgeLabel = judges.length ? judges.map((j) => j.type).join("\u2192") : "agent";
10876
- const idle = getMetadata().lifecycleState === "idle";
10877
- if (idle) {
10878
- const existingQueue = getMetadata().messageQueue || [];
10879
- const nudge = `You are now under supervision. Success criteria: ${criteria}
10880
- Continue working until they are met, or verify and finish \u2014 an independent Stop gate will re-check before you can stop.`;
10881
- setMetadata((m) => ({ ...m, messageQueue: [...existingQueue, { id: randomUUID$1(), text: nudge, displayText: `\u{1F441} Supervisor attached`, createdAt: Date.now() }] }));
10882
- onLoopActivated?.();
10883
- }
10884
- sessionService.pushMessage(
10885
- { type: "message", message: `\u{1F441} Supervisor attached \u2014 judges: ${judgeLabel}, max ${maxRounds}. Criteria: ${criteria.slice(0, 120)}${criteria.length > 120 ? "\u2026" : ""}` },
10886
- "event"
10887
- );
10888
- logger.log(`[svampConfig] Supervisor attached (judges: ${judgeLabel}, max ${maxRounds})`);
10889
- } else {
10890
- sessionService.pushMessage(
10891
- { type: "message", message: "Failed to attach supervisor \u2014 the loop skill could not be located. Reinstall with: svamp skills install loop --force", level: "error" },
10892
- "event"
10893
- );
10894
- }
10895
- } else {
10896
- deactivateLoop(directory, sessionId);
10897
- sessionService.pushMessage({ type: "message", message: "Supervisor detached." }, "event");
10898
- logger.log(`[svampConfig] Supervisor detached`);
10899
- }
10900
- const { supervisor: _s, ...restPatch } = patch;
10927
+ const { [_gateKey]: _drop, ...restPatch } = patch;
10901
10928
  patch = restPatch;
10902
10929
  }
10903
10930
  if ("checklist" in patch) {
@@ -11359,7 +11386,28 @@ async function startDaemon(options) {
11359
11386
  const list = loadExposedTunnels().filter((t) => t.name !== name);
11360
11387
  saveExposedTunnels(list);
11361
11388
  }
11362
- const { ServeManager } = await import('./serveManager-CxbgXYEo.mjs');
11389
+ async function createExposedTunnel(spec) {
11390
+ const { FrpcTunnel } = await import('./frpc-DrfDPPux.mjs');
11391
+ const tunnel = new FrpcTunnel({
11392
+ name: spec.name,
11393
+ ports: spec.ports,
11394
+ group: spec.group,
11395
+ groupKey: spec.groupKey,
11396
+ healthCheckType: spec.healthCheckType,
11397
+ healthCheckPath: spec.healthCheckPath,
11398
+ healthCheckInterval: spec.healthCheckInterval,
11399
+ // Backend-agnostic ghost/stuck-proxy detection via frpc's loopback
11400
+ // admin API — exposed backends rarely have an HTTP health endpoint.
11401
+ adminStatus: true,
11402
+ onError: (err) => logger.log(`[FRPC ${spec.name}] ${err.message}`),
11403
+ onConnect: () => logger.log(`[FRPC ${spec.name}] connected`),
11404
+ onDisconnect: () => logger.log(`[FRPC ${spec.name}] disconnected, will auto-reconnect`)
11405
+ });
11406
+ await tunnel.connect();
11407
+ return tunnel;
11408
+ }
11409
+ const tunnelRecreateState = /* @__PURE__ */ new Map();
11410
+ const { ServeManager } = await import('./serveManager-Csqa6icR.mjs');
11363
11411
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
11364
11412
  ensureAutoInstalledSkills(logger).catch(() => {
11365
11413
  });
@@ -14019,7 +14067,8 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14019
14067
  serveManager,
14020
14068
  sharingNotificationSync,
14021
14069
  persistExposedTunnel,
14022
- forgetExposedTunnel
14070
+ forgetExposedTunnel,
14071
+ listExposedTunnels: () => loadExposedTunnels().map((t) => ({ name: t.name, ports: t.ports, group: t.group, addedAt: t.addedAt }))
14023
14072
  }
14024
14073
  );
14025
14074
  logger.log(`Machine service registered: svamp-machine-${machineId}`);
@@ -14047,23 +14096,10 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14047
14096
  const specs = loadExposedTunnels();
14048
14097
  if (specs.length === 0) return;
14049
14098
  logger.log(`[exposed-tunnels] Restoring ${specs.length} tunnel(s) from ${EXPOSED_TUNNELS_FILE}`);
14050
- const { FrpcTunnel } = await import('./frpc-CWyoLax7.mjs');
14051
14099
  for (const spec of specs) {
14052
14100
  if (tunnels.has(spec.name)) continue;
14053
14101
  try {
14054
- const tunnel = new FrpcTunnel({
14055
- name: spec.name,
14056
- ports: spec.ports,
14057
- group: spec.group,
14058
- groupKey: spec.groupKey,
14059
- healthCheckType: spec.healthCheckType,
14060
- healthCheckPath: spec.healthCheckPath,
14061
- healthCheckInterval: spec.healthCheckInterval,
14062
- onError: (err) => logger.log(`[FRPC ${spec.name}] ${err.message}`),
14063
- onConnect: () => logger.log(`[FRPC ${spec.name}] connected (restored)`),
14064
- onDisconnect: () => logger.log(`[FRPC ${spec.name}] disconnected, will auto-reconnect`)
14065
- });
14066
- await tunnel.connect();
14102
+ const tunnel = await createExposedTunnel(spec);
14067
14103
  tunnels.set(spec.name, tunnel);
14068
14104
  logger.log(`[exposed-tunnels] Restored: ${spec.name} \u2192 ports ${spec.ports.join(",")}`);
14069
14105
  } catch (err) {
@@ -14421,11 +14457,39 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14421
14457
  for (const [name, tunnel] of tunnels) {
14422
14458
  const health = tunnel.status;
14423
14459
  const reason = tunnelLooksDead(health);
14424
- if (reason) {
14425
- logger.log(`frpc tunnel '${name}' ${reason} \u2014 destroying stale tunnel`);
14426
- tunnel.destroy();
14460
+ if (!reason) {
14461
+ tunnelRecreateState.delete(name);
14462
+ continue;
14463
+ }
14464
+ const spec = loadExposedTunnels().find((t) => t.name === name);
14465
+ if (!spec) {
14466
+ logger.log(`frpc tunnel '${name}' ${reason}, no persisted spec \u2014 destroying (cannot recreate)`);
14467
+ try {
14468
+ tunnel.destroy();
14469
+ } catch {
14470
+ }
14427
14471
  tunnels.delete(name);
14472
+ tunnelRecreateState.delete(name);
14473
+ continue;
14428
14474
  }
14475
+ const now = Date.now();
14476
+ const st = tunnelRecreateState.get(name) ?? { nextAttemptAt: 0, attempts: 0 };
14477
+ if (now < st.nextAttemptAt) continue;
14478
+ st.attempts++;
14479
+ st.nextAttemptAt = now + Math.min(15e3 * Math.pow(2, st.attempts - 1), 5 * 6e4);
14480
+ tunnelRecreateState.set(name, st);
14481
+ logger.log(`frpc tunnel '${name}' ${reason} \u2014 recreating (attempt ${st.attempts})`);
14482
+ try {
14483
+ tunnel.destroy();
14484
+ } catch {
14485
+ }
14486
+ tunnels.delete(name);
14487
+ createExposedTunnel(spec).then((fresh) => {
14488
+ tunnels.set(name, fresh);
14489
+ logger.log(`frpc tunnel '${name}' recreated`);
14490
+ }).catch((err) => {
14491
+ logger.log(`frpc tunnel '${name}' recreate failed: ${err.message} (will retry)`);
14492
+ });
14429
14493
  }
14430
14494
  } finally {
14431
14495
  heartbeatRunning = false;
@@ -54,7 +54,7 @@ async function handleServeCommand() {
54
54
  }
55
55
  }
56
56
  async function serveAdd(args, machineId) {
57
- const { connectAndGetMachine } = await import('./commands-BVx72l2K.mjs');
57
+ const { connectAndGetMachine } = await import('./commands-QGaI-ukW.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-BVx72l2K.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-QGaI-ukW.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-BVx72l2K.mjs');
185
+ const { connectAndGetMachine } = await import('./commands-QGaI-ukW.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-BVx72l2K.mjs');
205
+ const { connectAndGetMachine } = await import('./commands-QGaI-ukW.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-BVx72l2K.mjs');
238
+ const { connectAndGetMachine } = await import('./commands-QGaI-ukW.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 { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-C23-A9KM.mjs';
7
+ import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-DMahGhJP.mjs';
8
8
  import 'os';
9
9
  import 'fs/promises';
10
10
  import 'url';
@@ -713,7 +713,7 @@ class ServeManager {
713
713
  const mount = this.mounts.get(mountName);
714
714
  const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, `static-${subdomainSafe}-${mount.linkToken}`]]) : void 0;
715
715
  try {
716
- const { FrpcTunnel } = await import('./frpc-CWyoLax7.mjs');
716
+ const { FrpcTunnel } = await import('./frpc-DrfDPPux.mjs');
717
717
  let tunnel;
718
718
  tunnel = new FrpcTunnel({
719
719
  name: tunnelName,
@@ -1,4 +1,4 @@
1
- import { R as READ_ONLY_TOOLS, z as loadMachineContext, A as buildMachineInstructions, B as machineToolsForRole, C as buildMachineTools } from './run-C23-A9KM.mjs';
1
+ import { R as READ_ONLY_TOOLS, z as loadMachineContext, A as buildMachineInstructions, B as machineToolsForRole, C as buildMachineTools } from './run-DMahGhJP.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.128",
3
+ "version": "0.2.130",
4
4
  "description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
5
5
  "author": "Amun AI AB",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -20,7 +20,7 @@
20
20
  "scripts": {
21
21
  "build": "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/loop bin/skills/loop && cp -r ../../skills/crew bin/skills/crew && tsc --noEmit && pkgroll",
22
22
  "typecheck": "tsc --noEmit",
23
- "test": "npx tsx test/test-context-window.mjs && npx tsx test/test-instance-config.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-loop-activation.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-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.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-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.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-checklist.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.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 && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-checklist-watchdog.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs",
23
+ "test": "npx tsx test/test-context-window.mjs && npx tsx test/test-instance-config.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-loop-activation.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-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.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-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.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-checklist.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.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 && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-checklist-watchdog.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs",
24
24
  "test:hypha": "node --no-warnings test/test-hypha-service.mjs",
25
25
  "dev": "tsx src/cli.ts",
26
26
  "dev:daemon": "tsx src/cli.ts daemon start-sync",