svamp-cli 0.2.107 → 0.2.108

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 (26) hide show
  1. package/bin/skills/loop/bin/inject-loop.mjs +20 -6
  2. package/bin/skills/loop/bin/loop-init.mjs +21 -8
  3. package/bin/skills/loop/bin/loop-status.mjs +17 -4
  4. package/bin/skills/loop/bin/precompact.mjs +5 -2
  5. package/bin/skills/loop/bin/state-fp.mjs +5 -7
  6. package/bin/skills/loop/bin/stop-gate.mjs +17 -4
  7. package/bin/skills/loop/test/test-loop-gate.mjs +55 -18
  8. package/dist/{agentCommands-CduKZKhS.mjs → agentCommands-Cpq_Yk3h.mjs} +2 -2
  9. package/dist/{auth-Df9Vbe1o.mjs → auth-DBKbI5IE.mjs} +1 -1
  10. package/dist/cli.mjs +50 -50
  11. package/dist/{commands-Db5oGiGF.mjs → commands-4JPwWmBF.mjs} +2 -2
  12. package/dist/{commands-B6uZpAXr.mjs → commands-B7z0Yoi7.mjs} +1 -1
  13. package/dist/{commands-Bq2anCn7.mjs → commands-CjuVNGG4.mjs} +1 -1
  14. package/dist/{commands-DkDAm71w.mjs → commands-D38_YkF9.mjs} +5 -5
  15. package/dist/{commands-DMfzyn8l.mjs → commands-DOsK9QRw.mjs} +24 -8
  16. package/dist/{fleet-kxxGXRSB.mjs → fleet-D-YD8lYU.mjs} +1 -1
  17. package/dist/{frpc-C9lPF2nK.mjs → frpc-C5Bhpsdw.mjs} +1 -1
  18. package/dist/{headlessCli-BgWGL3_l.mjs → headlessCli-Cwqhpbm1.mjs} +2 -2
  19. package/dist/index.mjs +1 -1
  20. package/dist/{package-VWSohGLN.mjs → package-D7tAsMPM.mjs} +1 -1
  21. package/dist/{run-CCsUvTEL.mjs → run-LyzVTe3J.mjs} +44 -26
  22. package/dist/{run-CvT9o581.mjs → run-TjecLji1.mjs} +1 -1
  23. package/dist/{serveCommands-tid4kA9J.mjs → serveCommands-XlqflmVF.mjs} +5 -5
  24. package/dist/{serveManager-CeM1exTU.mjs → serveManager-QZxNxQq0.mjs} +2 -2
  25. package/dist/{sideband-fu9NMI64.mjs → sideband-CgiHKPJo.mjs} +1 -1
  26. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import os$1, { homedir as homedir$1 } from 'os';
2
2
  import fs, { mkdir as mkdir$1, readdir as readdir$1, readFile, writeFile as writeFile$1, rename, unlink } from 'fs/promises';
3
- import { readFileSync as readFileSync$1, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, renameSync as renameSync$1, existsSync as existsSync$1, rmSync as rmSync$1, unlinkSync as unlinkSync$1, copyFileSync, watch, rmdirSync, readdirSync as readdirSync$1 } from 'fs';
3
+ import { readFileSync as readFileSync$1, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, renameSync as renameSync$1, existsSync as existsSync$1, rmSync as rmSync$1, unlinkSync as unlinkSync$1, copyFileSync, readdirSync as readdirSync$1, watch, rmdirSync } from 'fs';
4
4
  import path__default, { join as join$1, dirname, basename, resolve } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { execFile, spawn as spawn$1, execSync as execSync$1, spawnSync } from 'child_process';
@@ -2527,7 +2527,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2527
2527
  const tunnels = handlers.tunnels;
2528
2528
  if (!tunnels) throw new Error("Tunnel management not available");
2529
2529
  if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
2530
- const { FrpcTunnel } = await import('./frpc-C9lPF2nK.mjs');
2530
+ const { FrpcTunnel } = await import('./frpc-C5Bhpsdw.mjs');
2531
2531
  const tunnel = new FrpcTunnel({
2532
2532
  name: params.name,
2533
2533
  ports: params.ports,
@@ -2788,7 +2788,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
2788
2788
  }
2789
2789
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
2790
2790
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
2791
- const { toolsForRole } = await import('./sideband-fu9NMI64.mjs');
2791
+ const { toolsForRole } = await import('./sideband-CgiHKPJo.mjs');
2792
2792
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
2793
2793
  return fmt(r2);
2794
2794
  }
