svamp-cli 0.2.321 → 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-BRiz5afS.mjs → adminCommands-CnJSw_fJ.mjs} +1 -1
  2. package/dist/{agentCommands-Cve_0_8K.mjs → agentCommands-ri042RB5.mjs} +5 -5
  3. package/dist/{auth-DrLE8Yp-.mjs → auth-CvQD_JbA.mjs} +1 -1
  4. package/dist/{cli-xMKB7O8k.mjs → cli-BPJoSvJ0.mjs} +76 -76
  5. package/dist/cli.mjs +2 -2
  6. package/dist/{commands-slA1eX13.mjs → commands-AOno1gcV.mjs} +1 -1
  7. package/dist/{commands-Fvgfzyo3.mjs → commands-BWWAxC-g.mjs} +11 -11
  8. package/dist/{commands-CXgDZgqh.mjs → commands-BW_5joei.mjs} +2 -2
  9. package/dist/{commands-D9-YqAI3.mjs → commands-BxG6r6us.mjs} +3 -3
  10. package/dist/{commands-D1d9snmv.mjs → commands-D7iQqb-i.mjs} +1 -1
  11. package/dist/{commands-DfRahEsO.mjs → commands-DR8N0cmJ.mjs} +3 -3
  12. package/dist/{commands-C-QNVo3l.mjs → commands-Db0PpuwO.mjs} +3 -3
  13. package/dist/{commands-BxHc_Exm.mjs → commands-yuhNv9AR.mjs} +2 -2
  14. package/dist/{fleet-umFHXPoE.mjs → fleet--8tb1jX3.mjs} +3 -3
  15. package/dist/{headlessCli-DgJ15daM.mjs → headlessCli-COD8n9AD.mjs} +2 -2
  16. package/dist/index.mjs +1 -1
  17. package/dist/{notifyCommands-Cip4lIYS.mjs → notifyCommands-DLo0ANDt.mjs} +1 -1
  18. package/dist/{package-DJRwvqcx.mjs → package-DK43B5gu.mjs} +2 -2
  19. package/dist/{pinnedClaudeCode-BkZfX5pW.mjs → pinnedClaudeCode-C8CmQv3y.mjs} +1 -1
  20. package/dist/{rpc-Bz9w7JV9.mjs → rpc-DMlurOlf.mjs} +1 -1
  21. package/dist/{rpc-CLoO6Z5Z.mjs → rpc-JWRwb6oY.mjs} +1 -1
  22. package/dist/{run-CKLatoxa.mjs → run-BXDA0YFP.mjs} +47 -29
  23. package/dist/{run-CxuKTe0N.mjs → run-RYTtTBDy.mjs} +1 -1
  24. package/dist/{scheduler-Bs0nAlhs.mjs → scheduler-CkYMjhum.mjs} +1 -1
  25. package/dist/{serveCommands-Bi7DJs-3.mjs → serveCommands-BX3D9l8T.mjs} +10 -10
  26. package/dist/{sideband-CFbMRvzr.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-xMKB7O8k.mjs';
3
- import './run-CKLatoxa.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-CKLatoxa.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-slA1eX13.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-Cve_0_8K.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-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-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-CKLatoxa.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-slA1eX13.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-slA1eX13.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-Cve_0_8K.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-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-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-slA1eX13.mjs';
2
- import { w as wantsHelp } from './cli-xMKB7O8k.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-CKLatoxa.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-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-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-slA1eX13.mjs';
4
- import { w as wantsHelp } from './cli-xMKB7O8k.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-CKLatoxa.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-slA1eX13.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-CKLatoxa.mjs';
6
- import { w as wantsHelp } from './cli-xMKB7O8k.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-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-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-CKLatoxa.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-CKLatoxa.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CFbMRvzr.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-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-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-CKLatoxa.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.321";
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-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-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-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-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
  };
@@ -3825,7 +3837,8 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3825
3837
  res.end(method === "HEAD" ? void 0 : JSON.stringify({ path: relPath, entries }));
