svamp-cli 0.2.346 → 0.2.356

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 (30) hide show
  1. package/bin/skills/artifact/SKILL.md +19 -5
  2. package/bin/skills/crew/SKILL.md +42 -11
  3. package/dist/{acpBackend-BZ1MJhQV.mjs → acpBackend-UaBD4zL3.mjs} +3 -0
  4. package/dist/{agentCommands-B2Nl7Fof.mjs → agentCommands-D91RcjqQ.mjs} +4 -4
  5. package/dist/{claudeAuth-iAerdaMr.mjs → claudeAuth-C0wc1GTM.mjs} +45 -1
  6. package/dist/cli.mjs +78 -69
  7. package/dist/{commands-D1pZq3d4.mjs → commands-B-yczgz_.mjs} +14 -10
  8. package/dist/{commands-BOpoVBOM.mjs → commands-BMeDrpSv.mjs} +3 -3
  9. package/dist/{commands-H4PsTGn8.mjs → commands-BbmypSgx.mjs} +5 -2
  10. package/dist/{commands-C2aODeVc.mjs → commands-BkdbelFo.mjs} +26 -11
  11. package/dist/{commands-BB1Kcyt-.mjs → commands-C13-yE2R.mjs} +32 -3
  12. package/dist/{commands-D69mnkYu.mjs → commands-CoOc4qiw.mjs} +2 -2
  13. package/dist/{commands-CiRCwjkJ.mjs → commands-sPvRcG3J.mjs} +9 -9
  14. package/dist/{detectIsolation-CzoDCEnh.mjs → detectIsolation-CrV8IFDv.mjs} +36 -16
  15. package/dist/{fleet-DM_Q7w69.mjs → fleet-Ca-UjJNL.mjs} +40 -15
  16. package/dist/{hookSettings-DYMTUgVA.mjs → hookSettings-FFc1pi8j.mjs} +174 -27
  17. package/dist/index.mjs +8 -8
  18. package/dist/{loopVerify-B47sSjxe.mjs → loopVerify-DALtTk2V.mjs} +1 -1
  19. package/dist/{notifyCommands-D-IKIxiq.mjs → notifyCommands-CCUE18Q-.mjs} +1 -1
  20. package/dist/package-BrsiNutS.mjs +64 -0
  21. package/dist/{rpc-BB6RF4-F.mjs → rpc-CBkSkzsI.mjs} +8 -8
  22. package/dist/{rpc-Cf0grcru.mjs → rpc-ccY7xvlo.mjs} +6 -3
  23. package/dist/{run-ChdsgaSD.mjs → run-DCq3aEiF.mjs} +3 -3
  24. package/dist/{run-DkjwF-zA.mjs → run-DDmeV9K3.mjs} +190 -59
  25. package/dist/{scheduler-BY30ZrB9.mjs → scheduler-BkVJ27Ki.mjs} +8 -8
  26. package/dist/{serveAuth-DbVLRCRR.mjs → serveAuth-4M0vwMyj.mjs} +53 -11
  27. package/dist/{serveCommands-CUHUiYnZ.mjs → serveCommands-CLhkccJM.mjs} +8 -8
  28. package/dist/{store-Bn0ByYev.mjs → store-B4E6NzG6.mjs} +10 -1
  29. package/package.json +2 -2
  30. package/dist/package-DtuINqf5.mjs +0 -64
@@ -1,5 +1,5 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import * as fs from 'fs';
2
- import { mkdirSync, chmodSync, writeFileSync, unlinkSync, existsSync, readFileSync, renameSync as renameSync$1 } from 'fs';
2
+ import { statSync, mkdirSync, chmodSync, writeFileSync, unlinkSync, existsSync, readFileSync, renameSync as renameSync$1 } from 'fs';
3
3
  import * as path from 'path';
4
4
  import path__default, { join } from 'path';
5
5
  import { randomUUID as randomUUID$1, randomBytes as randomBytes$1, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
@@ -17,12 +17,12 @@ import * as net from 'net';
17
17
  import { createServer } from 'net';
18
18
  import { homedir, platform, arch } from 'os';
19
19
  import { d as getFrpsSubdomainHost, e as getFrpsServerPort, f as getFrpsServerAddr, h as getHyphaServerUrl } from './instance-CeHz5C8v.mjs';
20
- import { S as ServeAuth, s as sanitizeLoginReturn, h as hasCookieToken, a as stripServeTokenParam, b as sanitizeForwardHeaders, c as stripServeAuthCookie } from './serveAuth-DbVLRCRR.mjs';
21
- import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, writeFileSync as writeFileSync$1, chmodSync as chmodSync$1, rmSync, cpSync, realpathSync, readdirSync, statSync, renameSync, appendFileSync, openSync, readSync, closeSync, fstatSync, writeSync, unlinkSync as unlinkSync$1 } from 'node:fs';
20
+ import { S as ServeAuth, s as sanitizeLoginReturn, h as hasCookieToken, a as stripServeTokenParam, b as sanitizeForwardHeaders, c as stripServeAuthCookie } from './serveAuth-4M0vwMyj.mjs';
21
+ import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, writeFileSync as writeFileSync$1, chmodSync as chmodSync$1, renameSync, rmSync, cpSync, realpathSync, readdirSync, statSync as statSync$1, appendFileSync, openSync, readSync, closeSync, fstatSync, writeSync, unlinkSync as unlinkSync$1 } from 'node:fs';
22
22
  import os, { homedir as homedir$1 } from 'node:os';
23
23
  import { join as join$1, extname, resolve, sep, basename, dirname } from 'node:path';
24
24
  import { e as envFlagEnabled, a as envFlagDisabled } from './envFlag-COOuJ3AH.mjs';
25
- import { normalizeProxyUrl, resolveHyphaProxyUrl, applyClaudeProxyEnv } from './claudeAuth-iAerdaMr.mjs';
25
+ import { normalizeProxyUrl, resolveHyphaProxyUrl, applyClaudeProxyEnv } from './claudeAuth-C0wc1GTM.mjs';
26
26
  import { CODEX_PROVIDER_KEY_ENV } from './codexProvider-BtxYc5Rj.mjs';
27
27
  import { spawn as spawn$1 } from 'node:child_process';
28
28
  import { b as applyInboxClear } from './friendlyName-1UZcyDhu.mjs';
@@ -74,6 +74,19 @@ function levelToRole(level) {
74
74
  const entry = Object.entries(ROLE_HIERARCHY).find(([, v]) => v === level);
75
75
  return entry?.[0] ?? null;
76
76
  }
