svamp-cli 0.2.321 → 0.2.323

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 (27) hide show
  1. package/dist/{adminCommands-BRiz5afS.mjs → adminCommands-Bmgpks9U.mjs} +1 -1
  2. package/dist/{agentCommands-Cve_0_8K.mjs → agentCommands-CjbndvZ2.mjs} +5 -5
  3. package/dist/{auth-DrLE8Yp-.mjs → auth-7A9m78i5.mjs} +1 -1
  4. package/dist/{cli-xMKB7O8k.mjs → cli-C3GwCq0z.mjs} +76 -76
  5. package/dist/cli.mjs +2 -2
  6. package/dist/{commands-C-QNVo3l.mjs → commands-BARTdhcw.mjs} +3 -3
  7. package/dist/{commands-slA1eX13.mjs → commands-C8im5Q2J.mjs} +1 -1
  8. package/dist/{commands-D9-YqAI3.mjs → commands-CZLE29kn.mjs} +3 -3
  9. package/dist/{commands-DfRahEsO.mjs → commands-CygFvR0a.mjs} +3 -3
  10. package/dist/{commands-BxHc_Exm.mjs → commands-DLQwUjpD.mjs} +2 -2
  11. package/dist/{commands-CXgDZgqh.mjs → commands-DVvR4X4G.mjs} +2 -2
  12. package/dist/{commands-Fvgfzyo3.mjs → commands-LMbH3V-v.mjs} +11 -11
  13. package/dist/{commands-D1d9snmv.mjs → commands-gQM3K8Yf.mjs} +1 -1
  14. package/dist/{fleet-umFHXPoE.mjs → fleet-C68s3qVt.mjs} +3 -3
  15. package/dist/{headlessCli-DgJ15daM.mjs → headlessCli-0_H-JwW2.mjs} +2 -2
  16. package/dist/index.mjs +1 -1
  17. package/dist/{notifyCommands-Cip4lIYS.mjs → notifyCommands-r0r8eyxA.mjs} +1 -1
  18. package/dist/{package-DJRwvqcx.mjs → package-BGIfEYpX.mjs} +2 -2
  19. package/dist/{pinnedClaudeCode-BkZfX5pW.mjs → pinnedClaudeCode-C8CmQv3y.mjs} +1 -1
  20. package/dist/{rpc-CLoO6Z5Z.mjs → rpc-BosOiRY-.mjs} +1 -1
  21. package/dist/{rpc-Bz9w7JV9.mjs → rpc-DP4CiR0g.mjs} +1 -1
  22. package/dist/{run-CKLatoxa.mjs → run-BiwqH1hw.mjs} +62 -30
  23. package/dist/{run-CxuKTe0N.mjs → run-DAo9Lw4D.mjs} +1 -1
  24. package/dist/{scheduler-Bs0nAlhs.mjs → scheduler-BN9GuvGN.mjs} +1 -1
  25. package/dist/{serveCommands-Bi7DJs-3.mjs → serveCommands-C_E-RAiL.mjs} +10 -10
  26. package/dist/{sideband-CFbMRvzr.mjs → sideband-L0YNMJhj.mjs} +1 -1
  27. package/package.json +3 -3
@@ -1,10 +1,10 @@
1
- import { connectAndResolveSession } from './commands-slA1eX13.mjs';
2
- import { w as wantsHelp } from './cli-xMKB7O8k.mjs';
1
+ import { connectAndResolveSession } from './commands-C8im5Q2J.mjs';
2
+ import { w as wantsHelp } from './cli-C3GwCq0z.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:child_process';
5
5
  import 'node:path';
6
6
  import 'node:os';
7
- import './run-CKLatoxa.mjs';
7
+ import './run-BiwqH1hw.mjs';
8
8
  import 'os';
9
9
  import 'fs/promises';
10
10
  import 'fs';
@@ -1,12 +1,12 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-slA1eX13.mjs';
4
- import { w as wantsHelp } from './cli-xMKB7O8k.mjs';
3
+ import { connectAndGetMachine } from './commands-C8im5Q2J.mjs';
4
+ import { w as wantsHelp } from './cli-C3GwCq0z.mjs';
5
5
  import 'node:fs';
6
6
  import 'node:child_process';
7
7
  import 'node:path';
8
8
  import 'node:os';
9
- import './run-CKLatoxa.mjs';
9
+ import './run-BiwqH1hw.mjs';
10
10
  import 'os';
11
11
  import 'fs/promises';
12
12
  import 'url';
@@ -1,8 +1,8 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
- import { f as flushAndExit } from './cli-xMKB7O8k.mjs';
5
- import { f as resolveProjectRoot, n as searchIssues, l as listIssues, m as isPendingIssue, i as resumeIssue, p as pauseIssue, j as addComment, u as updateIssue, h as getIssue, o as isVisibleTo, H as summarize, k as addIssue } from './run-CKLatoxa.mjs';
4
+ import { f as flushAndExit } from './cli-C3GwCq0z.mjs';
5
+ import { f as resolveProjectRoot, n as searchIssues, l as listIssues, m as isPendingIssue, i as resumeIssue, p as pauseIssue, j as addComment, u as updateIssue, h as getIssue, o as isVisibleTo, H as summarize, k as addIssue } from './run-BiwqH1hw.mjs';
6
6
  import './serviceManager-hlOVxkhW.mjs';
