svamp-cli 0.2.197 → 0.2.199

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-Dxuc65V_.mjs → agentCommands-C7HrSvD_.mjs} +5 -5
  2. package/dist/{auth-DweBQRAL.mjs → auth-BXaEbJ34.mjs} +1 -1
  3. package/dist/cli.mjs +60 -60
  4. package/dist/{commands-Bxb8oEBa.mjs → commands-B1lil9Ip.mjs} +1 -1
  5. package/dist/{commands-BF7fzTcc.mjs → commands-BfmWL88p.mjs} +1 -1
  6. package/dist/{commands-BJ3G0VVJ.mjs → commands-BnTqC2cq.mjs} +1 -1
  7. package/dist/{commands-C1V3SEF9.mjs → commands-CCjxPzJT.mjs} +5 -5
  8. package/dist/{commands-BWD_a3hE.mjs → commands-DoF9SAX3.mjs} +2 -2
  9. package/dist/{commands-BFZhHLhh.mjs → commands-eefkiBpA.mjs} +2 -2
  10. package/dist/{commands-BItE-9OU.mjs → commands-vs1xVOq6.mjs} +1 -1
  11. package/dist/{fleet-C-2EKVda.mjs → fleet-DrEOkILm.mjs} +1 -1
  12. package/dist/{frpc-BgabHfqV.mjs → frpc-DBu9GJrO.mjs} +1 -1
  13. package/dist/{headlessCli-CtTe4oJ4.mjs → headlessCli-DNFdPhIj.mjs} +2 -2
  14. package/dist/index.mjs +1 -1
  15. package/dist/{package-PTsbpBGF.mjs → package-1EKr6SAA.mjs} +2 -2
  16. package/dist/{rpc-C35Y8Vto.mjs → rpc-DL2Ng47j.mjs} +1 -1
  17. package/dist/{rpc-DlM7ml1e.mjs → rpc-DLS2-gvn.mjs} +1 -1
  18. package/dist/{run-DtTnHqcs.mjs → run-6OWcsJqy.mjs} +1 -1
  19. package/dist/{run-B3fosGEs.mjs → run-RJGmYTlI.mjs} +272 -77
  20. package/dist/{scheduler-B3hBIkt8.mjs → scheduler-BZnWgzcy.mjs} +1 -1
  21. package/dist/{serveCommands-Bj2aEfKX.mjs → serveCommands-2ubtJpD9.mjs} +5 -5
  22. package/dist/{serveManager-CCslS9Yt.mjs → serveManager-Bd2VxWKz.mjs} +2 -2
  23. package/dist/{sideband-BtZMx9Af.mjs → sideband-CTrvrrG-.mjs} +1 -1
  24. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
- import { N as resolveModel, $ as describeMisconfiguration, a0 as buildMachineDeps } from './run-B3fosGEs.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-BtZMx9Af.mjs';
1
+ import { N as resolveModel, $ as describeMisconfiguration, a0 as buildMachineDeps } from './run-RJGmYTlI.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CTrvrrG-.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-B3fosGEs.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-RJGmYTlI.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.197";
2
+ var version = "0.2.199";
3
3
  var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
4
4
  var author = "Amun AI AB";
5
5
  var license = "SEE LICENSE IN LICENSE";
