svamp-cli 0.2.198 → 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-2k-NbgEx.mjs → agentCommands-C7HrSvD_.mjs} +5 -5
  2. package/dist/{auth-BJcucXB4.mjs → auth-BXaEbJ34.mjs} +1 -1
  3. package/dist/cli.mjs +60 -60
  4. package/dist/{commands-CGWInQkH.mjs → commands-B1lil9Ip.mjs} +1 -1
  5. package/dist/{commands-gAeBivIW.mjs → commands-BfmWL88p.mjs} +1 -1
  6. package/dist/{commands-BTiqgsxT.mjs → commands-BnTqC2cq.mjs} +1 -1
  7. package/dist/{commands-BzyE06FJ.mjs → commands-CCjxPzJT.mjs} +5 -5
  8. package/dist/{commands-Bl25vZ_o.mjs → commands-DoF9SAX3.mjs} +2 -2
  9. package/dist/{commands-3tYa4wYQ.mjs → commands-eefkiBpA.mjs} +2 -2
  10. package/dist/{commands-BNITJyVN.mjs → commands-vs1xVOq6.mjs} +1 -1
  11. package/dist/{fleet-BqRvl85c.mjs → fleet-DrEOkILm.mjs} +1 -1
  12. package/dist/{frpc-CViS7oBy.mjs → frpc-DBu9GJrO.mjs} +1 -1
  13. package/dist/{headlessCli-Du-Td7v-.mjs → headlessCli-DNFdPhIj.mjs} +2 -2
  14. package/dist/index.mjs +1 -1
  15. package/dist/{package-C8cFp374.mjs → package-1EKr6SAA.mjs} +2 -2
  16. package/dist/{rpc-B43CaT9b.mjs → rpc-DL2Ng47j.mjs} +1 -1
  17. package/dist/{rpc-CC9VBNEi.mjs → rpc-DLS2-gvn.mjs} +1 -1
  18. package/dist/{run-EvEg4LNm.mjs → run-6OWcsJqy.mjs} +1 -1
  19. package/dist/{run-DDIwvxwA.mjs → run-RJGmYTlI.mjs} +270 -77
  20. package/dist/{scheduler-DPs8EnlX.mjs → scheduler-BZnWgzcy.mjs} +1 -1
  21. package/dist/{serveCommands-JhPd32Oh.mjs → serveCommands-2ubtJpD9.mjs} +5 -5
  22. package/dist/{serveManager-Dxm1mfaR.mjs → serveManager-Bd2VxWKz.mjs} +2 -2
  23. package/dist/{sideband-Dp9CVXzY.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-DDIwvxwA.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-Dp9CVXzY.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-DDIwvxwA.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.198";
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-DDIwvxwA.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-DDIwvxwA.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-DDIwvxwA.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-CViS7oBy.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-Dp9CVXzY.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-CGWInQkH.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) {
@@ -5381,7 +5384,10 @@ Output ONLY the full revised reply text \u2014 no preamble, no commentary, no su
5381
5384
  reregister: async () => {
5382
5385
  }
5383
5386
  };
5384
- return { store, rpcHandlers };
5387
+ const setCallbacks = (newCallbacks) => {
5388
+ callbacks = newCallbacks;
5389
+ };
5390
+ return { store, rpcHandlers, setCallbacks };
5385
5391
  }
5386
5392
 
5387
5393
  const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -5722,6 +5728,164 @@ function handleMatchesMetadata(parsed, metadata) {
5722
5728
  return true;
5723
5729
  }