3826
3838
  return;
3827
3839
  }
3828
- serveStaticMount(req, res, { rootDir, relPath: normRel ? `/${normRel}` : "/", mountUrlPrefix: "", browse: false});
3840
+ const asAttachment = url.searchParams.get("download") === "1";
3841
+ serveStaticMount(req, res, { rootDir, relPath: normRel ? `/${normRel}` : "/", mountUrlPrefix: "", browse: false, attachment: asAttachment});
3829
3842
  return;
3830
3843
  }
3831
3844
  if (method === "PUT" || method === "DELETE") {
@@ -4155,7 +4168,7 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
4155
4168
  });
4156
4169
  return;
4157
4170
  }
4158
- 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 };
4159
4172
  if (url.pathname === "/" || basePath === "/") {
4160
4173
  res.writeHead(200, { ...cors, "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
4161
4174
  res.end(this.mountListHtml());
@@ -8016,7 +8029,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
8016
8029
  }
8017
8030
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
8018
8031
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
8019
- const { toolsForRole } = await import('./sideband-CFbMRvzr.mjs');
8032
+ const { toolsForRole } = await import('./sideband-CdXFW-wu.mjs');
8020
8033
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
8021
8034
  return fmt(r2);
8022
8035
  }
@@ -8121,7 +8134,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
8121
8134
  return { ok: false, call_id: callId, status: "busy", error: "channel is busy (too many concurrent requests) \u2014 retry shortly" };
8122
8135
  }
8123
8136
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
8124
- const { queryCore } = await import('./commands-slA1eX13.mjs');
8137
+ const { queryCore } = await import('./commands-AOno1gcV.mjs');
8125
8138
  const timeout = c.reply?.timeout_sec || 120;
8126
8139
  let result;