@@ -19,7 +19,7 @@ var exports$1 = {
19
19
  var scripts = {
20
20
  build: "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/loop bin/skills/loop && cp -r ../../skills/crew bin/skills/crew && tsc --noEmit && pkgroll",
21
21
  typecheck: "tsc --noEmit",
22
- test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.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-sharing-notify-sync.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-btw-proxy-env.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-store.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-workflow-scheduler.mjs && npx tsx test/test-serve-link-subdomain.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-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-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-channel-upload.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 && npx tsx test/test-crew-verdict-routing.mjs && npx tsx test/test-crew-standalone.mjs",
22
+ test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.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-sharing-notify-sync.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-btw-proxy-env.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-store.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-workflow-scheduler.mjs && npx tsx test/test-serve-link-subdomain.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-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-hotreload-seam.mjs && npx tsx test/test-hot-reload.mjs && npx tsx test/test-hot-reload-live.mjs && npx tsx test/test-session-core.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-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-channel-upload.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 && npx tsx test/test-crew-verdict-routing.mjs && npx tsx test/test-crew-standalone.mjs",
23
23
  "test:hypha": "node --no-warnings test/test-hypha-service.mjs",
24
24
  dev: "tsx src/cli.ts",
25
25
  "dev:daemon": "tsx src/cli.ts daemon start-sync",
@@ -1,4 +1,4 @@
1
- import { m as resolveProjectRoot, u as updateIssue, n as getIssue, o as addComment, p as addIssue, q as listIssues, t as searchIssues, v as isVisibleTo } from './run-B3fosGEs.mjs';
1
+ import { m as resolveProjectRoot, u as updateIssue, n as getIssue, o as addComment, p as addIssue, q as listIssues, t as searchIssues, v as isVisibleTo } from './run-RJGmYTlI.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,5 +1,5 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { m as resolveProjectRoot } from './run-B3fosGEs.mjs';
2
+ import { m as resolveProjectRoot } from './run-RJGmYTlI.mjs';
3
3
  import { g as getWorkflow, w as workflowSteps, s as setWorkflowEnabled, r as removeWorkflow, a as saveWorkflow, b as rawWorkflow, l as listWorkflows } from './store-DEZ8e-uE.mjs';
4
4
  import 'os';
5
5
  import 'fs/promises';
@@ -1,4 +1,4 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a1 as applyClaudeProxyEnv, a2 as composeSessionId, a3 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a4 as generateHookSettings } from './run-B3fosGEs.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a1 as applyClaudeProxyEnv, a2 as composeSessionId, a3 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a4 as generateHookSettings } from './run-RJGmYTlI.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';
@@ -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, realpathSync as realpathSync$1, rmSync as rmSync$1, copyFileSync, unlinkSync as unlinkSync$1, readdirSync as readdirSync$1, watch, rmdirSync } from 'fs';
3
+ import fs__default, { readFileSync as readFileSync$1, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, renameSync as renameSync$1, existsSync as existsSync$1, realpathSync as realpathSync$1, rmSync as rmSync$1, copyFileSync, unlinkSync as unlinkSync$1, readdirSync as readdirSync$1, watch, rmdirSync } from 'fs';
4
4
  import path__default, { join as join$1, resolve as resolve$1, dirname as dirname$1, basename as basename$1 } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { execFile, spawn as spawn$1, execSync as execSync$1, spawnSync } from 'child_process';
@@ -2912,7 +2912,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2912
2912
  const tunnels = handlers.tunnels;
2913
2913
  if (!tunnels) throw new Error("Tunnel management not available");
2914
2914
  if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
2915
- const { FrpcTunnel } = await import('./frpc-BgabHfqV.mjs');
2915
+ const { FrpcTunnel } = await import('./frpc-DBu9GJrO.mjs');
2916
2916
  const tunnel = new FrpcTunnel({
2917
2917
  name: params.name,
2918
2918
  ports: params.ports,
@@ -3359,7 +3359,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3359
3359
  }
3360
3360
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
3361
3361
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
3362
- const { toolsForRole } = await import('./sideband-BtZMx9Af.mjs');
3362
+ const { toolsForRole } = await import('./sideband-CTrvrrG-.mjs');
3363
3363
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
3364
3364
  return fmt(r2);
3365
3365
  }
@@ -3458,7 +3458,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3458
3458
  if (r.error || !r.sender) return { error: r.error || "unauthorized" };
3459
3459
  const callId = "call_" + Math.random().toString(16).slice(2, 12);
3460
3460
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
3461
- const { queryCore } = await import('./commands-Bxb8oEBa.mjs');
3461
+ const { queryCore } = await import('./commands-B1lil9Ip.mjs');
3462
3462
  const timeout = c.reply?.timeout_sec || 120;
3463
3463
  let result;
