svamp-cli 0.2.198 → 0.2.200

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-BLig9RpJ.mjs} +5 -5
  2. package/dist/{auth-BJcucXB4.mjs → auth-BFDgK8NY.mjs} +1 -1
  3. package/dist/cli.mjs +60 -60
  4. package/dist/{commands-Bl25vZ_o.mjs → commands-2qJ_Bh8F.mjs} +2 -2
  5. package/dist/{commands-BNITJyVN.mjs → commands-C03E7eP5.mjs} +1 -1
  6. package/dist/{commands-3tYa4wYQ.mjs → commands-C0NGT-PG.mjs} +2 -2
  7. package/dist/{commands-gAeBivIW.mjs → commands-CrOYWa85.mjs} +1 -1
  8. package/dist/{commands-CGWInQkH.mjs → commands-DRI2MMHg.mjs} +1 -1
  9. package/dist/{commands-BzyE06FJ.mjs → commands-DgCf4FCQ.mjs} +5 -5
  10. package/dist/{commands-BTiqgsxT.mjs → commands-NKOF_jF-.mjs} +1 -1
  11. package/dist/{fleet-BqRvl85c.mjs → fleet-CaFacVAt.mjs} +1 -1
  12. package/dist/{frpc-CViS7oBy.mjs → frpc-gMUAwe3q.mjs} +1 -1
  13. package/dist/{headlessCli-Du-Td7v-.mjs → headlessCli-DxAlTlhs.mjs} +2 -2
  14. package/dist/index.mjs +1 -1
  15. package/dist/{package-C8cFp374.mjs → package-BNVXH7XA.mjs} +2 -2
  16. package/dist/{rpc-CC9VBNEi.mjs → rpc-GTsR01jv.mjs} +1 -1
  17. package/dist/{rpc-B43CaT9b.mjs → rpc-_aPtyAzL.mjs} +1 -1
  18. package/dist/{run-DDIwvxwA.mjs → run-DsGZVxkK.mjs} +277 -79
  19. package/dist/{run-EvEg4LNm.mjs → run-DyqabMH2.mjs} +1 -1
  20. package/dist/{scheduler-DPs8EnlX.mjs → scheduler-9mJf0_7T.mjs} +1 -1
  21. package/dist/{serveCommands-JhPd32Oh.mjs → serveCommands-CrjiFbbs.mjs} +5 -5
  22. package/dist/{serveManager-Dxm1mfaR.mjs → serveManager-CtbAmKJ7.mjs} +2 -2
  23. package/dist/{sideband-Dp9CVXzY.mjs → sideband-5D9B_PyP.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-DsGZVxkK.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-5D9B_PyP.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-DsGZVxkK.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.200";
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,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-DsGZVxkK.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 { 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-DsGZVxkK.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import '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-gMUAwe3q.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-5D9B_PyP.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-DRI2MMHg.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) {
@@ -3816,9 +3819,14 @@ function isRetryableRateLimit(text, apiErrorStatus) {
3816
3819
  const t = (text || "").toLowerCase();
3817
3820
  const hardLimit = t.includes("quota") || t.includes("credit") || t.includes("balance") || t.includes("billing") || t.includes("payment") || t.includes("subscription") || t.includes("1m-context") || t.includes("1m context") || t.includes("insufficient") || t.includes("usage limit") && !t.includes("not your usage limit");
3818
3821
  if (hardLimit) return false;
3819
- const authIssue = t.includes("unauthorized") || t.includes("invalid api key") || t.includes("authentication") || t.includes("forbidden");
3822
+ const authIssue = apiErrorStatus === 401 || apiErrorStatus === 403 || t.includes("unauthorized") || t.includes("invalid api key") || t.includes("authentication") || t.includes("forbidden");
3820
3823
  if (authIssue) return false;
3821
- return apiErrorStatus === 429 || apiErrorStatus === 529 || apiErrorStatus === 503 || /\b(429|529|503)\b/.test(t) || t.includes("temporarily limiting") || t.includes("not your usage limit") || t.includes("overloaded") || t.includes("overload") || t.includes("too many requests") || t.includes("server is busy") || t.includes("rate limit") || t.includes("rate-limit") || t.includes("rate limited");
3824
+ const clientError = apiErrorStatus === 400 || apiErrorStatus === 404 || apiErrorStatus === 422 || t.includes("invalid_request") || t.includes("invalid request") || t.includes("bad request");
3825
+ if (clientError) return false;
3826
+ const serverTransient = typeof apiErrorStatus === "number" && apiErrorStatus >= 500 && apiErrorStatus <= 599 || apiErrorStatus === 429 || /\b(429|500|502|503|504|520|521|522|523|524|529)\b/.test(t) || t.includes("temporarily limiting") || t.includes("not your usage limit") || t.includes("overloaded") || t.includes("overload") || t.includes("too many requests") || t.includes("server is busy") || t.includes("internal server error") || t.includes("bad gateway") || t.includes("service unavailable") || t.includes("gateway timeout") || t.includes("rate limit") || t.includes("rate-limit") || t.includes("rate limited");
3827
+ if (serverTransient) return true;
3828
+ const networkTransient = t.includes("socket hang up") || t.includes("closed unexpectedly") || t.includes("connection closed") || t.includes("connection reset") || t.includes("connection error") || t.includes("econnreset") || t.includes("etimedout") || t.includes("econnaborted") || t.includes("epipe") || t.includes("enetunreach") || t.includes("enetreset") || t.includes("ehostunreach") || t.includes("eai_again") || t.includes("network error") || t.includes("fetch failed") || t.includes("request timed out") || t.includes("timed out");
3829
+ return networkTransient;
3822
3830
  }
3823
3831
 
3824
3832
  const EXAMPLE_HYPHA_PROXY_URL = "https://proxy.hypha.aicell.io";
@@ -5381,7 +5389,10 @@ Output ONLY the full revised reply text \u2014 no preamble, no commentary, no su
5381
5389
  reregister: async () => {
5382
5390
  }
5383
5391
  };
5384
- return { store, rpcHandlers };
5392
+ const setCallbacks = (newCallbacks) => {
5393
+ callbacks = newCallbacks;
5394
+ };
5395
+ return { store, rpcHandlers, setCallbacks };
5385
5396
  }