7
7
  import 'os';
8
8
  import 'fs/promises';
@@ -1,6 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { f as resolveProjectRoot, I as workflowSteps, x as setWorkflowEnabled, D as isWorkflowEnabled, y as removeWorkflow, v as getWorkflow, C as listWorkflows, A as saveWorkflow, B as rawWorkflow } from './run-CKLatoxa.mjs';
3
- import { w as wantsHelp } from './cli-xMKB7O8k.mjs';
2
+ import { f as resolveProjectRoot, I as workflowSteps, x as setWorkflowEnabled, D as isWorkflowEnabled, y as removeWorkflow, v as getWorkflow, C as listWorkflows, A as saveWorkflow, B as rawWorkflow } from './run-BiwqH1hw.mjs';
3
+ import { w as wantsHelp } from './cli-C3GwCq0z.mjs';
4
4
  import 'os';
5
5
  import 'fs/promises';
6
6
  import 'fs';
@@ -1,6 +1,6 @@
1
1
  import * as path from 'path';
2
- import { w as wantsHelp } from './cli-xMKB7O8k.mjs';
3
- import './run-CKLatoxa.mjs';
2
+ import { w as wantsHelp } from './cli-C3GwCq0z.mjs';
3
+ import './run-BiwqH1hw.mjs';
4
4
  import 'os';
5
5
  import 'fs/promises';
6
6
  import 'fs';
@@ -83,7 +83,7 @@ async function serviceExpose(args) {
83
83
  process.exit(1);
84
84
  }