3464
3464
  try {
@@ -3628,6 +3628,9 @@ ${d?.error || "not found"}`;
3628
3628
  });
3629
3629
  },
3630
3630
  getLastInboundRpcAt: () => lastInboundRpcAt,
3631
+ setHandlers: (newHandlers) => {
3632
+ handlers = newHandlers;
3633
+ },
3631
3634
  disconnect: async () => {
3632
3635
  const toRemove = [...listeners];
3633
3636
  for (const listener of toRemove) {
@@ -4537,7 +4540,9 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
4537
4540
  } catch {
4538
4541
  }
4539
4542
  }
4543
+ const isBtwEcho = !!(parsed && parsed.meta && parsed.meta.btw) || !!(meta && meta.btw);
4540
4544
  const wrappedContent = parsed && parsed.role === "user" ? { role: "user", content: parsed.content } : { role: "user", content: { type: "text", text: typeof parsed === "string" ? parsed : JSON.stringify(parsed) } };
4545
+ if (isBtwEcho) wrappedContent.meta = { btw: true };
4541
4546
  const msg = {
4542
4547
  id: randomUUID(),
4543
4548
  seq: nextSeq++,
@@ -5379,7 +5384,10 @@ Output ONLY the full revised reply text \u2014 no preamble, no commentary, no su
5379
5384
  reregister: async () => {
5380
5385
  }
5381
5386
  };
5382
- return { store, rpcHandlers };
5387
+ const setCallbacks = (newCallbacks) => {
5388
+ callbacks = newCallbacks;
5389
+ };
5390
+ return { store, rpcHandlers, setCallbacks };
5383
5391
  }
5384
5392
 
5385
5393
  const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -5720,6 +5728,164 @@ function handleMatchesMetadata(parsed, metadata) {
5720
5728
  return true;
5721
5729
  }
5722
5730
 
5731
+ const HOTRELOAD_ENV = "SVAMP_DEV_HOTRELOAD";
5732
+ function isHotReloadEnabled(env = process.env) {
5733
+ const v = env[HOTRELOAD_ENV];
5734
+ return v === "1" || v === "true" || v === "yes";
5735
+ }
5736
+ async function reimportFresh(tsSourcePath) {
5737
+ const { createRequire } = await import('module');
5738
+ const req = createRequire(import.meta.url);
5739
+ const esbuild = req("esbuild");
5740
+ const { mkdtempSync, writeFileSync } = await import('fs');
5741
+ const { tmpdir } = await import('os');
5742
+ const { join } = await import('path');
5743
+ const { pathToFileURL } = await import('url');
5744
+ const out = await esbuild.build({
5745
+ entryPoints: [tsSourcePath],
5746
+ bundle: false,
5747
+ format: "esm",
5748
+ platform: "node",
5749
+ write: false
5750
+ });
5751
+ const dir = mkdtempSync(join(tmpdir(), "svamp-hotreload-"));
5752
+ const tmp = join(dir, "mod.mjs");
5753
+ writeFileSync(tmp, out.outputFiles[0].text);
5754
+ const nativeImport = new Function("u", "return import(u)");
5755
+ return nativeImport(pathToFileURL(tmp).href);
5756
+ }
5757
+ function createHotReloadCoordinator(opts = {}) {
5758
+ const env = opts.env ?? process.env;
5759
+ const enabled = isHotReloadEnabled(env);
5760
+ const log = opts.log ?? ((m) => console.log(`[HOTRELOAD] ${m}`));
5761
+ const debounceMs = Math.max(0, opts.debounceMs ?? 200);
5762
+ const targets = /* @__PURE__ */ new Map();
5763
+ const watchers = [];
5764
+ let debounceTimer = null;
5765
+ let reloading = false;
5766
+ let reloadQueued = false;
5767
+ const defaultWatch = (path, onChange) => {
5768
+ const fs = fs__default;
5769
+ return fs.watch(path, { recursive: true }, () => onChange());
5770
+ };
5771
+ const watchFactory = opts.watch ?? defaultWatch;
5772
+ async function reloadNow() {
5773
+ const result = { reloaded: [], failed: [] };
5774
+ if (!enabled) return result;
5775
+ if (reloading) {
5776
+ reloadQueued = true;
5777
+ return result;
5778
+ }
5779
+ reloading = true;
5780
+ try {
5781
+ for (const target of targets.values()) {
5782
+ try {
5783
+ const fresh = await target.rebuild();
5784
+ target.apply(fresh);
5785
+ result.reloaded.push(target.id);
5786
+ } catch (e) {
5787
+ result.failed.push(target.id);
5788
+ log(`reload FAILED for ${target.id}: ${e?.message || e}`);
5789
+ }
5790
+ }
5791
+ if (result.reloaded.length || result.failed.length) {
5792
+ log(`reloaded [${result.reloaded.join(", ")}]` + (result.failed.length ? ` \xB7 failed [${result.failed.join(", ")}]` : ""));
5793
+ }
5794
+ } finally {
5795
+ reloading = false;
5796
+ }
5797
+ if (reloadQueued) {
5798
+ reloadQueued = false;
5799
+ await reloadNow();
5800
+ }
5801
+ return result;
5802
+ }
5803
+ function scheduleReload() {
5804
+ if (!enabled) return;
5805
+ if (debounceTimer) clearTimeout(debounceTimer);
5806
+ debounceTimer = setTimeout(() => {
5807
+ debounceTimer = null;
5808
+ void reloadNow();
5809
+ }, debounceMs);
5810
+ }
5811
+ return {
5812
+ enabled,
5813
+ register(target) {
5814
+ targets.set(target.id, target);
5815
+ return () => targets.delete(target.id);
5816
+ },
5817
+ unregister(id) {
5818
+ targets.delete(id);
5819
+ },
5820
+ size() {
5821
+ return targets.size;
5822
+ },
5823
+ start(paths) {
5824
+ if (!enabled) return;
5825
+ for (const p of paths) {
5826
+ try {
5827
+ watchers.push(watchFactory(p, scheduleReload));
5828
+ } catch (e) {
5829
+ log(`watch FAILED for ${p}: ${e?.message || e}`);
5830
+ }
5831
+ }
5832
+ if (watchers.length) log(`watching ${watchers.length} path(s); edit & save to hot-reload daemon logic`);
5833
+ },
5834
+ stop() {
5835
+ if (debounceTimer) {
5836
+ clearTimeout(debounceTimer);
5837
+ debounceTimer = null;
5838
+ }
5839
+ for (const w of watchers) {
5840
+ try {
5841
+ w.close();
5842
+ } catch {
5843
+ }
5844
+ }
5845
+ watchers.length = 0;
5846
+ },
5847
+ reloadNow
5848
+ };
5849
+ }
5850
+
5851
+ function splitStreamLines(buffer, chunk) {
5852
+ const combined = buffer + chunk;
5853
+ const parts = combined.split("\n");
5854
+ const rest = parts.pop() ?? "";
5855
+ return { lines: parts, rest };
5856
+ }
5857
+ function handleClaudeMessage(ctx, msg) {
5858
+ if (!msg || typeof msg !== "object") return false;
5859
+ switch (msg.type) {
5860
+ case "control_cancel_request": {
5861
+ const requestId = msg.request_id;
5862
+ ctx.log(`Permission cancel: ${requestId}`);
5863
+ const corr = ctx.permRequestIdToCorrelation.get(requestId) || requestId;
5864
+ const pending = ctx.pendingPermissions.get(corr);
5865
+ if (pending) {
5866
+ pending.resolve({ behavior: "deny", message: "Cancelled" });
5867
+ ctx.pendingPermissions.delete(corr);
5868
+ ctx.permRequestIdToCorrelation.delete(requestId);
5869
+ }
5870
+ return true;
5871
+ }
5872
+ case "control_response": {
5873
+ ctx.log(`Control response: ${JSON.stringify(msg).slice(0, 200)}`);
5874
+ return true;
5875
+ }
5876
+ case "system": {
5877
+ if (msg.subtype === "task_notification" && msg.status === "completed") {
5878
+ ctx.noteBackgroundTaskCompleted();
5879
+ ctx.push(msg, "agent");
5880
+ return true;
5881
+ }
5882
+ return false;
5883
+ }
5884
+ default:
5885
+ return false;
5886
+ }
5887
+ }
5888
+
5723
5889
  function resolveProjectRoot$1(directory) {
5724
5890
  try {
5725
5891
  const top = execSync("git rev-parse --show-toplevel", {
@@ -11930,7 +12096,7 @@ async function startDaemon(options) {
11930
12096
  saveExposedTunnels(list);
11931
12097
  }
11932
12098
  async function createExposedTunnel(spec) {
11933
- const { FrpcTunnel } = await import('./frpc-BgabHfqV.mjs');
12099
+ const { FrpcTunnel } = await import('./frpc-DBu9GJrO.mjs');
11934
12100
  const tunnel = new FrpcTunnel({
11935
12101
  name: spec.name,
11936
12102
  ports: spec.ports,
@@ -11950,7 +12116,7 @@ async function startDaemon(options) {
11950
12116
  return tunnel;
11951
12117
  }
11952
12118
  const tunnelRecreateState = /* @__PURE__ */ new Map();
11953
- const { ServeManager } = await import('./serveManager-CCslS9Yt.mjs');
12119
+ const { ServeManager } = await import('./serveManager-Bd2VxWKz.mjs');
11954
12120
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
11955
12121
  ensureAutoInstalledSkills(logger).catch(() => {
11956
12122
  });
@@ -11990,6 +12156,10 @@ async function startDaemon(options) {
11990
12156
  logger.log(`Hypha connection permanently lost: ${reason}. Daemon continues running \u2014 restart manually to reconnect.`);
11991
12157
  });
11992
12158
  const pidToTrackedSession = /* @__PURE__ */ new Map();
12159
+ let sessionCoreRef = {
12160
+ splitStreamLines,
12161
+ handleClaudeMessage
12162
+ };
11993
12163
  const routeSupervisionVerdict = (parentId, v) => {
11994
12164
  try {
11995
12165
  if (!parentId) return;
@@ -12740,17 +12910,31 @@ ${parts.join("\n")}`);
12740
12910
  let stdoutBuffer = "";