5386
5397
 
5387
5398
  const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -5722,6 +5733,164 @@ function handleMatchesMetadata(parsed, metadata) {
5722
5733
  return true;
5723
5734
  }
5724
5735
 
5736
+ const HOTRELOAD_ENV = "SVAMP_DEV_HOTRELOAD";
5737
+ function isHotReloadEnabled(env = process.env) {
5738
+ const v = env[HOTRELOAD_ENV];
5739
+ return v === "1" || v === "true" || v === "yes";
5740
+ }
5741
+ async function reimportFresh(tsSourcePath) {
5742
+ const { createRequire } = await import('module');
5743
+ const req = createRequire(import.meta.url);
5744
+ const esbuild = req("esbuild");
5745
+ const { mkdtempSync, writeFileSync } = await import('fs');
5746
+ const { tmpdir } = await import('os');
5747
+ const { join } = await import('path');
5748
+ const { pathToFileURL } = await import('url');
5749
+ const out = await esbuild.build({
5750
+ entryPoints: [tsSourcePath],
5751
+ bundle: false,
5752
+ format: "esm",
5753
+ platform: "node",
5754
+ write: false
5755
+ });
5756
+ const dir = mkdtempSync(join(tmpdir(), "svamp-hotreload-"));
5757
+ const tmp = join(dir, "mod.mjs");
5758
+ writeFileSync(tmp, out.outputFiles[0].text);
5759
+ const nativeImport = new Function("u", "return import(u)");
5760
+ return nativeImport(pathToFileURL(tmp).href);
5761
+ }
5762
+ function createHotReloadCoordinator(opts = {}) {
5763
+ const env = opts.env ?? process.env;
5764
+ const enabled = isHotReloadEnabled(env);
5765
+ const log = opts.log ?? ((m) => console.log(`[HOTRELOAD] ${m}`));
5766
+ const debounceMs = Math.max(0, opts.debounceMs ?? 200);
5767
+ const targets = /* @__PURE__ */ new Map();
5768
+ const watchers = [];
5769
+ let debounceTimer = null;
5770
+ let reloading = false;
5771
+ let reloadQueued = false;
5772
+ const defaultWatch = (path, onChange) => {
5773
+ const fs = fs__default;
5774
+ return fs.watch(path, { recursive: true }, () => onChange());
5775
+ };
5776
+ const watchFactory = opts.watch ?? defaultWatch;
5777
+ async function reloadNow() {
5778
+ const result = { reloaded: [], failed: [] };
5779
+ if (!enabled) return result;
5780
+ if (reloading) {
5781
+ reloadQueued = true;
5782
+ return result;
5783
+ }
5784
+ reloading = true;
5785
+ try {
5786
+ for (const target of targets.values()) {
5787
+ try {
5788
+ const fresh = await target.rebuild();
5789
+ target.apply(fresh);
5790
+ result.reloaded.push(target.id);
5791
+ } catch (e) {
5792
+ result.failed.push(target.id);
5793
+ log(`reload FAILED for ${target.id}: ${e?.message || e}`);
5794
+ }
5795
+ }
5796
+ if (result.reloaded.length || result.failed.length) {
5797
+ log(`reloaded [${result.reloaded.join(", ")}]` + (result.failed.length ? ` \xB7 failed [${result.failed.join(", ")}]` : ""));
5798
+ }
5799
+ } finally {
5800
+ reloading = false;
5801
+ }
5802
+ if (reloadQueued) {
5803
+ reloadQueued = false;
5804
+ await reloadNow();
5805
+ }
5806
+ return result;
5807
+ }
5808
+ function scheduleReload() {
5809
+ if (!enabled) return;
5810
+ if (debounceTimer) clearTimeout(debounceTimer);
5811
+ debounceTimer = setTimeout(() => {
5812
+ debounceTimer = null;
5813
+ void reloadNow();
5814
+ }, debounceMs);
5815
+ }
5816
+ return {
5817
+ enabled,
5818
+ register(target) {
5819
+ targets.set(target.id, target);
5820
+ return () => targets.delete(target.id);
5821
+ },
5822
+ unregister(id) {
5823
+ targets.delete(id);
5824
+ },
5825
+ size() {
5826
+ return targets.size;
5827
+ },
5828
+ start(paths) {
5829
+ if (!enabled) return;
5830
+ for (const p of paths) {
5831
+ try {
5832
+ watchers.push(watchFactory(p, scheduleReload));
5833
+ } catch (e) {
5834
+ log(`watch FAILED for ${p}: ${e?.message || e}`);
5835
+ }
5836
+ }
5837
+ if (watchers.length) log(`watching ${watchers.length} path(s); edit & save to hot-reload daemon logic`);
5838
+ },
5839
+ stop() {
5840
+ if (debounceTimer) {
5841
+ clearTimeout(debounceTimer);
5842
+ debounceTimer = null;
5843
+ }
5844
+ for (const w of watchers) {
5845
+ try {
5846
+ w.close();
5847
+ } catch {
5848
+ }
5849
+ }
5850
+ watchers.length = 0;
5851
+ },
5852
+ reloadNow
5853
+ };
5854
+ }
5855
+
5856
+ function splitStreamLines(buffer, chunk) {
5857
+ const combined = buffer + chunk;
5858
+ const parts = combined.split("\n");
5859
+ const rest = parts.pop() ?? "";
5860
+ return { lines: parts, rest };
5861
+ }
5862
+ function handleClaudeMessage(ctx, msg) {
5863
+ if (!msg || typeof msg !== "object") return false;
5864
+ switch (msg.type) {
5865
+ case "control_cancel_request": {
5866
+ const requestId = msg.request_id;
5867
+ ctx.log(`Permission cancel: ${requestId}`);
5868
+ const corr = ctx.permRequestIdToCorrelation.get(requestId) || requestId;
5869
+ const pending = ctx.pendingPermissions.get(corr);
5870
+ if (pending) {
5871
+ pending.resolve({ behavior: "deny", message: "Cancelled" });
5872
+ ctx.pendingPermissions.delete(corr);
5873
+ ctx.permRequestIdToCorrelation.delete(requestId);
5874
+ }
5875
+ return true;
5876
+ }
5877
+ case "control_response": {
5878
+ ctx.log(`Control response: ${JSON.stringify(msg).slice(0, 200)}`);
5879
+ return true;
5880
+ }
5881
+ case "system": {
5882
+ if (msg.subtype === "task_notification" && msg.status === "completed") {
5883
+ ctx.noteBackgroundTaskCompleted();
5884
+ ctx.push(msg, "agent");
5885
+ return true;
5886
+ }
5887
+ return false;
5888
+ }
5889
+ default:
5890
+ return false;
5891
+ }
5892
+ }
5893
+
5725
5894
  function resolveProjectRoot$1(directory) {
5726
5895
  try {
5727
5896
  const top = execSync("git rev-parse --show-toplevel", {
@@ -11932,7 +12101,7 @@ async function startDaemon(options) {
11932
12101
  saveExposedTunnels(list);
11933
12102
  }
11934
12103
  async function createExposedTunnel(spec) {
11935
- const { FrpcTunnel } = await import('./frpc-CViS7oBy.mjs');
12104
+ const { FrpcTunnel } = await import('./frpc-gMUAwe3q.mjs');
11936
12105
  const tunnel = new FrpcTunnel({
11937
12106
  name: spec.name,
11938
12107
  ports: spec.ports,
@@ -11952,7 +12121,7 @@ async function startDaemon(options) {
11952
12121
  return tunnel;
11953
12122
  }
11954
12123
  const tunnelRecreateState = /* @__PURE__ */ new Map();
11955
- const { ServeManager } = await import('./serveManager-Dxm1mfaR.mjs');
12124
+ const { ServeManager } = await import('./serveManager-CtbAmKJ7.mjs');
11956
12125
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
11957
12126
  ensureAutoInstalledSkills(logger).catch(() => {
11958
12127
  });
@@ -11992,6 +12161,10 @@ async function startDaemon(options) {
11992
12161
  logger.log(`Hypha connection permanently lost: ${reason}. Daemon continues running \u2014 restart manually to reconnect.`);
11993
12162
  });
11994
12163
  const pidToTrackedSession = /* @__PURE__ */ new Map();
12164
+ let sessionCoreRef = {
12165
+ splitStreamLines,
12166
+ handleClaudeMessage
12167
+ };
11995
12168
  const routeSupervisionVerdict = (parentId, v) => {
11996
12169
  try {
11997
12170
  if (!parentId) return;
@@ -12742,17 +12915,31 @@ ${parts.join("\n")}`);
12742
12915
  let stdoutBuffer = "";
12743
12916
  let lastErrorMessagePushed = false;
12744
12917
  startStuckWatchdog();
12918
+ const pumpCtx = {
12919
+ sessionId,
12920
+ log: (m) => logger.log(`[Session ${sessionId}] ${m}`),
12921
+ pendingPermissions,
12922
+ permRequestIdToCorrelation,
12923
+ push: (data, kind) => sessionService.pushMessage(data, kind),
12924
+ noteBackgroundTaskCompleted: () => {
12925
+ backgroundTaskCount = Math.max(0, backgroundTaskCount - 1);
12926
+ if (backgroundTaskNames.length > 0) {
12927
+ const completed = backgroundTaskNames.shift();
12928
+ logger.log(`[Session ${sessionId}] Background task completed: ${completed} (remaining=${backgroundTaskCount})`);
12929
+ }
12930
+ }
12931
+ };
12745
12932
  child.stdout?.on("data", (chunk) => {
12746
12933
  lastOutputTime = Date.now();
12747
- stdoutBuffer += chunk.toString();
12748
- const lines = stdoutBuffer.split("\n");
12749
- stdoutBuffer = lines.pop() || "";
12750
- for (const line of lines) {
12934
+ const _split = sessionCoreRef.splitStreamLines(stdoutBuffer, chunk.toString());
12935
+ stdoutBuffer = _split.rest;
12936
+ for (const line of _split.lines) {
12751
12937
  if (!line.trim()) continue;
12752
12938
  logger.log(`[Session ${sessionId}] stdout line (${line.length} chars): ${line.slice(0, 500)}`);
12753
12939
  try {
12754
12940
  const msg = JSON.parse(line);
12755
12941
  logger.log(`[Session ${sessionId}] Parsed type=${msg.type} subtype=${msg.subtype || "n/a"}`);
12942
+ if (sessionCoreRef.handleClaudeMessage(pumpCtx, msg)) continue;
12756
12943
  if (msg.type === "control_request" && msg.request?.subtype === "can_use_tool") {
12757
12944
  const requestId = msg.request_id;
12758
12945
  const toolName = msg.request.tool_name;
@@ -12829,18 +13016,6 @@ ${parts.join("\n")}`);
12829
13016
  }).catch((err) => {
12830
13017
  logger.log(`[Session ${sessionId}] Permission handler error (request ${requestId}): ${err}`);
12831
13018
  });
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
13019
  } else if (msg.type === "assistant" || msg.type === "result") {
12845
13020
  if (msg.type === "assistant" && msg.isCompactSummary) {
12846
13021
  logger.log(`[Session ${sessionId}] Context compacted (/compact)`);
@@ -13074,13 +13249,6 @@ ${parts.join("\n")}`);
13074
13249
  consecutiveOverloadRetries = 0;
13075
13250
  }
13076
13251
  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
13252
  } else {
13085
13253
  sessionService.pushMessage(msg, "agent");
13086
13254
  }
@@ -13817,11 +13985,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
13817
13985
  });
13818
13986
  },
13819
13987
  onIssue: async (params) => {
13820
- const { issueRpc } = await import('./rpc-B43CaT9b.mjs');
13988
+ const { issueRpc } = await import('./rpc-_aPtyAzL.mjs');
13821
13989
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
13822
13990
  },
13823
13991
  onWorkflow: async (params) => {
13824
- const { workflowRpc } = await import('./rpc-CC9VBNEi.mjs');
13992
+ const { workflowRpc } = await import('./rpc-GTsR01jv.mjs');
13825
13993
  return workflowRpc(params?.cwd || directory, params || {});
13826
13994
  },
13827
13995
  onRipgrep: async (args, cwd) => {
@@ -14331,11 +14499,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14331
14499
  });
14332
14500
  },
14333
14501
  onIssue: async (params) => {
14334
- const { issueRpc } = await import('./rpc-B43CaT9b.mjs');
14502
+ const { issueRpc } = await import('./rpc-_aPtyAzL.mjs');
14335
14503
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
14336
14504
  },
14337
14505
  onWorkflow: async (params) => {
14338
- const { workflowRpc } = await import('./rpc-CC9VBNEi.mjs');
14506
+ const { workflowRpc } = await import('./rpc-GTsR01jv.mjs');
14339
14507
  return workflowRpc(params?.cwd || directory, params || {});
14340
14508
  },
14341
14509
  onRipgrep: async (args, cwd) => {
@@ -14772,56 +14940,86 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14772
14940
  const sharingNotificationSync = new SharingNotificationSync(server, logger.log);
14773
14941
  sharingNotificationSync.init().catch(() => {
14774
14942
  });
14943
+ const buildMachineHandlers = () => ({
14944
+ spawnSession,
14945
+ archiveSession,
14946
+ resumeSession,
14947
+ deleteSession,
14948
+ restartSession,
14949
+ requestShutdown: () => {
14950
+ logger.log("Shutdown requested via hypha-app (ignored \u2014 daemon never self-terminates)");
14951
+ },
14952
+ getTrackedSessions: getCurrentChildren,
14953
+ getSessionRPCHandlers: (sessionId) => {
14954
+ for (const [, session] of pidToTrackedSession) {
14955
+ if (session.svampSessionId === sessionId && !session.stopped && session.sessionRPCHandlers) {
14956
+ return session.sessionRPCHandlers;
14957
+ }
14958
+ }
14959
+ return void 0;
14960
+ },
14961
+ getSessionIds: () => {
14962
+ const ids = [];
14963
+ for (const [, session] of pidToTrackedSession) {
14964
+ if (session.svampSessionId && !session.stopped && session.sessionRPCHandlers) {
14965
+ ids.push(session.svampSessionId);
14966
+ }
14967
+ }
14968
+ return ids;
14969
+ },
14970
+ getSessionPid: (sessionId) => {
14971
+ for (const [, session] of pidToTrackedSession) {
14972
+ if (session.svampSessionId === sessionId && !session.stopped) {
14973
+ return session.pid;
14974
+ }
14975
+ }
14976
+ return void 0;
14977
+ },
14978
+ supervisor,
14979
+ tunnels,
14980
+ serveManager,
14981
+ sharingNotificationSync,
14982
+ persistExposedTunnel,
14983
+ forgetExposedTunnel,
14984
+ listExposedTunnels: () => loadExposedTunnels().map((t) => ({ name: t.name, ports: t.ports, group: t.group, addedAt: t.addedAt }))
14985
+ });
14775
14986
  const machineService = await registerMachineService(
14776
14987
  server,
14777
14988
  machineId,
14778
14989
  machineMetadata,
14779
14990
  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;
14991
+ buildMachineHandlers()
14992
+ );
14993
+ logger.log(`Machine service registered: svamp-machine-${machineId}`);
14994
+ if (isHotReloadEnabled()) {
14995
+ try {
14996
+ const hotReload = createHotReloadCoordinator({ log: logger.log });
14997
+ const sessionCoreSrc = join$1(__dirname$1, "sessionCore.ts");
14998
+ hotReload.register({
14999
+ id: "sessionCore",
15000
+ rebuild: async () => {
15001
+ if (!existsSync$1(sessionCoreSrc)) {
15002
+ logger.log("[HOTRELOAD] sessionCore.ts not found (bundled runtime) \u2014 hot-reload is dev-only; skipping reload");
15003
+ return sessionCoreRef;
14811
15004
  }
15005
+ const fresh = await reimportFresh(sessionCoreSrc);
15006
+ return { splitStreamLines: fresh.splitStreamLines, handleClaudeMessage: fresh.handleClaudeMessage };
15007
+ },
15008
+ apply: (mod) => {
15009
+ sessionCoreRef = mod;
14812
15010
  }
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 }))
15011
+ });
15012
+ hotReload.register({
15013
+ id: "machine",
15014
+ rebuild: buildMachineHandlers,
15015
+ apply: (h) => machineService.setHandlers(h)
15016
+ });
15017
+ hotReload.start([join$1(__dirname$1, "..")]);
15018
+ logger.log("[HOTRELOAD] dev hot-reload ENABLED (SVAMP_DEV_HOTRELOAD=1): sessionCore (live edit\u2192reload) + machine seam");
15019
+ } catch (e) {
15020
+ logger.log(`[HOTRELOAD] failed to start (continuing without it): ${e?.message || e}`);
14822
15021
  }
14823
- );
14824
- logger.log(`Machine service registered: svamp-machine-${machineId}`);
15022
+ }
14825
15023
  const channelHttpPort = Number(process.env.SVAMP_CHANNEL_HTTP_PORT) || 0;
14826
15024
  if (channelHttpPort > 0) {
14827
15025
  try {
@@ -15090,7 +15288,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15090
15288
  const PING_TIMEOUT_MS = 15e3;
15091
15289
  const POST_RECONNECT_GRACE_MS = 2e4;
15092
15290
  const RECONNECT_JITTER_MS = 2500;
15093
- const { WorkflowScheduler } = await import('./scheduler-DPs8EnlX.mjs');
15291
+ const { WorkflowScheduler } = await import('./scheduler-9mJf0_7T.mjs');
15094
15292
  const workflowScheduler = new WorkflowScheduler({
15095
15293
  projectRoots: () => {
15096
15294
  const dirs = /* @__PURE__ */ new Set();
@@ -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-DsGZVxkK.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,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-DsGZVxkK.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-DRI2MMHg.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-DRI2MMHg.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-DRI2MMHg.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-DRI2MMHg.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-DRI2MMHg.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-DsGZVxkK.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-gMUAwe3q.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-DsGZVxkK.mjs';
2
2
  import 'node:child_process';
3
3
  import 'os';
4
4
  import 'fs/promises';