@@ -2887,7 +2887,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
2887
2887
  if (r.error || !r.sender) return { error: r.error || "unauthorized" };
2888
2888
  const callId = "call_" + Math.random().toString(16).slice(2, 12);
2889
2889
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
2890
- const { queryCore } = await import('./commands-DMfzyn8l.mjs');
2890
+ const { queryCore } = await import('./commands-DOsK9QRw.mjs');
2891
2891
  const timeout = c.reply?.timeout_sec || 120;
2892
2892
  let result;
2893
2893
  try {
@@ -9698,29 +9698,36 @@ function writeSvampConfig(configPath, config) {
9698
9698
  renameSync$1(tmpPath, configPath);
9699
9699
  return content;
9700
9700
  }
9701
- function getLoopDir(directory) {
9701
+ function getLoopDir(directory, sessionId) {
9702
+ if (sessionId) {
9703
+ const scoped = join$1(directory, ".svamp", sessionId, "loop");
9704
+ if (existsSync$1(join$1(scoped, "loop-state.json"))) return scoped;
9705
+ const legacy = join$1(directory, ".claude", "loop");
9706
+ if (existsSync$1(join$1(legacy, "loop-state.json"))) return legacy;
9707
+ return scoped;
9708
+ }
9702
9709
  return join$1(directory, ".claude", "loop");
9703
9710
  }
9704
- function readLoopState(directory) {
9711
+ function readLoopState(directory, sessionId) {
9705
9712
  try {
9706
- const p = join$1(getLoopDir(directory), "loop-state.json");
9713
+ const p = join$1(getLoopDir(directory, sessionId), "loop-state.json");
9707
9714
  if (!existsSync$1(p)) return null;
9708
9715
  return JSON.parse(readFileSync$1(p, "utf-8"));
9709
9716
  } catch {
9710
9717
  return null;
9711
9718
  }
9712
9719
  }
9713
- function isLoopActive(directory) {
9714
- const s = readLoopState(directory);
9720
+ function isLoopActive(directory, sessionId) {
9721
+ const s = readLoopState(directory, sessionId);
9715
9722
  return !!s && s.active !== false && s.phase !== "done" && s.phase !== "gave_up" && s.phase !== "cancelled";
9716
9723
  }
9717
- function loopOwnerSession(directory) {
9718
- const s = readLoopState(directory);
9724
+ function loopOwnerSession(directory, sessionId) {
9725
+ const s = readLoopState(directory, sessionId);
9719
9726
  if (!s || s.active === false || s.phase === "done" || s.phase === "gave_up" || s.phase === "cancelled") return null;
9720
9727
  return typeof s.session_id === "string" ? s.session_id : null;
9721
9728
  }
9722
9729
  function isLoopActiveForSession(directory, sessionId) {
9723
- const s = readLoopState(directory);
9730
+ const s = readLoopState(directory, sessionId);
9724
9731
  if (!s || s.active === false || s.phase === "done" || s.phase === "gave_up" || s.phase === "cancelled") return false;
9725
9732
  if (typeof s.session_id !== "string") return true;
9726
9733
  return s.session_id === sessionId;
@@ -9746,9 +9753,9 @@ function initLoop(directory, cfg) {
9746
9753
  const res = spawnSync(process.execPath, args, { encoding: "utf-8", timeout: 3e4 });
9747
9754
  return res.status === 0;
9748
9755
  }
9749
- function deactivateLoop(directory) {
9756
+ function deactivateLoop(directory, sessionId) {
9750
9757
  try {
9751
- const p = join$1(getLoopDir(directory), "loop-state.json");
9758
+ const p = join$1(getLoopDir(directory, sessionId), "loop-state.json");
9752
9759
  if (!existsSync$1(p)) return;
9753
9760
  const s = JSON.parse(readFileSync$1(p, "utf-8"));
9754
9761
  s.active = false;
@@ -9873,7 +9880,7 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
9873
9880
  logger.log(`[svampConfig] Loop init failed \u2014 loop-init.mjs not found`);
9874
9881
  }
9875
9882
  } else {
9876
- deactivateLoop(directory);
9883
+ deactivateLoop(directory, sessionId);
9877
9884
  sessionService.pushMessage({ type: "message", message: "Loop cancelled." }, "event");
9878
9885
  logger.log(`[svampConfig] Loop cancelled`);
9879
9886
  }
@@ -10307,7 +10314,7 @@ async function startDaemon(options) {
10307
10314
  const list = loadExposedTunnels().filter((t) => t.name !== name);
10308
10315
  saveExposedTunnels(list);
10309
10316
  }
10310
- const { ServeManager } = await import('./serveManager-CeM1exTU.mjs');
10317
+ const { ServeManager } = await import('./serveManager-QZxNxQq0.mjs');
10311
10318
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
10312
10319
  ensureAutoInstalledSkills(logger).catch(() => {
10313
10320
  });
@@ -10546,7 +10553,7 @@ async function startDaemon(options) {
10546
10553
  stuckWatchdogTimer = setInterval(() => {
10547
10554
  if (!claudeProcess || claudeProcess.exitCode !== null) return;
10548
10555
  if (!sessionWasProcessing) return;
10549
- if (!isLoopActive(directory)) return;
10556
+ if (!isLoopActive(directory, sessionId)) return;
10550
10557
  if (claudeProcess.pid && hasActiveChildren(claudeProcess.pid)) {
10551
10558
  lastOutputTime = Date.now();
10552
10559
  return;
@@ -10560,7 +10567,7 @@ async function startDaemon(options) {
10560
10567
  );
10561
10568
  claudeProcess.kill("SIGTERM");
10562
10569
  setTimeout(() => {
10563
- if (!trackedSession.stopped && isLoopActive(directory)) {
10570
+ if (!trackedSession.stopped && isLoopActive(directory, sessionId)) {
10564
10571
  logger.log(`[Session ${sessionId}] Stuck watchdog: nudging loop to resume`);
10565
10572
  enqueueLoopContinue();
10566
10573
  processMessageQueueRef?.();
@@ -10668,7 +10675,7 @@ async function startDaemon(options) {
10668
10675
  if (options2.forceIsolation || sessionMetadata.sharing?.enabled) {
10669
10676
  rawPermissionMode = rawPermissionMode === "default" ? "auto-approve-all" : rawPermissionMode;
10670
10677
  }
10671
- if (isLoopActive(directory)) {
10678
+ if (isLoopActiveForSession(directory, sessionId)) {
10672
10679
  rawPermissionMode = "bypassPermissions";
10673
10680
  }
10674
10681
  const permissionMode = toClaudePermissionMode(rawPermissionMode);
@@ -10941,7 +10948,7 @@ async function startDaemon(options) {
10941
10948
  }
10942
10949
  }
10943
10950
  if (msg.type === "result") {
10944
- const loopActive = isLoopActive(directory);
10951
+ const loopActive = isLoopActiveForSession(directory, sessionId);
10945
10952
  if (!turnInitiatedByUser && !loopActive) {
10946
10953
  logger.log(`[Session ${sessionId}] Skipping stale result from SDK-initiated turn`);
10947
10954
  const hasBackgroundTasks = backgroundTaskCount > 0;
@@ -12464,7 +12471,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
12464
12471
  const wasInMemory = teardownTrackedSession(sessionId);
12465
12472
  const markedArchived = markSessionAsArchived(sessionId);
12466
12473
  if (loopDir && isLoopActiveForSession(loopDir, sessionId)) {
12467
- deactivateLoop(loopDir);
12474
+ deactivateLoop(loopDir, sessionId);
12468
12475
  logger.log(`Deactivated loop for archived session ${sessionId}`);
12469
12476
  }
12470
12477
  if (wasInMemory || markedArchived) {
@@ -12521,7 +12528,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
12521
12528
  teardownTrackedSession(sessionId);
12522
12529
  deletePersistedSession(sessionId);
12523
12530
  if (loopDir && isLoopActiveForSession(loopDir, sessionId)) {
12524
- deactivateLoop(loopDir);
12531
+ deactivateLoop(loopDir, sessionId);
12525
12532
  }
12526
12533
  logger.log(`Session ${sessionId} deleted`);
12527
12534
  return true;
@@ -12669,7 +12676,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
12669
12676
  const specs = loadExposedTunnels();
12670
12677
  if (specs.length === 0) return;
12671
12678
  logger.log(`[exposed-tunnels] Restoring ${specs.length} tunnel(s) from ${EXPOSED_TUNNELS_FILE}`);
12672
- const { FrpcTunnel } = await import('./frpc-C9lPF2nK.mjs');
12679
+ const { FrpcTunnel } = await import('./frpc-C5Bhpsdw.mjs');
12673
12680
  for (const spec of specs) {
12674
12681
  if (tunnels.has(spec.name)) continue;
12675
12682
  try {
@@ -12757,10 +12764,21 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
12757
12764
  for (const p of persistedSessions) {
12758
12765
  if (sweptDirs.has(p.directory)) continue;
12759
12766
  sweptDirs.add(p.directory);
12760
- const owner = loopOwnerSession(p.directory);
12761
- if (owner && !knownSessionIds.has(owner)) {
12767
+ try {
12768
+ for (const ent of readdirSync$1(join$1(p.directory, ".svamp"), { withFileTypes: true })) {
12769
+ if (!ent.isDirectory() || knownSessionIds.has(ent.name)) continue;
12770
+ const owner = loopOwnerSession(p.directory, ent.name);
12771
+ if (owner && !knownSessionIds.has(owner)) {
12772
+ deactivateLoop(p.directory, ent.name);
12773
+ logger.log(`[loop] Deactivated stale loop-state for ${ent.name} in ${p.directory} (owner no longer known)`);
12774
+ }
12775
+ }
12776
+ } catch {
12777
+ }
12778
+ const legacyOwner = loopOwnerSession(p.directory);
12779
+ if (legacyOwner && !knownSessionIds.has(legacyOwner)) {
12762
12780
  deactivateLoop(p.directory);
12763
- logger.log(`[loop] Deactivated stale loop-state in ${p.directory} (owner session ${owner} no longer known)`);
12781
+ logger.log(`[loop] Deactivated stale legacy loop-state in ${p.directory} (owner session ${legacyOwner} no longer known)`);
12764
12782
  }
12765
12783
  }
12766
12784
  }
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
2
2
  import os from 'node:os';
3
3
  import { resolve, join } from 'node:path';
4
4
  import { existsSync, readFileSync, watch } from 'node:fs';
5
- import { c as connectToHypha, a as createSessionStore, r as registerMachineService, P as generateHookSettings } from './run-CCsUvTEL.mjs';
5
+ import { c as connectToHypha, a as createSessionStore, r as registerMachineService, P as generateHookSettings } from './run-LyzVTe3J.mjs';
6
6
  import { createServer } from 'node:http';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';
@@ -54,7 +54,7 @@ async function handleServeCommand() {
54
54
  }
55
55
  }
56
56
  async function serveAdd(args, machineId) {
57
- const { connectAndGetMachine } = await import('./commands-DMfzyn8l.mjs');
57
+ const { connectAndGetMachine } = await import('./commands-DOsK9QRw.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-DMfzyn8l.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-DOsK9QRw.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-DMfzyn8l.mjs');
185
+ const { connectAndGetMachine } = await import('./commands-DOsK9QRw.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-DMfzyn8l.mjs');
205
+ const { connectAndGetMachine } = await import('./commands-DOsK9QRw.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-DMfzyn8l.mjs');
238
+ const { connectAndGetMachine } = await import('./commands-DOsK9QRw.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-CCsUvTEL.mjs';
7
+ import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-LyzVTe3J.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-C9lPF2nK.mjs');
716
+ const { FrpcTunnel } = await import('./frpc-C5Bhpsdw.mjs');
717
717
  let tunnel;
718
718
  tunnel = new FrpcTunnel({
719
719
  name: tunnelName,
@@ -1,4 +1,4 @@
1
- import { z as READ_ONLY_TOOLS, A as loadMachineContext, B as buildMachineInstructions, C as machineToolsForRole, D as buildMachineTools } from './run-CCsUvTEL.mjs';
1
+ import { z as READ_ONLY_TOOLS, A as loadMachineContext, B as buildMachineInstructions, C as machineToolsForRole, D as buildMachineTools } from './run-LyzVTe3J.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.107",
3
+ "version": "0.2.108",
4
4
  "description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
5
5
  "author": "Amun AI AB",
6
6
  "license": "SEE LICENSE IN LICENSE",