12741
12911
  let lastErrorMessagePushed = false;
12742
12912
  startStuckWatchdog();
12913
+ const pumpCtx = {
12914
+ sessionId,
12915
+ log: (m) => logger.log(`[Session ${sessionId}] ${m}`),
12916
+ pendingPermissions,
12917
+ permRequestIdToCorrelation,
12918
+ push: (data, kind) => sessionService.pushMessage(data, kind),
12919
+ noteBackgroundTaskCompleted: () => {
12920
+ backgroundTaskCount = Math.max(0, backgroundTaskCount - 1);
12921
+ if (backgroundTaskNames.length > 0) {
12922
+ const completed = backgroundTaskNames.shift();
12923
+ logger.log(`[Session ${sessionId}] Background task completed: ${completed} (remaining=${backgroundTaskCount})`);
12924
+ }
12925
+ }
12926
+ };
12743
12927
  child.stdout?.on("data", (chunk) => {
12744
12928
  lastOutputTime = Date.now();
12745
- stdoutBuffer += chunk.toString();
12746
- const lines = stdoutBuffer.split("\n");
12747
- stdoutBuffer = lines.pop() || "";
12748
- for (const line of lines) {
12929
+ const _split = sessionCoreRef.splitStreamLines(stdoutBuffer, chunk.toString());
12930
+ stdoutBuffer = _split.rest;
12931
+ for (const line of _split.lines) {
12749
12932
  if (!line.trim()) continue;
12750
12933
  logger.log(`[Session ${sessionId}] stdout line (${line.length} chars): ${line.slice(0, 500)}`);
12751
12934
  try {
12752
12935
  const msg = JSON.parse(line);
12753
12936
  logger.log(`[Session ${sessionId}] Parsed type=${msg.type} subtype=${msg.subtype || "n/a"}`);
12937
+ if (sessionCoreRef.handleClaudeMessage(pumpCtx, msg)) continue;
12754
12938
  if (msg.type === "control_request" && msg.request?.subtype === "can_use_tool") {
12755
12939
  const requestId = msg.request_id;
12756
12940
  const toolName = msg.request.tool_name;
@@ -12827,18 +13011,6 @@ ${parts.join("\n")}`);
12827
13011
  }).catch((err) => {
12828
13012
  logger.log(`[Session ${sessionId}] Permission handler error (request ${requestId}): ${err}`);
12829
13013
  });
12830
- } else if (msg.type === "control_cancel_request") {
12831
- const requestId = msg.request_id;
12832
- logger.log(`[Session ${sessionId}] Permission cancel: ${requestId}`);
12833
- const corr = permRequestIdToCorrelation.get(requestId) || requestId;
12834
- const pending = pendingPermissions.get(corr);
12835
- if (pending) {
12836
- pending.resolve({ behavior: "deny", message: "Cancelled" });
12837
- pendingPermissions.delete(corr);
12838
- permRequestIdToCorrelation.delete(requestId);
12839
- }
12840
- } else if (msg.type === "control_response") {
12841
- logger.log(`[Session ${sessionId}] Control response: ${JSON.stringify(msg).slice(0, 200)}`);
12842
13014
  } else if (msg.type === "assistant" || msg.type === "result") {
12843
13015
  if (msg.type === "assistant" && msg.isCompactSummary) {
12844
13016
  logger.log(`[Session ${sessionId}] Context compacted (/compact)`);
@@ -13072,13 +13244,6 @@ ${parts.join("\n")}`);
13072
13244
  consecutiveOverloadRetries = 0;
13073
13245
  }
13074
13246
  sessionService.pushMessage(msg, "agent");
13075
- } else if (msg.type === "system" && msg.subtype === "task_notification" && msg.status === "completed") {
13076
- backgroundTaskCount = Math.max(0, backgroundTaskCount - 1);
13077
- if (backgroundTaskNames.length > 0) {
13078
- const completed = backgroundTaskNames.shift();
13079
- logger.log(`[Session ${sessionId}] Background task completed: ${completed} (remaining=${backgroundTaskCount})`);
13080
- }
13081
- sessionService.pushMessage(msg, "agent");
13082
13247
  } else {
13083
13248
  sessionService.pushMessage(msg, "agent");
13084
13249
  }
@@ -13815,11 +13980,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
13815
13980
  });
13816
13981
  },