5724
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
+
5725
5889
  function resolveProjectRoot$1(directory) {
5726
5890
  try {
5727
5891
  const top = execSync("git rev-parse --show-toplevel", {
@@ -11932,7 +12096,7 @@ async function startDaemon(options) {
11932
12096
  saveExposedTunnels(list);
11933
12097
  }
11934
12098
  async function createExposedTunnel(spec) {
11935
- const { FrpcTunnel } = await import('./frpc-CViS7oBy.mjs');
12099
+ const { FrpcTunnel } = await import('./frpc-DBu9GJrO.mjs');
11936
12100
  const tunnel = new FrpcTunnel({
11937
12101
  name: spec.name,
11938
12102
  ports: spec.ports,
@@ -11952,7 +12116,7 @@ async function startDaemon(options) {
11952
12116
  return tunnel;
11953
12117
  }
11954
12118
  const tunnelRecreateState = /* @__PURE__ */ new Map();
11955
- const { ServeManager } = await import('./serveManager-Dxm1mfaR.mjs');
12119
+ const { ServeManager } = await import('./serveManager-Bd2VxWKz.mjs');
11956
12120
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
11957
12121
  ensureAutoInstalledSkills(logger).catch(() => {
11958
12122
  });
@@ -11992,6 +12156,10 @@ async function startDaemon(options) {
11992
12156
  logger.log(`Hypha connection permanently lost: ${reason}. Daemon continues running \u2014 restart manually to reconnect.`);
11993
12157
  });
11994
12158
  const pidToTrackedSession = /* @__PURE__ */ new Map();
12159
+ let sessionCoreRef = {
12160
+ splitStreamLines,
12161
+ handleClaudeMessage
12162
+ };
11995
12163
  const routeSupervisionVerdict = (parentId, v) => {
11996
12164
  try {
11997
12165
  if (!parentId) return;
@@ -12742,17 +12910,31 @@ ${parts.join("\n")}`);
12742
12910
  let stdoutBuffer = "";
12743
12911
  let lastErrorMessagePushed = false;
12744
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
+ };
12745
12927
  child.stdout?.on("data", (chunk) => {
12746
12928
  lastOutputTime = Date.now();
12747
- stdoutBuffer += chunk.toString();
12748
- const lines = stdoutBuffer.split("\n");
12749
- stdoutBuffer = lines.pop() || "";
12750
- for (const line of lines) {
12929
+ const _split = sessionCoreRef.splitStreamLines(stdoutBuffer, chunk.toString());
12930
+ stdoutBuffer = _split.rest;
12931
+ for (const line of _split.lines) {
12751
12932
  if (!line.trim()) continue;
12752
12933
  logger.log(`[Session ${sessionId}] stdout line (${line.length} chars): ${line.slice(0, 500)}`);
12753
12934
  try {
12754
12935
  const msg = JSON.parse(line);
12755
12936
  logger.log(`[Session ${sessionId}] Parsed type=${msg.type} subtype=${msg.subtype || "n/a"}`);
12937
+ if (sessionCoreRef.handleClaudeMessage(pumpCtx, msg)) continue;
12756
12938
  if (msg.type === "control_request" && msg.request?.subtype === "can_use_tool") {
12757
12939
  const requestId = msg.request_id;
12758
12940
  const toolName = msg.request.tool_name;
@@ -12829,18 +13011,6 @@ ${parts.join("\n")}`);
12829
13011
  }).catch((err) => {
12830
13012
  logger.log(`[Session ${sessionId}] Permission handler error (request ${requestId}): ${err}`);
12831
13013
  });
12832
- } else if (msg.type === "control_cancel_request") {
12833
- const requestId = msg.request_id;
12834
- logger.log(`[Session ${sessionId}] Permission cancel: ${requestId}`);
12835
- const corr = permRequestIdToCorrelation.get(requestId) || requestId;
12836
- const pending = pendingPermissions.get(corr);
12837
- if (pending) {
12838
- pending.resolve({ behavior: "deny", message: "Cancelled" });
12839
- pendingPermissions.delete(corr);
12840
- permRequestIdToCorrelation.delete(requestId);
12841
- }
12842
- } else if (msg.type === "control_response") {
12843
- logger.log(`[Session ${sessionId}] Control response: ${JSON.stringify(msg).slice(0, 200)}`);
12844
13014
  } else if (msg.type === "assistant" || msg.type === "result") {
12845
13015
  if (msg.type === "assistant" && msg.isCompactSummary) {
12846
13016
  logger.log(`[Session ${sessionId}] Context compacted (/compact)`);
@@ -13074,13 +13244,6 @@ ${parts.join("\n")}`);
13074
13244
  consecutiveOverloadRetries = 0;
13075
13245
  }
13076
13246
  sessionService.pushMessage(msg, "agent");
13077
- } else if (msg.type === "system" && msg.subtype === "task_notification" && msg.status === "completed") {
13078
- backgroundTaskCount = Math.max(0, backgroundTaskCount - 1);
13079
- if (backgroundTaskNames.length > 0) {
13080
- const completed = backgroundTaskNames.shift();
13081
- logger.log(`[Session ${sessionId}] Background task completed: ${completed} (remaining=${backgroundTaskCount})`);
13082
- }
13083
- sessionService.pushMessage(msg, "agent");
13084
13247
  } else {
13085
13248
  sessionService.pushMessage(msg, "agent");
13086
13249
  }
@@ -13817,11 +13980,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
13817
13980
  });
13818
13981
  },
13819
13982
  onIssue: async (params) => {
13820
- const { issueRpc } = await import('./rpc-B43CaT9b.mjs');
13983
+ const { issueRpc } = await import('./rpc-DL2Ng47j.mjs');
13821
13984
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
13822
13985
  },
13823
13986
  onWorkflow: async (params) => {
13824
- const { workflowRpc } = await import('./rpc-CC9VBNEi.mjs');
13987
+ const { workflowRpc } = await import('./rpc-DLS2-gvn.mjs');
13825
13988
  return workflowRpc(params?.cwd || directory, params || {});
13826
13989
  },
13827
13990
  onRipgrep: async (args, cwd) => {
@@ -14331,11 +14494,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14331
14494
  });
14332
14495
  },
14333
14496
  onIssue: async (params) => {
14334
- const { issueRpc } = await import('./rpc-B43CaT9b.mjs');
14497
+ const { issueRpc } = await import('./rpc-DL2Ng47j.mjs');
14335
14498
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
14336
14499
  },
14337
14500
  onWorkflow: async (params) => {
14338
- const { workflowRpc } = await import('./rpc-CC9VBNEi.mjs');
14501
+ const { workflowRpc } = await import('./rpc-DLS2-gvn.mjs');
14339
14502
  return workflowRpc(params?.cwd || directory, params || {});
14340
14503
  },
14341
14504
  onRipgrep: async (args, cwd) => {
@@ -14772,56 +14935,86 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14772
14935
  const sharingNotificationSync = new SharingNotificationSync(server, logger.log);
14773
14936
  sharingNotificationSync.init().catch(() => {
14774
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
+ });
14775
14981
  const machineService = await registerMachineService(
14776
14982
  server,
14777
14983
  machineId,
14778
14984
  machineMetadata,
14779
14985
  initialDaemonState,
14780
- {
14781
- spawnSession,
14782
- archiveSession,
14783
- resumeSession,
14784
- deleteSession,
14785
- restartSession,
14786
- requestShutdown: () => {
14787
- logger.log("Shutdown requested via hypha-app (ignored \u2014 daemon never self-terminates)");
14788
- },
14789
- getTrackedSessions: getCurrentChildren,
14790
- getSessionRPCHandlers: (sessionId) => {
14791
- for (const [, session] of pidToTrackedSession) {
14792
- if (session.svampSessionId === sessionId && !session.stopped && session.sessionRPCHandlers) {
14793
- return session.sessionRPCHandlers;
14794
- }
14795
- }
14796
- return void 0;
14797
- },
14798
- getSessionIds: () => {
14799
- const ids = [];
14800
- for (const [, session] of pidToTrackedSession) {
14801
- if (session.svampSessionId && !session.stopped && session.sessionRPCHandlers) {
14802
- ids.push(session.svampSessionId);
14803
- }
14804
- }
14805
- return ids;
14806
- },
14807
- getSessionPid: (sessionId) => {
14808
- for (const [, session] of pidToTrackedSession) {
14809
- if (session.svampSessionId === sessionId && !session.stopped) {
14810
- 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;
14811
14999
  }
15000
+ const fresh = await reimportFresh(sessionCoreSrc);
15001
+ return { splitStreamLines: fresh.splitStreamLines, handleClaudeMessage: fresh.handleClaudeMessage };
15002
+ },
15003
+ apply: (mod) => {
15004
+ sessionCoreRef = mod;
14812
15005
  }
14813
- return void 0;
14814
- },
14815
- supervisor,
14816
- tunnels,
14817
- serveManager,
14818
- sharingNotificationSync,
14819
- persistExposedTunnel,
14820
- forgetExposedTunnel,
14821
- 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}`);
14822
15016
  }
14823
- );
14824
- logger.log(`Machine service registered: svamp-machine-${machineId}`);
15017
+ }
14825
15018
  const channelHttpPort = Number(process.env.SVAMP_CHANNEL_HTTP_PORT) || 0;
14826
15019
  if (channelHttpPort > 0) {
14827
15020
  try {
@@ -15090,7 +15283,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15090
15283
  const PING_TIMEOUT_MS = 15e3;
15091
15284
  const POST_RECONNECT_GRACE_MS = 2e4;
15092
15285
  const RECONNECT_JITTER_MS = 2500;
15093
- const { WorkflowScheduler } = await import('./scheduler-DPs8EnlX.mjs');
15286
+ const { WorkflowScheduler } = await import('./scheduler-BZnWgzcy.mjs');
15094
15287
  const workflowScheduler = new WorkflowScheduler({
15095
15288
  projectRoots: () => {
15096
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-DDIwvxwA.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-CGWInQkH.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-CGWInQkH.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-CGWInQkH.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-CGWInQkH.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-CGWInQkH.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-DDIwvxwA.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-CViS7oBy.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-DDIwvxwA.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';