8127
8140
  try {
@@ -17434,7 +17447,7 @@ function summarizeExtensions(extensions, maxExtensions = DEFAULT_LOOP_MAX_EXTENS
17434
17447
  return `${n} extension${n === 1 ? "" : "s"} granted (+${turns} turns)${reasons ? `: ${reasons}` : ""}`;
17435
17448
  }
17436
17449
  const DEFAULT_LOOP_STUCK_CHECKPOINTS = 3;
17437
- const DEFAULT_LOOP_MAX_AUTORESUMES = Number.POSITIVE_INFINITY;
17450
+ const DEFAULT_LOOP_MAX_AUTORESUMES = 3;
17438
17451
  const PROGRESS_HISTORY_CAP = 12;
17439
17452
  function resolveStuckLimit(envValue) {
17440
17453
  const n = Number(envValue);
@@ -17443,6 +17456,8 @@ function resolveStuckLimit(envValue) {
17443
17456
  }
17444
17457
  function resolveMaxAutoResumes(envValue) {
17445
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;
17446
17461
  const n = Number(envValue);
17447
17462
  if (Number.isFinite(n) && n >= 0) return Math.floor(n);
17448
17463
  return DEFAULT_LOOP_MAX_AUTORESUMES;
@@ -19651,7 +19666,7 @@ async function startDaemon(options) {
19651
19666
  try {
19652
19667
  const dir = loadSessionIndex()[sessionId]?.directory;
19653
19668
  if (!dir) return;
19654
- const { reconcileServiceLinks } = await import('./agentCommands-Cve_0_8K.mjs');
19669
+ const { reconcileServiceLinks } = await import('./agentCommands-ri042RB5.mjs');
19655
19670
  const configPath = getSvampConfigPath(dir, sessionId);
19656
19671
  const config = readSvampConfig(configPath);
19657
19672
  const entries = Array.from(urls.entries());
@@ -19673,7 +19688,7 @@ async function startDaemon(options) {
19673
19688
  try {
19674
19689
  const dir = loadSessionIndex()[sessionId]?.directory;
19675
19690
  if (!dir) return;
19676
- const { reconcileServiceLinks } = await import('./agentCommands-Cve_0_8K.mjs');
19691
+ const { reconcileServiceLinks } = await import('./agentCommands-ri042RB5.mjs');
19677
19692
  const configPath = getSvampConfigPath(dir, sessionId);
19678
19693
  const config = readSvampConfig(configPath);
19679
19694
  const incoming = [{
@@ -19694,7 +19709,7 @@ async function startDaemon(options) {
19694
19709
  try {
19695
19710
  const dir = loadSessionIndex()[sessionId]?.directory;
19696
19711
  if (!dir) return;
19697
- const { dropServiceLinks } = await import('./agentCommands-Cve_0_8K.mjs');
19712
+ const { dropServiceLinks } = await import('./agentCommands-ri042RB5.mjs');
19698
19713
  const configPath = getSvampConfigPath(dir, sessionId);
19699
19714
  const config = readSvampConfig(configPath);
19700
19715
  if (dropServiceLinks(config, "serve", mountName)) {
@@ -19737,7 +19752,7 @@ async function startDaemon(options) {
19737
19752
  ensureAutoInstalledCommands(logger);
19738
19753
  (async () => {
19739
19754
  try {
19740
- const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-BkZfX5pW.mjs');
19755
+ const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-C8CmQv3y.mjs');
19741
19756
  beginClaudeVersionReconcile((msg) => logger.log(msg));
19742
19757
  } catch (e) {
19743
19758
  logger.log(`[claude-version] check failed: ${e?.message || e}`);
@@ -20491,8 +20506,9 @@ ${parts.join("\n")}`);
20491
20506
  progressHistory: progress_history || [],
20492
20507
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
20493
20508
  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).
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).
20496
20512
  maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, resolveMaxExtensions(process.env.SVAMP_LOOP_MAX_EXTENSIONS)),
20497
20513
  stuckReason: result.reason
20498
20514
  });
@@ -20510,12 +20526,13 @@ ${parts.join("\n")}`);
20510
20526
  max_iterations: ls.max_iterations,
20511
20527
  budget,
20512
20528
  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.
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.
20515
20532
  holds: decision.kind === "progress" ? 0 : holds,
20516
20533
  ledger,
20517
20534
  progress_history,
20518
- auto_resumes: nextAuto,
20535
+ auto_resumes: decision.kind === "progress" ? 0 : nextAuto,
20519
20536
  extensions,
20520
20537
  durable: ls.durable,
20521
20538
  verify_errors: 0
@@ -22065,11 +22082,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
22065
22082
  });
22066
22083
  },
22067
22084
  onIssue: async (params) => {
22068
- const { issueRpc } = await import('./rpc-CLoO6Z5Z.mjs');
22085
+ const { issueRpc } = await import('./rpc-JWRwb6oY.mjs');
22069
22086
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
22070
22087
  },
22071
22088
  onWorkflow: async (params) => {
22072
- const { workflowRpc } = await import('./rpc-Bz9w7JV9.mjs');
22089
+ const { workflowRpc } = await import('./rpc-DMlurOlf.mjs');
22073
22090
  return workflowRpc(params?.cwd || directory, params || {});
22074
22091
  },
22075
22092
  onRipgrep: async (args, cwd) => {
@@ -22776,11 +22793,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
22776
22793
  });
22777
22794
  },
22778
22795
  onIssue: async (params) => {
22779
- const { issueRpc } = await import('./rpc-CLoO6Z5Z.mjs');
22796
+ const { issueRpc } = await import('./rpc-JWRwb6oY.mjs');
22780
22797
  return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
22781
22798
  },
22782
22799
  onWorkflow: async (params) => {
22783
- const { workflowRpc } = await import('./rpc-Bz9w7JV9.mjs');
22800
+ const { workflowRpc } = await import('./rpc-DMlurOlf.mjs');
22784
22801
  return workflowRpc(params?.cwd || directory, params || {});
22785
22802
  },
22786
22803
  onRipgrep: async (args, cwd) => {
@@ -23179,12 +23196,13 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
23179
23196
  progressHistory: ls.progress_history || [],
23180
23197
  stuckLimit: resolveStuckLimit(process.env.SVAMP_LOOP_STUCK_CHECKPOINTS),
23181
23198
  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).
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).
23183
23201
  maxAutoResumes: resolveMaxAutoResumes(process.env.SVAMP_LOOP_MAX_AUTORESUMES) + grantedExtensionCount(ls.extensions, acpMaxExt),
23184
23202
  stuckReason: result.reason
23185
23203
  });
23186
23204
  if (decision.action === "continue") {
23187
- 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);
23188
23206
  writeGoalLoopState(directory, sessionId, { ...ls, active: true, phase: "continue", holds, started_at: startedAt, ledger, auto_resumes: nextAuto });
23189
23207
  const label = decision.kind === "autoresume" ? "\u{1F501} Auto-resuming stalled loop" : "\u{1F501} Loop still progressing";
23190
23208
  sessionService.pushMessage({ type: "message", message: `${label} \u2014 ${decision.reason}` }, "event");
@@ -23831,7 +23849,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
23831
23849
  }
23832
23850
  if (persistedSessions.length > 0) {
23833
23851
  try {
23834
- const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-BkZfX5pW.mjs');
23852
+ const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-C8CmQv3y.mjs');
23835
23853
  await awaitClaudeVersionReady();
23836
23854
  } catch {
23837
23855
  }
@@ -24080,7 +24098,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
24080
24098
  const PING_TIMEOUT_MS = 15e3;
24081
24099
  const POST_RECONNECT_GRACE_MS = 2e4;
24082
24100
  const RECONNECT_JITTER_MS = 2500;
24083
- const { WorkflowScheduler } = await import('./scheduler-Bs0nAlhs.mjs');
24101
+ const { WorkflowScheduler } = await import('./scheduler-CkYMjhum.mjs');
24084
24102
  const workflowProjectRoots = () => {
24085
24103
  const dirs = /* @__PURE__ */ new Set();
24086
24104
  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-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-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-BXDA0YFP.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-BPJoSvJ0.mjs';
3
+ import './run-BXDA0YFP.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-AOno1gcV.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-ri042RB5.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-AOno1gcV.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-ri042RB5.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-AOno1gcV.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-ri042RB5.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-AOno1gcV.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-AOno1gcV.mjs');
287
287
  const { machine, server } = await connectAndGetMachine(machineId);
288
288
  try {
289
289
  const info = await machine.serveInfo();
@@ -1,4 +1,4 @@
1
- import { R as READ_ONLY_TOOLS, M as loadMachineContext, N as buildMachineInstructions, O as machineToolsForRole, P as buildMachineTools } from './run-CKLatoxa.mjs';
1
+ import { R as READ_ONLY_TOOLS, M as loadMachineContext, N as buildMachineInstructions, O as machineToolsForRole, P as buildMachineTools } from './run-BXDA0YFP.mjs';
2
2
  import 'node:child_process';
3
3
  import 'os';
4
4
  import 'fs/promises';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "svamp-cli",
3
- "version": "0.2.321",
4
- "description": "Svamp CLI \u2014 AI workspace daemon on Hypha Cloud",
3
+ "version": "0.2.322",
4
+ "description": "Svamp CLI AI workspace daemon on Hypha Cloud",
5
5
  "author": "Amun AI AB",
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "type": "module",
@@ -26,7 +26,7 @@
26
26
  "dev:daemon": "tsx src/cli.ts daemon start-sync",
27
27
  "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",
28
28
  "test:frpc": "npx tsx test/test-frpc-e2e.mjs",
29
- "prepublishOnly": "yarn build"
29
+ "prepublishOnly": "node ../../scripts/bump-cli-version.mjs --check && yarn build"
30
30
  },
31
31
  "dependencies": {
32
32
  "@agentclientprotocol/sdk": "^0.14.1",