13817
13982
  onIssue: async (params) => {
13818
- const { issueRpc } = await import('./rpc-C35Y8Vto.mjs');
13983
+ const { issueRpc } = await import('./rpc-DL2Ng47j.mjs');
13819
13984
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
13820
13985
  },
13821
13986
  onWorkflow: async (params) => {
13822
- const { workflowRpc } = await import('./rpc-DlM7ml1e.mjs');
13987
+ const { workflowRpc } = await import('./rpc-DLS2-gvn.mjs');
13823
13988
  return workflowRpc(params?.cwd || directory, params || {});
13824
13989
  },
13825
13990
  onRipgrep: async (args, cwd) => {
@@ -14329,11 +14494,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14329
14494
  });
14330
14495
  },
14331
14496
  onIssue: async (params) => {
14332
- const { issueRpc } = await import('./rpc-C35Y8Vto.mjs');
14497
+ const { issueRpc } = await import('./rpc-DL2Ng47j.mjs');
14333
14498
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
14334
14499
  },
14335
14500
  onWorkflow: async (params) => {
14336
- const { workflowRpc } = await import('./rpc-DlM7ml1e.mjs');
14501
+ const { workflowRpc } = await import('./rpc-DLS2-gvn.mjs');
14337
14502
  return workflowRpc(params?.cwd || directory, params || {});
14338
14503
  },
