commonswarm 0.1.33 → 0.1.35

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 (2) hide show
  1. package/cswarm.cjs +594 -289
  2. package/package.json +1 -1
package/cswarm.cjs CHANGED
@@ -4381,8 +4381,8 @@ var require_RealtimeChannel = __commonJS({
4381
4381
  }
4382
4382
  /** @internal */
4383
4383
  _notThisChannelEvent(event, ref) {
4384
- const { close, error, leave, join: join17 } = constants_1.CHANNEL_EVENTS;
4385
- const events = [close, error, leave, join17];
4384
+ const { close, error, leave, join: join18 } = constants_1.CHANNEL_EVENTS;
4385
+ const events = [close, error, leave, join18];
4386
4386
  return ref && events.includes(event) && ref !== this.joinPush.ref;
4387
4387
  }
4388
4388
  /** @internal */
@@ -13523,7 +13523,7 @@ module.exports = __toCommonJS(cli_exports);
13523
13523
  var import_node_crypto19 = require("node:crypto");
13524
13524
  var import_node_fs7 = require("node:fs");
13525
13525
  var import_promises11 = require("node:fs/promises");
13526
- var import_node_path19 = require("node:path");
13526
+ var import_node_path20 = require("node:path");
13527
13527
  var import_promises12 = require("node:readline/promises");
13528
13528
 
13529
13529
  // src/cloud/auth.ts
@@ -29571,8 +29571,195 @@ async function runInboxFollow(options) {
29571
29571
  }
29572
29572
  }
29573
29573
 
29574
- // src/cloud/delivery-receipts.ts
29574
+ // src/cloud/arrival-watch.ts
29575
+ var import_node_os4 = require("node:os");
29576
+ var import_node_path4 = require("node:path");
29575
29577
  var UUID_RE8 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