77
+ function isOwnerEquivalentStrict(context, sharing) {
78
+ if (!context?.user) return true;
79
+ if (isSameOwnerWorkspace(context)) return true;
80
+ if (!sharing) return false;
81
+ const userEmail = context.user.email;
82
+ if (userEmail && sharing.owner && userEmail.toLowerCase() === sharing.owner.toLowerCase()) return true;
83
+ return false;
84
+ }
85
+ function isAdminEquivalentStrict(context, sharing) {
86
+ if (!context?.user) return true;
87
+ if (isSameOwnerWorkspace(context)) return true;
88
+ return !!sharing && getEffectiveRole(context, sharing) === "admin";
89
+ }
77
90
  function authorizeRequest(context, sharing, requiredRole = "view") {
78
91
  if (!context?.user) return;
79
92
  if (isSameOwnerWorkspace(context)) return;
@@ -124,6 +137,18 @@ function workflowOpMinRole(op) {
124
137
  if (typeof op === "string" && WORKFLOW_READ_OPS.has(op)) return "view";
125
138
  return "admin";
126
139
  }
140
+ function issueVerifyRefusalReason(params, isOwner) {
141
+ if (isOwner) return null;
142
+ const p = params;
143
+ if (!p || typeof p !== "object") return null;
144
+ const op = typeof p.op === "string" ? p.op : "";
145
+ if (op !== "add" && op !== "edit" && op !== "triage") return null;
146
+ const v = p.verify;
147
+ const structuredIsCommand = !!v && typeof v === "object" && v.type === "command";
148
+ const flatCommand = typeof p.verifyCmd === "string" && p.verifyCmd.length > 0;
149
+ if (!structuredIsCommand && !flatCommand) return null;
150
+ return "Access denied: only the session owner may attach a command verify-cmd. It is executed by the daemon outside the sandbox when the issue is closed. Use --verify '<criterion>' (an agent-evaluated check) or --manual instead.";
151
+ }
127
152
 
128
153
  function toSchema(t) {
129
154
  return { name: t.name, description: t.description, parameters: t.parameters || { type: "object", properties: {} } };
@@ -279,6 +304,17 @@ const DEFAULT_PROBE_FAILURE_THRESHOLD = 3;
279
304
  const MAX_RESTART_DELAY_S = 300;
280
305
  const BACKOFF_RESET_WINDOW_MS = 6e4;
281
306
  const MAX_LOG_LINES = 300;
307
+ function checkWorkdir(workdir, stat = statSync) {
308
+ if (!workdir) return null;
309
+ try {
310
+ if (!stat(workdir).isDirectory()) return `workdir is not a directory: ${workdir}`;
311
+ return null;
312
+ } catch (err) {
313
+ if (err?.code === "ENOENT") return `workdir does not exist: ${workdir}`;
314
+ if (err?.code === "EACCES") return `workdir is not accessible: ${workdir}`;
315
+ return null;
316
+ }
317
+ }
282
318
  const CRASH_LOOP_FAILURE_THRESHOLD = 10;
283
319
  function accumulateCrashLoopFailure(prev, healthy, now) {
284
320
  if (healthy) return { consecutiveFailures: 0, failureWindowStart: void 0 };
@@ -654,6 +690,16 @@ class ProcessSupervisor {
654
690
  const { spec, state } = entry;
655
691
  if (entry.deleted) return;
656
692
  state.consecutiveProbeFailures = 0;
693
+ const workdirProblem = checkWorkdir(spec.workdir);
694
+ if (workdirProblem) {
695
+ state.status = "failed";
696
+ state.stoppedAt = Date.now();
697
+ entry.logBuffer.push(`[supervisor] ${workdirProblem}`);
698
+ console.error(
699
+ `[SUPERVISOR] Not starting '${spec.name}': ${workdirProblem} (permanent \u2014 not retrying; fix the path or run 'svamp process restart ${spec.name}')`
700
+ );
701
+ return;
702
+ }
657
703
  try {
658
704
  const env = { ...process.env, ...spec.env ?? {} };
659
705
  const child = spawn(spec.command, spec.args, {
@@ -2068,9 +2114,10 @@ function serveStaticMount(req, res, opts) {
2068
2114
  return;
2069
2115
  }
2070
2116
  if (st.isDirectory()) {
2071
- const reqPath = (req.url || "/").split("?")[0];
2072
- if (!reqPath.endsWith("/")) {
2073
- res.writeHead(302, { ...CORS, Location: reqPath + "/" });
2117
+ const normalizedPath = (relPath || "/").split("?")[0];
2118
+ const redirectTo = ("/" + normalizedPath.replace(/^\/+/, "")).replace(/\/+$/, "") + "/";
2119
+ if (!normalizedPath.endsWith("/")) {
2120
+ res.writeHead(302, { ...CORS, Location: mountUrlPrefix ? mountUrlPrefix.replace(/\/$/, "") + redirectTo : redirectTo });
2074
2121
  res.end();
2075
2122
  return;
2076
2123
  }
@@ -2251,7 +2298,13 @@ function resolveMountOwnerEmail(suppliedOwnerEmail, callerEmail, machineOwnerEma
2251
2298
  function sanitizeMountForRole(mount, isAdmin) {
2252
2299
  if (isAdmin) return mount;
2253
2300
  const { linkToken: _lt, directory: _dir, process: proc, url, ...rest } = mount;
2254
- const safeProcess = proc ? { ...proc, env: proc.env ? Object.fromEntries(Object.keys(proc.env).map((k) => [k, "***"])) : proc.env } : proc;
2301
+ const safeProcess = proc ? (() => {
2302
+ const { env, workdir: _wd, command: _cmd, args: _args, ...procRest } = proc;
2303
+ return {
2304
+ ...procRest,
2305
+ env: env ? Object.fromEntries(Object.keys(env).map((k) => [k, "***"])) : env
2306
+ };
2307
+ })() : proc;
2255
2308
  const safeUrl = mount.access === "link" ? void 0 : url;
2256
2309
  return { ...rest, process: safeProcess, ...safeUrl !== void 0 ? { url: safeUrl } : {} };
2257
2310
  }
@@ -3410,6 +3463,13 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3410
3463
  res.end("Write access denied: public mounts are read-only.");
3411
3464
  return;
3412
3465
  }
3466
+ const writeBadSeg = hiddenSegmentOf(basePath);
3467
+ if (writeBadSeg) {
3468
+ this.log(`Write DENY '${mountName}': blocked dotfile segment '${writeBadSeg}' (${basePath})`);
3469
+ res.writeHead(403, { "Content-Type": "text/plain" });
3470
+ res.end("Forbidden: hidden/dot-prefixed paths are not writable.");
3471
+ return;
3472
+ }
3413
3473
  const filePath = resolveContained();
3414
3474
  if (!filePath) {
3415
3475
  this.log(`Write DENY '${mountName}': path escapes mount root (${basePath})`);
@@ -3419,13 +3479,17 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3419
3479
  }
3420
3480
  if (req.method === "PUT") {
3421
3481
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
3422
- const ws = fs.createWriteStream(filePath);
3482
+ const tmpPath = path.join(
3483
+ path.dirname(filePath),
3484
+ `.svamp-put-${process.pid}-${crypto.randomBytes(6).toString("hex")}.part`
3485
+ );
3486
+ const ws = fs.createWriteStream(tmpPath);
3423
3487
  let done = false;
3424
3488
  const cleanupPartial = () => {
3425
3489
  if (done) return;
3426
3490
  done = true;
3427
3491
  ws.destroy();
3428
- fs.unlink(filePath, () => {
3492
+ fs.unlink(tmpPath, () => {
3429
3493
  });
3430
3494
  };
3431
3495
  req.on("aborted", cleanupPartial);
@@ -3434,13 +3498,25 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
3434
3498
  });
3435
3499
  req.pipe(ws);
3436
3500
  ws.on("finish", () => {
3501
+ if (done) return;
3437
3502
  done = true;
3503
+ try {
3504
+ fs.renameSync(tmpPath, filePath);
3505
+ } catch (err) {
3506
+ fs.unlink(tmpPath, () => {
3507
+ });
3508
+ res.writeHead(500);
3509
+ res.end(err?.message || "rename failed");
3510
+ return;
3511
+ }
3438
3512
  res.writeHead(201);
3439
3513
  res.end();
3440
3514
  });
3441
3515
  ws.on("error", (err) => {
3442
3516
  if (done) return;
3443
3517
  done = true;
3518
+ fs.unlink(tmpPath, () => {
3519
+ });
3444
3520
  res.writeHead(500);
3445
3521
  res.end(err.message);
3446
3522
  });
@@ -3823,9 +3899,13 @@ function loadAccounts(svampHome) {
3823
3899
  if (!existsSync$1(file)) return [];
3824
3900
  try {
3825
3901
  const parsed = JSON.parse(readFileSync$1(file, "utf-8"));
3826
- if (!parsed || !Array.isArray(parsed.accounts)) return [];
3902
+ if (!parsed || !Array.isArray(parsed.accounts)) {
3903
+ console.warn(`[accounts] ${file} is present but malformed \u2014 treating as empty. Configured backend accounts will appear to have vanished; restore from a backup rather than re-adding blindly. (#1629)`);
3904
+ return [];
3905
+ }
3827
3906
  return parsed.accounts;
3828
- } catch {
3907
+ } catch (err) {
3908
+ console.warn(`[accounts] failed to read ${file}: ${err?.message || err}. Treating as empty \u2014 every configured backend account will appear to have vanished. (#1629)`);
3829
3909
  return [];
3830
3910
  }
3831
3911
  }
@@ -3834,7 +3914,13 @@ function saveAccounts(accounts, svampHome) {
3834
3914
  const dir = join$1(file, "..");
3835
3915
  if (!existsSync$1(dir)) mkdirSync$1(dir, { recursive: true });
3836
3916
  const payload = { version: 1, accounts };
3837
- writeFileSync$1(file, JSON.stringify(payload, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
3917
+ const tmp = `${file}.tmp-${process.pid}`;
3918
+ writeFileSync$1(tmp, JSON.stringify(payload, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
3919
+ try {
3920
+ chmodSync$1(tmp, 384);
3921
+ } catch {
3922
+ }
3923
+ renameSync(tmp, file);
3838
3924
  try {
3839
3925
  chmodSync$1(file, 384);
3840
3926
  } catch {
@@ -4520,7 +4606,7 @@ function validateUpload(input) {
4520
4606
  if (existsSync$1(destDir)) {
4521
4607
  const count = readdirSync(destDir).filter((f) => {
4522
4608
  try {
4523
- return statSync(join$1(destDir, f)).isFile();
4609
+ return statSync$1(join$1(destDir, f)).isFile();
4524
4610
  } catch {
4525
4611
  return false;
4526
4612
  }
@@ -4733,7 +4819,7 @@ class ChannelStore {
4733
4819
  list() {
4734
4820
  let st;
4735
4821
  try {
4736
- const s = statSync(this.dir);
4822
+ const s = statSync$1(this.dir);
4737
4823
  st = { mtimeMs: s.mtimeMs, size: s.size };
4738
4824
  } catch {
4739
4825
  _channelListCache.delete(this.dir);
@@ -5202,7 +5288,7 @@ class ChannelOutbox {
5202
5288
  /** Current on-disk (mtimeMs, size), or (0, -1) if the file does not exist. */
5203
5289
  _stat() {
5204
5290
  try {
5205
- const st = statSync(this.file);
5291
+ const st = statSync$1(this.file);
5206
5292
  return { mtimeMs: st.mtimeMs, size: st.size };
5207
5293
  } catch {
5208
5294
  return { mtimeMs: 0, size: -1 };
@@ -5442,6 +5528,9 @@ const SESSION_METHOD_MIN_ROLE = {
5442
5528
  channelReply: "admin",
5443
5529
  updateAgentState: "admin",
5444
5530
  switchMode: "admin",
5531
+ // #1628: rotating the outpost token DESTROYS a live capability and mints a new one — admin,
5532
+ // like outpostConnectInfo which hands the same capability out.
5533
+ outpostRotateToken: "admin",
5445
5534
  restartClaude: "admin",
5446
5535
  archiveSession: "admin",
5447
5536
  readFile: "admin",
@@ -6014,7 +6103,11 @@ async function registerMachineService(server, machineId, metadata, daemonState,
6014
6103
  } else if (options.sharing?.enabled && !options.sharing.owner && callerEmail) {
6015
6104
  options = {
6016
6105
  ...options,
6017
- sharing: { ...options.sharing, owner: callerEmail }
6106
+ sharing: {
6107
+ ...options.sharing,
6108
+ owner: callerEmail,
6109
+ ...options.sharing.allowedUsers ? { allowedUsers: options.sharing.allowedUsers.map((u) => normalizeAllowedUser(u, "spawn-explicit")) } : {}
6110
+ }
6018
6111
  };
6019
6112
  }
6020
6113
  if (currentMetadata.securityContextConfig && callerEmail) {
@@ -6356,12 +6449,12 @@ async function registerMachineService(server, machineId, metadata, daemonState,
6356
6449
  return { success: true };
6357
6450
  },
6358
6451
  // Shell access
6359
- bash: async (command, cwd, context) => {
6452
+ bash: async (command, cwd, timeoutMs, context) => {
6360
6453
  authorizeRequest(context, currentMetadata.sharing, "admin");
6361
6454
  const { exec } = await import('child_process');
6362
6455
  const { homedir } = await import('os');
6363
6456
  return new Promise((resolve) => {
6364
- exec(command, { cwd: cwd || homedir(), timeout: 3e4, maxBuffer: EXEC_MAX_BUFFER }, (err, stdout, stderr) => {
6457
+ exec(command, { cwd: cwd || homedir(), timeout: timeoutMs ?? 3e4, maxBuffer: EXEC_MAX_BUFFER }, (err, stdout, stderr) => {
6365
6458
  if (err) resolve(execFailureOutcome(err, stdout, stderr));
6366
6459
  else resolve(execSuccessOutcome(stdout, stderr));
6367
6460
  });
@@ -7477,7 +7570,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
7477
7570
  return { ok: false, call_id: callId, status: "busy", error: "channel is busy (too many concurrent requests) \u2014 retry shortly" };
7478
7571
  }
7479
7572
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
7480
- const { queryCore } = await import('./commands-D1pZq3d4.mjs');
7573
+ const { queryCore } = await import('./commands-B-yczgz_.mjs');
7481
7574
  const timeout = c.reply?.timeout_sec || 120;
7482
7575
  let result;
7483
7576
  let thrownSessionId;
@@ -7746,7 +7839,7 @@ ${d?.error || "not found"}`;
7746
7839
  const CHUNK_BYTES$1 = 1024 * 1024;
7747
7840
  const LF = 10;
7748
7841
  function countFileLines(path) {
7749
- const size = statSync(path).size;
7842
+ const size = statSync$1(path).size;
7750
7843
  if (size === 0) return 0;
7751
7844
  const fd = openSync(path, "r");
7752
7845
  try {
@@ -7984,6 +8077,17 @@ function ensureOutpostToken(projectDir, session) {
7984
8077
  }
7985
8078
  return rec;
7986
8079
  }
8080
+ function rotateOutpostToken(projectDir, session) {
8081
+ const rec = { version: 1, session, token: genToken(), createdAt: Date.now() };
8082
+ const file = tokenPath(projectDir, session);
8083
+ mkdirSync$1(dirname(file), { recursive: true });
8084
+ writeFileSync$1(file, JSON.stringify(rec, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
8085
+ try {
8086
+ chmodSync$1(file, 384);
8087
+ } catch {
8088
+ }
8089
+ return rec;
8090
+ }
7987
8091
  function outpostTokenMatches(rec, presented) {
7988
8092
  if (!rec || typeof presented !== "string" || presented.length !== rec.token.length) return false;
7989
8093
  let diff = 0;
@@ -8430,10 +8534,10 @@ function formatInboxMessageXml(msg) {
8430
8534
  }
8431
8535
  if (msg.to) attrs.push(`to="${escapeXml(msg.to)}"`);
8432
8536
  if (msg.subject) attrs.push(`subject="${escapeXml(msg.subject)}"`);
8433
- if (msg.urgency) attrs.push(`urgency="${msg.urgency}"`);
8537
+ if (msg.urgency) attrs.push(`urgency="${escapeXml(String(msg.urgency))}"`);
8434
8538
  if (msg.replyTo) attrs.push(`reply-to="${escapeXml(msg.replyTo)}"`);
8435
8539
  if (msg.threadId) attrs.push(`thread-id="${escapeXml(msg.threadId)}"`);
8436
- attrs.push(`timestamp="${msg.timestamp}"`);
8540
+ attrs.push(`timestamp="${escapeXml(String(msg.timestamp))}"`);
8437
8541
  return `<svamp-message ${attrs.join(" ")}>
8438
8542
  ${msg.body}
8439
8543
  </svamp-message>`;
@@ -8544,7 +8648,7 @@ function countMessagesOnDisk(messagesDir, fallbackInMemory) {
8544
8648
  const filePath = join$1(messagesDir, "messages.jsonl");
8545
8649
  if (!existsSync$1(filePath)) return fallbackInMemory;
8546
8650
  try {
8547
- const st = statSync(filePath);
8651
+ const st = statSync$1(filePath);
8548
8652
  const cached = messageCountCache.get(filePath);
8549
8653
  if (cached && cached.size === st.size && cached.mtimeMs === st.mtimeMs) return cached.count;
8550
8654
  let count;
@@ -8803,7 +8907,8 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
8803
8907
  } else if (role === "session") {
8804
8908
  wrappedContent = { role: "session", content: { type: "session", data: content } };
8805
8909
  } else {
8806
- const text = typeof content === "string" ? content : content?.text || content?.content || JSON.stringify(content);
8910
+ const rawText = typeof content === "string" ? content : content?.text ?? content?.content ?? content;
8911
+ const text = typeof rawText === "string" ? rawText : rawText && typeof rawText === "object" && typeof rawText.text === "string" ? rawText.text : JSON.stringify(content);
8807
8912
  wrappedContent = { role: "user", content: { type: "text", text } };
8808
8913
  }
8809
8914
  const msg = {
@@ -9099,7 +9204,21 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
9099
9204
  }
9100
9205
  }
9101
9206
  const isBtwEcho = !!(parsed && parsed.meta && parsed.meta.btw) || !!(meta && meta.btw);
9102
- const coerceUserContent = (c) => typeof c === "string" ? { type: "text", text: c } : c;
9207
+ const coerceUserText = (t, depth = 0) => {
9208
+ if (typeof t === "string") return t;
9209
+ if (t && typeof t === "object" && depth < 4) {
9210
+ if (typeof t.text === "string") return t.text;
9211
+ if (t.text && typeof t.text === "object") return coerceUserText(t.text, depth + 1);
9212
+ }
9213
+ return typeof t === "undefined" ? "" : JSON.stringify(t);
9214
+ };
9215
+ const coerceUserContent = (c) => {
9216
+ if (typeof c === "string") return { type: "text", text: c };
9217
+ if (c && typeof c === "object" && c.type === "text") {
9218
+ return { ...c, text: coerceUserText(c.text) };
9219
+ }
9220
+ return c;
9221
+ };
9103
9222
  const wrappedContent = parsed && parsed.role === "user" ? { role: "user", content: coerceUserContent(parsed.content) } : { role: "user", content: { type: "text", text: typeof parsed === "string" ? parsed : JSON.stringify(parsed) } };
9104
9223
  if (isBtwEcho) wrappedContent.meta = { btw: true };
9105
9224
  const msg = {
@@ -9276,6 +9395,32 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
9276
9395
  // `svamp outpost up`, so the install command never drifts. NO channel is created — the remote
9277
9396
  // dials the machine's public `:outpost` gateway and this session's token authenticates it.
9278
9397
  // Admin-gated: the returned token is a capability to run commands on whatever machine connects.
9398
+ // #1628: REVOKE this session's outpost token by minting a fresh one, then return the new
9399
+ // install info. The durable token is a capability ("whoever holds it can run commands on
9400
+ // connected outposts") that never expired and had no rotate path — and the documented
9401
+ // workflow PRINTS it in an install one-liner meant to be pasted into someone else's
9402
+ // terminal, so it routinely lands in shell history, chat and screen shares. Every prior
9403
+ // outpost fix (#0757, #0778, #1035, #1374) closed a LEAK; none gave the operator a way to
9404
+ // invalidate a token that had already leaked.
9405
+ //
9406
+ // Admin-gated like outpostConnectInfo — this both destroys a capability and mints a new one.
9407
+ // Live pairing codes for the session are burned in the same act: leaving a code that
9408
+ // resolves to the OLD token would defeat the rotation.
9409
+ outpostRotateToken: async (params, context) => {
9410
+ authorizeRequest(context, metadata.sharing, "admin");
9411
+ if (!outpostServiceId) return { error: "the outpost service is not available on this machine" };
9412
+ try {
9413
+ rotateOutpostToken(outpostProjectDir(), sessionId);
9414
+ try {
9415
+ const am = await server.getService("public/artifact-manager");
9416
+ if (am) await burnSessionPairings(am, sessionId, void 0, (m) => console.log(m));
9417
+ } catch {
9418
+ }
9419
+ } catch (err) {
9420
+ return { error: `could not rotate the outpost token: ${err?.message || err}` };
9421
+ }
9422
+ return await rpcHandlers.outpostConnectInfo(params, context);
9423
+ },
9279
9424
  outpostConnectInfo: async (params, context) => {
9280
9425
  authorizeRequest(context, metadata.sharing, "admin");
9281
9426
  if (!outpostServiceId) return { error: "the outpost service is not available on this machine" };
@@ -9694,7 +9839,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
9694
9839
  authorizeRequest(context, metadata.sharing, "interact");
9695
9840
  let forwarded = params;
9696
9841
  if (params && (params.mode !== void 0 || params.allowTools !== void 0)) {
9697
- if (!roleAtLeast(getEffectiveRole(context, metadata.sharing), "admin")) {
9842
+ if (!isAdminEquivalentStrict(context, metadata.sharing)) {
9698
9843
  const { mode: _droppedMode, allowTools: _droppedTools, ...rest } = params;
9699
9844
  forwarded = rest;
9700
9845
  console.warn(
@@ -9812,6 +9957,8 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
9812
9957
  // workflow writes 'admin' (direct server-side command exec). See issueOpMinRole above.
9813
9958
  issue: async (params, context) => {
9814
9959
  authorizeRequest(context, metadata.sharing, issueOpMinRole(params?.op));
9960
+ const refusal = issueVerifyRefusalReason(params, isOwnerEquivalentStrict(context, metadata.sharing));
9961
+ if (refusal) throw new Error(refusal);
9815
9962
  if (!callbacks.onIssue) throw new Error("issue not supported");
9816
9963
  return await callbacks.onIssue(params);
9817
9964
  },
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  export { c as connectToHypha, g as getHyphaServerUrl } from './hyphaClient-ybivOjZo.mjs';
2
- export { c as createSessionStore, r as registerMachineService } from './hookSettings-DYMTUgVA.mjs';
3
- export { d as daemonStatus, s as startDaemon, a as stopDaemon } from './run-DkjwF-zA.mjs';
2
+ export { c as createSessionStore, r as registerMachineService } from './hookSettings-FFc1pi8j.mjs';
3
+ export { d as daemonStatus, s as startDaemon, a as stopDaemon } from './run-DDmeV9K3.mjs';
4
4
  import 'fs';
5
5
  import 'path';
6
6
  import 'node:crypto';
@@ -18,11 +18,11 @@ import 'http';
18
18
  import 'net';
19
19
  import 'os';
20
20
  import './instance-CeHz5C8v.mjs';
21
- import './serveAuth-DbVLRCRR.mjs';
21
+ import './serveAuth-4M0vwMyj.mjs';
22
22
  import 'node:os';
23
23
  import 'node:path';
24
24
  import './envFlag-COOuJ3AH.mjs';
25
- import './claudeAuth-iAerdaMr.mjs';
25
+ import './claudeAuth-C0wc1GTM.mjs';
26
26
  import './fileLock-BMPwCrB6.mjs';
27
27
  import './codexProvider-BtxYc5Rj.mjs';
28
28
  import './friendlyName-1UZcyDhu.mjs';
@@ -30,7 +30,7 @@ import 'node:events';
30
30
  import './cron-hHGdb5kU.mjs';
31
31
  import 'url';
32
32
  import './sharingNotificationSync-qGIQ-3yf.mjs';
33
- import './acpBackend-BZ1MJhQV.mjs';
33
+ import './acpBackend-UaBD4zL3.mjs';
34
34
  import '@agentclientprotocol/sdk';
35
35
  import './DefaultTransport-vfp78fug.mjs';
36
36
  import './wrapCommand-CdNawSaa.mjs';
@@ -43,12 +43,12 @@ import './GeminiTransport-3OkhtFRO.mjs';
43
43
  import './KimiTransport-D8n009Tr.mjs';
44
44
  import './kimiProvider-DbxODebR.mjs';
45
45
  import './kimiSetup-NGsoYB5h.mjs';
46
- import './detectIsolation-CzoDCEnh.mjs';
46
+ import './detectIsolation-CrV8IFDv.mjs';
47
47
  import 'node:fs/promises';
48
48
  import './pinnedNono-5ZHb6328.mjs';
49
49
  import './bootStatus-DqtNgJch.mjs';
50
- import './loopVerify-B47sSjxe.mjs';
51
- import './store-Bn0ByYev.mjs';
50
+ import './loopVerify-DALtTk2V.mjs';
51
+ import './store-B4E6NzG6.mjs';
52
52
  import './api-BHjyC0Ph.mjs';
53
53
  import './store-fi0f-ff1.mjs';
54
54
  import 'yaml';
@@ -1,6 +1,6 @@
1
1
  import { n as normalizeAllowedUser } from './types-57J3Re0n.mjs';
2
2
  import { c as getSvampWebBaseUrl } from './instance-CeHz5C8v.mjs';
3
- import { l as listIssues, i as isPendingIssue, j as isVisibleTo } from './store-Bn0ByYev.mjs';
3
+ import { l as listIssues, j as isPendingIssue, k as isVisibleTo } from './store-B4E6NzG6.mjs';
4
4
 
5
5
  function getShareBaseUrl() {
6
6
  return getSvampWebBaseUrl();
@@ -1,6 +1,6 @@
1
1
  import { c as connectToHypha } from './hyphaClient-ybivOjZo.mjs';
2
2
  import { S as SharingNotificationSync } from './sharingNotificationSync-qGIQ-3yf.mjs';
3
- import { p as parseJwtEmail } from './serveAuth-DbVLRCRR.mjs';
3
+ import { p as parseJwtEmail } from './serveAuth-4M0vwMyj.mjs';
4
4
  import { randomUUID } from 'node:crypto';
5
5
  import { existsSync, readFileSync } from 'node:fs';
6
6
  import { join } from 'node:path';
@@ -0,0 +1,64 @@
1
+ var name = "svamp-cli";
2
+ var version = "0.2.356";
3
+ var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
4
+ var author = "Amun AI AB";
5
+ var license = "SEE LICENSE IN LICENSE";
6
+ var type = "module";
7
+ var bin = {
8
+ svamp: "./bin/svamp.mjs"
9
+ };
10
+ var files = [
11
+ "dist",
12
+ "bin"
13
+ ];
14
+ var main = "./dist/index.mjs";
15
+ var exports$1 = {
16
+ ".": "./dist/index.mjs",
17
+ "./cli": "./dist/cli.mjs"
18
+ };
19
+ var scripts = {
20
+ build: "rm -rf dist bin/skills bin/commands && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/crew bin/skills/crew && cp -r ../../commands bin/commands && tsc --noEmit && pkgroll",
21
+ typecheck: "tsc --noEmit",
22
+ test: "node test/with-timeout.mjs 420 npx tsx test/test-context-window.mjs && node test/with-timeout.mjs 420 npx tsx test/test-ratelimit-retry.mjs && node test/with-timeout.mjs 420 npx tsx test/test-completed-requests.mjs && node test/with-timeout.mjs 420 npx tsx test/test-reconnect-health.mjs &&node test/with-timeout.mjs 420 npx tsx test/test-fleet-version-parse.mjs &&node test/with-timeout.mjs 420 npx tsx test/test-instance-config.mjs && node test/with-timeout.mjs 420 npx tsx test/test-authorize.mjs && node test/with-timeout.mjs 420 npx tsx test/test-normalize-allowed-user.mjs && node test/with-timeout.mjs 420 npx tsx test/test-share-url.mjs && node test/with-timeout.mjs 420 npx tsx test/test-update-sharing-normalization.mjs && node test/with-timeout.mjs 420 npx tsx test/test-sharing-notify-sync.mjs && node test/with-timeout.mjs 420 npx tsx test/test-sharing-notify-resolve.mjs && node test/with-timeout.mjs 420 npx tsx test/test-staged-homes-sweep.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-helpers.mjs && node test/with-timeout.mjs 420 npx tsx test/test-cli-routing.mjs && node test/with-timeout.mjs 420 npx tsx test/test-security-context.mjs && node test/with-timeout.mjs 420 npx tsx test/test-isolation-decision.mjs && node test/with-timeout.mjs 420 npx tsx test/test-message-helpers.mjs && node test/with-timeout.mjs 420 npx tsx test/test-stdin-delivery.mjs && node test/with-timeout.mjs 420 npx tsx test/test-agent-config.mjs && node test/with-timeout.mjs 420 npx tsx test/test-wrap-command.mjs && node test/with-timeout.mjs 420 npx tsx test/test-credential-staging.mjs && node test/with-timeout.mjs 420 npx tsx test/test-claude-auth.mjs && node test/with-timeout.mjs 420 npx tsx test/test-backend-accounts.mjs && node test/with-timeout.mjs 420 npx tsx test/test-codex-force-model.mjs && node test/with-timeout.mjs 420 npx tsx test/test-backend-oauth.mjs && node test/with-timeout.mjs 420 npx tsx test/test-btw-proxy-env.mjs && node test/with-timeout.mjs 420 npx tsx test/test-output-formatters.mjs && node test/with-timeout.mjs 420 npx tsx test/test-inbox-guard.mjs && node test/with-timeout.mjs 420 npx tsx test/test-user-events.mjs && node test/with-timeout.mjs 420 npx tsx test/test-migrate-children.mjs && node test/with-timeout.mjs 420 npx tsx test/test-outpost-install.mjs && node test/with-timeout.mjs 420 npx tsx test/test-outpost-setup.mjs && node test/with-timeout.mjs 420 npx tsx test/test-outpost-pairing.mjs && node test/with-timeout.mjs 420 npx tsx test/test-outpost-coordinator.mjs && node test/with-timeout.mjs 420 npx tsx test/e2e-outpost-transport.mjs && node test/with-timeout.mjs 420 npx tsx test/test-inbox-reconcile.mjs && node test/with-timeout.mjs 420 npx tsx test/test-auto-topic.mjs && node test/with-timeout.mjs 420 npx tsx test/test-project-info.mjs && node test/with-timeout.mjs 420 npx tsx test/test-agent-types.mjs && node test/with-timeout.mjs 420 npx tsx test/test-transport.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-update-handlers.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-scanner.mjs && node test/with-timeout.mjs 420 npx tsx test/test-hypha-client.mjs && node test/with-timeout.mjs 420 npx tsx test/test-hook-settings.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-service-logic.mjs && node test/with-timeout.mjs 420 npx tsx test/test-daemon-persistence.mjs && node test/with-timeout.mjs 420 npx tsx test/test-detect-isolation.mjs && node test/with-timeout.mjs 420 npx tsx test/test-isolation-disable.mjs && node test/with-timeout.mjs 420 npx tsx test/test-machine-service-logic.mjs && node test/with-timeout.mjs 420 npx tsx test/test-machine-session-visibility.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-access-fallback.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-rpc-role-map.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-workflow-op-roles.mjs && npx tsx test/test-issue-verify-cmd-authorship.mjs && node test/with-timeout.mjs 420 npx tsx test/test-interactive-helpers.mjs && node test/with-timeout.mjs 420 npx tsx test/test-pinned-codex.mjs && node test/with-timeout.mjs 420 npx tsx test/test-pinned-hypha-rpc.mjs && node test/with-timeout.mjs 420 npx tsx test/test-pinned-kimi.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-receive-cap.mjs && node test/with-timeout.mjs 420 npx tsx test/test-dns-shadowing.mjs && node test/with-timeout.mjs 420 npx tsx test/test-codex-request-timeout.mjs && node test/with-timeout.mjs 420 npx tsx test/test-codex-app-server.mjs && node test/with-timeout.mjs 420 npx tsx test/test-kimi-provider.mjs && node test/with-timeout.mjs 420 npx tsx test/test-acp-backend.mjs && node test/with-timeout.mjs 420 npx tsx test/test-acp-bridge.mjs && node test/with-timeout.mjs 420 npx tsx test/test-listener-backoff.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-identity-env.mjs && node test/with-timeout.mjs 420 npx tsx test/test-hook-server.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-commands.mjs && node test/with-timeout.mjs 420 npx tsx test/test-interactive-console.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-messages.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-send-query.mjs && node test/with-timeout.mjs 420 npx tsx test/test-skills.mjs && node test/with-timeout.mjs 420 npx tsx test/test-agent-grouping.mjs && node test/with-timeout.mjs 420 npx tsx test/test-machine-list-directory.mjs && node test/with-timeout.mjs 420 npx tsx test/test-service-commands.mjs && node test/with-timeout.mjs 420 npx tsx test/test-supervisor.mjs && node test/with-timeout.mjs 420 npx tsx test/test-supervisor-lock.mjs && node test/with-timeout.mjs 420 node test/test-supervisor-restart.mjs && node test/with-timeout.mjs 420 npx tsx test/test-clear-detection.mjs && node test/with-timeout.mjs 420 npx tsx test/test-compact-detect.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-consolidation.mjs && node test/with-timeout.mjs 420 npx tsx test/test-inbox-store.mjs && node test/with-timeout.mjs 420 npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-xml-escaping.mjs && node test/with-timeout.mjs 420 npx tsx test/test-inbox-cross-machine.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-store.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-store-lock.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-close-gate.mjs && node test/with-timeout.mjs 420 npx tsx test/test-loop-verify.mjs && npx tsx test/test-loop-verify-error-guards.mjs && node test/with-timeout.mjs 420 npx tsx test/test-restore-decision.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-rpc.mjs && npx tsx test/test-verify-gate-async.mjs && npx tsx test/test-process-env-redaction.mjs && npx tsx test/test-provisioner-pin-published.mjs && npx tsx test/test-pinned-nono.mjs && npx tsx test/test-nono-install-executability.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-pause.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-store.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-rpc.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-scheduler.mjs && node test/with-timeout.mjs 420 npx tsx test/test-cron.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-runs.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-runs-lock.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-idle.mjs && node test/with-timeout.mjs 420 npx tsx test/test-workflow-reconcile.mjs && npx tsx test/test-workflow-reconcile-grace.mjs && node test/with-timeout.mjs 420 npx tsx test/test-serve-link-subdomain.mjs &&node test/with-timeout.mjs 420 npx tsx test/test-frpc-footprint.mjs && npx tsx test/test-serve-regenerate-url.mjs && node test/with-timeout.mjs 420 npx tsx test/test-short-id.mjs && node test/with-timeout.mjs 420 npx tsx test/test-transcript-edit.mjs && node test/with-timeout.mjs 420 npx tsx test/test-edit-history.mjs && node test/with-timeout.mjs 420 npx tsx test/test-friendly-name.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-rpc-dispatch.mjs && node test/with-timeout.mjs 420 npx tsx test/test-nightly-1615-1630.mjs && node test/with-timeout.mjs 420 npx tsx test/test-sandbox-cli.mjs && node test/with-timeout.mjs 420 npx tsx test/test-serve-manager.mjs && node test/with-timeout.mjs 420 npx tsx test/test-serve-listen-failure.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-files-gateway.mjs && node test/with-timeout.mjs 420 npx tsx test/test-serve-ws-upgrade.mjs && node test/with-timeout.mjs 420 npx tsx test/test-serve-auth.mjs && node test/with-timeout.mjs 420 npx tsx test/test-static-file-server.mjs && node test/with-timeout.mjs 420 npx tsx test/test-serve-stability.mjs && node test/with-timeout.mjs 420 npx tsx test/test-frpc-e2e.mjs --unit-only && node test/with-timeout.mjs 420 npx tsx test/test-frpc-status.mjs && node test/with-timeout.mjs 420 npx tsx test/test-frpc-orphan-reap.mjs && node test/with-timeout.mjs 420 node test/pinnedClaudeCode.test.mjs && node test/with-timeout.mjs 420 npx tsx test/test-claude-version-recheck.mjs && node test/with-timeout.mjs 420 node test/fleet.test.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-file.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-rpc.mjs && node test/with-timeout.mjs 420 npx tsx test/test-wise-agent.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-agent.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channels-service.mjs && node test/with-timeout.mjs 420 npx tsx test/test-hotreload-seam.mjs && node test/with-timeout.mjs 420 npx tsx test/test-hot-reload.mjs && node test/with-timeout.mjs 420 npx tsx test/test-hot-reload-live.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-core.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-async-reply.mjs && node test/with-timeout.mjs 420 npx tsx test/test-outbox-reload.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-binding.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-store-lock.mjs && npx tsx test/test-channel-lost-update.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-identity.mjs && node test/with-timeout.mjs 420 npx tsx test/test-stateless-dispatch-limiter.mjs && node test/with-timeout.mjs 420 npx tsx test/test-shared-session-identity.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-authz-boundaries.mjs && node test/with-timeout.mjs 420 npx tsx test/test-wise-agent-auth.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-http.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-upload.mjs && node test/with-timeout.mjs 420 npx tsx test/test-channel-file-access.mjs && node test/with-timeout.mjs 420 npx tsx test/test-wise-voice.mjs && node test/with-timeout.mjs 420 npx tsx test/test-wise-headless.mjs && node test/with-timeout.mjs 420 npx tsx test/test-wise-machine.mjs && node test/with-timeout.mjs 420 npx tsx test/test-crew-merge.mjs && node test/with-timeout.mjs 420 npx tsx test/test-crew-merge-closes-issue.mjs && node test/with-timeout.mjs 420 npx tsx test/test-crew-verdict-routing.mjs && node test/with-timeout.mjs 420 npx tsx test/test-crew-standalone.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-links.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-loop-pause-guard.mjs && node test/with-timeout.mjs 420 npx tsx test/test-artifact-guard.mjs && node test/with-timeout.mjs 420 npx tsx test/test-artifact-sync-pagination.mjs && node test/with-timeout.mjs 420 npx tsx test/test-graceful-restart.mjs && node test/with-timeout.mjs 420 npx tsx test/test-flush-exit.mjs && node test/with-timeout.mjs 420 npx tsx test/test-codex-skills.mjs && node test/with-timeout.mjs 420 npx tsx test/test-nightly-0807-fixes.mjs && node test/with-timeout.mjs 420 npx tsx test/test-nightly-0814-fixes.mjs && node test/with-timeout.mjs 420 npx tsx test/test-log-prune.mjs && node test/with-timeout.mjs 420 node test/test-message-count-cache.mjs && node test/with-timeout.mjs 420 node test/test-serve-link-gate.mjs && node test/with-timeout.mjs 420 node test/test-security-context-unenforceable.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-id-resolution.mjs && node test/with-timeout.mjs 420 npx tsx test/test-issue-positional.mjs && npx tsx test/test-issue-status-validation.mjs && npx tsx test/test-issue-triage-reopen-guard.mjs && npx tsx test/test-process-positional.mjs && npx tsx test/test-crew-root-and-max.mjs && npx tsx test/test-channel-sse-close.mjs && node test/with-timeout.mjs 420 npx tsx test/test-help-flag-never-acts.mjs && node test/with-timeout.mjs 420 npx tsx test/test-with-timeout.mjs && node test/with-timeout.mjs 420 npx tsx test/test-message-queue-cap.mjs && node test/with-timeout.mjs 420 npx tsx test/test-compaction-backstop.mjs && tsx test/test-launchpad-reconcile.mjs && tsx test/test-file-lock-failopen.mjs && node test/with-timeout.mjs 420 npx tsx test/test-log-format.mjs && npx tsx test/test-deploy-manifests.mjs && npx tsx test/test-kimi-default-model-1169.mjs && npx tsx test/test-loop-dormant-runtime-1170.mjs && npx tsx test/test-skill-install-atomic.mjs && node test/test-version-unpublished.mjs && node test/test-pin-holds.mjs && node test/test-hypha-token-renewal.mjs && node test/with-timeout.mjs 420 npx tsx test/test-boot-status.mjs && node test/with-timeout.mjs 420 npx tsx test/test-stream-log-policy.mjs && node test/with-timeout.mjs 420 npx tsx test/test-count-file-lines.mjs && node test/with-timeout.mjs 420 npx tsx test/test-read-jsonl-lines.mjs && node test/with-timeout.mjs 420 npx tsx test/test-messages-reverse-pager.mjs && node test/with-timeout.mjs 420 npx tsx test/test-spawn-index-scans.mjs && node test/with-timeout.mjs 420 npx tsx test/test-session-cwd-containment.mjs && node test/with-timeout.mjs 420 npx tsx test/test-register-listener.mjs && node test/with-timeout.mjs 420 npx tsx test/test-unreachable-machines.mjs",
23
+ "test:hypha": "node --no-warnings test/test-hypha-service.mjs",
24
+ dev: "tsx src/cli.ts",
25
+ "dev:daemon": "tsx src/cli.ts daemon start-sync",
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 && npx tsx test/e2e-cluster-manifest-drift.mjs && node test/with-timeout.mjs 600 npx tsx test/test-rev-lock-contention.mjs && npx tsx test/test-embed-headers.mjs && bash tests/test-sandbox-isolation.sh && bash tests/test-credential-staging.sh && bash tests/test-claude-sandbox-e2e.sh",
27
+ "test:frpc": "npx tsx test/test-frpc-e2e.mjs",
28
+ prepublishOnly: "node ../../scripts/bump-cli-version.mjs --check && yarn build && yarn test"
29
+ };
30
+ var dependencies = {
31
+ "@agentclientprotocol/sdk": "^0.14.1",
32
+ "@modelcontextprotocol/sdk": "^1.25.3",
33
+ "hypha-rpc": "0.21.46",
34
+ "node-pty": "1.2.0-beta.11",
35
+ ws: "^8.18.0",
36
+ yaml: "^2.8.2",
37
+ zod: "^3.24.4"
38
+ };
39
+ var devDependencies = {
40
+ "@types/node": ">=20",
41
+ "@types/ws": "^8.5.14",
42
+ pkgroll: "^2.14.2",
43
+ tsx: "^4.20.6",
44
+ typescript: "5.9.3"
45
+ };
46
+ var packageManager = "yarn@1.22.22";
47
+ var _package = {
48
+ name: name,
49
+ version: version,
50
+ description: description,
51
+ author: author,
52
+ license: license,
53
+ type: type,
54
+ bin: bin,
55
+ files: files,
56
+ main: main,
57
+ exports: exports$1,
58
+ scripts: scripts,
59
+ dependencies: dependencies,
60
+ devDependencies: devDependencies,
61
+ packageManager: packageManager
62
+ };
63
+
64
+ export { author, bin, _package as default, dependencies, description, devDependencies, exports$1 as exports, files, license, main, name, packageManager, scripts, type, version };
@@ -1,6 +1,6 @@
1
- import { r as resolveProjectRoot } from './store-Bn0ByYev.mjs';
1
+ import { r as resolveProjectRoot } from './store-B4E6NzG6.mjs';
2
2
  import { g as getWorkflow, s as setWorkflowEnabled, r as removeWorkflow, v as validateWorkflowName, a as saveWorkflow, b as rawWorkflow, l as listWorkflows } from './store-fi0f-ff1.mjs';
3
- import { g as getRun, l as listRuns, r as runWorkflow } from './run-DkjwF-zA.mjs';
3
+ import { g as getRun, l as listRuns, r as runWorkflow } from './run-DDmeV9K3.mjs';
4
4
  import { v as validateCronExpr } from './cron-hHGdb5kU.mjs';
5
5
  import 'node:fs';
6
6
  import 'node:path';
@@ -15,7 +15,7 @@ import 'path';
15
15
  import 'url';
16
16
  import 'child_process';
17
17
  import 'crypto';
18
- import './hookSettings-DYMTUgVA.mjs';
18
+ import './hookSettings-FFc1pi8j.mjs';
19
19
  import './types-57J3Re0n.mjs';
20
20
  import './securityContext-Cm5UTCuD.mjs';
21
21
  import './machineTools-DygM1jXW.mjs';
@@ -24,16 +24,16 @@ import 'util';
24
24
  import 'http';
25
25
  import 'net';
26
26
  import './instance-CeHz5C8v.mjs';
27
- import './serveAuth-DbVLRCRR.mjs';
27
+ import './serveAuth-4M0vwMyj.mjs';
28
28
  import 'node:os';
29
29
  import './envFlag-COOuJ3AH.mjs';
30
- import './claudeAuth-iAerdaMr.mjs';
30
+ import './claudeAuth-C0wc1GTM.mjs';
31
31
  import './codexProvider-BtxYc5Rj.mjs';
32
32
  import './friendlyName-1UZcyDhu.mjs';
33
33
  import 'node:events';
34
34
  import './hyphaClient-ybivOjZo.mjs';
35
35
  import './sharingNotificationSync-qGIQ-3yf.mjs';
36
- import './acpBackend-BZ1MJhQV.mjs';
36
+ import './acpBackend-UaBD4zL3.mjs';
37
37
  import '@agentclientprotocol/sdk';
38
38
  import './DefaultTransport-vfp78fug.mjs';
39
39
  import './wrapCommand-CdNawSaa.mjs';
@@ -46,11 +46,11 @@ import './GeminiTransport-3OkhtFRO.mjs';
46
46
  import './KimiTransport-D8n009Tr.mjs';
47
47
  import './kimiProvider-DbxODebR.mjs';
48
48
  import './kimiSetup-NGsoYB5h.mjs';
49
- import './detectIsolation-CzoDCEnh.mjs';
49
+ import './detectIsolation-CrV8IFDv.mjs';
50
50
  import 'node:fs/promises';
51
51
  import './pinnedNono-5ZHb6328.mjs';
52
52
  import './bootStatus-DqtNgJch.mjs';
53
- import './loopVerify-B47sSjxe.mjs';
53
+ import './loopVerify-DALtTk2V.mjs';
54
54
  import './api-BHjyC0Ph.mjs';
55
55
 
56
56
  async function workflowRpc(cwd, params) {