14339
14504
  onRipgrep: async (args, cwd) => {
@@ -14770,56 +14935,86 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14770
14935
  const sharingNotificationSync = new SharingNotificationSync(server, logger.log);
14771
14936
  sharingNotificationSync.init().catch(() => {
14772
14937
  });
14938
+ const buildMachineHandlers = () => ({
14939
+ spawnSession,
14940
+ archiveSession,
14941
+ resumeSession,
14942
+ deleteSession,
14943
+ restartSession,
14944
+ requestShutdown: () => {
14945
+ logger.log("Shutdown requested via hypha-app (ignored \u2014 daemon never self-terminates)");
14946
+ },
14947
+ getTrackedSessions: getCurrentChildren,
14948
+ getSessionRPCHandlers: (sessionId) => {
14949
+ for (const [, session] of pidToTrackedSession) {
14950
+ if (session.svampSessionId === sessionId && !session.stopped && session.sessionRPCHandlers) {
14951
+ return session.sessionRPCHandlers;
14952
+ }
14953
+ }
14954
+ return void 0;
14955
+ },
14956
+ getSessionIds: () => {
14957
+ const ids = [];
14958
+ for (const [, session] of pidToTrackedSession) {
14959
+ if (session.svampSessionId && !session.stopped && session.sessionRPCHandlers) {
14960
+ ids.push(session.svampSessionId);
14961
+ }
14962
+ }
14963
+ return ids;
14964
+ },
14965
+ getSessionPid: (sessionId) => {
14966
+ for (const [, session] of pidToTrackedSession) {
14967
+ if (session.svampSessionId === sessionId && !session.stopped) {
14968
+ return session.pid;
14969
+ }
14970
+ }
14971
+ return void 0;
14972
+ },
14973
+ supervisor,
14974
+ tunnels,
14975
+ serveManager,
14976
+ sharingNotificationSync,
14977
+ persistExposedTunnel,
14978
+ forgetExposedTunnel,
14979
+ listExposedTunnels: () => loadExposedTunnels().map((t) => ({ name: t.name, ports: t.ports, group: t.group, addedAt: t.addedAt }))
14980
+ });
14773
14981
  const machineService = await registerMachineService(
14774
14982
  server,
14775
14983
  machineId,
14776
14984
  machineMetadata,
14777
14985
  initialDaemonState,
14778
- {
14779
- spawnSession,
14780
- archiveSession,
14781
- resumeSession,
14782
- deleteSession,
14783
- restartSession,
14784
- requestShutdown: () => {
14785
- logger.log("Shutdown requested via hypha-app (ignored \u2014 daemon never self-terminates)");
14786
- },
14787
- getTrackedSessions: getCurrentChildren,
14788
- getSessionRPCHandlers: (sessionId) => {
14789
- for (const [, session] of pidToTrackedSession) {
14790
- if (session.svampSessionId === sessionId && !session.stopped && session.sessionRPCHandlers) {
14791
- return session.sessionRPCHandlers;
14792
- }
14793
- }
14794
- return void 0;
14795
- },
14796
- getSessionIds: () => {
14797
- const ids = [];
14798
- for (const [, session] of pidToTrackedSession) {
14799
- if (session.svampSessionId && !session.stopped && session.sessionRPCHandlers) {
14800
- ids.push(session.svampSessionId);
14801
- }
14802
- }
14803
- return ids;
14804
- },
14805
- getSessionPid: (sessionId) => {
14806
- for (const [, session] of pidToTrackedSession) {
14807
- if (session.svampSessionId === sessionId && !session.stopped) {
14808
- return session.pid;
14986
+ buildMachineHandlers()
14987
+ );
14988
+ logger.log(`Machine service registered: svamp-machine-${machineId}`);
14989
+ if (isHotReloadEnabled()) {
14990
+ try {
14991
+ const hotReload = createHotReloadCoordinator({ log: logger.log });
14992
+ const sessionCoreSrc = join$1(__dirname$1, "sessionCore.ts");
14993
+ hotReload.register({
14994
+ id: "sessionCore",
14995
+ rebuild: async () => {
14996
+ if (!existsSync$1(sessionCoreSrc)) {
14997
+ logger.log("[HOTRELOAD] sessionCore.ts not found (bundled runtime) \u2014 hot-reload is dev-only; skipping reload");
14998
+ return sessionCoreRef;
14809
14999
  }
15000
+ const fresh = await reimportFresh(sessionCoreSrc);
15001
+ return { splitStreamLines: fresh.splitStreamLines, handleClaudeMessage: fresh.handleClaudeMessage };
15002
+ },
15003
+ apply: (mod) => {
15004
+ sessionCoreRef = mod;
14810
15005
  }
14811
- return void 0;
14812
- },
14813
- supervisor,
14814
- tunnels,
14815
- serveManager,
14816
- sharingNotificationSync,
14817
- persistExposedTunnel,
14818
- forgetExposedTunnel,
14819
- listExposedTunnels: () => loadExposedTunnels().map((t) => ({ name: t.name, ports: t.ports, group: t.group, addedAt: t.addedAt }))
15006
+ });
15007
+ hotReload.register({
15008
+ id: "machine",
15009
+ rebuild: buildMachineHandlers,
15010
+ apply: (h) => machineService.setHandlers(h)
15011
+ });
15012
+ hotReload.start([join$1(__dirname$1, "..")]);
15013
+ logger.log("[HOTRELOAD] dev hot-reload ENABLED (SVAMP_DEV_HOTRELOAD=1): sessionCore (live edit\u2192reload) + machine seam");
15014
+ } catch (e) {
15015
+ logger.log(`[HOTRELOAD] failed to start (continuing without it): ${e?.message || e}`);
14820
15016
  }
14821
- );
14822
- logger.log(`Machine service registered: svamp-machine-${machineId}`);
15017
+ }
14823
15018
  const channelHttpPort = Number(process.env.SVAMP_CHANNEL_HTTP_PORT) || 0;
14824
15019
  if (channelHttpPort > 0) {
14825
15020
  try {
@@ -15088,7 +15283,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15088
15283
  const PING_TIMEOUT_MS = 15e3;
15089
15284
  const POST_RECONNECT_GRACE_MS = 2e4;
15090
15285
  const RECONNECT_JITTER_MS = 2500;
15091
- const { WorkflowScheduler } = await import('./scheduler-B3hBIkt8.mjs');
15286
+ const { WorkflowScheduler } = await import('./scheduler-BZnWgzcy.mjs');
15092
15287
  const workflowScheduler = new WorkflowScheduler({
15093
15288
  projectRoots: () => {
15094
15289
  const dirs = /* @__PURE__ */ new Set();
@@ -1,5 +1,5 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { m as resolveProjectRoot, w as cronMatches } from './run-B3fosGEs.mjs';
2
+ import { m as resolveProjectRoot, w as cronMatches } from './run-RJGmYTlI.mjs';
3
3
  import { l as listWorkflows, i as isWorkflowEnabled, c as workflowCrons, w as workflowSteps } from './store-DEZ8e-uE.mjs';
4
4
  import 'os';
5
5
  import 'fs/promises';
@@ -54,7 +54,7 @@ async function handleServeCommand() {
54
54
  }
55
55
  }
56
56
  async function serveAdd(args, machineId) {
57
- const { connectAndGetMachine } = await import('./commands-Bxb8oEBa.mjs');
57
+ const { connectAndGetMachine } = await import('./commands-B1lil9Ip.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-Bxb8oEBa.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-B1lil9Ip.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-Bxb8oEBa.mjs');
185
+ const { connectAndGetMachine } = await import('./commands-B1lil9Ip.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-Bxb8oEBa.mjs');
205
+ const { connectAndGetMachine } = await import('./commands-B1lil9Ip.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-Bxb8oEBa.mjs');
238
+ const { connectAndGetMachine } = await import('./commands-B1lil9Ip.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-B3fosGEs.mjs';
7
+ import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-RJGmYTlI.mjs';
8
8
  import 'os';
9
9
  import 'fs/promises';
10
10
  import 'url';
@@ -733,7 +733,7 @@ class ServeManager {
733
733
  const mount = this.mounts.get(mountName);
734
734
  const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
735
735
  try {
736
- const { FrpcTunnel } = await import('./frpc-BgabHfqV.mjs');
736
+ const { FrpcTunnel } = await import('./frpc-DBu9GJrO.mjs');
737
737
  let tunnel;
738
738
  tunnel = new FrpcTunnel({
739
739
  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-B3fosGEs.mjs';
1
+ import { R as READ_ONLY_TOOLS, z as loadMachineContext, A as buildMachineInstructions, B as machineToolsForRole, C as buildMachineTools } from './run-RJGmYTlI.mjs';
2
2
  import 'node:child_process';
3
3
  import 'os';
4
4
  import 'fs/promises';