svamp-cli 0.2.320 → 0.2.322

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-JGAVkD1F.mjs → adminCommands-CnJSw_fJ.mjs} +1 -1
  2. package/dist/{agentCommands-CoCcX8K1.mjs → agentCommands-ri042RB5.mjs} +5 -5
  3. package/dist/{auth-CFGN1ArQ.mjs → auth-CvQD_JbA.mjs} +1 -1
  4. package/dist/{cli-C0tO-Dnx.mjs → cli-BPJoSvJ0.mjs} +76 -76
  5. package/dist/cli.mjs +2 -2
  6. package/dist/{commands-CubsoWG-.mjs → commands-AOno1gcV.mjs} +1 -1
  7. package/dist/{commands-CeFjRNKk.mjs → commands-BWWAxC-g.mjs} +11 -11
  8. package/dist/{commands-BUZUle6g.mjs → commands-BW_5joei.mjs} +2 -2
  9. package/dist/{commands-BHcPDQCC.mjs → commands-BxG6r6us.mjs} +3 -3
  10. package/dist/{commands-XN2UtO-W.mjs → commands-D7iQqb-i.mjs} +1 -1
  11. package/dist/{commands-6KY9uV6s.mjs → commands-DR8N0cmJ.mjs} +3 -3
  12. package/dist/{commands-BwkoaGfZ.mjs → commands-Db0PpuwO.mjs} +3 -3
  13. package/dist/{commands-DPi7PGxP.mjs → commands-yuhNv9AR.mjs} +2 -2
  14. package/dist/{fleet-BKrbG7G-.mjs → fleet--8tb1jX3.mjs} +3 -3
  15. package/dist/{headlessCli-nywi2aop.mjs → headlessCli-COD8n9AD.mjs} +2 -2
  16. package/dist/index.mjs +1 -1
  17. package/dist/{notifyCommands-BFr80nfh.mjs → notifyCommands-DLo0ANDt.mjs} +1 -1
  18. package/dist/{package-D4zdkORw.mjs → package-DK43B5gu.mjs} +2 -2
  19. package/dist/{pinnedClaudeCode-BkZfX5pW.mjs → pinnedClaudeCode-C8CmQv3y.mjs} +1 -1
  20. package/dist/{rpc-rpH-yXR7.mjs → rpc-DMlurOlf.mjs} +1 -1
  21. package/dist/{rpc-DVtlZahE.mjs → rpc-JWRwb6oY.mjs} +1 -1
  22. package/dist/{run-CvwPIrfo.mjs → run-BXDA0YFP.mjs} +73 -32
  23. package/dist/{run-C22c9FOe.mjs → run-RYTtTBDy.mjs} +1 -1
  24. package/dist/{scheduler-CYyGe6kn.mjs → scheduler-CkYMjhum.mjs} +1 -1
  25. package/dist/{serveCommands-DRMwdDXS.mjs → serveCommands-BX3D9l8T.mjs} +10 -10
  26. package/dist/{sideband-D1dsa-t0.mjs → sideband-CdXFW-wu.mjs} +1 -1
  27. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
1
  import * as path from 'path';
2
- import { w as wantsHelp } from './cli-C0tO-Dnx.mjs';
3
- import './run-CvwPIrfo.mjs';
2
+ import { w as wantsHelp } from './cli-BPJoSvJ0.mjs';
3
+ import './run-BXDA0YFP.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-CvwPIrfo.mjs').then(function (n) { return n.ao; });
86
+ const { runFrpcTunnel } = await import('./run-BXDA0YFP.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-CubsoWG-.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-AOno1gcV.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-CoCcX8K1.mjs');
118
+ const { autoAddSessionLink } = await import('./agentCommands-ri042RB5.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-CvwPIrfo.mjs').then(function (n) { return n.ap; });
155
- const { getFreePort } = await import('./run-CvwPIrfo.mjs').then(function (n) { return n.ao; });
154
+ const { serveStaticMount } = await import('./run-BXDA0YFP.mjs').then(function (n) { return n.ap; });
155
+ const { getFreePort } = await import('./run-BXDA0YFP.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-CvwPIrfo.mjs').then(function (n) { return n.ao; });
178
+ const { runFrpcTunnel } = await import('./run-BXDA0YFP.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-CubsoWG-.mjs');
188
+ const { connectAndGetMachine } = await import('./commands-AOno1gcV.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-CubsoWG-.mjs');
228
+ const { connectAndGetMachine } = await import('./commands-AOno1gcV.mjs');
229
229
  const { server, machine } = await connectAndGetMachine();