85
85
  if (foreground) {
86
- const { runFrpcTunnel } = await import('./run-CKLatoxa.mjs').then(function (n) { return n.ao; });
86
+ const { runFrpcTunnel } = await import('./run-BiwqH1hw.mjs').then(function (n) { return n.ao; });
87
87
  await runFrpcTunnel(name, ports, void 0, {
88
88
  group,
89
89
  groupKey,
@@ -93,7 +93,7 @@ async function serviceExpose(args) {
93
93
  });
94
94
  return;
95
95
  }
96
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
97
97
  const { server, machine } = await connectAndGetMachine();
98
98
  try {
99
99
  const status = await machine.tunnelStart({
@@ -115,7 +115,7 @@ async function serviceExpose(args) {
115
115
  console.log(` port ${port}: ${url}`);
116
116
  }
117
117
  if (process.env.SVAMP_SESSION_ID) {
118
- const { autoAddSessionLink } = await import('./agentCommands-Cve_0_8K.mjs');
118
+ const { autoAddSessionLink } = await import('./agentCommands-CjbndvZ2.mjs');
119
119
  let added = 0;
120
120
  for (const [port, url] of urlEntries) {
121
121
  const label = urlEntries.length > 1 ? `${name}:${port}` : name;
@@ -151,8 +151,8 @@ async function serviceServe(args) {
151
151
  const resolvedDir = path.resolve(directory);
152
152
  console.log(`Serving ${resolvedDir}`);
153
153
  const http = await import('http');
154
- const { serveStaticMount } = await import('./run-CKLatoxa.mjs').then(function (n) { return n.ap; });
155
- const { getFreePort } = await import('./run-CKLatoxa.mjs').then(function (n) { return n.ao; });
154
+ const { serveStaticMount } = await import('./run-BiwqH1hw.mjs').then(function (n) { return n.ap; });
155
+ const { getFreePort } = await import('./run-BiwqH1hw.mjs').then(function (n) { return n.ao; });
156
156
  const server = http.createServer((req, res) => {
157
157
  const u = new URL(req.url || "/", "http://127.0.0.1");
158
158
  let rel = u.pathname;
@@ -175,7 +175,7 @@ async function serviceServe(args) {
175
175
  resolve(18080);
176
176
  });
177
177
  });
178
- const { runFrpcTunnel } = await import('./run-CKLatoxa.mjs').then(function (n) { return n.ao; });
178
+ const { runFrpcTunnel } = await import('./run-BiwqH1hw.mjs').then(function (n) { return n.ao; });
179
179
  void server;
180
180
  await runFrpcTunnel(name, [servePort]);
181
181
  } catch (err) {
@@ -185,7 +185,7 @@ async function serviceServe(args) {
185
185
  }
186
186
  async function serviceList(_args) {
187
187
  try {
188
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
188
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
189
189
  const { server, machine } = await connectAndGetMachine();
190
190
  try {
191
191
  const tunnels = await machine.tunnelList({});
@@ -225,11 +225,11 @@ async function serviceDelete(args) {
225
225
  process.exit(1);
226
226
  }
227
227
  try {
228
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
228
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
229
229
  const { server, machine } = await connectAndGetMachine();
230
230
  try {
231
231
  await machine.tunnelStop({ name });
232
- const { removeSessionLinkByService } = await import('./agentCommands-Cve_0_8K.mjs');
232
+ const { removeSessionLinkByService } = await import('./agentCommands-CjbndvZ2.mjs');
233
233
  removeSessionLinkByService("tunnel", name);
234
234
  console.log(`Stopped tunnel '${name}'.`);
235
235
  } catch (err) {
@@ -1,7 +1,7 @@
1
1
  import os from 'os';
2
2
  import fs__default from 'fs';
3
3
  import { resolve, join, relative } from 'path';
4
- import { Q as parseFrontmatter, T as getSkillsServer, U as getSkillsWorkspaceName, V as getSkillsCollectionName, W as fetchWithTimeout, X as searchSkills, Y as SKILLS_DIR, Z as getSkillInfo, _ as downloadSkillFile, $ as listSkillFiles } from './run-CKLatoxa.mjs';
4
+ import { Q as parseFrontmatter, T as getSkillsServer, U as getSkillsWorkspaceName, V as getSkillsCollectionName, W as fetchWithTimeout, X as searchSkills, Y as SKILLS_DIR, Z as getSkillInfo, _ as downloadSkillFile, $ as listSkillFiles } from './run-BiwqH1hw.mjs';
5
5
  import 'fs/promises';
6
6
  import 'url';
7
7
  import 'child_process';
@@ -1,8 +1,8 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import os from 'node:os';
4
- import { ad as PINNED_CODEX_VERSION, c as connectToHypha } from './run-CKLatoxa.mjs';
5
- import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-BkZfX5pW.mjs';
4
+ import { ad as PINNED_CODEX_VERSION, c as connectToHypha } from './run-BiwqH1hw.mjs';
5
+ import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-C8CmQv3y.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -23,7 +23,7 @@ import 'node:fs/promises';
23
23
  import 'yaml';
24
24
 
25
25
  const KIMI_NPM_PACKAGE = "@moonshot-ai/kimi-code";
26
- const PINNED_KIMI_VERSION = "0.34.0";
26
+ const PINNED_KIMI_VERSION = "0.35.0";
27
27
 
28
28
  const SVAMP_HOME = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
29
29
  const DAEMON_STATE_FILE = join(SVAMP_HOME, "daemon.state.json");
@@ -1,5 +1,5 @@
1
- import { a0 as resolveModel, ah as describeMisconfiguration, ai as buildMachineDeps } from './run-CKLatoxa.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CFbMRvzr.mjs';
1
+ import { a0 as resolveModel, ah as describeMisconfiguration, ai as buildMachineDeps } from './run-BiwqH1hw.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-L0YNMJhj.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-CKLatoxa.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-BiwqH1hw.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,4 +1,4 @@
1
- import { c as connectToHypha, S as SharingNotificationSync, J as parseJwtEmail } from './run-CKLatoxa.mjs';
1
+ import { c as connectToHypha, S as SharingNotificationSync, J as parseJwtEmail } from './run-BiwqH1hw.mjs';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { existsSync, readFileSync } from 'node:fs';
4
4
  import { join } from 'node:path';
@@ -1,5 +1,5 @@
1
1
  var name = "svamp-cli";
2
- var version = "0.2.321";
2
+ var version = "0.2.323";
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";
@@ -25,7 +25,7 @@ var scripts = {
25
25
  "dev:daemon": "tsx src/cli.ts daemon start-sync",
26
26
  "test:e2e": "node --no-warnings test/e2e-session-tests.mjs && npx tsx test/e2e-codex-midturn-steer.mjs && npx tsx test/e2e-serve-iframe-login.mjs && npx tsx test/test-archive-preserves-claude-file.mjs && npx tsx test/test-daemon-e2e.mjs && npx tsx test/test-hypha-service.mjs && npx tsx test/test-permission-e2e.mjs && npx tsx test/test-serve-e2e.mjs && npx tsx test/test-session-archive-resume.mjs && npx tsx test/test-session-rpc-e2e.mjs && npx tsx test/test-skills-integration.mjs && npx tsx test/test-wm-refresh.mjs && npx tsx test/e2e-session-files-gateway.mjs && npx tsx test/e2e-dns-production-hosts.mjs",
27
27
  "test:frpc": "npx tsx test/test-frpc-e2e.mjs",
28
- prepublishOnly: "yarn build"
28
+ prepublishOnly: "node ../../scripts/bump-cli-version.mjs --check && yarn build"
29
29
  };
30
30
  var dependencies = {
31
31
  "@agentclientprotocol/sdk": "^0.14.1",
@@ -1,7 +1,7 @@
1
1
  import { spawn, exec as exec$1 } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
3
 
4
- const PINNED_CLAUDE_CODE_VERSION = "2.1.227";
4
+ const PINNED_CLAUDE_CODE_VERSION = "2.1.229";
5
5
  const exec = promisify(exec$1);
6
6
  let _reconcile = null;
7
7
  function beginClaudeVersionReconcile(log) {
@@ -1,4 +1,4 @@
1
- import { f as resolveProjectRoot, u as updateIssue, h as getIssue, i as resumeIssue, p as pauseIssue, j as addComment, k as addIssue, l as listIssues, m as isPendingIssue, n as searchIssues, o as isVisibleTo } from './run-CKLatoxa.mjs';
1
+ import { f as resolveProjectRoot, u as updateIssue, h as getIssue, i as resumeIssue, p as pauseIssue, j as addComment, k as addIssue, l as listIssues, m as isPendingIssue, n as searchIssues, o as isVisibleTo } from './run-BiwqH1hw.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,4 +1,4 @@
1
- import { f as resolveProjectRoot, q as getRun, t as listRuns, v as getWorkflow, w as runWorkflow, x as setWorkflowEnabled, y as removeWorkflow, z as validateWorkflowName, A as saveWorkflow, B as rawWorkflow, C as listWorkflows } from './run-CKLatoxa.mjs';
1
+ import { f as resolveProjectRoot, q as getRun, t as listRuns, v as getWorkflow, w as runWorkflow, x as setWorkflowEnabled, y as removeWorkflow, z as validateWorkflowName, A as saveWorkflow, B as rawWorkflow, C as listWorkflows } from './run-BiwqH1hw.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -2398,14 +2398,17 @@ h1{font-size:1.15rem;word-break:break-all}ul{list-style:none;padding:0}li{paddin
2398
2398
  a{color:#0969da;text-decoration:none}a:hover{text-decoration:underline}</style></head>
2399
2399
  <body><h1>${esc(base)}</h1><ul>${rows || "<li>(empty)</li>"}</ul></body></html>`;
2400
2400
  }
2401
+ const CORS_ALLOW_HEADERS = "Authorization, *";
2401
2402
  const CORS = {
2402
2403
  "Access-Control-Allow-Origin": "*",
2403
2404
  "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS",
2404
- "Access-Control-Allow-Headers": "*"
2405
+ "Access-Control-Allow-Headers": CORS_ALLOW_HEADERS
2405
2406
  };
2406
2407
  function serveStaticMount(req, res, opts) {
2407
2408
  const { rootDir, relPath, mountUrlPrefix } = opts;
2408
2409
  const browse = opts.browse !== false;
2410
+ const attachment = opts.attachment === true;
2411
+ const allowHidden = opts.allowHidden === true;
2409
2412
  const method = (req.method || "GET").toUpperCase();
2410
2413
  if (method === "OPTIONS") {
2411
2414
  res.writeHead(204, CORS);
@@ -2426,10 +2429,10 @@ function serveStaticMount(req, res, opts) {
2426
2429
  return;
2427
2430
  }
2428
2431
  if (rootStat.isFile()) {
2429
- sendFile(req, res, rootDir, rootStat);
2432
+ sendFile(req, res, rootDir, rootStat, attachment);
2430
2433
  return;
2431
2434
  }
2432
- if (hasBlockedDotSegment(relPath)) {
2435
+ if (!allowHidden && hasBlockedDotSegment(relPath)) {
2433
2436
  res.writeHead(404, CORS);
2434
2437
  res.end("Not Found");
2435
2438
  return;
@@ -2466,7 +2469,7 @@ function serveStaticMount(req, res, opts) {
2466
2469
  try {
2467
2470
  const ist = fs.statSync(indexPath);
2468
2471
  if (ist.isFile()) {
2469
- sendFile(req, res, indexPath, ist);
2472
+ sendFile(req, res, indexPath, ist, attachment);
2470
2473
  return;
2471
2474
  }
2472
2475
  } catch {
@@ -2492,7 +2495,7 @@ function serveStaticMount(req, res, opts) {
2492
2495
  return;
2493
2496
  }
2494
2497
  if (st.isFile()) {
2495
- sendFile(req, res, target, st);
2498
+ sendFile(req, res, target, st, attachment);
2496
2499
  return;
2497
2500
  }
2498
2501
  res.writeHead(404, CORS);
@@ -2501,7 +2504,12 @@ function serveStaticMount(req, res, opts) {
2501
2504
  function etagFor(st) {
2502
2505
  return `"${st.size.toString(16)}-${Math.floor(st.mtimeMs).toString(16)}"`;
2503
2506
  }
2504
- function sendFile(req, res, filePath, st) {
2507
+ function attachmentDisposition(filePath) {
2508
+ const name = path.basename(filePath) || "download";
2509
+ const ascii = name.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_") || "download";
2510
+ return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(name)}`;
2511
+ }
2512
+ function sendFile(req, res, filePath, st, attachment = false) {
2505
2513
  const method = (req.method || "GET").toUpperCase();
2506
2514
  const etag = etagFor(st);
2507
2515
  const lastMod = new Date(st.mtimeMs).toUTCString();
@@ -2511,8 +2519,9 @@ function sendFile(req, res, filePath, st) {
2511
2519
  "Accept-Ranges": "bytes",
2512
2520
  ETag: etag,
2513
2521
  "Last-Modified": lastMod,
2514
- "Cache-Control": "no-cache"
2522
+ "Cache-Control": "no-cache",
2515
2523
  // revalidate via ETag; content can change under a mount
2524
+ ...attachment ? { "Content-Disposition": attachmentDisposition(filePath) } : {}
2516
2525
  };
2517
2526
  const inm = req.headers["if-none-match"];
2518
2527
  const ims = req.headers["if-modified-since"];
@@ -2559,6 +2568,8 @@ function pipeStream(stream, res) {
2559
2568
 
2560
2569
  var staticFileServer = /*#__PURE__*/Object.freeze({
2561
2570
  __proto__: null,
2571
+ CORS_ALLOW_HEADERS: CORS_ALLOW_HEADERS,
2572
+ attachmentDisposition: attachmentDisposition,
2562
2573
  containedPath: containedPath,
2563
2574
  contentTypeFor: contentTypeFor,
2564
2575
  directoryListingHtml: directoryListingHtml,
@@ -3746,7 +3757,9 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3746
3757
  const CORS = {
3747
3758
  "Access-Control-Allow-Origin": "*",
3748
3759
  "Access-Control-Allow-Methods": "GET, HEAD, PUT, DELETE, OPTIONS",
3749
- "Access-Control-Allow-Headers": "*",
3760
+ // #0963: MUST name Authorization explicitly — the `*` wildcard does not cover it, and the
3761
+ // uploader authenticates with a Bearer header on a cross-origin PUT. See CORS_ALLOW_HEADERS.
3762
+ "Access-Control-Allow-Headers": CORS_ALLOW_HEADERS,
3750
3763
  "Access-Control-Expose-Headers": "Content-Length, Content-Range, ETag",
3751
3764
  "Access-Control-Max-Age": "600"
3752
3765
  };
@@ -3825,7 +3838,8 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3825
3838
  res.end(method === "HEAD" ? void 0 : JSON.stringify({ path: relPath, entries }));
3826
3839
  return;
3827
3840
  }
3828
- serveStaticMount(req, res, { rootDir, relPath: normRel ? `/${normRel}` : "/", mountUrlPrefix: "", browse: false});
3841
+ const asAttachment = url.searchParams.get("download") === "1";
3842
+ serveStaticMount(req, res, { rootDir, relPath: normRel ? `/${normRel}` : "/", mountUrlPrefix: "", browse: false, attachment: asAttachment, allowHidden: true});
3829
3843
  return;
3830
3844
  }
3831
3845
  if (method === "PUT" || method === "DELETE") {
@@ -4155,7 +4169,7 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
4155
4169
  });
4156
4170
  return;
4157
4171
  }
4158
- const cors = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS", "Access-Control-Allow-Headers": "*" };
4172
+ const cors = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS", "Access-Control-Allow-Headers": CORS_ALLOW_HEADERS };
4159
4173
  if (url.pathname === "/" || basePath === "/") {
4160
4174
  res.writeHead(200, { ...cors, "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
4161
4175
  res.end(this.mountListHtml());
@@ -8016,7 +8030,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
8016
8030
  }
8017
8031
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
8018
8032
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
8019
- const { toolsForRole } = await import('./sideband-CFbMRvzr.mjs');
8033
+ const { toolsForRole } = await import('./sideband-L0YNMJhj.mjs');
8020
8034
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
8021
8035
  return fmt(r2);
8022
8036
  }
@@ -8121,7 +8135,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
8121
8135
  return { ok: false, call_id: callId, status: "busy", error: "channel is busy (too many concurrent requests) \u2014 retry shortly" };
8122
8136
  }
8123
8137
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
8124
- const { queryCore } = await import('./commands-slA1eX13.mjs');
8138
+ const { queryCore } = await import('./commands-C8im5Q2J.mjs');
8125
8139
  const timeout = c.reply?.timeout_sec || 120;
8126
8140
  let result;
8127
8141
  try {
@@ -10435,17 +10449,29 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
10435
10449
  return { ...lastActivity, sessionId, pendingPermissions };
10436
10450
  },
10437
10451
  // ── File Operations (optional, admin-only) ──
10452
+ // #0965: file BYTES now travel over the HTTP files-gateway (the always-on frp tunnel,
10453
+ // GET/HEAD/PUT/DELETE + ?list=1 in serveManager), NOT this hypha-rpc control WebSocket. A
10454
+ // large base64 body over RPC died on any WS blip and starved the session heartbeat. So
10455
+ // `writeFile`, `writeFileChunk` and `listDirectory` below are DEPRECATED — no current
10456
+ // frontend calls them; they're retained only so a cached/stale PWA build still has a
10457
+ // working handler (there is no client-version guard). EXCEPTIONS that stay first-class:
10458
+ // • `readFile` — control-plane, NOT file transfer: the CLI `loop status` and the
10459
+ // frontend `getSessionLoopStatus` read small `.svamp/<id>/loop/*.json` files through
10460
+ // it. Keeping loop status off the file tunnel avoids coupling the loop UI to it.
10461
+ // • `filesEndpoint` — resolves the gateway URL the frontend uses for all of the above.
10438
10462
  readFile: async (path, context) => {
10439
10463
  authorizeRequest(context, metadata.sharing, "admin");
10440
10464
  if (!callbacks.onReadFile) throw new Error("readFile not supported");
10441
10465
  return await callbacks.onReadFile(path);
10442
10466
  },
10467
+ /** @deprecated #0965 — use the HTTP files-gateway (PUT). Retained for cached-PWA skew only. */
10443
10468
  writeFile: async (path, content, context) => {
10444
10469
  authorizeRequest(context, metadata.sharing, "admin");
10445
10470
  if (!callbacks.onWriteFile) throw new Error("writeFile not supported");
10446
10471
  await callbacks.onWriteFile(path, content);
10447
10472
  return { success: true };
10448
10473
  },
10474
+ /** @deprecated #0965 — superseded by the HTTP files-gateway (PUT). Retained for cached-PWA skew only. */
10449
10475
  writeFileChunk: async (path, content, uploadId, chunkIndex, totalChunks, isLast, context) => {
10450
10476
  authorizeRequest(context, metadata.sharing, "admin");
10451
10477
  if (!callbacks.onWriteFileChunk) throw new Error("writeFileChunk not supported");
@@ -10459,6 +10485,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
10459
10485
  authorizeRequest(context, metadata.sharing, "admin");
10460
10486
  return { url: callbacks.onFilesEndpoint?.() ?? null };
10461
10487
  },
10488
+ /** @deprecated #0965 — use the HTTP files-gateway (GET ?list=1). Retained for cached-PWA skew only. */
10462
10489
  listDirectory: async (path, context) => {
10463
10490
  authorizeRequest(context, metadata.sharing, "admin");
10464
10491
  if (!callbacks.onListDirectory) throw new Error("listDirectory not supported");
@@ -17434,7 +17461,7 @@ function summarizeExtensions(extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENS
17434
17461
  return `${n} extension${n === 1 ? "" : "s"} granted (+${turns} turns)${reasons ? `: ${reasons}` : ""}`;
17435
17462
  }
17436
17463
  const DEFAULT_LOOP_STUCK_CHECKPOINTS = 3;
17437
- const DEFAULT_LOOP_MAX_AUTORESUMES = Number.POSITIVE_INFINITY;
17464
+ const DEFAULT_LOOP_MAX_AUTORESUMES = 3;
17438
17465
  const PROGRESS_HISTORY_CAP = 12;
17439
17466
  function resolveStuckLimit(envValue) {
17440
17467
  const n = Number(envValue);
@@ -17443,6 +17470,8 @@ function resolveStuckLimit(envValue) {
17443
17470
  }
17444
17471
  function resolveMaxAutoResumes(envValue) {
17445
17472
  if (envValue == null || envValue.trim() === "") return DEFAULT_LOOP_MAX_AUTORESUMES;
17473
+ const s = envValue.trim().toLowerCase();
17474
+ if (s === "unbounded" || s === "inf" || s === "infinity" || s === "-1") return Number.POSITIVE_INFINITY;
17446
17475
  const n = Number(envValue);
17447
17476
  if (Number.isFinite(n) && n >= 0) return Math.floor(n);
17448
17477
  return DEFAULT_LOOP_MAX_AUTORESUMES;
@@ -19651,7 +19680,7 @@ async function startDaemon(options) {
19651
19680
  try {
19652
19681
  const dir = loadSessionIndex()[sessionId]?.directory;
19653
19682
  if (!dir) return;
19654
- const { reconcileServiceLinks } = await import('./agentCommands-Cve_0_8K.mjs');
19683
+ const { reconcileServiceLinks } = await import('./agentCommands-CjbndvZ2.mjs');
19655
19684
  const configPath = getSvampConfigPath(dir, sessionId);
19656
19685
  const config = readSvampConfig(configPath);
19657
19686
  const entries = Array.from(urls.entries());
@@ -19673,7 +19702,7 @@ async function startDaemon(options) {
19673
19702
  try {
19674
19703
  const dir = loadSessionIndex()[sessionId]?.directory;
19675
19704
  if (!dir) return;
19676
- const { reconcileServiceLinks } = await import('./agentCommands-Cve_0_8K.mjs');
19705
+ const { reconcileServiceLinks } = await import('./agentCommands-CjbndvZ2.mjs');
19677
19706
  const configPath = getSvampConfigPath(dir, sessionId);
19678
19707
  const config = readSvampConfig(configPath);
19679
19708
  const incoming = [{
@@ -19694,7 +19723,7 @@ async function startDaemon(options) {
19694
19723
  try {
19695
19724
  const dir = loadSessionIndex()[sessionId]?.directory;
19696
19725
  if (!dir) return;
19697
- const { dropServiceLinks } = await import('./agentCommands-Cve_0_8K.mjs');
19726
+ const { dropServiceLinks } = await import('./agentCommands-CjbndvZ2.mjs');
19698
19727
  const configPath = getSvampConfigPath(dir, sessionId);
19699
19728
  const config = readSvampConfig(configPath);
19700
19729
  if (dropServiceLinks(config, "serve", mountName)) {
@@ -19737,7 +19766,7 @@ async function startDaemon(options) {
19737
19766
  ensureAutoInstalledCommands(logger);
19738
19767
  (async () => {
19739
19768
  try {
19740
- const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-BkZfX5pW.mjs');
19769
+ const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-C8CmQv3y.mjs');
19741
19770
  beginClaudeVersionReconcile((msg) => logger.log(msg));
19742
19771
  } catch (e) {
19743
19772
  logger.log(`[claude-version] check failed: ${e?.message || e}`);
@@ -20491,8 +20520,9 @@ ${parts.join("\n")}`);
20491
20520
  progressHistory: progress_history || [],
20492
20521
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
20493
20522
  autoResumes: typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0,
20494
- // #0320: extensions also raise a FINITE auto-resume cap (one extra resume each). With
20495
- // the unbounded #0319 default this is a no-op (Infinity + n = Infinity).
20523
+ // #0320: extensions also raise the FINITE auto-resume cap (one extra resume each).
20524
+ // #0958: the cap is finite by default now, so this genuinely enlarges it (was a
20525
+ // no-op under the old Infinity default).
20496
20526
  maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS)),
20497
20527
  stuckReason: result.reason
20498
20528
  });
@@ -20510,12 +20540,13 @@ ${parts.join("\n")}`);
20510
20540
  max_iterations: ls.max_iterations,
20511
20541
  budget,
20512
20542
  started_at: startedAt,
20513
- // #0319: a PROGRESSING loop resets its hold counter so the evaluator-guided re-kick
20514
- // mechanism re-engages fresh (it's making headway, not stuck); an auto-resume keeps it.
20543
+ // #0319/#0958: a PROGRESSING loop resets its hold counter AND its consecutive-fruitless
20544
+ // auto-resume counter it's making headway, not wedged, so the finite auto-resume cap
20545
+ // (#0958) only ever bounds a genuine back-to-back stall, never a slow-but-productive loop.
20515
20546
  holds: decision.kind === "progress" ? 0 : holds,
20516
20547
  ledger,
20517
20548
  progress_history,
20518
- auto_resumes: nextAuto,
20549
+ auto_resumes: decision.kind === "progress" ? 0 : nextAuto,
20519
20550
  extensions,
20520
20551
  durable: ls.durable,
20521
20552
  verify_errors: 0
@@ -22065,11 +22096,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
22065
22096
  });
22066
22097
  },
22067
22098
  onIssue: async (params) => {
22068
- const { issueRpc } = await import('./rpc-CLoO6Z5Z.mjs');
22099
+ const { issueRpc } = await import('./rpc-BosOiRY-.mjs');
22069
22100
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
22070
22101
  },
22071
22102
  onWorkflow: async (params) => {
22072
- const { workflowRpc } = await import('./rpc-Bz9w7JV9.mjs');
22103
+ const { workflowRpc } = await import('./rpc-DP4CiR0g.mjs');
22073
22104
  return workflowRpc(params?.cwd || directory, params || {});
22074
22105
  },
22075
22106
  onRipgrep: async (args, cwd) => {
@@ -22776,11 +22807,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
22776
22807
  });
22777
22808
  },
22778
22809
  onIssue: async (params) => {
22779
- const { issueRpc } = await import('./rpc-CLoO6Z5Z.mjs');
22810
+ const { issueRpc } = await import('./rpc-BosOiRY-.mjs');
22780
22811
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
22781
22812
  },
22782
22813
  onWorkflow: async (params) => {
22783
- const { workflowRpc } = await import('./rpc-Bz9w7JV9.mjs');
22814
+ const { workflowRpc } = await import('./rpc-DP4CiR0g.mjs');
22784
22815
  return workflowRpc(params?.cwd || directory, params || {});
22785
22816
  },
22786
22817
  onRipgrep: async (args, cwd) => {
@@ -23179,12 +23210,13 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
23179
23210
  progressHistory: ls.progress_history || [],
23180
23211
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
23181
23212
  autoResumes: typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0,
23182
- // #0320: extensions also raise a FINITE auto-resume cap (no-op under the unbounded default).
23213
+ // #0320/#0958: extensions raise the FINITE auto-resume cap (genuinely enlarges it now
23214
+ // that the default is finite — was a no-op under the old unbounded default).
23183
23215
  maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, acpMaxExt),
23184
23216
  stuckReason: result.reason
23185
23217
  });
23186
23218
  if (decision.action === "continue") {
23187
- const nextAuto = (typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0) + (decision.consumeAutoResume ? 1 : 0);
23219
+ const nextAuto = decision.kind === "progress" ? 0 : (typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0) + (decision.consumeAutoResume ? 1 : 0);
23188
23220
  writeGoalLoopState(directory, sessionId, { ...ls, active: true, phase: "continue", holds, started_at: startedAt, ledger, auto_resumes: nextAuto });
23189
23221
  const label = decision.kind === "autoresume" ? "\u{1F501} Auto-resuming stalled loop" : "\u{1F501} Loop still progressing";
23190
23222
  sessionService.pushMessage({ type: "message", message: `${label} \u2014 ${decision.reason}` }, "event");
@@ -23831,7 +23863,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
23831
23863
  }
23832
23864
  if (persistedSessions.length > 0) {
23833
23865
  try {
23834
- const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-BkZfX5pW.mjs');
23866
+ const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-C8CmQv3y.mjs');
23835
23867
  await awaitClaudeVersionReady();
23836
23868
  } catch {
23837
23869
  }
@@ -24080,7 +24112,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
24080
24112
  const PING_TIMEOUT_MS = 15e3;
24081
24113
  const POST_RECONNECT_GRACE_MS = 2e4;
24082
24114
  const RECONNECT_JITTER_MS = 2500;
24083
- const { WorkflowScheduler } = await import('./scheduler-Bs0nAlhs.mjs');
24115
+ const { WorkflowScheduler } = await import('./scheduler-BN9GuvGN.mjs');
24084
24116
  const workflowProjectRoots = () => {
24085
24117
  const dirs = /* @__PURE__ */ new Set();
24086
24118
  for (const s of pidToTrackedSession.values()) {
@@ -1,4 +1,4 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { aj as applyClaudeProxyEnv, ak as composeSessionId, al as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, am as generateHookSettings } from './run-CKLatoxa.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { aj as applyClaudeProxyEnv, ak as composeSessionId, al as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, am as generateHookSettings } from './run-BiwqH1hw.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,4 +1,4 @@
1
- import { f as resolveProjectRoot, C as listWorkflows, D as isWorkflowEnabled, E as workflowSchedules, F as inZone, w as runWorkflow, G as cronMatches } from './run-CKLatoxa.mjs';
1
+ import { f as resolveProjectRoot, C as listWorkflows, D as isWorkflowEnabled, E as workflowSchedules, F as inZone, w as runWorkflow, G as cronMatches } from './run-BiwqH1hw.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,6 +1,6 @@
1
1
  import * as path from 'path';
2
- import { w as wantsHelp } from './cli-xMKB7O8k.mjs';
3
- import './run-CKLatoxa.mjs';
2
+ import { w as wantsHelp } from './cli-C3GwCq0z.mjs';
3
+ import './run-BiwqH1hw.mjs';
4
4
  import 'os';
5
5
  import 'fs/promises';
6
6
  import 'fs';
@@ -77,7 +77,7 @@ async function handleServeCommand() {
77
77
  }
78
78
  }
79
79
  async function serveAdd(args, machineId) {
80
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
80
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
81
81
  const pos = positionalArgs(args);
82
82
  const name = pos[0];
83
83
  if (!name) {
@@ -110,7 +110,7 @@ async function serveAdd(args, machineId) {
110
110
  }
111
111
  if (sessionId && result?.url) {
112
112
  try {
113
- const { autoAddSessionLink } = await import('./agentCommands-Cve_0_8K.mjs');
113
+ const { autoAddSessionLink } = await import('./agentCommands-CjbndvZ2.mjs');
114
114
  autoAddSessionLink(String(result.url), name, void 0, { kind: "serve", name });
115
115
  } catch {
116
116
  }
@@ -124,7 +124,7 @@ async function serveAdd(args, machineId) {
124
124
  }
125
125
  }
126
126
  async function serveApply(args, machineId) {
127
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
127
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
128
128
  const fs = await import('fs');
129
129
  const yaml = await import('yaml');
130
130
  const file = positionalArgs(args)[0];
@@ -206,7 +206,7 @@ async function serveApply(args, machineId) {
206
206
  console.log(`URL: ${result.url}`);
207
207
  if (params.sessionId && result?.url) {
208
208
  try {
209
- const { autoAddSessionLink } = await import('./agentCommands-Cve_0_8K.mjs');
209
+ const { autoAddSessionLink } = await import('./agentCommands-CjbndvZ2.mjs');
210
210
  const prevSession = process.env.SVAMP_SESSION_ID;
211
211
  process.env.SVAMP_SESSION_ID = String(params.sessionId);
212
212
  try {
@@ -227,7 +227,7 @@ async function serveApply(args, machineId) {
227
227
  }
228
228
  }
229
229
  async function serveRemove(args, machineId) {
230
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
230
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
231
231
  const pos = positionalArgs(args);
232
232
  const name = pos[0];
233
233
  if (!name) {
@@ -237,7 +237,7 @@ async function serveRemove(args, machineId) {
237
237
  const { machine, server } = await connectAndGetMachine(machineId);
238
238
  try {
239
239
  await machine.serveRemove({ name });
240
- const { removeSessionLinkByService } = await import('./agentCommands-Cve_0_8K.mjs');
240
+ const { removeSessionLinkByService } = await import('./agentCommands-CjbndvZ2.mjs');
241
241
  removeSessionLinkByService("serve", name);
242
242
  console.log(`Mount '${name}' removed.`);
243
243
  } catch (err) {
@@ -249,7 +249,7 @@ async function serveRemove(args, machineId) {
249
249
  }
250
250
  }
251
251
  async function serveList(args, machineId) {
252
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
252
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
253
253
  const all = hasFlag(args, "--all", "-a");
254
254
  const json = hasFlag(args, "--json");
255
255
  const sessionId = getFlag(args, "--session");
@@ -283,7 +283,7 @@ async function serveList(args, machineId) {
283
283
  }
284
284
  }
285
285
  async function serveInfo(machineId) {
286
- const { connectAndGetMachine } = await import('./commands-slA1eX13.mjs');
286
+ const { connectAndGetMachine } = await import('./commands-C8im5Q2J.mjs');
287
287
  const { machine, server } = await connectAndGetMachine(machineId);
288
288
  try {
289
289
  const info = await machine.serveInfo();