29578
+ var CURSOR_MAX_BYTES = 4 * 1024;
29579
+ var ARRIVAL_SNIPPET_MAX = 180;
29580
+ var ARRIVAL_WATCH_POLL_MS = 25e3;
29581
+ function stateRoot() {
29582
+ return process.env.XDG_STATE_HOME ? (0, import_node_path4.join)(process.env.XDG_STATE_HOME, "cswarm", "arrival-cursors") : (0, import_node_path4.join)((0, import_node_os4.homedir)(), ".cswarm", "arrival-cursors");
29583
+ }
29584
+ function arrivalCursorPath(target2, workspaceId2, principalId, root = stateRoot()) {
29585
+ return (0, import_node_path4.join)(
29586
+ root,
29587
+ `${target2.profileId}-${workspaceId2.toLowerCase()}-${principalId.toLowerCase()}.json`
29588
+ );
29589
+ }
29590
+ function parseCursor(raw, workspaceId2, principalId) {
29591
+ let value;
29592
+ try {
29593
+ value = JSON.parse(raw);
29594
+ } catch {
29595
+ throw new Error("stored arrival cursor is malformed");
29596
+ }
29597
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29598
+ throw new Error("stored arrival cursor is malformed");
29599
+ }
29600
+ const row = value;
29601
+ const keys = Object.keys(row).sort();
29602
+ const cursor = row.cursor;
29603
+ if (keys.join(",") !== "cursor,principal_id,version,workspace_id" || row.version !== 1 || row.workspace_id !== workspaceId2.toLowerCase() || row.principal_id !== principalId.toLowerCase() || !(cursor === null || typeof cursor === "object" && !Array.isArray(cursor) && Object.keys(cursor).sort().join(",") === "created_at,id" && typeof cursor.created_at === "string" && Number.isFinite(Date.parse(cursor.created_at)) && typeof cursor.id === "string" && UUID_RE8.test(cursor.id))) {
29604
+ throw new Error("stored arrival cursor is malformed");
29605
+ }
29606
+ if (cursor === null) return null;
29607
+ return {
29608
+ created_at: cursor.created_at,
29609
+ id: cursor.id.toLowerCase()
29610
+ };
29611
+ }
29612
+ function fileArrivalCursorStore(options) {
29613
+ const workspaceId2 = options.workspaceId.toLowerCase();
29614
+ const principalId = options.principalId.toLowerCase();
29615
+ if (!UUID_RE8.test(workspaceId2) || !UUID_RE8.test(principalId)) {
29616
+ throw new Error("arrival cursor identity must use workspace and principal UUIDs");
29617
+ }
29618
+ const location2 = arrivalCursorPath(
29619
+ options.target,
29620
+ workspaceId2,
29621
+ principalId,
29622
+ options.stateDirectory
29623
+ );
29624
+ return {
29625
+ location: location2,
29626
+ async read() {
29627
+ const raw = await readSecureJsonFile(location2, CURSOR_MAX_BYTES);
29628
+ return raw === null ? void 0 : parseCursor(raw, workspaceId2, principalId);
29629
+ },
29630
+ async write(cursor) {
29631
+ const record = {
29632
+ version: 1,
29633
+ workspace_id: workspaceId2,
29634
+ principal_id: principalId,
29635
+ cursor
29636
+ };
29637
+ await writeSecureJsonFile(location2, JSON.stringify(record));
29638
+ }
29639
+ };
29640
+ }
29641
+ function arrivalSnippet(body) {
29642
+ const oneLine = body.replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").replace(/\s+/g, " ").trim();
29643
+ if (oneLine.length <= ARRIVAL_SNIPPET_MAX) return oneLine;
29644
+ return `${oneLine.slice(0, ARRIVAL_SNIPPET_MAX - 1).trimEnd()}\u2026`;
29645
+ }
29646
+ function arrivalReplyCommand(signalId, workspaceId2, target2) {
29647
+ return `cswarm reply ${signalId} "<answer>" --agent-token-stdin --url ${target2.url} --anon-key ${target2.anonKey} --workspace-id ${workspaceId2}`;
29648
+ }
29649
+ function arrivalNotification(signal, workspaceId2, target2) {
29650
+ return {
29651
+ type: "arrival",
29652
+ workspace_id: workspaceId2,
29653
+ signal_id: signal.id,
29654
+ sender: signal.from,
29655
+ sender_kind: signal.from_kind,
29656
+ kind: signal.kind,
29657
+ snippet: arrivalSnippet(signal.body),
29658
+ reply_command: arrivalReplyCommand(signal.id, workspaceId2, target2)
29659
+ };
29660
+ }
29661
+ function formatArrivalNotification(notification) {
29662
+ return `CommonSwarm from ${notification.sender_kind} ${notification.sender}: ${notification.snippet} \u2014 reply: ${notification.reply_command}`;
29663
+ }
29664
+ function cursorOf(signal) {
29665
+ return { created_at: signal.created_at, id: signal.id };
29666
+ }
29667
+ function assertCursorPage(page) {
29668
+ if (!page.capabilities.cursorAfter || page.legacyCursorFallback) {
29669
+ throw new Error(
29670
+ "arrival watch needs a read service with durable cursor support"
29671
+ );
29672
+ }
29673
+ }
29674
+ async function runArrivalWatch(options) {
29675
+ const pollMs = options.pollMs ?? ARRIVAL_WATCH_POLL_MS;
29676
+ const random = options.random ?? Math.random;
29677
+ let cursor = await options.store.read();
29678
+ let baseline = cursor === void 0;
29679
+ let attempt = 0;
29680
+ const cancelled = () => options.signal?.aborted === true;
29681
+ const wait = async (ms) => {
29682
+ if (options.sleep) {
29683
+ await options.sleep(ms);
29684
+ return;
29685
+ }
29686
+ await new Promise((resolve) => {
29687
+ let timer2;
29688
+ const finish = () => {
29689
+ if (timer2 !== void 0) clearTimeout(timer2);
29690
+ options.signal?.removeEventListener("abort", finish);
29691
+ resolve();
29692
+ };
29693
+ if (cancelled() || ms <= 0) {
29694
+ resolve();
29695
+ return;
29696
+ }
29697
+ options.signal?.addEventListener("abort", finish, { once: true });
29698
+ timer2 = setTimeout(finish, ms);
29699
+ });
29700
+ };
29701
+ while (!cancelled()) {
29702
+ try {
29703
+ const page = await options.readPage({
29704
+ after: cursor ?? null,
29705
+ baseline,
29706
+ limit: baseline ? 1 : SIGNAL_FOLLOW_PAGE_LIMIT
29707
+ });
29708
+ assertCursorPage(page);
29709
+ if (page.signals.some(
29710
+ (row) => row.workspace_id !== options.workspaceId || row.to_agent !== options.principalId
29711
+ )) {
29712
+ throw new Error(
29713
+ "arrival read returned a message directed to another workspace or agent"
29714
+ );
29715
+ }
29716
+ attempt = 0;
29717
+ if (baseline) {
29718
+ if (page.rawCount > 0 && page.nextCursor === null) {
29719
+ throw new Error("arrival baseline returned no safe terminal cursor");
29720
+ }
29721
+ cursor = page.nextCursor;
29722
+ await options.store.write(cursor);
29723
+ baseline = false;
29724
+ if (cancelled()) break;
29725
+ await wait(pollMs);
29726
+ continue;
29727
+ }
29728
+ for (const row of page.signals) {
29729
+ if (cancelled()) break;
29730
+ await options.emit(row);
29731
+ cursor = cursorOf(row);
29732
+ await options.store.write(cursor);
29733
+ }
29734
+ if (cancelled()) break;
29735
+ const fullPage = page.rawCount >= SIGNAL_FOLLOW_PAGE_LIMIT;
29736
+ await wait(fullPage ? 0 : pollMs);
29737
+ } catch (error) {
29738
+ if (cancelled()) break;
29739
+ const http = followHttpDetails(error);
29740
+ const retryable = isRetryableFollowError(error) || http?.status === 429 || http !== null && http.status >= 500;
29741
+ if (!retryable) {
29742
+ return {
29743
+ reason: "error",
29744
+ error: error instanceof Error ? error : new Error(String(error))
29745
+ };
29746
+ }
29747
+ attempt += 1;
29748
+ const delayMs = nextFollowBackoffMs(
29749
+ attempt,
29750
+ http?.retryAfterMs ?? null,
29751
+ random
29752
+ );
29753
+ const typed = error instanceof Error ? error : new Error(String(error));
29754
+ options.onRetry?.(typed, delayMs);
29755
+ await wait(delayMs);
29756
+ }
29757
+ }
29758
+ return { reason: "cancelled" };
29759
+ }
29760
+
29761
+ // src/cloud/delivery-receipts.ts
29762
+ var UUID_RE9 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
29576
29763
  var DeliveryReceiptReadError = class extends Error {
29577
29764
  constructor(code, message, status = null) {
29578
29765
  super(message);
@@ -29591,7 +29778,7 @@ var ACK_OUTCOMES = /* @__PURE__ */ new Set([
29591
29778
  "failed_terminal"
29592
29779
  ]);
29593
29780
  function uuid3(value, field) {
29594
- if (typeof value !== "string" || !UUID_RE8.test(value)) {
29781
+ if (typeof value !== "string" || !UUID_RE9.test(value)) {
29595
29782
  throw new DeliveryReceiptReadError(
29596
29783
  "protocol",
29597
29784
  `delivery receipt returned a malformed ${field}`
@@ -29980,8 +30167,8 @@ function attachStderrTailExitObserver(child, onStderrTail) {
29980
30167
  // src/host/opencode.ts
29981
30168
  var import_node_fs3 = require("node:fs");
29982
30169
  var import_promises4 = require("node:fs/promises");
29983
- var import_node_os4 = require("node:os");
29984
- var import_node_path5 = require("node:path");
30170
+ var import_node_os5 = require("node:os");
30171
+ var import_node_path6 = require("node:path");
29985
30172
 
29986
30173
  // src/host/bounds.ts
29987
30174
  var ACP_MAX_LINE_BYTES = 1048576;
@@ -30063,7 +30250,7 @@ function sanitizeChildEnv(parent = process.env) {
30063
30250
 
30064
30251
  // src/host/session.ts
30065
30252
  var import_node_fs2 = require("node:fs");
30066
- var import_node_path4 = require("node:path");
30253
+ var import_node_path5 = require("node:path");
30067
30254
 
30068
30255
  // src/host/permission.ts
30069
30256
  function allowOnceOrDeny(request) {
@@ -30544,7 +30731,7 @@ function assertAbsoluteExistingCwd(cwd) {
30544
30731
  if (!cwd || typeof cwd !== "string") {
30545
30732
  throw new AcpProtocolError("cwd is required", "invalid_cwd");
30546
30733
  }
30547
- if (!(0, import_node_path4.isAbsolute)(cwd)) {
30734
+ if (!(0, import_node_path5.isAbsolute)(cwd)) {
30548
30735
  throw new AcpProtocolError("cwd must be an absolute path", "invalid_cwd");
30549
30736
  }
30550
30737
  let st;
@@ -31254,8 +31441,8 @@ function isProcessAlive(pid) {
31254
31441
  }
31255
31442
  }
31256
31443
  function resolveOpenCodeExecutable(executable = "opencode", pathEnv) {
31257
- if ((0, import_node_path5.isAbsolute)(executable) || executable.includes("/")) {
31258
- const abs = (0, import_node_path5.resolve)(executable);
31444
+ if ((0, import_node_path6.isAbsolute)(executable) || executable.includes("/")) {
31445
+ const abs = (0, import_node_path6.resolve)(executable);
31259
31446
  try {
31260
31447
  (0, import_node_fs3.accessSync)(abs, import_node_fs3.constants.X_OK);
31261
31448
  } catch {
@@ -31273,7 +31460,7 @@ function resolveOpenCodeExecutable(executable = "opencode", pathEnv) {
31273
31460
  const pathValue = pathEnv ?? process.env.PATH ?? "";
31274
31461
  for (const dir of pathValue.split(":")) {
31275
31462
  if (!dir) continue;
31276
- const candidate = (0, import_node_path5.join)(dir, executable);
31463
+ const candidate = (0, import_node_path6.join)(dir, executable);
31277
31464
  try {
31278
31465
  (0, import_node_fs3.accessSync)(candidate, import_node_fs3.constants.X_OK);
31279
31466
  try {
@@ -31305,7 +31492,7 @@ function buildOpenCodeHomeOwner(options) {
31305
31492
  };
31306
31493
  }
31307
31494
  async function writeOpenCodeHomeOwner(home, owner) {
31308
- const path = (0, import_node_path5.join)(home, OPENCODE_HOME_OWNER_FILE);
31495
+ const path = (0, import_node_path6.join)(home, OPENCODE_HOME_OWNER_FILE);
31309
31496
  await (0, import_promises4.writeFile)(path, `${JSON.stringify(owner)}
31310
31497
  `, {
31311
31498
  flag: "wx",
@@ -31314,7 +31501,7 @@ async function writeOpenCodeHomeOwner(home, owner) {
31314
31501
  await (0, import_promises4.chmod)(path, 384);
31315
31502
  }
31316
31503
  async function readOpenCodeHomeOwner(home) {
31317
- const path = (0, import_node_path5.join)(home, OPENCODE_HOME_OWNER_FILE);
31504
+ const path = (0, import_node_path6.join)(home, OPENCODE_HOME_OWNER_FILE);
31318
31505
  let raw;
31319
31506
  try {
31320
31507
  raw = await (0, import_promises4.readFile)(path, "utf8");
@@ -31332,7 +31519,7 @@ async function readOpenCodeHomeOwner(home) {
31332
31519
  }
31333
31520
  }
31334
31521
  async function releaseOpenCodeHome(home, instanceId) {
31335
- if (!(0, import_node_path5.isAbsolute)(home)) return;
31522
+ if (!(0, import_node_path6.isAbsolute)(home)) return;
31336
31523
  const owner = await readOpenCodeHomeOwner(home);
31337
31524
  if (owner && owner.instanceId !== instanceId) {
31338
31525
  return;
@@ -31457,15 +31644,15 @@ async function readValidatedOpenCodeAuth(sourceAuthPath, options) {
31457
31644
  }
31458
31645
  function resolveOpenCodeAuthSourcePath(parent = process.env) {
31459
31646
  const xdgData = parent.XDG_DATA_HOME;
31460
- if (typeof xdgData === "string" && (0, import_node_path5.isAbsolute)(xdgData)) {
31461
- return (0, import_node_path5.join)(xdgData, "opencode", "auth.json");
31647
+ if (typeof xdgData === "string" && (0, import_node_path6.isAbsolute)(xdgData)) {
31648
+ return (0, import_node_path6.join)(xdgData, "opencode", "auth.json");
31462
31649
  }
31463
- const home = parent.HOME ?? (0, import_node_os4.homedir)();
31464
- return (0, import_node_path5.join)(home, ".local", "share", "opencode", "auth.json");
31650
+ const home = parent.HOME ?? (0, import_node_os5.homedir)();
31651
+ return (0, import_node_path6.join)(home, ".local", "share", "opencode", "auth.json");
31465
31652
  }
31466
31653
  async function prepareOpenCodeIsolatedHome(options) {
31467
- const home = options.home ?? await (0, import_promises4.mkdtemp)((0, import_node_path5.join)((0, import_node_os4.tmpdir)(), OPENCODE_HOME_PREFIX));
31468
- if (!(0, import_node_path5.isAbsolute)(home)) {
31654
+ const home = options.home ?? await (0, import_promises4.mkdtemp)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), OPENCODE_HOME_PREFIX));
31655
+ if (!(0, import_node_path6.isAbsolute)(home)) {
31469
31656
  throw new AcpHostError(
31470
31657
  "isolated_home_invalid",
31471
31658
  "isolated OpenCode home must be absolute"
@@ -31473,21 +31660,21 @@ async function prepareOpenCodeIsolatedHome(options) {
31473
31660
  }
31474
31661
  await (0, import_promises4.chmod)(home, 448);
31475
31662
  try {
31476
- const xdgConfig = (0, import_node_path5.join)(home, "xdg-config");
31477
- const xdgData = (0, import_node_path5.join)(home, "xdg-data");
31478
- const xdgCache = (0, import_node_path5.join)(home, "xdg-cache");
31479
- const xdgState = (0, import_node_path5.join)(home, "xdg-state");
31663
+ const xdgConfig = (0, import_node_path6.join)(home, "xdg-config");
31664
+ const xdgData = (0, import_node_path6.join)(home, "xdg-data");
31665
+ const xdgCache = (0, import_node_path6.join)(home, "xdg-cache");
31666
+ const xdgState = (0, import_node_path6.join)(home, "xdg-state");
31480
31667
  for (const dir of [xdgConfig, xdgData, xdgCache, xdgState]) {
31481
31668
  await (0, import_promises4.mkdir)(dir, { recursive: true, mode: 448 });
31482
31669
  await (0, import_promises4.chmod)(dir, 448);
31483
31670
  }
31484
- const configDir = (0, import_node_path5.join)(xdgConfig, "opencode");
31485
- const dataDir = (0, import_node_path5.join)(xdgData, "opencode");
31671
+ const configDir = (0, import_node_path6.join)(xdgConfig, "opencode");
31672
+ const dataDir = (0, import_node_path6.join)(xdgData, "opencode");
31486
31673
  await (0, import_promises4.mkdir)(configDir, { recursive: true, mode: 448 });
31487
31674
  await (0, import_promises4.mkdir)(dataDir, { recursive: true, mode: 448 });
31488
31675
  await (0, import_promises4.chmod)(configDir, 448);
31489
31676
  await (0, import_promises4.chmod)(dataDir, 448);
31490
- const configPath = (0, import_node_path5.join)(configDir, "opencode.json");
31677
+ const configPath = (0, import_node_path6.join)(configDir, "opencode.json");
31491
31678
  await (0, import_promises4.writeFile)(
31492
31679
  configPath,
31493
31680
  buildOpenCodeSafeConfigJson(
@@ -31501,7 +31688,7 @@ async function prepareOpenCodeIsolatedHome(options) {
31501
31688
  allowMissing: options.allowMissingAuth === true
31502
31689
  });
31503
31690
  if (authBytes) {
31504
- const destAuth = (0, import_node_path5.join)(dataDir, "auth.json");
31691
+ const destAuth = (0, import_node_path6.join)(dataDir, "auth.json");
31505
31692
  await (0, import_promises4.writeFile)(destAuth, authBytes, { flag: "wx", mode: 384 });
31506
31693
  await (0, import_promises4.chmod)(destAuth, 384);
31507
31694
  }
@@ -31516,7 +31703,7 @@ async function prepareOpenCodeIsolatedHome(options) {
31516
31703
  }
31517
31704
  }
31518
31705
  function buildOpenCodeChildEnv(parent, home) {
31519
- if (!(0, import_node_path5.isAbsolute)(home)) {
31706
+ if (!(0, import_node_path6.isAbsolute)(home)) {
31520
31707
  throw new AcpHostError(
31521
31708
  "isolated_home_invalid",
31522
31709
  "isolated OpenCode home must be absolute"
@@ -31526,20 +31713,20 @@ function buildOpenCodeChildEnv(parent, home) {
31526
31713
  return {
31527
31714
  ...base,
31528
31715
  HOME: home,
31529
- XDG_CONFIG_HOME: (0, import_node_path5.join)(home, "xdg-config"),
31530
- XDG_DATA_HOME: (0, import_node_path5.join)(home, "xdg-data"),
31531
- XDG_CACHE_HOME: (0, import_node_path5.join)(home, "xdg-cache"),
31532
- XDG_STATE_HOME: (0, import_node_path5.join)(home, "xdg-state"),
31716
+ XDG_CONFIG_HOME: (0, import_node_path6.join)(home, "xdg-config"),
31717
+ XDG_DATA_HOME: (0, import_node_path6.join)(home, "xdg-data"),
31718
+ XDG_CACHE_HOME: (0, import_node_path6.join)(home, "xdg-cache"),
31719
+ XDG_STATE_HOME: (0, import_node_path6.join)(home, "xdg-state"),
31533
31720
  // Measured 1.18.10: private home alone still merges project opencode.json.
31534
31721
  OPENCODE_DISABLE_PROJECT_CONFIG: "1"
31535
31722
  };
31536
31723
  }
31537
31724
  async function assertOpenCodeEffectiveConfig(options) {
31538
- const hostile = await (0, import_promises4.mkdtemp)((0, import_node_path5.join)((0, import_node_os4.tmpdir)(), "cswarm-opencode-hostile-"));
31725
+ const hostile = await (0, import_promises4.mkdtemp)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), "cswarm-opencode-hostile-"));
31539
31726
  try {
31540
31727
  await (0, import_promises4.chmod)(hostile, 448);
31541
31728
  await (0, import_promises4.writeFile)(
31542
- (0, import_node_path5.join)(hostile, "opencode.json"),
31729
+ (0, import_node_path6.join)(hostile, "opencode.json"),
31543
31730
  `${JSON.stringify({
31544
31731
  permission: {
31545
31732
  bash: "allow",
@@ -31647,7 +31834,7 @@ async function sweepStaleOpenCodeHomes(options) {
31647
31834
  const maxAgeMs = options?.maxAgeMs ?? STALE_HOME_MAX_AGE_MS;
31648
31835
  const now = options?.now ?? Date.now();
31649
31836
  const alive = options?.isAlive ?? isProcessAlive;
31650
- const root = options?.root ?? (0, import_node_os4.tmpdir)();
31837
+ const root = options?.root ?? (0, import_node_os5.tmpdir)();
31651
31838
  const selfUid = typeof process.getuid === "function" ? process.getuid() : null;
31652
31839
  let removed = 0;
31653
31840
  let entries;
@@ -31658,7 +31845,7 @@ async function sweepStaleOpenCodeHomes(options) {
31658
31845
  }
31659
31846
  for (const name of entries) {
31660
31847
  if (!name.startsWith(OPENCODE_HOME_PREFIX)) continue;
31661
- const full = (0, import_node_path5.join)(root, name);
31848
+ const full = (0, import_node_path6.join)(root, name);
31662
31849
  try {
31663
31850
  const st = await (0, import_promises4.lstat)(full);
31664
31851
  if (!st.isDirectory() || st.isSymbolicLink()) continue;
@@ -31836,7 +32023,7 @@ async function openOpenCodeAcpSession(options) {
31836
32023
  // src/host/claude.ts
31837
32024
  var import_node_child_process4 = require("node:child_process");
31838
32025
  var import_node_fs4 = require("node:fs");
31839
- var import_node_path6 = require("node:path");
32026
+ var import_node_path7 = require("node:path");
31840
32027
  var CHILD_EXIT_WAIT_MS2 = 3e3;
31841
32028
  var CHILD_KILL_WAIT_MS2 = 1e3;
31842
32029
  var WINDOWS_NPM_SHIM_MAX_BYTES = 64 * 1024;
@@ -31856,11 +32043,11 @@ function isPackagedClaudeBridge(executable) {
31856
32043
  function resolvePackagedClaudeBridge(pathEnv, platform = process.platform) {
31857
32044
  const pathValue = pathEnv ?? process.env.PATH ?? "";
31858
32045
  const names = platform === "win32" ? ["claude-agent-acp.cmd"] : ["claude-agent-acp"];
31859
- for (const dir of pathValue.split(import_node_path6.delimiter)) {
32046
+ for (const dir of pathValue.split(import_node_path7.delimiter)) {
31860
32047
  if (!dir) continue;
31861
32048
  for (const name of names) {
31862
32049
  try {
31863
- const candidate = resolvedClaudeCandidate((0, import_node_path6.join)(dir, name), platform);
32050
+ const candidate = resolvedClaudeCandidate((0, import_node_path7.join)(dir, name), platform);
31864
32051
  if (isPackagedClaudeBridge(candidate)) return candidate;
31865
32052
  } catch {
31866
32053
  }
@@ -31889,7 +32076,7 @@ function resolveWindowsNpmShim(shim) {
31889
32076
  `unrecognized claude-agent-acp npm shim: ${shim}`
31890
32077
  );
31891
32078
  }
31892
- const target2 = (0, import_node_path6.join)((0, import_node_path6.dirname)(shim), ...WINDOWS_NPM_ENTRYPOINT);
32079
+ const target2 = (0, import_node_path7.join)((0, import_node_path7.dirname)(shim), ...WINDOWS_NPM_ENTRYPOINT);
31893
32080
  try {
31894
32081
  (0, import_node_fs4.accessSync)(target2, import_node_fs4.constants.R_OK);
31895
32082
  return (0, import_node_fs4.realpathSync)(target2);
@@ -31903,12 +32090,12 @@ function resolveWindowsNpmShim(shim) {
31903
32090
  function resolvedClaudeCandidate(candidate, platform) {
31904
32091
  (0, import_node_fs4.accessSync)(candidate, import_node_fs4.constants.X_OK);
31905
32092
  const real = (0, import_node_fs4.realpathSync)(candidate);
31906
- return platform === "win32" && (0, import_node_path6.extname)(real).toLowerCase() === ".cmd" ? resolveWindowsNpmShim(real) : real;
32093
+ return platform === "win32" && (0, import_node_path7.extname)(real).toLowerCase() === ".cmd" ? resolveWindowsNpmShim(real) : real;
31907
32094
  }
31908
32095
  function resolveClaudeExecutable(executable = "claude-agent-acp", pathEnv, platform = process.platform) {
31909
- if ((0, import_node_path6.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
31910
- const abs = (0, import_node_path6.resolve)(executable);
31911
- const candidates = platform === "win32" && (0, import_node_path6.extname)(abs) === "" ? [`${abs}.cmd`] : [abs];
32096
+ if ((0, import_node_path7.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
32097
+ const abs = (0, import_node_path7.resolve)(executable);
32098
+ const candidates = platform === "win32" && (0, import_node_path7.extname)(abs) === "" ? [`${abs}.cmd`] : [abs];
31912
32099
  for (const candidate of candidates) {
31913
32100
  try {
31914
32101
  return resolvedClaudeCandidate(candidate, platform);
@@ -31919,11 +32106,11 @@ function resolveClaudeExecutable(executable = "claude-agent-acp", pathEnv, platf
31919
32106
  throw new AcpHostError("executable_missing", `not executable: ${abs}`);
31920
32107
  }
31921
32108
  const pathValue = pathEnv ?? process.env.PATH ?? "";
31922
- const names = platform === "win32" && (0, import_node_path6.extname)(executable) === "" ? [`${executable}.cmd`] : [executable];
31923
- for (const dir of pathValue.split(import_node_path6.delimiter)) {
32109
+ const names = platform === "win32" && (0, import_node_path7.extname)(executable) === "" ? [`${executable}.cmd`] : [executable];
32110
+ for (const dir of pathValue.split(import_node_path7.delimiter)) {
31924
32111
  if (!dir) continue;
31925
32112
  for (const name of names) {
31926
- const candidate = (0, import_node_path6.join)(dir, name);
32113
+ const candidate = (0, import_node_path7.join)(dir, name);
31927
32114
  try {
31928
32115
  return resolvedClaudeCandidate(candidate, platform);
31929
32116
  } catch (error) {
@@ -31937,7 +32124,7 @@ function resolveClaudeExecutable(executable = "claude-agent-acp", pathEnv, platf
31937
32124
  );
31938
32125
  }
31939
32126
  function buildClaudeLaunch(executable, args, platform = process.platform) {
31940
- return platform === "win32" && (0, import_node_path6.extname)(executable).toLowerCase() === ".js" ? { command: process.execPath, args: [executable, ...args] } : { command: executable, args: [...args] };
32127
+ return platform === "win32" && (0, import_node_path7.extname)(executable).toLowerCase() === ".js" ? { command: process.execPath, args: [executable, ...args] } : { command: executable, args: [...args] };
31941
32128
  }
31942
32129
  function parseClaudeVersionOutput(stdout) {
31943
32130
  return parseProviderVersionOutput(stdout, /\bclaude-agent-acp\b/i);
@@ -32190,7 +32377,7 @@ async function openClaudeAcpSession(options) {
32190
32377
  // src/host/codex.ts
32191
32378
  var import_node_child_process5 = require("node:child_process");
32192
32379
  var import_node_fs5 = require("node:fs");
32193
- var import_node_path7 = require("node:path");
32380
+ var import_node_path8 = require("node:path");
32194
32381
  var CHILD_EXIT_WAIT_MS3 = 3e3;
32195
32382
  var CHILD_KILL_WAIT_MS3 = 1e3;
32196
32383
  var WINDOWS_NPM_SHIM_MAX_BYTES2 = 64 * 1024;
@@ -32219,7 +32406,7 @@ function resolveWindowsNpmShim2(shim) {
32219
32406
  `unrecognized codex-acp npm shim: ${shim}`
32220
32407
  );
32221
32408
  }
32222
- const target2 = (0, import_node_path7.join)((0, import_node_path7.dirname)(shim), ...WINDOWS_NPM_ENTRYPOINT2);
32409
+ const target2 = (0, import_node_path8.join)((0, import_node_path8.dirname)(shim), ...WINDOWS_NPM_ENTRYPOINT2);
32223
32410
  try {
32224
32411
  (0, import_node_fs5.accessSync)(target2, import_node_fs5.constants.R_OK);
32225
32412
  return (0, import_node_fs5.realpathSync)(target2);
@@ -32233,12 +32420,12 @@ function resolveWindowsNpmShim2(shim) {
32233
32420
  function resolvedCodexCandidate(candidate, platform) {
32234
32421
  (0, import_node_fs5.accessSync)(candidate, import_node_fs5.constants.X_OK);
32235
32422
  const real = (0, import_node_fs5.realpathSync)(candidate);
32236
- return platform === "win32" && (0, import_node_path7.extname)(real).toLowerCase() === ".cmd" ? resolveWindowsNpmShim2(real) : real;
32423
+ return platform === "win32" && (0, import_node_path8.extname)(real).toLowerCase() === ".cmd" ? resolveWindowsNpmShim2(real) : real;
32237
32424
  }
32238
32425
  function resolveCodexExecutable(executable = "codex-acp", pathEnv, platform = process.platform) {
32239
- if ((0, import_node_path7.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
32240
- const abs = (0, import_node_path7.resolve)(executable);
32241
- const candidates = platform === "win32" && (0, import_node_path7.extname)(abs) === "" ? [`${abs}.cmd`] : [abs];
32426
+ if ((0, import_node_path8.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
32427
+ const abs = (0, import_node_path8.resolve)(executable);
32428
+ const candidates = platform === "win32" && (0, import_node_path8.extname)(abs) === "" ? [`${abs}.cmd`] : [abs];
32242
32429
  for (const candidate of candidates) {
32243
32430
  try {
32244
32431
  return resolvedCodexCandidate(candidate, platform);
@@ -32249,11 +32436,11 @@ function resolveCodexExecutable(executable = "codex-acp", pathEnv, platform = pr
32249
32436
  throw new AcpHostError("executable_missing", `not executable: ${abs}`);
32250
32437
  }
32251
32438
  const pathValue = pathEnv ?? process.env.PATH ?? "";
32252
- const names = platform === "win32" && (0, import_node_path7.extname)(executable) === "" ? [`${executable}.cmd`] : [executable];
32253
- for (const dir of pathValue.split(import_node_path7.delimiter)) {
32439
+ const names = platform === "win32" && (0, import_node_path8.extname)(executable) === "" ? [`${executable}.cmd`] : [executable];
32440
+ for (const dir of pathValue.split(import_node_path8.delimiter)) {
32254
32441
  if (!dir) continue;
32255
32442
  for (const name of names) {
32256
- const candidate = (0, import_node_path7.join)(dir, name);
32443
+ const candidate = (0, import_node_path8.join)(dir, name);
32257
32444
  try {
32258
32445
  return resolvedCodexCandidate(candidate, platform);
32259
32446
  } catch (error) {
@@ -32267,7 +32454,7 @@ function resolveCodexExecutable(executable = "codex-acp", pathEnv, platform = pr
32267
32454
  );
32268
32455
  }
32269
32456
  function buildCodexLaunch(executable, args, platform = process.platform) {
32270
- return platform === "win32" && (0, import_node_path7.extname)(executable).toLowerCase() === ".js" ? { command: process.execPath, args: [executable, ...args] } : { command: executable, args: [...args] };
32457
+ return platform === "win32" && (0, import_node_path8.extname)(executable).toLowerCase() === ".js" ? { command: process.execPath, args: [executable, ...args] } : { command: executable, args: [...args] };
32271
32458
  }
32272
32459
  function parseCodexVersionOutput(stdout) {
32273
32460
  return parseProviderVersionOutput(stdout, /@agentclientprotocol\/codex-acp\b/i);
@@ -32481,7 +32668,7 @@ async function resolveBudgetAndPrompt(session, prompt, budget) {
32481
32668
  }
32482
32669
 
32483
32670
  // src/listener/engine.ts
32484
- var UUID_RE9 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
32671
+ var UUID_RE10 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
32485
32672
  var TERMINAL_STATES = /* @__PURE__ */ new Set(["done", "expired", "failed"]);
32486
32673
  var REPLY_MAX_CODE_UNITS = 2e3;
32487
32674
  var TRUNCATION_SUFFIX = "\n[Reply truncated by CommonSwarm]";
@@ -32489,7 +32676,7 @@ var UNSAFE_CONTROLS_RE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u
32489
32676
  var LISTENER_MAX_PROMPT_ATTEMPTS = 3;
32490
32677
  var LISTENER_MAX_POST_ATTEMPTS = 5;
32491
32678
  function listenerReplyCommandId(signalId, effectOrdinal = 0) {
32492
- if (!UUID_RE9.test(signalId)) {
32679
+ if (!UUID_RE10.test(signalId)) {
32493
32680
  throw new Error("listener signal id must be a UUID");
32494
32681
  }
32495
32682
  if (!Number.isSafeInteger(effectOrdinal) || effectOrdinal < 0) {
@@ -32950,10 +33137,10 @@ var ListenerEngine = class {
32950
33137
 
32951
33138
  // src/listener/file-store.ts
32952
33139
  var import_node_crypto13 = require("node:crypto");
32953
- var import_node_os5 = require("node:os");
32954
- var import_node_path8 = require("node:path");
33140
+ var import_node_os6 = require("node:os");
33141
+ var import_node_path9 = require("node:path");
32955
33142
  var import_node_util = require("node:util");
32956
- var UUID_RE10 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
33143
+ var UUID_RE11 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
32957
33144
  var COMMAND_ID_RE2 = /^[A-Za-z0-9_-]{8,72}$/;
32958
33145
  var MAX_EFFECT_BYTES = 1024 * 1024;
32959
33146
  var STATES = /* @__PURE__ */ new Set([
@@ -32988,10 +33175,10 @@ var V1_EFFECT_KEYS = /* @__PURE__ */ new Set([
32988
33175
  ]);
32989
33176
  var V2_EFFECT_KEYS = /* @__PURE__ */ new Set([...V1_EFFECT_KEYS, "signalKind"]);
32990
33177
  function defaultListenerStateDirectory() {
32991
- return process.env.XDG_STATE_HOME ? (0, import_node_path8.join)(process.env.XDG_STATE_HOME, "cswarm", "listeners") : (0, import_node_path8.join)((0, import_node_os5.homedir)(), ".cswarm", "listeners");
33178
+ return process.env.XDG_STATE_HOME ? (0, import_node_path9.join)(process.env.XDG_STATE_HOME, "cswarm", "listeners") : (0, import_node_path9.join)((0, import_node_os6.homedir)(), ".cswarm", "listeners");
32992
33179
  }
32993
33180
  function listenerInstanceKey(input) {
32994
- if (!UUID_RE10.test(input.workspaceId) || !UUID_RE10.test(input.principalId)) {
33181
+ if (!UUID_RE11.test(input.workspaceId) || !UUID_RE11.test(input.principalId)) {
32995
33182
  throw new Error("listener workspace and principal ids must be UUIDs");
32996
33183
  }
32997
33184
  if (!input.profileId || input.profileId.includes("\0")) {
@@ -33023,7 +33210,7 @@ function parseListenerEffectRecord(raw, expectedId) {
33023
33210
  throw new Error("stored listener effect is malformed");
33024
33211
  }
33025
33212
  const row = value;
33026
- if (typeof row.version !== "number" || row.version !== 1 && row.version !== 2 || typeof row.signalId !== "string" || row.signalId.toLowerCase() !== expectedId || !UUID_RE10.test(row.signalId)) {
33213
+ if (typeof row.version !== "number" || row.version !== 1 && row.version !== 2 || typeof row.signalId !== "string" || row.signalId.toLowerCase() !== expectedId || !UUID_RE11.test(row.signalId)) {
33027
33214
  throw new Error("stored listener effect is malformed");
33028
33215
  }
33029
33216
  if (row.version === 1) {
@@ -33040,7 +33227,7 @@ function upcastV1Ask(row) {
33040
33227
  if (row.effectOrdinal !== 0 || typeof row.commandId !== "string" || !COMMAND_ID_RE2.test(row.commandId) || typeof row.askBody !== "string" || row.askBody.length < 1 || typeof row.askUntil !== "string" || !Number.isFinite(Date.parse(row.askUntil)) || typeof row.senderOwnerRelation !== "string" || !RELATIONS.has(row.senderOwnerRelation) || typeof row.state !== "string" || !STATES.has(row.state) || !integer(row.promptAttempts) || !integer(row.postAttempts) || !nullableString(row.replyBody, 2e3) || typeof row.replyTruncated !== "boolean" || !nullableString(row.replySignalId, 64) || !nullableString(row.failureCode, 96) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt))) {
33041
33228
  throw new Error("stored listener effect is malformed");
33042
33229
  }
33043
- if (row.replySignalId !== null && !UUID_RE10.test(row.replySignalId)) {
33230
+ if (row.replySignalId !== null && !UUID_RE11.test(row.replySignalId)) {
33044
33231
  throw new Error("stored listener effect is malformed");
33045
33232
  }
33046
33233
  return {
@@ -33068,7 +33255,7 @@ function parseV2Record(row) {
33068
33255
  throw new Error("stored listener effect is malformed");
33069
33256
  }
33070
33257
  if (signalKind2 === "note") {
33071
- if (typeof row.commandId !== "string" || row.commandId !== "" || row.state !== "observed" || row.promptAttempts !== 0 || row.postAttempts !== 0 || row.replyBody !== null || row.replyTruncated !== false || row.replySignalId !== null || row.failureCode !== null) {
33258
+ if (typeof row.commandId !== "string" || row.commandId !== "" || row.state !== "observed" && row.state !== "routed_main" || row.promptAttempts !== 0 || row.postAttempts !== 0 || row.replyBody !== null || row.replyTruncated !== false || row.replySignalId !== null || row.failureCode !== null) {
33072
33259
  throw new Error("stored listener effect is malformed");
33073
33260
  }
33074
33261
  } else if (row.state === "routed_main") {
@@ -33079,7 +33266,7 @@ function parseV2Record(row) {
33079
33266
  if (typeof row.commandId !== "string" || !COMMAND_ID_RE2.test(row.commandId) || row.state === "observed") {
33080
33267
  throw new Error("stored listener effect is malformed");
33081
33268
  }
33082
- if (row.replySignalId !== null && !UUID_RE10.test(row.replySignalId)) {
33269
+ if (row.replySignalId !== null && !UUID_RE11.test(row.replySignalId)) {
33083
33270
  throw new Error("stored listener effect is malformed");
33084
33271
  }
33085
33272
  }
@@ -33103,7 +33290,7 @@ function parseV2Record(row) {
33103
33290
  };
33104
33291
  }
33105
33292
  function newObservedNoteRecord(input) {
33106
- if (!UUID_RE10.test(input.signalId)) {
33293
+ if (!UUID_RE11.test(input.signalId)) {
33107
33294
  throw new Error("listener note signal id must be a UUID");
33108
33295
  }
33109
33296
  if (input.body.length < 1) {
@@ -33137,11 +33324,11 @@ function newObservedNoteRecord(input) {
33137
33324
  updatedAt: input.updatedAt
33138
33325
  };
33139
33326
  }
33140
- function newRoutedMainAskRecord(input) {
33327
+ function newRoutedMainRecord(input) {
33141
33328
  const base = newObservedNoteRecord(input);
33142
33329
  return {
33143
33330
  ...base,
33144
- signalKind: "ask",
33331
+ signalKind: input.signalKind,
33145
33332
  state: "routed_main"
33146
33333
  };
33147
33334
  }
@@ -33210,16 +33397,16 @@ var FileListenerEffectStore = class {
33210
33397
  effectsDirectory;
33211
33398
  constructor(options) {
33212
33399
  const root = options.stateDirectory ?? defaultListenerStateDirectory();
33213
- if (!(0, import_node_path8.isAbsolute)(root)) {
33400
+ if (!(0, import_node_path9.isAbsolute)(root)) {
33214
33401
  throw new Error("listener state directory must be absolute");
33215
33402
  }
33216
- this.instanceDirectory = (0, import_node_path8.join)(root, listenerInstanceKey(options));
33217
- this.effectsDirectory = (0, import_node_path8.join)(this.instanceDirectory, "effects");
33403
+ this.instanceDirectory = (0, import_node_path9.join)(root, listenerInstanceKey(options));
33404
+ this.effectsDirectory = (0, import_node_path9.join)(this.instanceDirectory, "effects");
33218
33405
  }
33219
33406
  async read(signalId) {
33220
33407
  const id = this.checkedId(signalId);
33221
33408
  const raw = await readSecureJsonFile(
33222
- (0, import_node_path8.join)(this.effectsDirectory, `${id}.json`),
33409
+ (0, import_node_path9.join)(this.effectsDirectory, `${id}.json`),
33223
33410
  MAX_EFFECT_BYTES
33224
33411
  );
33225
33412
  return raw === null ? null : parseListenerEffectRecord(raw, id);
@@ -33232,12 +33419,12 @@ var FileListenerEffectStore = class {
33232
33419
  throw new Error("listener effect is too large");
33233
33420
  }
33234
33421
  await writeSecureJsonFile(
33235
- (0, import_node_path8.join)(this.effectsDirectory, `${id}.json`),
33422
+ (0, import_node_path9.join)(this.effectsDirectory, `${id}.json`),
33236
33423
  serialized
33237
33424
  );
33238
33425
  }
33239
33426
  checkedId(signalId) {
33240
- if (!UUID_RE10.test(signalId)) {
33427
+ if (!UUID_RE11.test(signalId)) {
33241
33428
  throw new Error("listener signal id must be a UUID");
33242
33429
  }
33243
33430
  return signalId.toLowerCase();
@@ -33246,18 +33433,18 @@ var FileListenerEffectStore = class {
33246
33433
 
33247
33434
  // src/listener/grok-model.ts
33248
33435
  var import_promises5 = require("node:fs/promises");
33249
- var import_node_os6 = require("node:os");
33250
- var import_node_path10 = require("node:path");
33436
+ var import_node_os7 = require("node:os");
33437
+ var import_node_path11 = require("node:path");
33251
33438
 
33252
33439
  // src/host/grok.ts
33253
33440
  var import_node_child_process6 = require("node:child_process");
33254
33441
  var import_node_fs6 = require("node:fs");
33255
- var import_node_path9 = require("node:path");
33442
+ var import_node_path10 = require("node:path");
33256
33443
  var CHILD_EXIT_WAIT_MS4 = 3e3;
33257
33444
  var CHILD_KILL_WAIT_MS4 = 1e3;
33258
33445
  function resolveGrokExecutable(executable = "grok") {
33259
- if ((0, import_node_path9.isAbsolute)(executable) || executable.includes("/")) {
33260
- const abs = (0, import_node_path9.resolve)(executable);
33446
+ if ((0, import_node_path10.isAbsolute)(executable) || executable.includes("/")) {
33447
+ const abs = (0, import_node_path10.resolve)(executable);
33261
33448
  try {
33262
33449
  (0, import_node_fs6.accessSync)(abs, import_node_fs6.constants.X_OK);
33263
33450
  } catch {
@@ -33502,11 +33689,11 @@ var GrokListenerModel = class {
33502
33689
  async validateLocalAuth() {
33503
33690
  if (this.options.open) return;
33504
33691
  const parent = this.options.env ?? process.env;
33505
- const sourceHome = parent.GROK_HOME ?? (0, import_node_path10.join)(parent.HOME ?? (0, import_node_os6.homedir)(), ".grok");
33506
- if (!(0, import_node_path10.isAbsolute)(sourceHome)) {
33692
+ const sourceHome = parent.GROK_HOME ?? (0, import_node_path11.join)(parent.HOME ?? (0, import_node_os7.homedir)(), ".grok");
33693
+ if (!(0, import_node_path11.isAbsolute)(sourceHome)) {
33507
33694
  throw new Error("Grok home must be an absolute path");
33508
33695
  }
33509
- const sourceAuth = (0, import_node_path10.join)(sourceHome, "auth.json");
33696
+ const sourceAuth = (0, import_node_path11.join)(sourceHome, "auth.json");
33510
33697
  let info;
33511
33698
  try {
33512
33699
  info = await (0, import_promises5.lstat)(sourceAuth);
@@ -33556,7 +33743,7 @@ var GrokListenerModel = class {
33556
33743
  // src/listener/opencode-model.ts
33557
33744
  var import_node_crypto14 = require("node:crypto");
33558
33745
  var import_promises6 = require("node:fs/promises");
33559
- var import_node_path11 = require("node:path");
33746
+ var import_node_path12 = require("node:path");
33560
33747
  function asError(error) {
33561
33748
  return error instanceof Error ? error : new Error(String(error));
33562
33749
  }
@@ -33567,7 +33754,7 @@ var OpenCodeListenerModel = class {
33567
33754
  this.openSession = options.open ?? openOpenCodeAcpSession;
33568
33755
  this.prepareHome = options.prepareHome ?? prepareOpenCodeIsolatedHome;
33569
33756
  this.prepareWorkerCwd = options.prepareWorkerCwd ?? (async (home) => {
33570
- const cwd = await (0, import_promises6.mkdtemp)((0, import_node_path11.join)(home, "canary-cwd-"));
33757
+ const cwd = await (0, import_promises6.mkdtemp)((0, import_node_path12.join)(home, "canary-cwd-"));
33571
33758
  await (0, import_promises6.chmod)(cwd, 448);
33572
33759
  return cwd;
33573
33760
  });
@@ -33989,8 +34176,8 @@ var OpenCodeListenerModel = class {
33989
34176
  // src/listener/claude-model.ts
33990
34177
  var import_node_crypto15 = require("node:crypto");
33991
34178
  var import_promises7 = require("node:fs/promises");
33992
- var import_node_os7 = require("node:os");
33993
- var import_node_path12 = require("node:path");
34179
+ var import_node_os8 = require("node:os");
34180
+ var import_node_path13 = require("node:path");
33994
34181
  var ClaudeListenerClosedDuringOpen = class extends Error {
33995
34182
  constructor() {
33996
34183
  super("listener model closed while the Claude worker was opening");
@@ -34128,8 +34315,8 @@ var ClaudeListenerModel = class {
34128
34315
  }
34129
34316
  /** Force Claude's measured Write permission path without changing worker cwd. */
34130
34317
  async enablePromptsAfterClaudeCanary(handle) {
34131
- const sentinelPath = (0, import_node_path12.join)(
34132
- (0, import_node_os7.tmpdir)(),
34318
+ const sentinelPath = (0, import_node_path13.join)(
34319
+ (0, import_node_os8.tmpdir)(),
34133
34320
  `cswarm-claude-permission-canary-${process.pid}-${(0, import_node_crypto15.randomUUID)()}`
34134
34321
  );
34135
34322
  let sentinelCreated = false;
@@ -34158,8 +34345,8 @@ var ClaudeListenerModel = class {
34158
34345
  // src/listener/codex-model.ts
34159
34346
  var import_node_crypto16 = require("node:crypto");
34160
34347
  var import_promises8 = require("node:fs/promises");
34161
- var import_node_os8 = require("node:os");
34162
- var import_node_path13 = require("node:path");
34348
+ var import_node_os9 = require("node:os");
34349
+ var import_node_path14 = require("node:path");
34163
34350
  var CodexListenerClosedDuringOpen = class extends Error {
34164
34351
  constructor() {
34165
34352
  super("listener model closed while the Codex worker was opening");
@@ -34297,8 +34484,8 @@ var CodexListenerModel = class {
34297
34484
  }
34298
34485
  /** Force Codex's measured shell permission path without changing worker cwd. */
34299
34486
  async enablePromptsAfterCodexCanary(handle) {
34300
- const sentinelPath = (0, import_node_path13.join)(
34301
- (0, import_node_os8.tmpdir)(),
34487
+ const sentinelPath = (0, import_node_path14.join)(
34488
+ (0, import_node_os9.tmpdir)(),
34302
34489
  `cswarm-codex-permission-canary-${process.pid}-${(0, import_node_crypto16.randomUUID)()}`
34303
34490
  );
34304
34491
  let sentinelCreated = false;
@@ -34328,7 +34515,7 @@ var CodexListenerModel = class {
34328
34515
  var import_node_crypto17 = require("node:crypto");
34329
34516
 
34330
34517
  // src/cloud/delivery.ts
34331
- var UUID_RE11 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
34518
+ var UUID_RE12 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
34332
34519
  var RFC3339_TIMESTAMP_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))$/i;
34333
34520
  var DELIVERY_KINDS = /* @__PURE__ */ new Set(["ask", "note"]);
34334
34521
  var SENDER_OWNER_RELATIONS2 = /* @__PURE__ */ new Set([
@@ -34415,7 +34602,7 @@ var DeliveryProtocolError = class extends Error {
34415
34602
  }
34416
34603
  };
34417
34604
  function checkedUuid3(value, field) {
34418
- if (typeof value !== "string" || !UUID_RE11.test(value)) {
34605
+ if (typeof value !== "string" || !UUID_RE12.test(value)) {
34419
34606
  throw new DeliveryProtocolError(
34420
34607
  `delivery response returned a malformed ${field}`
34421
34608
  );
@@ -34526,7 +34713,7 @@ function checkedClaimCapabilities(value) {
34526
34713
  }
34527
34714
  function checkedOptionalUuidArray(value, field) {
34528
34715
  if (value === void 0) return;
34529
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE11.test(item))) {
34716
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE12.test(item))) {
34530
34717
  throw new DeliveryProtocolError(
34531
34718
  `delivery response returned a malformed ${field}`
34532
34719
  );
@@ -34673,7 +34860,7 @@ function checkedCommandId(value) {
34673
34860
  return value;
34674
34861
  }
34675
34862
  function checkedUuidRequest(value, field) {
34676
- if (!UUID_RE11.test(value)) {
34863
+ if (!UUID_RE12.test(value)) {
34677
34864
  throw new Error(`${field} must be a UUID for an agent delivery command`);
34678
34865
  }
34679
34866
  }
@@ -34909,8 +35096,8 @@ var DeliveryCommandClient = class {
34909
35096
  };
34910
35097
 
34911
35098
  // src/listener/main-routing.ts
34912
- var import_node_path14 = require("node:path");
34913
- var UUID_RE12 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
35099
+ var import_node_path15 = require("node:path");
35100
+ var UUID_RE13 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
34914
35101
  var MAX_QUEUE_BYTES = 1024 * 1024;
34915
35102
  var QUEUE_FILE = "pending-for-main.json";
34916
35103
  var QUEUE_LOCK = "pending-for-main";
@@ -34965,7 +35152,7 @@ function parseEntry(value) {
34965
35152
  if (Object.keys(row).some((key2) => !allowed.has(key2))) {
34966
35153
  throw new Error("stored pending-for-main entry is malformed");
34967
35154
  }
34968
- if (typeof row.signalId !== "string" || !UUID_RE12.test(row.signalId) || typeof row.workspaceId !== "string" || !UUID_RE12.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE12.test(row.principalId) || typeof row.fromId !== "string" || !UUID_RE12.test(row.fromId) || row.fromKind !== "user" && row.fromKind !== "agent" || !(row.kind === void 0 || row.kind === "ask" || row.kind === "note") || !(row.senderName === null || typeof row.senderName === "string" && row.senderName.length <= 200) || typeof row.body !== "string" || row.body.length < 1 || !checkedTimestamp2(row.createdAt) || !checkedTimestamp2(row.queuedAt) || !(row.observationPending === void 0 || row.observationPending === true)) {
35155
+ if (typeof row.signalId !== "string" || !UUID_RE13.test(row.signalId) || typeof row.workspaceId !== "string" || !UUID_RE13.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE13.test(row.principalId) || typeof row.fromId !== "string" || !UUID_RE13.test(row.fromId) || row.fromKind !== "user" && row.fromKind !== "agent" || !(row.kind === void 0 || row.kind === "ask" || row.kind === "note") || !(row.senderName === null || typeof row.senderName === "string" && row.senderName.length <= 200) || typeof row.body !== "string" || row.body.length < 1 || !checkedTimestamp2(row.createdAt) || !checkedTimestamp2(row.queuedAt) || !(row.observationPending === void 0 || row.observationPending === true)) {
34969
35156
  throw new Error("stored pending-for-main entry is malformed");
34970
35157
  }
34971
35158
  return {
@@ -35008,11 +35195,11 @@ var FilePendingMainQueue = class {
35008
35195
  path;
35009
35196
  directory;
35010
35197
  constructor(instanceDirectory) {
35011
- if (!(0, import_node_path14.isAbsolute)(instanceDirectory)) {
35198
+ if (!(0, import_node_path15.isAbsolute)(instanceDirectory)) {
35012
35199
  throw new Error("pending-for-main directory must be absolute");
35013
35200
  }
35014
35201
  this.directory = instanceDirectory;
35015
- this.path = (0, import_node_path14.join)(instanceDirectory, QUEUE_FILE);
35202
+ this.path = (0, import_node_path15.join)(instanceDirectory, QUEUE_FILE);
35016
35203
  }
35017
35204
  async readUnlocked() {
35018
35205
  const raw = await readSecureJsonFile(this.path, MAX_QUEUE_BYTES);
@@ -35076,8 +35263,8 @@ var FilePendingMainQueue = class {
35076
35263
  }
35077
35264
  };
35078
35265
  function pendingMainEntry(signal, principalId, provenance, now, options = {}) {
35079
- if (signal.kind !== "ask") {
35080
- throw new Error("only directed asks can enter the pending-for-main queue");
35266
+ if (signal.kind !== "ask" && signal.kind !== "note") {
35267
+ throw new Error("only directed asks and notes can enter the pending-for-main queue");
35081
35268
  }
35082
35269
  return parseEntry({
35083
35270
  signalId: signal.id,
@@ -35085,6 +35272,7 @@ function pendingMainEntry(signal, principalId, provenance, now, options = {}) {
35085
35272
  principalId,
35086
35273
  fromId: signal.from,
35087
35274
  fromKind: signal.from_kind,
35275
+ kind: signal.kind,
35088
35276
  senderName: provenance.senderName,
35089
35277
  body: signal.body,
35090
35278
  createdAt: signal.created_at,
@@ -35103,7 +35291,7 @@ var LISTENER_REPLY_ONLY_MINIMUM_MS = SIGNAL_REQUEST_TIMEOUT_MS + LISTENER_ACK_ON
35103
35291
  var LISTENER_PROMPT_START_MINIMUM_MS = SIGNAL_READ_TIMEOUT_MS + ACP_DEFAULT_REQUEST_TIMEOUT_MS + LISTENER_REPLY_ONLY_MINIMUM_MS;
35104
35292
  var LISTENER_DELIVERY_RETRY_INITIAL_MS = 500;
35105
35293
  var LISTENER_DELIVERY_RETRY_MAX_MS = 3e4;
35106
- var UUID_RE13 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
35294
+ var UUID_RE14 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
35107
35295
  var ListenerCapabilityError = class extends Error {
35108
35296
  code;
35109
35297
  constructor(code, message) {
@@ -35182,7 +35370,7 @@ function ackForTerminalEffect(record, now) {
35182
35370
  if (record.state === "observed" && record.signalKind === "note") {
35183
35371
  return { outcome: "observed", lastErrorCode: null };
35184
35372
  }
35185
- if (record.state === "routed_main" && record.signalKind === "ask") {
35373
+ if (record.state === "routed_main") {
35186
35374
  return { outcome: "queued", lastErrorCode: null };
35187
35375
  }
35188
35376
  if (record.state === "expired" && record.signalKind === "ask" && Date.parse(record.askUntil) <= now()) {
@@ -35204,7 +35392,7 @@ function ackForTerminalEffect(record, now) {
35204
35392
  return { outcome: "failed_terminal", lastErrorCode: "local_effect_failed" };
35205
35393
  }
35206
35394
  function isAckableTerminalEffect(record, now) {
35207
- return record.state === "done" && record.signalKind === "ask" && !!record.replySignalId || record.state === "observed" && record.signalKind === "note" || record.state === "routed_main" && record.signalKind === "ask" || record.state === "expired" && record.signalKind === "ask" && Date.parse(record.askUntil) <= now() || record.state === "failed" && record.signalKind === "ask";
35395
+ return record.state === "done" && record.signalKind === "ask" && !!record.replySignalId || record.state === "observed" && record.signalKind === "note" || record.state === "routed_main" || record.state === "expired" && record.signalKind === "ask" && Date.parse(record.askUntil) <= now() || record.state === "failed" && record.signalKind === "ask";
35208
35396
  }
35209
35397
  function effectPhaseBudget(record) {
35210
35398
  if (record === null || record.state === "received" || record.state === "prompting") {
@@ -35215,6 +35403,9 @@ function effectPhaseBudget(record) {
35215
35403
  }
35216
35404
  return LISTENER_ACK_ONLY_MINIMUM_MS;
35217
35405
  }
35406
+ function observedNoteNeedsMainRoute(record, routeMode, deferOverChars) {
35407
+ return record?.state === "observed" && record.signalKind === "note" && decideListenerRoute(routeMode, deferOverChars, record.askBody.length) === "main";
35408
+ }
35218
35409
  function verifyPreparedAckEffect(record, active, now) {
35219
35410
  if (record === null || record.signalId !== active.signalId || active.ack === null) {
35220
35411
  throw new Error("prepared delivery ACK has no matching terminal effect");
@@ -35378,7 +35569,7 @@ async function runListenerRuntime(options) {
35378
35569
  new Error("listener instance id and delivery journal must be configured together")
35379
35570
  );
35380
35571
  }
35381
- if (hasInstanceId && !UUID_RE13.test(options.listenerInstanceId)) {
35572
+ if (hasInstanceId && !UUID_RE14.test(options.listenerInstanceId)) {
35382
35573
  return await closeBeforeStart(
35383
35574
  options.model,
35384
35575
  new Error("listener instance id must be a UUID")
@@ -35450,7 +35641,11 @@ async function runListenerRuntime(options) {
35450
35641
  ...options.resolveSenderProvenance === void 0 ? {} : { resolveSenderProvenance: options.resolveSenderProvenance },
35451
35642
  isCredentialFailure: isCredentialLoss
35452
35643
  });
35453
- const routeAskToMain = async (signal) => {
35644
+ const routeSignalToMain = async (signal) => {
35645
+ if (signal.kind !== "ask" && signal.kind !== "note") {
35646
+ throw new Error("only directed asks and notes can route to the main session");
35647
+ }
35648
+ const signalKind2 = signal.kind;
35454
35649
  let provenance = {
35455
35650
  senderName: null,
35456
35651
  operatorId: null,
@@ -35480,13 +35675,19 @@ async function runListenerRuntime(options) {
35480
35675
  });
35481
35676
  const existing = await options.store.read(signal.id);
35482
35677
  if (existing !== null) {
35483
- if (!sameEffectSignal(existing, signal) || existing.state !== "routed_main") {
35484
- throw new Error("stored listener effect does not match the main-routed ask");
35678
+ if (!sameEffectSignal(existing, signal)) {
35679
+ throw new Error("stored listener effect does not match the main-routed message");
35680
+ }
35681
+ if (existing.state === "routed_main") {
35682
+ return existing;
35683
+ }
35684
+ if (!(existing.signalKind === "note" && existing.state === "observed")) {
35685
+ throw new Error("stored listener effect does not match the main-routed message");
35485
35686
  }
35486
- return existing;
35487
35687
  }
35488
- await options.store.write(newRoutedMainAskRecord({
35688
+ await options.store.write(newRoutedMainRecord({
35489
35689
  signalId: signal.id,
35690
+ signalKind: signalKind2,
35490
35691
  body: signal.body,
35491
35692
  until: signal.until,
35492
35693
  senderOwnerRelation: signal.sender_owner_relation ?? "unknown",
@@ -35494,7 +35695,7 @@ async function runListenerRuntime(options) {
35494
35695
  }));
35495
35696
  const persisted = await options.store.read(signal.id);
35496
35697
  if (persisted === null || !sameEffectSignal(persisted, signal) || persisted.state !== "routed_main") {
35497
- throw new Error("main-routed listener effect could not be verified");
35698
+ throw new Error("main-routed message effect could not be verified");
35498
35699
  }
35499
35700
  return persisted;
35500
35701
  };
@@ -35716,7 +35917,20 @@ async function runListenerRuntime(options) {
35716
35917
  const recovery = currentJournalRecord?.active ?? null;
35717
35918
  if (recovery?.phase === "ack_pending") {
35718
35919
  const horizon = Date.parse(recovery.leasedUntil) + LISTENER_DELIVERY_SAFETY_MARGIN_MS;
35719
- if (page.capabilities.deliveryAck && now() < horizon) {
35920
+ let preparedNeedsMainRoute = false;
35921
+ if (recovery.signalId !== null) {
35922
+ try {
35923
+ preparedNeedsMainRoute = observedNoteNeedsMainRoute(
35924
+ await options.store.read(recovery.signalId),
35925
+ routeMode,
35926
+ deferOverChars
35927
+ );
35928
+ } catch (error) {
35929
+ stop = { reason: "fatal", error: asError2(error) };
35930
+ break;
35931
+ }
35932
+ }
35933
+ if (page.capabilities.deliveryAck && now() < horizon && !preparedNeedsMainRoute) {
35720
35934
  const ackStop = await sendPreparedAck(recovery);
35721
35935
  if (ackStop !== null) {
35722
35936
  stop = ackStop;
@@ -35755,7 +35969,7 @@ async function runListenerRuntime(options) {
35755
35969
  terminal = null;
35756
35970
  }
35757
35971
  }
35758
- if (terminal !== null && sameRecoveredEffect(recovery, terminal) && isAckableTerminalEffect(terminal, now)) {
35972
+ if (terminal !== null && sameRecoveredEffect(recovery, terminal) && !observedNoteNeedsMainRoute(terminal, routeMode, deferOverChars) && isAckableTerminalEffect(terminal, now)) {
35759
35973
  try {
35760
35974
  const mapped = ackForTerminalEffect(terminal, now);
35761
35975
  await options.deliveryJournal.prepareAck({
@@ -35949,7 +36163,33 @@ async function runListenerRuntime(options) {
35949
36163
  if (existing !== null && !sameEffectSignal(existing, signal)) {
35950
36164
  throw new Error("stored listener effect does not match the authoritative delivery");
35951
36165
  }
35952
- if (signal.kind === "note") {
36166
+ if (signal.kind !== "ask" && signal.kind !== "note") {
36167
+ throw new Error("claimed delivery has an unsupported signal kind");
36168
+ }
36169
+ const decision = decideListenerRoute(
36170
+ routeMode,
36171
+ deferOverChars,
36172
+ signal.body.length
36173
+ );
36174
+ options.onEvent?.({
36175
+ type: "routing_decision",
36176
+ signalId: signal.id,
36177
+ routeMode,
36178
+ decision,
36179
+ threshold: deferOverChars,
36180
+ bodyLength: signal.body.length,
36181
+ ts: eventTime(now)
36182
+ });
36183
+ if (decision === "main") {
36184
+ terminal = await routeSignalToMain(signal);
36185
+ options.onEvent?.({
36186
+ type: "effect",
36187
+ signalId: signal.id,
36188
+ status: "routed_main",
36189
+ failureCode: null,
36190
+ ts: eventTime(now)
36191
+ });
36192
+ } else if (signal.kind === "note") {
35953
36193
  if (existing === null) {
35954
36194
  await options.store.write(newObservedNoteRecord({
35955
36195
  signalId: signal.id,
@@ -35970,85 +36210,58 @@ async function runListenerRuntime(options) {
35970
36210
  failureCode: null,
35971
36211
  ts: eventTime(now)
35972
36212
  });
35973
- } else if (signal.kind === "ask") {
35974
- const decision = decideListenerRoute(
35975
- routeMode,
35976
- deferOverChars,
35977
- signal.body.length
35978
- );
35979
- options.onEvent?.({
35980
- type: "routing_decision",
35981
- signalId: signal.id,
35982
- routeMode,
35983
- decision,
35984
- threshold: deferOverChars,
35985
- bodyLength: signal.body.length,
35986
- ts: eventTime(now)
35987
- });
35988
- if (decision === "main") {
35989
- terminal = await routeAskToMain(signal);
36213
+ } else {
36214
+ let processAttempt = 0;
36215
+ while (terminal === null) {
36216
+ const before = await options.store.read(signal.id);
36217
+ if (before !== null && !sameEffectSignal(before, signal)) {
36218
+ throw new Error("stored listener effect does not match the authoritative delivery");
36219
+ }
36220
+ const requiredBudget = effectPhaseBudget(before);
36221
+ if (leasedUntilMs <= now() + requiredBudget) {
36222
+ await sleep2(
36223
+ Math.max(
36224
+ 0,
36225
+ leasedUntilMs + LISTENER_DELIVERY_SAFETY_MARGIN_MS - now()
36226
+ ),
36227
+ abort
36228
+ );
36229
+ if (abort?.aborted) {
36230
+ stop = { reason: "cancelled" };
36231
+ break;
36232
+ }
36233
+ if (now() >= leasedUntilMs + LISTENER_DELIVERY_SAFETY_MARGIN_MS) {
36234
+ await journal.clearActive(eventTime(now));
36235
+ after = null;
36236
+ }
36237
+ break;
36238
+ }
36239
+ const processed = await engine.process(signal);
36240
+ const effect = "record" in processed ? processed.record : null;
35990
36241
  options.onEvent?.({
35991
36242
  type: "effect",
35992
36243
  signalId: signal.id,
35993
- status: "routed_main",
35994
- failureCode: null,
36244
+ status: processed.status,
36245
+ failureCode: effect?.failureCode ?? null,
35995
36246
  ts: eventTime(now)
35996
36247
  });
35997
- } else {
35998
- let processAttempt = 0;
35999
- while (terminal === null) {
36000
- const before = await options.store.read(signal.id);
36001
- if (before !== null && !sameEffectSignal(before, signal)) {
36002
- throw new Error("stored listener effect does not match the authoritative delivery");
36003
- }
36004
- const requiredBudget = effectPhaseBudget(before);
36005
- if (leasedUntilMs <= now() + requiredBudget) {
36006
- await sleep2(
36007
- Math.max(
36008
- 0,
36009
- leasedUntilMs + LISTENER_DELIVERY_SAFETY_MARGIN_MS - now()
36010
- ),
36011
- abort
36012
- );
36013
- if (abort?.aborted) {
36014
- stop = { reason: "cancelled" };
36015
- break;
36016
- }
36017
- if (now() >= leasedUntilMs + LISTENER_DELIVERY_SAFETY_MARGIN_MS) {
36018
- await journal.clearActive(eventTime(now));
36019
- after = null;
36020
- }
36248
+ if (processed.status === "ignored") {
36249
+ throw new Error("claimed delivery was ignored by the listener engine");
36250
+ }
36251
+ if (processed.status === "retry_pending") {
36252
+ processAttempt += 1;
36253
+ await sleep2(
36254
+ deliveryRetryDelay(processAttempt, null, random),
36255
+ abort
36256
+ );
36257
+ if (abort?.aborted) {
36258
+ stop = { reason: "cancelled" };
36021
36259
  break;
36022
36260
  }
36023
- const processed = await engine.process(signal);
36024
- const effect = "record" in processed ? processed.record : null;
36025
- options.onEvent?.({
36026
- type: "effect",
36027
- signalId: signal.id,
36028
- status: processed.status,
36029
- failureCode: effect?.failureCode ?? null,
36030
- ts: eventTime(now)
36031
- });
36032
- if (processed.status === "ignored") {
36033
- throw new Error("claimed delivery was ignored by the listener engine");
36034
- }
36035
- if (processed.status === "retry_pending") {
36036
- processAttempt += 1;
36037
- await sleep2(
36038
- deliveryRetryDelay(processAttempt, null, random),
36039
- abort
36040
- );
36041
- if (abort?.aborted) {
36042
- stop = { reason: "cancelled" };
36043
- break;
36044
- }
36045
- continue;
36046
- }
36047
- terminal = processed.record;
36261
+ continue;
36048
36262
  }
36263
+ terminal = processed.record;
36049
36264
  }
36050
- } else {
36051
- throw new Error("claimed delivery has an unsupported signal kind");
36052
36265
  }
36053
36266
  } catch (error) {
36054
36267
  if (abort?.aborted) {
@@ -36097,24 +36310,7 @@ async function runListenerRuntime(options) {
36097
36310
  stop = { reason: "cancelled" };
36098
36311
  break;
36099
36312
  }
36100
- if (signal.kind === "note") {
36101
- try {
36102
- await readOrReplaceUnreadableEffect(options.store, signal, now);
36103
- const record2 = await observeFallbackNote(options.store, signal, now);
36104
- options.onEvent?.({
36105
- type: "effect",
36106
- signalId: signal.id,
36107
- status: "observed",
36108
- failureCode: record2.failureCode,
36109
- ts: eventTime(now)
36110
- });
36111
- } catch (error) {
36112
- stop = { reason: "fatal", error: asError2(error) };
36113
- break;
36114
- }
36115
- continue;
36116
- }
36117
- if (signal.kind !== "ask") continue;
36313
+ if (signal.kind !== "ask" && signal.kind !== "note") continue;
36118
36314
  let result;
36119
36315
  try {
36120
36316
  await readOrReplaceUnreadableEffect(options.store, signal, now);
@@ -36133,7 +36329,7 @@ async function runListenerRuntime(options) {
36133
36329
  ts: eventTime(now)
36134
36330
  });
36135
36331
  if (decision === "main") {
36136
- const record2 = await routeAskToMain(signal);
36332
+ await routeSignalToMain(signal);
36137
36333
  options.onEvent?.({
36138
36334
  type: "effect",
36139
36335
  signalId: signal.id,
@@ -36143,6 +36339,17 @@ async function runListenerRuntime(options) {
36143
36339
  });
36144
36340
  continue;
36145
36341
  }
36342
+ if (signal.kind === "note") {
36343
+ const record2 = await observeFallbackNote(options.store, signal, now);
36344
+ options.onEvent?.({
36345
+ type: "effect",
36346
+ signalId: signal.id,
36347
+ status: "observed",
36348
+ failureCode: record2.failureCode,
36349
+ ts: eventTime(now)
36350
+ });
36351
+ continue;
36352
+ }
36146
36353
  result = await engine.process(signal);
36147
36354
  } catch (error) {
36148
36355
  if (abort?.aborted) {
@@ -36202,8 +36409,8 @@ async function runListenerRuntime(options) {
36202
36409
  // src/listener/control.ts
36203
36410
  var import_node_net = require("node:net");
36204
36411
  var import_promises9 = require("node:fs/promises");
36205
- var import_node_path15 = require("node:path");
36206
- var UUID_RE14 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
36412
+ var import_node_path16 = require("node:path");
36413
+ var UUID_RE15 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
36207
36414
  var SEMVER_RE2 = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
36208
36415
  var MAX_STATUS_BYTES = 16 * 1024;
36209
36416
  var MAX_CONTROL_BYTES = 8 * 1024;
@@ -36218,19 +36425,19 @@ var ListenerAlreadyRunningError = class extends Error {
36218
36425
  };
36219
36426
  function listenerPaths(options) {
36220
36427
  const root = options.stateDirectory ?? defaultListenerStateDirectory();
36221
- if (!(0, import_node_path15.isAbsolute)(root)) {
36428
+ if (!(0, import_node_path16.isAbsolute)(root)) {
36222
36429
  throw new Error("listener state directory must be absolute");
36223
36430
  }
36224
36431
  const key2 = listenerInstanceKey(options);
36225
- const instanceDirectory = (0, import_node_path15.join)(root, key2);
36432
+ const instanceDirectory = (0, import_node_path16.join)(root, key2);
36226
36433
  const uid2 = typeof process.getuid === "function" ? process.getuid() : process.pid;
36227
- const controlDirectory = process.platform === "win32" ? "" : (0, import_node_path15.join)("/tmp", `cswarm-control-${uid2}`);
36228
- const socketPath = process.platform === "win32" ? `\\\\.\\pipe\\cswarm-${key2}` : (0, import_node_path15.join)(controlDirectory, `${key2.slice(0, 32)}.sock`);
36434
+ const controlDirectory = process.platform === "win32" ? "" : (0, import_node_path16.join)("/tmp", `cswarm-control-${uid2}`);
36435
+ const socketPath = process.platform === "win32" ? `\\\\.\\pipe\\cswarm-${key2}` : (0, import_node_path16.join)(controlDirectory, `${key2.slice(0, 32)}.sock`);
36229
36436
  return {
36230
36437
  key: key2,
36231
36438
  instanceDirectory,
36232
- statusPath: (0, import_node_path15.join)(instanceDirectory, "status.json"),
36233
- logPath: (0, import_node_path15.join)(instanceDirectory, "events.ndjson"),
36439
+ statusPath: (0, import_node_path16.join)(instanceDirectory, "status.json"),
36440
+ logPath: (0, import_node_path16.join)(instanceDirectory, "events.ndjson"),
36234
36441
  socketPath
36235
36442
  };
36236
36443
  }
@@ -36309,10 +36516,10 @@ function parseStatus(raw) {
36309
36516
  throw new Error("stored listener status is malformed");
36310
36517
  }
36311
36518
  }
36312
- const nullableUuid2 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE14.test(candidate);
36519
+ const nullableUuid2 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE15.test(candidate);
36313
36520
  const nullableCount = (candidate) => candidate === null || typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate >= 0;
36314
36521
  const nullableTimestamp2 = (candidate) => candidate === null || typeof candidate === "string" && Number.isFinite(Date.parse(candidate));
36315
- if (row.version !== 1 || typeof row.instanceId !== "string" || !UUID_RE14.test(row.instanceId) || row.provider !== "grok" && row.provider !== "opencode" && row.provider !== "claude" && row.provider !== "codex" || typeof row.profileId !== "string" || typeof row.workspaceId !== "string" || !UUID_RE14.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE14.test(row.principalId) || !Number.isSafeInteger(row.pid) || row.pid < 1 || typeof row.state !== "string" || !["starting", "ready", "stopping", "stopped", "failed"].includes(row.state) || typeof row.startedAt !== "string" || !Number.isFinite(Date.parse(row.startedAt)) || !(row.readyAt === null || typeof row.readyAt === "string" && Number.isFinite(Date.parse(row.readyAt))) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt)) || !(row.stoppedAt === null || typeof row.stoppedAt === "string" && Number.isFinite(Date.parse(row.stoppedAt))) || !nullableUuid2(row.lastSignalId) || !(row.lastErrorCode === null || typeof row.lastErrorCode === "string" && /^[a-z0-9_-]{1,96}$/.test(row.lastErrorCode)) || !(row.providerVersion === void 0 || row.providerVersion === null || typeof row.providerVersion === "string" && SEMVER_RE2.test(row.providerVersion)) || !(row.providerLastMeasuredVersion === void 0 || row.providerLastMeasuredVersion === null || typeof row.providerLastMeasuredVersion === "string" && SEMVER_RE2.test(row.providerLastMeasuredVersion)) || (row.providerVersion === null || row.providerVersion === void 0) !== (row.providerLastMeasuredVersion === null || row.providerLastMeasuredVersion === void 0) || !(row.lastWorkerStderrTail === void 0 || row.lastWorkerStderrTail === null || typeof row.lastWorkerStderrTail === "string" && row.lastWorkerStderrTail.length > 0 && row.lastWorkerStderrTail.length <= 2048 && !/swm_(?:agt|inv|cap)_/i.test(row.lastWorkerStderrTail)) || typeof row.logPath !== "string" || !(0, import_node_path15.isAbsolute)(row.logPath) || !(row.deliveryMode === void 0 || row.deliveryMode === null || typeof row.deliveryMode === "string" && STATUS_DELIVERY_MODES.has(row.deliveryMode)) || !(row.pendingDeliveryCount === void 0 || nullableCount(row.pendingDeliveryCount)) || !(row.lastTerminalDeliveryFailureCount === void 0 || nullableCount(row.lastTerminalDeliveryFailureCount)) || !(row.lastTerminalDeliveryFailureAt === void 0 || nullableTimestamp2(row.lastTerminalDeliveryFailureAt)) || !(row.lastClaimAt === void 0 || nullableTimestamp2(row.lastClaimAt)) || !(row.lastAckAt === void 0 || nullableTimestamp2(row.lastAckAt)) || !(row.routeMode === void 0 || row.routeMode === "worker" || row.routeMode === "main" || row.routeMode === "split") || !(row.deferOverChars === void 0 || row.deferOverChars === null || typeof row.deferOverChars === "number" && Number.isSafeInteger(row.deferOverChars) && row.deferOverChars >= 1 && row.deferOverChars <= 1e4) || !(row.pendingForMainCount === void 0 || typeof row.pendingForMainCount === "number" && Number.isSafeInteger(row.pendingForMainCount) && row.pendingForMainCount >= 0) || !(row.droppedForMainCount === void 0 || typeof row.droppedForMainCount === "number" && Number.isSafeInteger(row.droppedForMainCount) && row.droppedForMainCount >= 0)) {
36522
+ if (row.version !== 1 || typeof row.instanceId !== "string" || !UUID_RE15.test(row.instanceId) || row.provider !== "grok" && row.provider !== "opencode" && row.provider !== "claude" && row.provider !== "codex" || typeof row.profileId !== "string" || typeof row.workspaceId !== "string" || !UUID_RE15.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE15.test(row.principalId) || !Number.isSafeInteger(row.pid) || row.pid < 1 || typeof row.state !== "string" || !["starting", "ready", "stopping", "stopped", "failed"].includes(row.state) || typeof row.startedAt !== "string" || !Number.isFinite(Date.parse(row.startedAt)) || !(row.readyAt === null || typeof row.readyAt === "string" && Number.isFinite(Date.parse(row.readyAt))) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt)) || !(row.stoppedAt === null || typeof row.stoppedAt === "string" && Number.isFinite(Date.parse(row.stoppedAt))) || !nullableUuid2(row.lastSignalId) || !(row.lastErrorCode === null || typeof row.lastErrorCode === "string" && /^[a-z0-9_-]{1,96}$/.test(row.lastErrorCode)) || !(row.providerVersion === void 0 || row.providerVersion === null || typeof row.providerVersion === "string" && SEMVER_RE2.test(row.providerVersion)) || !(row.providerLastMeasuredVersion === void 0 || row.providerLastMeasuredVersion === null || typeof row.providerLastMeasuredVersion === "string" && SEMVER_RE2.test(row.providerLastMeasuredVersion)) || (row.providerVersion === null || row.providerVersion === void 0) !== (row.providerLastMeasuredVersion === null || row.providerLastMeasuredVersion === void 0) || !(row.lastWorkerStderrTail === void 0 || row.lastWorkerStderrTail === null || typeof row.lastWorkerStderrTail === "string" && row.lastWorkerStderrTail.length > 0 && row.lastWorkerStderrTail.length <= 2048 && !/swm_(?:agt|inv|cap)_/i.test(row.lastWorkerStderrTail)) || typeof row.logPath !== "string" || !(0, import_node_path16.isAbsolute)(row.logPath) || !(row.deliveryMode === void 0 || row.deliveryMode === null || typeof row.deliveryMode === "string" && STATUS_DELIVERY_MODES.has(row.deliveryMode)) || !(row.pendingDeliveryCount === void 0 || nullableCount(row.pendingDeliveryCount)) || !(row.lastTerminalDeliveryFailureCount === void 0 || nullableCount(row.lastTerminalDeliveryFailureCount)) || !(row.lastTerminalDeliveryFailureAt === void 0 || nullableTimestamp2(row.lastTerminalDeliveryFailureAt)) || !(row.lastClaimAt === void 0 || nullableTimestamp2(row.lastClaimAt)) || !(row.lastAckAt === void 0 || nullableTimestamp2(row.lastAckAt)) || !(row.routeMode === void 0 || row.routeMode === "worker" || row.routeMode === "main" || row.routeMode === "split") || !(row.deferOverChars === void 0 || row.deferOverChars === null || typeof row.deferOverChars === "number" && Number.isSafeInteger(row.deferOverChars) && row.deferOverChars >= 1 && row.deferOverChars <= 1e4) || !(row.pendingForMainCount === void 0 || typeof row.pendingForMainCount === "number" && Number.isSafeInteger(row.pendingForMainCount) && row.pendingForMainCount >= 0) || !(row.droppedForMainCount === void 0 || typeof row.droppedForMainCount === "number" && Number.isSafeInteger(row.droppedForMainCount) && row.droppedForMainCount >= 0)) {
36316
36523
  throw new Error("stored listener status is malformed");
36317
36524
  }
36318
36525
  const routeMode = row.routeMode ?? "worker";
@@ -36486,7 +36693,7 @@ function writeResponse(socket, response) {
36486
36693
  }
36487
36694
  async function startupLock(paths) {
36488
36695
  await ensureSecureStateDirectory(paths.instanceDirectory);
36489
- const lockPath = (0, import_node_path15.join)(paths.instanceDirectory, "starting.lock");
36696
+ const lockPath = (0, import_node_path16.join)(paths.instanceDirectory, "starting.lock");
36490
36697
  const deadline = Date.now() + START_LOCK_WAIT_MS;
36491
36698
  while (Date.now() < deadline) {
36492
36699
  let handle;
@@ -36527,7 +36734,7 @@ async function startupLock(paths) {
36527
36734
  async function prepareSocket(paths) {
36528
36735
  if (process.platform !== "win32") {
36529
36736
  const uid2 = typeof process.getuid === "function" ? process.getuid() : process.pid;
36530
- const directory = (0, import_node_path15.join)("/tmp", `cswarm-control-${uid2}`);
36737
+ const directory = (0, import_node_path16.join)("/tmp", `cswarm-control-${uid2}`);
36531
36738
  await ensureSecureStateDirectory(directory);
36532
36739
  }
36533
36740
  try {
@@ -36662,7 +36869,7 @@ async function queryListenerControl(paths, command2, timeoutMs = CONTROL_TIMEOUT
36662
36869
 
36663
36870
  // src/listener/supervisor.ts
36664
36871
  var import_node_crypto18 = require("node:crypto");
36665
- var UUID_RE15 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
36872
+ var UUID_RE16 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
36666
36873
  var LISTENER_RESTART_MAX_ATTEMPTS = 5;
36667
36874
  var LISTENER_RESTART_INITIAL_MS = 1e3;
36668
36875
  var LISTENER_RESTART_MAX_MS = 6e4;
@@ -36791,7 +36998,7 @@ async function runListenerSupervisor(options) {
36791
36998
  // before the socket can answer, before any status/event persistence.
36792
36999
  initialize: prepare ? async () => {
36793
37000
  const selected = await prepare(proposedInstanceId);
36794
- if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE15.test(selected.instanceId)) {
37001
+ if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE16.test(selected.instanceId)) {
36795
37002
  throw new Error("listener prepare returned an invalid instance id");
36796
37003
  }
36797
37004
  status = { ...status, instanceId: selected.instanceId };
@@ -37147,9 +37354,9 @@ async function waitForListenerReady(paths, options = {}) {
37147
37354
  }
37148
37355
 
37149
37356
  // src/listener/delivery-journal.ts
37150
- var import_node_path16 = require("node:path");
37357
+ var import_node_path17 = require("node:path");
37151
37358
  var import_node_util2 = require("node:util");
37152
- var UUID_RE16 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
37359
+ var UUID_RE17 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
37153
37360
  var COMMAND_ID_RE3 = /^[A-Za-z0-9_-]{8,72}$/;
37154
37361
  var SIGNAL_FINGERPRINT_RE = /^[0-9a-f]{64}$/;
37155
37362
  var MAX_JOURNAL_BYTES = 8192;
@@ -37244,7 +37451,7 @@ var ALLOWED_ERROR_CODES = /* @__PURE__ */ new Set([
37244
37451
  "credential_unavailable"
37245
37452
  ]);
37246
37453
  function claimCommandId(listenerInstanceId, claimOrdinal) {
37247
- if (!UUID_RE16.test(listenerInstanceId)) {
37454
+ if (!UUID_RE17.test(listenerInstanceId)) {
37248
37455
  throw new Error("stored delivery journal is malformed");
37249
37456
  }
37250
37457
  if (!Number.isSafeInteger(claimOrdinal) || claimOrdinal < 0) {
@@ -37259,7 +37466,7 @@ function claimCommandId(listenerInstanceId, claimOrdinal) {
37259
37466
  return id;
37260
37467
  }
37261
37468
  function ackCommandId(leaseId) {
37262
- if (!UUID_RE16.test(leaseId)) {
37469
+ if (!UUID_RE17.test(leaseId)) {
37263
37470
  throw new Error("stored delivery journal is malformed");
37264
37471
  }
37265
37472
  const cleanLease = leaseId.toLowerCase().replace(/-/g, "");
@@ -37342,19 +37549,19 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId) {
37342
37549
  if (row.version !== 1) {
37343
37550
  throw new Error("stored delivery journal is malformed");
37344
37551
  }
37345
- if (typeof row.workspaceId !== "string" || !UUID_RE16.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
37552
+ if (typeof row.workspaceId !== "string" || !UUID_RE17.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
37346
37553
  throw new Error("stored delivery journal is malformed");
37347
37554
  }
37348
37555
  if (expectedWorkspaceId && row.workspaceId !== expectedWorkspaceId.toLowerCase()) {
37349
37556
  throw new Error("stored delivery journal is malformed");
37350
37557
  }
37351
- if (typeof row.principalId !== "string" || !UUID_RE16.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
37558
+ if (typeof row.principalId !== "string" || !UUID_RE17.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
37352
37559
  throw new Error("stored delivery journal is malformed");
37353
37560
  }
37354
37561
  if (expectedPrincipalId && row.principalId !== expectedPrincipalId.toLowerCase()) {
37355
37562
  throw new Error("stored delivery journal is malformed");
37356
37563
  }
37357
- if (typeof row.listenerInstanceId !== "string" || !UUID_RE16.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
37564
+ if (typeof row.listenerInstanceId !== "string" || !UUID_RE17.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
37358
37565
  throw new Error("stored delivery journal is malformed");
37359
37566
  }
37360
37567
  if (!Number.isSafeInteger(row.nextClaimOrdinal) || row.nextClaimOrdinal < 0) {
@@ -37418,10 +37625,10 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId) {
37418
37625
  if (active.claimLastAttemptAt === null) {
37419
37626
  throw new Error("stored delivery journal is malformed");
37420
37627
  }
37421
- if (typeof active.signalId !== "string" || !UUID_RE16.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
37628
+ if (typeof active.signalId !== "string" || !UUID_RE17.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
37422
37629
  throw new Error("stored delivery journal is malformed");
37423
37630
  }
37424
- if (typeof active.leaseId !== "string" || !UUID_RE16.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
37631
+ if (typeof active.leaseId !== "string" || !UUID_RE17.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
37425
37632
  throw new Error("stored delivery journal is malformed");
37426
37633
  }
37427
37634
  if (!isValidIsoTimestamp(active.leasedUntil) || Date.parse(active.leasedUntil) <= Date.parse(active.claimCreatedAt)) {
@@ -37493,7 +37700,7 @@ var FileListenerDeliveryJournal = class {
37493
37700
  ["profileId", "workspaceId", "principalId"],
37494
37701
  "delivery journal configuration rejected"
37495
37702
  );
37496
- if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE16.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE16.test(options.principalId)) {
37703
+ if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE17.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE17.test(options.principalId)) {
37497
37704
  throw new Error("delivery journal configuration rejected");
37498
37705
  }
37499
37706
  if (options.stateDirectory !== void 0) {
@@ -37508,11 +37715,11 @@ var FileListenerDeliveryJournal = class {
37508
37715
  stateDirectory: options.stateDirectory
37509
37716
  });
37510
37717
  const root = this.options.stateDirectory ?? defaultListenerStateDirectory();
37511
- if (!(0, import_node_path16.isAbsolute)(root)) {
37718
+ if (!(0, import_node_path17.isAbsolute)(root)) {
37512
37719
  throw new Error("delivery journal configuration rejected");
37513
37720
  }
37514
- this.instanceDirectory = (0, import_node_path16.join)(root, listenerInstanceKey(this.options));
37515
- this.journalPath = (0, import_node_path16.join)(this.instanceDirectory, "delivery-journal.json");
37721
+ this.instanceDirectory = (0, import_node_path17.join)(root, listenerInstanceKey(this.options));
37722
+ this.journalPath = (0, import_node_path17.join)(this.instanceDirectory, "delivery-journal.json");
37516
37723
  }
37517
37724
  async readRecordUnlocked() {
37518
37725
  let raw;
@@ -37614,7 +37821,7 @@ var FileListenerDeliveryJournal = class {
37614
37821
  ["signalId", "leaseId", "leasedUntil"],
37615
37822
  "delivery journal mutation rejected"
37616
37823
  );
37617
- if (typeof input.signalId !== "string" || !UUID_RE16.test(input.signalId) || typeof input.leaseId !== "string" || !UUID_RE16.test(input.leaseId) || !isValidIsoTimestamp(input.leasedUntil) || input.signalFingerprint !== void 0 && (typeof input.signalFingerprint !== "string" || !SIGNAL_FINGERPRINT_RE.test(input.signalFingerprint))) {
37824
+ if (typeof input.signalId !== "string" || !UUID_RE17.test(input.signalId) || typeof input.leaseId !== "string" || !UUID_RE17.test(input.leaseId) || !isValidIsoTimestamp(input.leasedUntil) || input.signalFingerprint !== void 0 && (typeof input.signalFingerprint !== "string" || !SIGNAL_FINGERPRINT_RE.test(input.signalFingerprint))) {
37618
37825
  throw new Error("delivery journal mutation rejected");
37619
37826
  }
37620
37827
  const canonicalSignalId = input.signalId.toLowerCase();
@@ -37746,7 +37953,7 @@ async function openListenerDeliveryJournal(options) {
37746
37953
  ["profileId", "workspaceId", "principalId", "proposedListenerInstanceId"],
37747
37954
  "delivery journal configuration rejected"
37748
37955
  );
37749
- if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE16.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE16.test(options.principalId) || typeof options.proposedListenerInstanceId !== "string" || !UUID_RE16.test(options.proposedListenerInstanceId)) {
37956
+ if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE17.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE17.test(options.principalId) || typeof options.proposedListenerInstanceId !== "string" || !UUID_RE17.test(options.proposedListenerInstanceId)) {
37750
37957
  throw new Error("delivery journal configuration rejected");
37751
37958
  }
37752
37959
  if (options.stateDirectory !== void 0) {
@@ -37841,9 +38048,9 @@ async function openListenerDeliveryJournal(options) {
37841
38048
 
37842
38049
  // src/listener/detach.ts
37843
38050
  var import_node_child_process7 = require("node:child_process");
37844
- var import_node_path17 = require("node:path");
38051
+ var import_node_path18 = require("node:path");
37845
38052
  function isNativeAbsolutePath(value, platform = process.platform) {
37846
- return platform === "win32" ? import_node_path17.win32.isAbsolute(value) : import_node_path17.posix.isAbsolute(value);
38053
+ return platform === "win32" ? import_node_path18.win32.isAbsolute(value) : import_node_path18.posix.isAbsolute(value);
37847
38054
  }
37848
38055
  function listenerNodeExecArgv(values2) {
37849
38056
  const safe = [];
@@ -37960,8 +38167,8 @@ async function spawnDetachedListener(options) {
37960
38167
 
37961
38168
  // src/listener/hook.ts
37962
38169
  var import_promises10 = require("node:fs/promises");
37963
- var import_node_path18 = require("node:path");
37964
- var UUID_RE17 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
38170
+ var import_node_path19 = require("node:path");
38171
+ var UUID_RE18 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
37965
38172
  var TOKEN_RE = /^swm_agt_[A-Za-z0-9_-]{43}$/;
37966
38173
  var INSTANCE_KEY_RE = /^[0-9a-f]{64}$/;
37967
38174
  var MAX_HOOK_CREDENTIAL_BYTES = 8 * 1024;
@@ -38002,7 +38209,7 @@ function parseListenerCredential(raw) {
38002
38209
  "principalId",
38003
38210
  "credential",
38004
38211
  "updatedAt"
38005
- ]) || row.version !== 1 || typeof row.profileId !== "string" || !/^[0-9a-f]{24}$/.test(row.profileId) || typeof row.targetUrl !== "string" || typeof row.anonKey !== "string" || row.anonKey.length < 1 || row.anonKey.length > 4096 || typeof row.workspaceId !== "string" || !UUID_RE17.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE17.test(row.principalId) || typeof row.credential !== "string" || !TOKEN_RE.test(row.credential) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt))) {
38212
+ ]) || row.version !== 1 || typeof row.profileId !== "string" || !/^[0-9a-f]{24}$/.test(row.profileId) || typeof row.targetUrl !== "string" || typeof row.anonKey !== "string" || row.anonKey.length < 1 || row.anonKey.length > 4096 || typeof row.workspaceId !== "string" || !UUID_RE18.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE18.test(row.principalId) || typeof row.credential !== "string" || !TOKEN_RE.test(row.credential) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt))) {
38006
38213
  throw new Error("stored listener hook credential is malformed");
38007
38214
  }
38008
38215
  const target2 = cloudTarget(row.targetUrl, row.anonKey);
@@ -38021,7 +38228,7 @@ function parseListenerCredential(raw) {
38021
38228
  };
38022
38229
  }
38023
38230
  async function writeListenerCredentialState(instanceDirectory, input) {
38024
- if (!(0, import_node_path18.isAbsolute)(instanceDirectory)) {
38231
+ if (!(0, import_node_path19.isAbsolute)(instanceDirectory)) {
38025
38232
  throw new Error("listener hook state directory must be absolute");
38026
38233
  }
38027
38234
  const record = parseListenerCredential(JSON.stringify({
@@ -38035,16 +38242,16 @@ async function writeListenerCredentialState(instanceDirectory, input) {
38035
38242
  updatedAt: new Date(input.now ?? Date.now()).toISOString()
38036
38243
  }));
38037
38244
  await writeSecureJsonFile(
38038
- (0, import_node_path18.join)(instanceDirectory, LISTENER_CREDENTIAL_FILE),
38245
+ (0, import_node_path19.join)(instanceDirectory, LISTENER_CREDENTIAL_FILE),
38039
38246
  JSON.stringify(record)
38040
38247
  );
38041
38248
  await deleteSecureJsonFile(
38042
- (0, import_node_path18.join)(instanceDirectory, RETIRED_HOOK_CREDENTIAL_FILE)
38249
+ (0, import_node_path19.join)(instanceDirectory, RETIRED_HOOK_CREDENTIAL_FILE)
38043
38250
  ).catch(() => void 0);
38044
38251
  }
38045
38252
  async function readListenerCredentialState(instanceDirectory) {
38046
38253
  const raw = await readSecureJsonFile(
38047
- (0, import_node_path18.join)(instanceDirectory, LISTENER_CREDENTIAL_FILE),
38254
+ (0, import_node_path19.join)(instanceDirectory, LISTENER_CREDENTIAL_FILE),
38048
38255
  MAX_HOOK_CREDENTIAL_BYTES
38049
38256
  );
38050
38257
  return raw === null ? null : parseListenerCredential(raw);
@@ -38062,7 +38269,7 @@ function parseSurface(raw) {
38062
38269
  const row = value;
38063
38270
  if (Object.keys(row).some(
38064
38271
  (key2) => key2 !== "version" && key2 !== "surfacedSignalIds" && key2 !== "reportedDroppedCount" && key2 !== "credentialFailureReported"
38065
- ) || row.version !== 1 || !Array.isArray(row.surfacedSignalIds) || row.surfacedSignalIds.length > HOOK_SURFACED_IDS_MAX || row.surfacedSignalIds.some((id) => typeof id !== "string" || !UUID_RE17.test(id)) || !(row.reportedDroppedCount === void 0 || typeof row.reportedDroppedCount === "number" && Number.isSafeInteger(row.reportedDroppedCount) && row.reportedDroppedCount >= 0) || !(row.credentialFailureReported === void 0 || typeof row.credentialFailureReported === "boolean")) {
38272
+ ) || row.version !== 1 || !Array.isArray(row.surfacedSignalIds) || row.surfacedSignalIds.length > HOOK_SURFACED_IDS_MAX || row.surfacedSignalIds.some((id) => typeof id !== "string" || !UUID_RE18.test(id)) || !(row.reportedDroppedCount === void 0 || typeof row.reportedDroppedCount === "number" && Number.isSafeInteger(row.reportedDroppedCount) && row.reportedDroppedCount >= 0) || !(row.credentialFailureReported === void 0 || typeof row.credentialFailureReported === "boolean")) {
38066
38273
  throw new Error("stored listener hook surface state is malformed");
38067
38274
  }
38068
38275
  const ids = row.surfacedSignalIds.map((id) => String(id).toLowerCase());
@@ -38079,10 +38286,10 @@ function parseSurface(raw) {
38079
38286
  var FileHookSurfaceStore = class {
38080
38287
  constructor(instanceDirectory) {
38081
38288
  this.instanceDirectory = instanceDirectory;
38082
- if (!(0, import_node_path18.isAbsolute)(instanceDirectory)) {
38289
+ if (!(0, import_node_path19.isAbsolute)(instanceDirectory)) {
38083
38290
  throw new Error("listener hook surface directory must be absolute");
38084
38291
  }
38085
- this.path = (0, import_node_path18.join)(instanceDirectory, HOOK_SURFACE_FILE);
38292
+ this.path = (0, import_node_path19.join)(instanceDirectory, HOOK_SURFACE_FILE);
38086
38293
  }
38087
38294
  instanceDirectory;
38088
38295
  path;
@@ -38099,7 +38306,7 @@ var FileHookSurfaceStore = class {
38099
38306
  const unseen = [];
38100
38307
  for (const item of items) {
38101
38308
  const signalId = item.signalId.toLowerCase();
38102
- if (!UUID_RE17.test(signalId) || seen.has(signalId)) continue;
38309
+ if (!UUID_RE18.test(signalId) || seen.has(signalId)) continue;
38103
38310
  seen.add(signalId);
38104
38311
  unseen.push(item);
38105
38312
  }
@@ -38122,7 +38329,7 @@ var FileHookSurfaceStore = class {
38122
38329
  const seen = new Set(state.surfacedSignalIds);
38123
38330
  for (const signalId of options.signalIds ?? []) {
38124
38331
  const checked = signalId.toLowerCase();
38125
- if (UUID_RE17.test(checked)) seen.add(checked);
38332
+ if (UUID_RE18.test(checked)) seen.add(checked);
38126
38333
  }
38127
38334
  await writeSecureJsonFile(
38128
38335
  this.path,
@@ -38161,7 +38368,7 @@ function parseGlobalState(raw) {
38161
38368
  }
38162
38369
  async function reserveCheck(stateDirectory2, cooldownMs, now) {
38163
38370
  return await withFileLock(stateDirectory2, GLOBAL_STATE_LOCK, async () => {
38164
- const path = (0, import_node_path18.join)(stateDirectory2, GLOBAL_STATE_FILE);
38371
+ const path = (0, import_node_path19.join)(stateDirectory2, GLOBAL_STATE_FILE);
38165
38372
  const raw = await readSecureJsonFile(path, MAX_GLOBAL_STATE_BYTES);
38166
38373
  const previous = raw === null ? null : parseGlobalState(raw);
38167
38374
  if (previous !== null && now - previous.lastCheckAt < cooldownMs) return false;
@@ -38181,8 +38388,8 @@ async function statusContext(stateDirectory2, key2, instanceDirectory) {
38181
38388
  const provisional = {
38182
38389
  key: key2,
38183
38390
  instanceDirectory,
38184
- statusPath: (0, import_node_path18.join)(instanceDirectory, "status.json"),
38185
- logPath: (0, import_node_path18.join)(instanceDirectory, "events.ndjson"),
38391
+ statusPath: (0, import_node_path19.join)(instanceDirectory, "status.json"),
38392
+ logPath: (0, import_node_path19.join)(instanceDirectory, "events.ndjson"),
38186
38393
  socketPath: ""
38187
38394
  };
38188
38395
  const status = await readListenerStatus(provisional).catch(() => null);
@@ -38218,7 +38425,7 @@ async function discoverContexts(stateDirectory2, isListenerLive = listenerIsLive
38218
38425
  const contexts = [];
38219
38426
  for (const entry of entries) {
38220
38427
  if (!entry.isDirectory() || !INSTANCE_KEY_RE.test(entry.name)) continue;
38221
- const instanceDirectory = (0, import_node_path18.join)(stateDirectory2, entry.name);
38428
+ const instanceDirectory = (0, import_node_path19.join)(stateDirectory2, entry.name);
38222
38429
  const storedStatus = await statusContext(
38223
38430
  stateDirectory2,
38224
38431
  entry.name,
@@ -38237,7 +38444,7 @@ async function discoverContexts(stateDirectory2, isListenerLive = listenerIsLive
38237
38444
  continue;
38238
38445
  }
38239
38446
  await deleteSecureJsonFile(
38240
- (0, import_node_path18.join)(instanceDirectory, RETIRED_HOOK_CREDENTIAL_FILE)
38447
+ (0, import_node_path19.join)(instanceDirectory, RETIRED_HOOK_CREDENTIAL_FILE)
38241
38448
  ).catch(() => void 0);
38242
38449
  try {
38243
38450
  const credential = await readListenerCredentialState(instanceDirectory);
@@ -38388,7 +38595,7 @@ async function recordQueuedObservations(check, signalIds, options, now) {
38388
38595
  async function checkListenerHooks(options) {
38389
38596
  try {
38390
38597
  const stateDirectory2 = options.stateDirectory ?? defaultListenerStateDirectory();
38391
- if (!(0, import_node_path18.isAbsolute)(stateDirectory2)) return "";
38598
+ if (!(0, import_node_path19.isAbsolute)(stateDirectory2)) return "";
38392
38599
  const now = options.now ?? Date.now;
38393
38600
  const cooldownSeconds = options.cooldownSeconds ?? HOOK_DEFAULT_COOLDOWN_SECONDS;
38394
38601
  if (!Number.isSafeInteger(cooldownSeconds) || cooldownSeconds < 0 || cooldownSeconds > 86400) {
@@ -38569,6 +38776,7 @@ var KNOWN_FLAGS = /* @__PURE__ */ new Set([
38569
38776
  "name",
38570
38777
  "ndjson",
38571
38778
  "no-browser",
38779
+ "notify",
38572
38780
  "opencode-executable",
38573
38781
  "out",
38574
38782
  "permissions",
@@ -38608,11 +38816,12 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
38608
38816
  "link-stdin",
38609
38817
  "local",
38610
38818
  "ndjson",
38819
+ "notify",
38611
38820
  "no-browser",
38612
38821
  "reveal-anon-key",
38613
38822
  "write"
38614
38823
  ]);
38615
- var UUID_RE18 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
38824
+ var UUID_RE19 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
38616
38825
  var AGENT_CREDENTIAL_MESSAGE = "Agent credential minted. It is bound to this task and run so the agent's work stays scoped and attributable.";
38617
38826
  var AGENT_CREDENTIAL_MESSAGE_D088 = "Agent credential minted. It is bound to this run, so the agent's work is attributable to it.";
38618
38827
  var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
@@ -38620,8 +38829,8 @@ var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
38620
38829
  AGENT_CREDENTIAL_MESSAGE_D088
38621
38830
  ];
38622
38831
  function packageVersion() {
38623
- if ("0.1.33".length > 0) {
38624
- return "0.1.33";
38832
+ if ("0.1.35".length > 0) {
38833
+ return "0.1.35";
38625
38834
  }
38626
38835
  try {
38627
38836
  const value = JSON.parse(
@@ -38743,6 +38952,7 @@ Usage:
38743
38952
  cswarm receipt <signal-id> --agent-token-stdin [--url <url> --anon-key <key>] --workspace-id <uuid> [--json]
38744
38953
  cswarm feed [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--about <ref>] [--kind <kind>] [--since <timestamp>] [--limit <n>] [--include-stale] [--json]
38745
38954
  cswarm inbox [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--kind <kind>] [--about <ref>] [--since <timestamp>] [--limit <n>] [--include-stale] [--wait <seconds>] [--json]
38955
+ cswarm inbox --notify --agent-token-stdin [--url <url> --anon-key <key>] --workspace-id <uuid> [--json]
38746
38956
  cswarm inbox --follow --ndjson [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--kind <kind>] [--about <ref>] [--since <timestamp>] [--limit <n>] [--include-stale]
38747
38957
  cswarm file put <local-path> [--name <name>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--agent-token-stdin] [--json]
38748
38958
  cswarm file ls [--include-tombstoned] [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--agent-token-stdin] [--json]
@@ -38788,6 +38998,7 @@ Credential selection for command/dogfood:
38788
38998
  JSON artifact, because it needs a field a bare secret does not carry:
38789
38999
  members reads only -- either form
38790
39000
  receipt reads only -- either form
39001
+ inbox --notify persists a per-agent cursor -- needs principal_id
38791
39002
  file put, file ls, file get, file rm, file restore
38792
39003
  read and command, nothing persisted -- either form
38793
39004
  feedback command only, nothing persisted -- either form
@@ -38820,11 +39031,11 @@ TTL); a turn that lands just before a rotation can be clamped to the ~5m
38820
39031
  renewal lead, and if it times out there, durable delivery retries it on the
38821
39032
  fresh credential.
38822
39033
 
38823
- listen start --route worker|main|split chooses where directed asks go. worker
38824
- is the unchanged default. main queues every ask for the interactive session.
38825
- split queues asks whose body is longer than --defer-over <chars>; the bound is
38826
- 1..10000 and an equal-length ask stays on the worker path. Run cswarm hook check
38827
- to surface queued asks. hook check has its own 3s ceiling, exits 0 on every
39034
+ listen start --route worker|main|split chooses where directed messages go. worker
39035
+ is the unchanged default. main queues every ask or note for the interactive session.
39036
+ split queues messages whose body is longer than --defer-over <chars>; the bound is
39037
+ 1..10000 and an equal-length message stays on the worker path. Run cswarm hook check
39038
+ to surface queued messages. hook check has its own 3s ceiling, exits 0 on every
38828
39039
  outcome, and skips network checks made within --cooldown seconds (default 30).
38829
39040
  hook install claude prints the UserPromptSubmit JSON by default and changes the
38830
39041
  project's .claude/settings.json only with --write; uninstall also requires --write.
@@ -38957,7 +39168,7 @@ function parsedAgentCredential(value) {
38957
39168
  const withExpiry = [...requiredKeys, "expires_at"].sort();
38958
39169
  const actualKeys = Object.keys(artifact).sort();
38959
39170
  const shape = actualKeys.length === requiredKeys.length ? requiredKeys : withExpiry;
38960
- if (actualKeys.length !== shape.length || !actualKeys.every((key2, index) => key2 === shape[index]) || !ACCEPTED_AGENT_CREDENTIAL_MESSAGES.includes(artifact.message) || artifact.status !== "accepted" || typeof artifact.principal_id !== "string" || !UUID_RE18.test(artifact.principal_id) || typeof artifact.token_id !== "string" || !UUID_RE18.test(artifact.token_id) || typeof artifact.run_id !== "string" || !UUID_RE18.test(artifact.run_id) || typeof artifact.agent_token !== "string") {
39171
+ if (actualKeys.length !== shape.length || !actualKeys.every((key2, index) => key2 === shape[index]) || !ACCEPTED_AGENT_CREDENTIAL_MESSAGES.includes(artifact.message) || artifact.status !== "accepted" || typeof artifact.principal_id !== "string" || !UUID_RE19.test(artifact.principal_id) || typeof artifact.token_id !== "string" || !UUID_RE19.test(artifact.token_id) || typeof artifact.run_id !== "string" || !UUID_RE19.test(artifact.run_id) || typeof artifact.agent_token !== "string") {
38961
39172
  throw new Error("agent credential JSON is malformed");
38962
39173
  }
38963
39174
  let expiresAt = null;
@@ -39195,7 +39406,7 @@ async function runNew(args) {
39195
39406
  project: {
39196
39407
  workspace_id: created,
39197
39408
  name,
39198
- stream_id: typeof response.stream_id === "string" && UUID_RE18.test(response.stream_id) ? response.stream_id : null
39409
+ stream_id: typeof response.stream_id === "string" && UUID_RE19.test(response.stream_id) ? response.stream_id : null
39199
39410
  }
39200
39411
  });
39201
39412
  return;
@@ -39969,7 +40180,7 @@ async function runLinkNew(args) {
39969
40180
  2
39970
40181
  );
39971
40182
  const taskId = args.required("task-id");
39972
- if (!UUID_RE18.test(taskId)) {
40183
+ if (!UUID_RE19.test(taskId)) {
39973
40184
  throw new Error("--task-id must be the work item's UUID");
39974
40185
  }
39975
40186
  const site = capabilitySiteOrigin(
@@ -40029,7 +40240,7 @@ async function runLinkRevoke(args) {
40029
40240
  2
40030
40241
  );
40031
40242
  const capabilityId = args.required("capability-id");
40032
- if (!UUID_RE18.test(capabilityId)) {
40243
+ if (!UUID_RE19.test(capabilityId)) {
40033
40244
  throw new Error(
40034
40245
  "--capability-id must be the id printed when the link was created"
40035
40246
  );
@@ -40608,7 +40819,7 @@ async function runReply(args) {
40608
40819
  "json"
40609
40820
  ], 3);
40610
40821
  const signalId = args.positionals[1];
40611
- if (signalId === void 0 || !UUID_RE18.test(signalId)) {
40822
+ if (signalId === void 0 || !UUID_RE19.test(signalId)) {
40612
40823
  throw new Error("reply requires the signal UUID being answered");
40613
40824
  }
40614
40825
  const body = args.positionals[2];
@@ -40750,18 +40961,29 @@ async function runMembers(args) {
40750
40961
  process.stdout.write(renderRoster(directory, memberNames));
40751
40962
  }
40752
40963
  async function runSignalRead(args, inbox) {
40753
- args.assertShape([
40964
+ const notify = inbox && args.has("notify");
40965
+ args.assertShape(notify ? [
40966
+ ...TARGET_FLAGS,
40967
+ "workspace-id",
40968
+ ...CREDENTIAL_FLAGS,
40969
+ "notify",
40970
+ "json"
40971
+ ] : [
40754
40972
  ...TARGET_FLAGS,
40755
40973
  "workspace-id",
40756
40974
  ...CREDENTIAL_FLAGS,
40757
40975
  "about",
40758
40976
  "kind",
40759
- ...inbox ? ["wait", "follow", "ndjson"] : [],
40977
+ ...inbox ? ["wait", "follow", "ndjson", "notify"] : [],
40760
40978
  "since",
40761
40979
  "limit",
40762
40980
  "include-stale",
40763
40981
  "json"
40764
40982
  ], 1);
40983
+ if (notify) {
40984
+ await runInboxNotifyCommand(args);
40985
+ return;
40986
+ }
40765
40987
  if (inbox && args.has("follow")) {
40766
40988
  if (!args.has("ndjson")) {
40767
40989
  throw new Error("inbox --follow requires --ndjson");
@@ -40838,6 +41060,89 @@ async function runSignalRead(args, inbox) {
40838
41060
  })}
40839
41061
  `);
40840
41062
  }
41063
+ async function writeMonitorLine(line) {
41064
+ await new Promise((resolve, reject) => {
41065
+ process.stdout.write(`${line}
41066
+ `, (error) => {
41067
+ if (error) reject(error);
41068
+ else resolve();
41069
+ });
41070
+ });
41071
+ }
41072
+ async function runInboxNotifyCommand(args) {
41073
+ if (!args.has("agent-token-stdin")) {
41074
+ throw new Error(
41075
+ "inbox --notify is for one agent; provide its JSON credential with --agent-token-stdin"
41076
+ );
41077
+ }
41078
+ const cloud = await target(args);
41079
+ const selected = await commandWorkspaceAndCredential(args, cloud, {
41080
+ validateHumanWorkspace: true
41081
+ });
41082
+ const principalId = selected.agent?.principalId ?? null;
41083
+ if (selected.kind !== "agent" || principalId === null) {
41084
+ throw new Error(
41085
+ "inbox --notify needs the full JSON agent credential so its durable cursor is tied to one agent"
41086
+ );
41087
+ }
41088
+ const controller = new AbortController();
41089
+ const stop = () => controller.abort();
41090
+ process.on("SIGINT", stop);
41091
+ process.on("SIGTERM", stop);
41092
+ try {
41093
+ const cursorStore = fileArrivalCursorStore({
41094
+ target: cloud,
41095
+ workspaceId: selected.selectedWorkspace,
41096
+ principalId
41097
+ });
41098
+ const result = await runArrivalWatch({
41099
+ workspaceId: selected.selectedWorkspace,
41100
+ principalId,
41101
+ store: cursorStore,
41102
+ signal: controller.signal,
41103
+ readPage: async ({ after, baseline, limit }) => {
41104
+ const token = selected.session ? await selected.session.bearer() : selected.bearer;
41105
+ return await readAgentSignalPage(
41106
+ cloud,
41107
+ { kind: "agent", token },
41108
+ {
41109
+ workspaceId: selected.selectedWorkspace,
41110
+ inbox: true,
41111
+ limit,
41112
+ includeStale: false,
41113
+ ...baseline ? {} : {
41114
+ ascending: true,
41115
+ ...after === null ? {} : { after }
41116
+ }
41117
+ },
41118
+ { signal: controller.signal }
41119
+ );
41120
+ },
41121
+ emit: async (signal) => {
41122
+ const notification = arrivalNotification(
41123
+ signal,
41124
+ selected.selectedWorkspace,
41125
+ cloud
41126
+ );
41127
+ await writeMonitorLine(
41128
+ args.has("json") ? JSON.stringify(notification) : formatArrivalNotification(notification)
41129
+ );
41130
+ },
41131
+ onRetry: (_error, delayMs) => {
41132
+ process.stderr.write(
41133
+ `cswarm: arrival read failed; still watching and retrying in ${delayMs}ms.
41134
+ `
41135
+ );
41136
+ }
41137
+ });
41138
+ if (result.reason === "error") {
41139
+ throw result.error ?? new Error("arrival watch stopped");
41140
+ }
41141
+ } finally {
41142
+ process.off("SIGINT", stop);
41143
+ process.off("SIGTERM", stop);
41144
+ }
41145
+ }
40841
41146
  async function runReceipt(args) {
40842
41147
  args.assertShape([
40843
41148
  ...TARGET_FLAGS,
@@ -40846,7 +41151,7 @@ async function runReceipt(args) {
40846
41151
  "json"
40847
41152
  ], 2);
40848
41153
  const signalId = args.positionals[1];
40849
- if (!UUID_RE18.test(signalId)) {
41154
+ if (!UUID_RE19.test(signalId)) {
40850
41155
  throw new Error("signal-id must be a UUID");
40851
41156
  }
40852
41157
  if (!args.has("agent-token-stdin")) {
@@ -40984,7 +41289,7 @@ async function runInboxFollowCommand(args) {
40984
41289
  }
40985
41290
  }
40986
41291
  function listenerUuid(value, flag) {
40987
- if (!value || !UUID_RE18.test(value)) {
41292
+ if (!value || !UUID_RE19.test(value)) {
40988
41293
  throw new Error(`--${flag} must be a UUID`);
40989
41294
  }
40990
41295
  return value.toLowerCase();
@@ -40997,7 +41302,7 @@ function listenerPermissionMode(value) {
40997
41302
  function listenerStateDirectory(args) {
40998
41303
  const value = args.optional("state-dir");
40999
41304
  if (value === void 0) return void 0;
41000
- if (!(0, import_node_path19.isAbsolute)(value)) {
41305
+ if (!(0, import_node_path20.isAbsolute)(value)) {
41001
41306
  throw new Error("--state-dir must be an absolute path");
41002
41307
  }
41003
41308
  return value;
@@ -41328,7 +41633,7 @@ function resolveDetachedClaudeExecutable(executable = "claude-agent-acp", pathEn
41328
41633
  } catch (error) {
41329
41634
  const code = error.code;
41330
41635
  if (typeof code === "string") {
41331
- if ((0, import_node_path19.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
41636
+ if ((0, import_node_path20.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
41332
41637
  const detail = error instanceof Error ? error.message : code;
41333
41638
  throw new Error(
41334
41639
  `could not use --claude-executable: ${detail}; install the current bridge with npm install -g @agentclientprotocol/claude-agent-acp@latest if this path should be replaced`
@@ -41345,7 +41650,7 @@ function resolveDetachedCodexExecutable(executable = "codex-acp", pathEnv = proc
41345
41650
  } catch (error) {
41346
41651
  const code = error.code;
41347
41652
  if (typeof code === "string") {
41348
- if ((0, import_node_path19.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
41653
+ if ((0, import_node_path20.isAbsolute)(executable) || executable.includes("/") || executable.includes("\\")) {
41349
41654
  const detail = error instanceof Error ? error.message : code;
41350
41655
  throw new Error(
41351
41656
  `could not use --codex-executable: ${detail}; install the current bridge with npm install -g @agentclientprotocol/codex-acp@latest if this path should be replaced`
@@ -41612,7 +41917,7 @@ async function runListenStart(args) {
41612
41917
  assertDurableListenerCredential(agent);
41613
41918
  const principalId = agent.principalId;
41614
41919
  const cwd = args.optional("cwd") ?? process.cwd();
41615
- if (!(0, import_node_path19.isAbsolute)(cwd)) throw new Error("--cwd must be an absolute path");
41920
+ if (!(0, import_node_path20.isAbsolute)(cwd)) throw new Error("--cwd must be an absolute path");
41616
41921
  const permissionMode = listenerPermissionMode(args.optional("permissions"));
41617
41922
  const stateDirectory2 = listenerStateDirectory(args);
41618
41923
  const paths = listenerPaths({
@@ -41649,7 +41954,7 @@ async function runListenStart(args) {
41649
41954
  });
41650
41955
  } else {
41651
41956
  const entrypoint = process.argv[1];
41652
- if (!entrypoint || !(0, import_node_path19.isAbsolute)(entrypoint)) {
41957
+ if (!entrypoint || !(0, import_node_path20.isAbsolute)(entrypoint)) {
41653
41958
  throw new Error("cannot locate the cswarm executable for detached start");
41654
41959
  }
41655
41960
  const artifact = JSON.stringify(agentCredentialArtifact({
@@ -41787,7 +42092,7 @@ async function runListenSupervisor(args) {
41787
42092
  const agent = await stdinCredential();
41788
42093
  assertDurableListenerCredential(agent, principalId);
41789
42094
  const cwd = args.required("cwd");
41790
- if (!(0, import_node_path19.isAbsolute)(cwd)) throw new Error("--cwd must be an absolute path");
42095
+ if (!(0, import_node_path20.isAbsolute)(cwd)) throw new Error("--cwd must be an absolute path");
41791
42096
  const status = await runConfiguredListener({
41792
42097
  cloud,
41793
42098
  workspaceId: workspaceId2,
@@ -41889,7 +42194,7 @@ function claudeUserPromptHookSnippet() {
41889
42194
  };
41890
42195
  }
41891
42196
  function projectClaudeSettingsPath() {
41892
- return (0, import_node_path19.join)(process.cwd(), ".claude", "settings.json");
42197
+ return (0, import_node_path20.join)(process.cwd(), ".claude", "settings.json");
41893
42198
  }
41894
42199
  function readProjectSettings(path) {
41895
42200
  let raw;
@@ -42001,7 +42306,7 @@ async function runHook(args) {
42001
42306
  const path = projectClaudeSettingsPath();
42002
42307
  const settings = readProjectSettings(path);
42003
42308
  const updated = command2 === "install" ? installClaudeHook(settings) : uninstallClaudeHook(settings);
42004
- (0, import_node_fs7.mkdirSync)((0, import_node_path19.dirname)(path), { recursive: true });
42309
+ (0, import_node_fs7.mkdirSync)((0, import_node_path20.dirname)(path), { recursive: true });
42005
42310
  (0, import_node_fs7.writeFileSync)(path, `${JSON.stringify(updated, null, 2)}
42006
42311
  `, {
42007
42312
  encoding: "utf8",
@@ -42047,7 +42352,7 @@ async function fileRows(context) {
42047
42352
  );
42048
42353
  }
42049
42354
  async function resolveFileSelector(context, selector) {
42050
- if (UUID_RE18.test(selector)) return selector.toLowerCase();
42355
+ if (UUID_RE19.test(selector)) return selector.toLowerCase();
42051
42356
  const rows3 = await fileRows(context);
42052
42357
  const match = rows3.find(
42053
42358
  (row) => row.name.toLowerCase() === selector.toLowerCase()
@@ -42069,7 +42374,7 @@ async function runFilePut(args) {
42069
42374
  } catch {
42070
42375
  throw new Error(`could not read ${localPath}; check the path and permissions`);
42071
42376
  }
42072
- const name = args.optional("name") ?? (0, import_node_path19.basename)(localPath);
42377
+ const name = args.optional("name") ?? (0, import_node_path20.basename)(localPath);
42073
42378
  if (bytes.byteLength > FILE_MAX_VERSION_BYTES) {
42074
42379
  throw new Error(
42075
42380
  `this file is ${formatFileSize(bytes.byteLength)}; the per-file limit is ${formatFileSize(FILE_MAX_VERSION_BYTES)}, so the upload was not started`
@@ -42171,7 +42476,7 @@ async function runFileGet(args) {
42171
42476
  credential: context.selected.bearer
42172
42477
  };
42173
42478
  const grant = await fileDownloadUrl(send, { fileId, versionN });
42174
- const destination = args.optional("out") ?? (0, import_node_path19.basename)(grant.name);
42479
+ const destination = args.optional("out") ?? (0, import_node_path20.basename)(grant.name);
42175
42480
  const bytes = await getObject(context.cloud, grant.download_path);
42176
42481
  writeDestination(destination, bytes, args.has("force"), import_node_fs7.writeFileSync);
42177
42482
  if (args.has("json")) {
@@ -42387,7 +42692,7 @@ async function runSeed(args) {
42387
42692
  throw new Error("DATABASE_URL is required for the fixture bridge");
42388
42693
  }
42389
42694
  const tokenOut = process.env.SEED_TOKEN_OUT;
42390
- if (!tokenOut || !(0, import_node_path19.isAbsolute)(tokenOut)) {
42695
+ if (!tokenOut || !(0, import_node_path20.isAbsolute)(tokenOut)) {
42391
42696
  throw new Error("SEED_TOKEN_OUT must be an absolute path");
42392
42697
  }
42393
42698
  const tokenFile = await (0, import_promises11.open)(tokenOut, "wx", 384).catch((error) => {