230
230
  try {
231
231
  await machine.tunnelStop({ name });
232
- const { removeSessionLinkByService } = await import('./agentCommands-CoCcX8K1.mjs');
232
+ const { removeSessionLinkByService } = await import('./agentCommands-ri042RB5.mjs');
233
233
  removeSessionLinkByService("tunnel", name);
234
234
  console.log(`Stopped tunnel '${name}'.`);
235
235
  } catch (err) {
@@ -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-CvwPIrfo.mjs';
3
- import { w as wantsHelp } from './cli-C0tO-Dnx.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-BXDA0YFP.mjs';
3
+ import { w as wantsHelp } from './cli-BPJoSvJ0.mjs';
4
4
  import 'os';
5
5
  import 'fs/promises';
6
6
  import 'fs';
@@ -1,10 +1,10 @@
1
- import { connectAndResolveSession } from './commands-CubsoWG-.mjs';
2
- import { w as wantsHelp } from './cli-C0tO-Dnx.mjs';
1
+ import { connectAndResolveSession } from './commands-AOno1gcV.mjs';
2
+ import { w as wantsHelp } from './cli-BPJoSvJ0.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-CvwPIrfo.mjs';
7
+ import './run-BXDA0YFP.mjs';
8
8
  import 'os';
9
9
  import 'fs/promises';
10
10
  import 'fs';
@@ -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-CvwPIrfo.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-BXDA0YFP.mjs';
5
5
  import 'fs/promises';
6
6
  import 'url';
7
7
  import 'child_process';
@@ -1,12 +1,12 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-CubsoWG-.mjs';
4
- import { w as wantsHelp } from './cli-C0tO-Dnx.mjs';
3
+ import { connectAndGetMachine } from './commands-AOno1gcV.mjs';
4
+ import { w as wantsHelp } from './cli-BPJoSvJ0.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-CvwPIrfo.mjs';
9
+ import './run-BXDA0YFP.mjs';
10
10
  import 'os';
11
11
  import 'fs/promises';
12
12
  import 'url';
@@ -1,9 +1,9 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { join, resolve } from 'node:path';
3
- import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-CubsoWG-.mjs';
3
+ import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-AOno1gcV.mjs';
4
4
  import { execFileSync } from 'node:child_process';
5
- import { ag as withFileLock, u as updateIssue, j as addComment, k as addIssue, e as shortId } from './run-CvwPIrfo.mjs';
6
- import { w as wantsHelp } from './cli-C0tO-Dnx.mjs';
5
+ import { ag as withFileLock, u as updateIssue, j as addComment, k as addIssue, e as shortId } from './run-BXDA0YFP.mjs';
6
+ import { w as wantsHelp } from './cli-BPJoSvJ0.mjs';
7
7
  import 'node:os';
8
8
  import 'os';
9
9
  import 'fs/promises';
@@ -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-C0tO-Dnx.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-CvwPIrfo.mjs';
4
+ import { f as flushAndExit } from './cli-BPJoSvJ0.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-BXDA0YFP.mjs';
6
6
  import './serviceManager-hlOVxkhW.mjs';
7
7
  import 'os';
8
8
  import 'fs/promises';
@@ -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-CvwPIrfo.mjs';
5
- import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-BkZfX5pW.mjs';
4
+ import { ad as PINNED_CODEX_VERSION, c as connectToHypha } from './run-BXDA0YFP.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-CvwPIrfo.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-D1dsa-t0.mjs';
1
+ import { a0 as resolveModel, ah as describeMisconfiguration, ai as buildMachineDeps } from './run-BXDA0YFP.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CdXFW-wu.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-CvwPIrfo.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-BXDA0YFP.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-CvwPIrfo.mjs';
1
+ import { c as connectToHypha, S as SharingNotificationSync, J as parseJwtEmail } from './run-BXDA0YFP.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.320";
2
+ var version = "0.2.322";
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, 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-CvwPIrfo.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-BXDA0YFP.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -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-CvwPIrfo.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-BXDA0YFP.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -2398,14 +2398,16 @@ 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;
2409
2411
  const method = (req.method || "GET").toUpperCase();
2410
2412
  if (method === "OPTIONS") {
2411
2413
  res.writeHead(204, CORS);
@@ -2426,7 +2428,7 @@ function serveStaticMount(req, res, opts) {
2426
2428
  return;
2427
2429
  }
2428
2430
  if (rootStat.isFile()) {
2429
- sendFile(req, res, rootDir, rootStat);
2431
+ sendFile(req, res, rootDir, rootStat, attachment);
2430
2432
  return;
2431
2433
  }
2432
2434
  if (hasBlockedDotSegment(relPath)) {
@@ -2466,7 +2468,7 @@ function serveStaticMount(req, res, opts) {
2466
2468
  try {
2467
2469
  const ist = fs.statSync(indexPath);
2468
2470
  if (ist.isFile()) {
2469
- sendFile(req, res, indexPath, ist);
2471
+ sendFile(req, res, indexPath, ist, attachment);
2470
2472
  return;
2471
2473
  }
2472
2474
  } catch {
@@ -2492,7 +2494,7 @@ function serveStaticMount(req, res, opts) {
2492
2494
  return;
2493
2495
  }
2494
2496
  if (st.isFile()) {
2495
- sendFile(req, res, target, st);
2497
+ sendFile(req, res, target, st, attachment);
2496
2498
  return;
2497
2499
  }
2498
2500
  res.writeHead(404, CORS);
@@ -2501,7 +2503,12 @@ function serveStaticMount(req, res, opts) {
2501
2503
  function etagFor(st) {
2502
2504
  return `"${st.size.toString(16)}-${Math.floor(st.mtimeMs).toString(16)}"`;
2503
2505
  }
2504
- function sendFile(req, res, filePath, st) {
2506
+ function attachmentDisposition(filePath) {
2507
+ const name = path.basename(filePath) || "download";
2508
+ const ascii = name.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_") || "download";
2509
+ return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(name)}`;
2510
+ }
2511
+ function sendFile(req, res, filePath, st, attachment = false) {
2505
2512
  const method = (req.method || "GET").toUpperCase();
2506
2513
  const etag = etagFor(st);
2507
2514
  const lastMod = new Date(st.mtimeMs).toUTCString();
@@ -2511,8 +2518,9 @@ function sendFile(req, res, filePath, st) {
2511
2518
  "Accept-Ranges": "bytes",
2512
2519
  ETag: etag,
2513
2520
  "Last-Modified": lastMod,
2514
- "Cache-Control": "no-cache"
2521
+ "Cache-Control": "no-cache",
2515
2522
  // revalidate via ETag; content can change under a mount
2523
+ ...attachment ? { "Content-Disposition": attachmentDisposition(filePath) } : {}
2516
2524
  };
2517
2525
  const inm = req.headers["if-none-match"];
2518
2526
  const ims = req.headers["if-modified-since"];
@@ -2559,6 +2567,8 @@ function pipeStream(stream, res) {
2559
2567
 
2560
2568
  var staticFileServer = /*#__PURE__*/Object.freeze({
2561
2569
  __proto__: null,
2570
+ CORS_ALLOW_HEADERS: CORS_ALLOW_HEADERS,
2571
+ attachmentDisposition: attachmentDisposition,
2562
2572
  containedPath: containedPath,
2563
2573
  contentTypeFor: contentTypeFor,
2564
2574
  directoryListingHtml: directoryListingHtml,
@@ -3746,7 +3756,9 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3746
3756
  const CORS = {
3747
3757
  "Access-Control-Allow-Origin": "*",
3748
3758
  "Access-Control-Allow-Methods": "GET, HEAD, PUT, DELETE, OPTIONS",
3749
- "Access-Control-Allow-Headers": "*",
3759
+ // #0963: MUST name Authorization explicitly — the `*` wildcard does not cover it, and the
3760
+ // uploader authenticates with a Bearer header on a cross-origin PUT. See CORS_ALLOW_HEADERS.
3761
+ "Access-Control-Allow-Headers": CORS_ALLOW_HEADERS,
3750
3762
  "Access-Control-Expose-Headers": "Content-Length, Content-Range, ETag",
3751
3763
  "Access-Control-Max-Age": "600"
3752
3764
  };
@@ -3795,9 +3807,10 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3795
3807
  }
3796
3808
  }
3797
3809
  const rootDir = target.cwd;
3810
+ const normRel = this.toSessionRelative(rootDir, m[2] || "");
3798
3811
  if (method === "GET" || method === "HEAD") {
3799
3812
  if (url.searchParams.get("list") === "1") {
3800
- const lex = containedPath(rootDir, relPath.replace(/^\/+/, ""));
3813
+ const lex = containedPath(rootDir, normRel);
3801
3814
  if (!lex) {
3802
3815
  deny(403, "Forbidden");
3803
3816
  return;
@@ -3824,11 +3837,12 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3824
3837
  res.end(method === "HEAD" ? void 0 : JSON.stringify({ path: relPath, entries }));
3825
3838
  return;
3826
3839
  }
3827
- serveStaticMount(req, res, { rootDir, relPath, mountUrlPrefix: "", browse: false});
3840
+ const asAttachment = url.searchParams.get("download") === "1";
3841
+ serveStaticMount(req, res, { rootDir, relPath: normRel ? `/${normRel}` : "/", mountUrlPrefix: "", browse: false, attachment: asAttachment});
3828
3842
  return;
3829
3843
  }
3830
3844
  if (method === "PUT" || method === "DELETE") {
3831
- const filePath = this.resolveContainedPath(rootDir, relPath);
3845
+ const filePath = this.resolveContainedPath(rootDir, normRel);
3832
3846
  if (!filePath) {
3833
3847
  deny(403, "Forbidden: path escapes session root");
3834
3848
  return;
@@ -3890,6 +3904,27 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3890
3904
  }
3891
3905
  deny(405, "Method not allowed");
3892
3906
  }
3907
+ /**
3908
+ * #126 root-cause fix: the frontend builds gateway URLs from the file's ABSOLUTE path (the
3909
+ * session cwd + name), e.g. `/s/<id>/Users/me/proj/big.bin` for a file at
3910
+ * `/Users/me/proj/big.bin` in a session whose cwd is `/Users/me/proj`. A URL path can't carry
3911
+ * the leading slash, so a naive join against cwd DOUBLE-NESTS it
3912
+ * (`/Users/me/proj/Users/me/proj/big.bin`) — the file uploads with a 201 but lands in the wrong
3913
+ * place (and downloads 404). The RPC path never hit this because Node's `resolve(cwd, absPath)`
3914
+ * returns the absolute path as-is. Mirror that semantics here: reconstruct the remainder as an
3915
+ * absolute path; if it IS the cwd or lives under it, the caller meant an absolute path — return
3916
+ * it relative to cwd. Otherwise it's already cwd-relative. Returns a cwd-relative path with no
3917
+ * leading slash (containment is still enforced downstream by `containedPath`/`resolveContainedPath`).
3918
+ */
3919
+ toSessionRelative(rootDir, remainder) {
3920
+ const rel = (remainder || "").replace(/^\/+/, "");
3921
+ if (!rel) return "";
3922
+ const base = path.resolve(rootDir);
3923
+ const asAbsolute = path.resolve("/", rel);
3924
+ if (asAbsolute === base) return "";
3925
+ if (asAbsolute.startsWith(base + path.sep)) return asAbsolute.slice(base.length + 1);
3926
+ return rel;
3927
+ }
3893
3928
  /**
3894
3929
  * #126: resolve a session-relative path against `rootDir` with lexical + symlink containment
3895
3930
  * (mirrors the static PUT handler's resolveContained). Allows a not-yet-existing target (for
@@ -4133,7 +4168,7 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
4133
4168
  });
4134
4169
  return;
4135
4170
  }
4136
- const cors = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS", "Access-Control-Allow-Headers": "*" };
4171
+ const cors = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS", "Access-Control-Allow-Headers": CORS_ALLOW_HEADERS };
4137
4172
  if (url.pathname === "/" || basePath === "/") {
4138
4173
  res.writeHead(200, { ...cors, "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
4139
4174
  res.end(this.mountListHtml());
@@ -7994,7 +8029,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
7994
8029
  }
7995
8030
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
7996
8031
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
7997
- const { toolsForRole } = await import('./sideband-D1dsa-t0.mjs');
8032
+ const { toolsForRole } = await import('./sideband-CdXFW-wu.mjs');
7998
8033
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
7999
8034
  return fmt(r2);
8000
8035
  }
@@ -8099,7 +8134,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
8099
8134
  return { ok: false, call_id: callId, status: "busy", error: "channel is busy (too many concurrent requests) \u2014 retry shortly" };
8100
8135
  }
8101
8136
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
8102
- const { queryCore } = await import('./commands-CubsoWG-.mjs');
8137
+ const { queryCore } = await import('./commands-AOno1gcV.mjs');
8103
8138
  const timeout = c.reply?.timeout_sec || 120;
8104
8139
  let result;
8105
8140
  try {
@@ -17412,7 +17447,7 @@ function summarizeExtensions(extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENS
17412
17447
  return `${n} extension${n === 1 ? "" : "s"} granted (+${turns} turns)${reasons ? `: ${reasons}` : ""}`;
17413
17448
  }
17414
17449
  const DEFAULT_LOOP_STUCK_CHECKPOINTS = 3;
17415
- const DEFAULT_LOOP_MAX_AUTORESUMES = Number.POSITIVE_INFINITY;
17450
+ const DEFAULT_LOOP_MAX_AUTORESUMES = 3;
17416
17451
  const PROGRESS_HISTORY_CAP = 12;
17417
17452
  function resolveStuckLimit(envValue) {
17418
17453
  const n = Number(envValue);
@@ -17421,6 +17456,8 @@ function resolveStuckLimit(envValue) {
17421
17456
  }
17422
17457
  function resolveMaxAutoResumes(envValue) {
17423
17458
  if (envValue == null || envValue.trim() === "") return DEFAULT_LOOP_MAX_AUTORESUMES;
17459
+ const s = envValue.trim().toLowerCase();
17460
+ if (s === "unbounded" || s === "inf" || s === "infinity" || s === "-1") return Number.POSITIVE_INFINITY;
17424
17461
  const n = Number(envValue);
17425
17462
  if (Number.isFinite(n) && n >= 0) return Math.floor(n);
17426
17463
  return DEFAULT_LOOP_MAX_AUTORESUMES;
@@ -17796,6 +17833,7 @@ function nextFailuresAfterZombieProbeFailure(consecutiveHeartbeatFailures) {
17796
17833
  return consecutiveHeartbeatFailures + 1;
17797
17834
  }
17798
17835
  function shouldForceReconnect(consecutiveHeartbeatFailures) {
17836
+ if (consecutiveHeartbeatFailures < 2) return false;
17799
17837
  return consecutiveHeartbeatFailures === 2 || consecutiveHeartbeatFailures % 3 === 0;
17800
17838
  }
17801
17839
 
@@ -19431,6 +19469,7 @@ async function startDaemon(options) {
19431
19469
  };
19432
19470
  });
19433
19471
  let consecutiveHeartbeatFailures = 0;
19472
+ let lastReconnectAt = 0;
19434
19473
  process.on("SIGINT", () => requestShutdown("os-signal"));
19435
19474
  process.on("SIGTERM", () => requestShutdown("os-signal"));
19436
19475
  process.on("SIGUSR1", () => requestShutdown("os-signal-cleanup"));
@@ -19627,7 +19666,7 @@ async function startDaemon(options) {
19627
19666
  try {
19628
19667
  const dir = loadSessionIndex()[sessionId]?.directory;
19629
19668
  if (!dir) return;
19630
- const { reconcileServiceLinks } = await import('./agentCommands-CoCcX8K1.mjs');
19669
+ const { reconcileServiceLinks } = await import('./agentCommands-ri042RB5.mjs');
19631
19670
  const configPath = getSvampConfigPath(dir, sessionId);
19632
19671
  const config = readSvampConfig(configPath);
19633
19672
  const entries = Array.from(urls.entries());
@@ -19649,7 +19688,7 @@ async function startDaemon(options) {
19649
19688
  try {
19650
19689
  const dir = loadSessionIndex()[sessionId]?.directory;
19651
19690
  if (!dir) return;
19652
- const { reconcileServiceLinks } = await import('./agentCommands-CoCcX8K1.mjs');
19691
+ const { reconcileServiceLinks } = await import('./agentCommands-ri042RB5.mjs');
19653
19692
  const configPath = getSvampConfigPath(dir, sessionId);
19654
19693
  const config = readSvampConfig(configPath);
19655
19694
  const incoming = [{
@@ -19670,7 +19709,7 @@ async function startDaemon(options) {
19670
19709
  try {
19671
19710
  const dir = loadSessionIndex()[sessionId]?.directory;
19672
19711
  if (!dir) return;
19673
- const { dropServiceLinks } = await import('./agentCommands-CoCcX8K1.mjs');
19712
+ const { dropServiceLinks } = await import('./agentCommands-ri042RB5.mjs');
19674
19713
  const configPath = getSvampConfigPath(dir, sessionId);
19675
19714
  const config = readSvampConfig(configPath);
19676
19715
  if (dropServiceLinks(config, "serve", mountName)) {
@@ -19713,7 +19752,7 @@ async function startDaemon(options) {
19713
19752
  ensureAutoInstalledCommands(logger);
19714
19753
  (async () => {
19715
19754
  try {
19716
- const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-BkZfX5pW.mjs');
19755
+ const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-C8CmQv3y.mjs');
19717
19756
  beginClaudeVersionReconcile((msg) => logger.log(msg));
19718
19757
  } catch (e) {
19719
19758
  logger.log(`[claude-version] check failed: ${e?.message || e}`);
@@ -20467,8 +20506,9 @@ ${parts.join("\n")}`);
20467
20506
  progressHistory: progress_history || [],
20468
20507
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
20469
20508
  autoResumes: typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0,
20470
- // #0320: extensions also raise a FINITE auto-resume cap (one extra resume each). With
20471
- // the unbounded #0319 default this is a no-op (Infinity + n = Infinity).
20509
+ // #0320: extensions also raise the FINITE auto-resume cap (one extra resume each).
20510
+ // #0958: the cap is finite by default now, so this genuinely enlarges it (was a
20511
+ // no-op under the old Infinity default).
20472
20512
  maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS)),
20473
20513
  stuckReason: result.reason
20474
20514
  });
@@ -20486,12 +20526,13 @@ ${parts.join("\n")}`);
20486
20526
  max_iterations: ls.max_iterations,
20487
20527
  budget,
20488
20528
  started_at: startedAt,
20489
- // #0319: a PROGRESSING loop resets its hold counter so the evaluator-guided re-kick
20490
- // mechanism re-engages fresh (it's making headway, not stuck); an auto-resume keeps it.
20529
+ // #0319/#0958: a PROGRESSING loop resets its hold counter AND its consecutive-fruitless
20530
+ // auto-resume counter it's making headway, not wedged, so the finite auto-resume cap
20531
+ // (#0958) only ever bounds a genuine back-to-back stall, never a slow-but-productive loop.
20491
20532
  holds: decision.kind === "progress" ? 0 : holds,
20492
20533
  ledger,
20493
20534
  progress_history,
20494
- auto_resumes: nextAuto,
20535
+ auto_resumes: decision.kind === "progress" ? 0 : nextAuto,
20495
20536
  extensions,
20496
20537
  durable: ls.durable,
20497
20538
  verify_errors: 0
@@ -22041,11 +22082,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
22041
22082
  });
22042
22083
  },
22043
22084
  onIssue: async (params) => {
22044
- const { issueRpc } = await import('./rpc-DVtlZahE.mjs');
22085
+ const { issueRpc } = await import('./rpc-JWRwb6oY.mjs');
22045
22086
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
22046
22087
  },
22047
22088
  onWorkflow: async (params) => {
22048
- const { workflowRpc } = await import('./rpc-rpH-yXR7.mjs');
22089
+ const { workflowRpc } = await import('./rpc-DMlurOlf.mjs');
22049
22090
  return workflowRpc(params?.cwd || directory, params || {});
22050
22091
  },
22051
22092
  onRipgrep: async (args, cwd) => {
@@ -22752,11 +22793,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
22752
22793
  });
22753
22794
  },
22754
22795
  onIssue: async (params) => {
22755
- const { issueRpc } = await import('./rpc-DVtlZahE.mjs');
22796
+ const { issueRpc } = await import('./rpc-JWRwb6oY.mjs');
22756
22797
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
22757
22798
  },
22758
22799
  onWorkflow: async (params) => {
22759
- const { workflowRpc } = await import('./rpc-rpH-yXR7.mjs');
22800
+ const { workflowRpc } = await import('./rpc-DMlurOlf.mjs');
22760
22801
  return workflowRpc(params?.cwd || directory, params || {});
22761
22802
  },
22762
22803
  onRipgrep: async (args, cwd) => {
@@ -23155,12 +23196,13 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
23155
23196
  progressHistory: ls.progress_history || [],
23156
23197
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
23157
23198
  autoResumes: typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0,
23158
- // #0320: extensions also raise a FINITE auto-resume cap (no-op under the unbounded default).
23199
+ // #0320/#0958: extensions raise the FINITE auto-resume cap (genuinely enlarges it now
23200
+ // that the default is finite — was a no-op under the old unbounded default).
23159
23201
  maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, acpMaxExt),
23160
23202
  stuckReason: result.reason
23161
23203
  });
23162
23204
  if (decision.action === "continue") {
23163
- const nextAuto = (typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0) + (decision.consumeAutoResume ? 1 : 0);
23205
+ const nextAuto = decision.kind === "progress" ? 0 : (typeof ls.auto_resumes === "number" ? ls.auto_resumes : 0) + (decision.consumeAutoResume ? 1 : 0);
23164
23206
  writeGoalLoopState(directory, sessionId, { ...ls, active: true, phase: "continue", holds, started_at: startedAt, ledger, auto_resumes: nextAuto });
23165
23207
  const label = decision.kind === "autoresume" ? "\u{1F501} Auto-resuming stalled loop" : "\u{1F501} Loop still progressing";
23166
23208
  sessionService.pushMessage({ type: "message", message: `${label} \u2014 ${decision.reason}` }, "event");
@@ -23807,7 +23849,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
23807
23849
  }
23808
23850
  if (persistedSessions.length > 0) {
23809
23851
  try {
23810
- const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-BkZfX5pW.mjs');
23852
+ const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-C8CmQv3y.mjs');
23811
23853
  await awaitClaudeVersionReady();
23812
23854
  } catch {
23813
23855
  }
@@ -24056,7 +24098,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
24056
24098
  const PING_TIMEOUT_MS = 15e3;
24057
24099
  const POST_RECONNECT_GRACE_MS = 2e4;
24058
24100
  const RECONNECT_JITTER_MS = 2500;
24059
- const { WorkflowScheduler } = await import('./scheduler-CYyGe6kn.mjs');
24101
+ const { WorkflowScheduler } = await import('./scheduler-CkYMjhum.mjs');
24060
24102
  const workflowProjectRoots = () => {
24061
24103
  const dirs = /* @__PURE__ */ new Set();
24062
24104
  for (const s of pidToTrackedSession.values()) {
@@ -24096,7 +24138,6 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
24096
24138
  runOAuthAccountRefresh();
24097
24139
  const backendAccountRefreshInterval = setInterval(runOAuthAccountRefresh, 5 * 6e4);
24098
24140
  let heartbeatRunning = false;
24099
- let lastReconnectAt = 0;
24100
24141
  let heartbeatCycle = 0;
24101
24142
  const heartbeatInterval = setInterval(async () => {
24102
24143
  if (heartbeatRunning) return;
@@ -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-CvwPIrfo.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-BXDA0YFP.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-CvwPIrfo.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-BXDA0YFP.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';