commonswarm 0.1.30 → 0.1.32

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 +494 -77
  2. package/package.json +1 -1
package/cswarm.cjs CHANGED
@@ -28271,8 +28271,8 @@ function relativeMagnitude(milliseconds) {
28271
28271
  const amount = magnitude < 6e4 ? "under 1m" : magnitude < 36e5 ? `${Math.ceil(magnitude / 6e4)}m` : magnitude < 864e5 ? `${Math.ceil(magnitude / 36e5)}h` : `${Math.ceil(magnitude / 864e5)}d`;
28272
28272
  return amount;
28273
28273
  }
28274
- function relativeAge(timestamp2, now = Date.now()) {
28275
- return `${relativeMagnitude(Math.max(0, now - Date.parse(timestamp2)))} ago`;
28274
+ function relativeAge(timestamp3, now = Date.now()) {
28275
+ return `${relativeMagnitude(Math.max(0, now - Date.parse(timestamp3)))} ago`;
28276
28276
  }
28277
28277
  function relativeExpiry(expiry, now = Date.now()) {
28278
28278
  const remaining = Date.parse(expiry) - now;
@@ -29571,6 +29571,318 @@ async function runInboxFollow(options) {
29571
29571
  }
29572
29572
  }
29573
29573
 
29574
+ // src/cloud/delivery-receipts.ts
29575
+ 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;
29576
+ var DeliveryReceiptReadError = class extends Error {
29577
+ constructor(code, message, status = null) {
29578
+ super(message);
29579
+ this.code = code;
29580
+ this.status = status;
29581
+ this.name = "DeliveryReceiptReadError";
29582
+ }
29583
+ code;
29584
+ status;
29585
+ };
29586
+ var ACK_OUTCOMES = /* @__PURE__ */ new Set([
29587
+ "replied",
29588
+ "observed",
29589
+ "expired",
29590
+ "failed_terminal"
29591
+ ]);
29592
+ function uuid3(value, field) {
29593
+ if (typeof value !== "string" || !UUID_RE8.test(value)) {
29594
+ throw new DeliveryReceiptReadError(
29595
+ "protocol",
29596
+ `delivery receipt returned a malformed ${field}`
29597
+ );
29598
+ }
29599
+ return value.toLowerCase();
29600
+ }
29601
+ function timestamp2(value, field) {
29602
+ if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) {
29603
+ throw new DeliveryReceiptReadError(
29604
+ "protocol",
29605
+ `delivery receipt returned a malformed ${field}`
29606
+ );
29607
+ }
29608
+ return value;
29609
+ }
29610
+ function nullableTimestamp(value, field) {
29611
+ return value === null ? null : timestamp2(value, field);
29612
+ }
29613
+ function nonNegativeInteger(value, field) {
29614
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
29615
+ throw new DeliveryReceiptReadError(
29616
+ "protocol",
29617
+ `delivery receipt returned a malformed ${field}`
29618
+ );
29619
+ }
29620
+ return value;
29621
+ }
29622
+ function parseDeliveryReceipt(value) {
29623
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29624
+ throw new DeliveryReceiptReadError(
29625
+ "protocol",
29626
+ "delivery receipt returned a malformed row"
29627
+ );
29628
+ }
29629
+ const row = value;
29630
+ const ackedAt = nullableTimestamp(row.acked_at, "acked_at");
29631
+ const ackOutcome = row.ack_outcome === null ? null : typeof row.ack_outcome === "string" && ACK_OUTCOMES.has(row.ack_outcome) ? row.ack_outcome : (() => {
29632
+ throw new DeliveryReceiptReadError(
29633
+ "protocol",
29634
+ "delivery receipt returned a malformed ack_outcome"
29635
+ );
29636
+ })();
29637
+ if (ackedAt === null !== (ackOutcome === null)) {
29638
+ throw new DeliveryReceiptReadError(
29639
+ "protocol",
29640
+ "delivery receipt returned an inconsistent acknowledgement"
29641
+ );
29642
+ }
29643
+ return {
29644
+ recipient_agent_principal_id: uuid3(
29645
+ row.recipient_agent_principal_id,
29646
+ "recipient_agent_principal_id"
29647
+ ),
29648
+ enqueued_at: timestamp2(row.enqueued_at, "enqueued_at"),
29649
+ delivered_at: nullableTimestamp(row.delivered_at, "delivered_at"),
29650
+ leased_until: nullableTimestamp(row.leased_until, "leased_until"),
29651
+ acked_at: ackedAt,
29652
+ ack_outcome: ackOutcome,
29653
+ attempt_count: nonNegativeInteger(row.attempt_count, "attempt_count"),
29654
+ lease_expiry_count: nonNegativeInteger(
29655
+ row.lease_expiry_count,
29656
+ "lease_expiry_count"
29657
+ ),
29658
+ last_error_code: row.last_error_code === null ? null : typeof row.last_error_code === "string" && /^[a-z][a-z0-9_]{0,63}$/.test(row.last_error_code) ? row.last_error_code : (() => {
29659
+ throw new DeliveryReceiptReadError(
29660
+ "protocol",
29661
+ "delivery receipt returned a malformed last_error_code"
29662
+ );
29663
+ })()
29664
+ };
29665
+ }
29666
+ function parseDeliveryReceiptResult(value) {
29667
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29668
+ throw new DeliveryReceiptReadError(
29669
+ "protocol",
29670
+ "delivery receipt read returned malformed JSON"
29671
+ );
29672
+ }
29673
+ const body = value;
29674
+ if (!(body.addressed === null || typeof body.addressed === "boolean") || !Array.isArray(body.receipts)) {
29675
+ throw new DeliveryReceiptReadError(
29676
+ "protocol",
29677
+ "delivery receipt read returned malformed JSON"
29678
+ );
29679
+ }
29680
+ const receipts = body.receipts.map(parseDeliveryReceipt);
29681
+ if (body.addressed === false && receipts.length !== 0) {
29682
+ throw new DeliveryReceiptReadError(
29683
+ "protocol",
29684
+ "delivery receipt read returned recipients for a broadcast"
29685
+ );
29686
+ }
29687
+ if (body.addressed === true && receipts.length === 0) {
29688
+ throw new DeliveryReceiptReadError(
29689
+ "protocol",
29690
+ "delivery receipt read returned no recipient for an addressed signal"
29691
+ );
29692
+ }
29693
+ const recipientIds = new Set(
29694
+ receipts.map((row) => row.recipient_agent_principal_id)
29695
+ );
29696
+ if (recipientIds.size !== receipts.length) {
29697
+ throw new DeliveryReceiptReadError(
29698
+ "protocol",
29699
+ "delivery receipt read returned duplicate recipients"
29700
+ );
29701
+ }
29702
+ return { addressed: body.addressed, receipts };
29703
+ }
29704
+ function deliveryReceiptState(receipt, nowMs = Date.now()) {
29705
+ if (receipt.ack_outcome !== null) return receipt.ack_outcome;
29706
+ if (receipt.leased_until !== null && Date.parse(receipt.leased_until) > nowMs) {
29707
+ return "leased";
29708
+ }
29709
+ if (receipt.delivered_at !== null) return "delivered";
29710
+ return "enqueued";
29711
+ }
29712
+ async function readAgentDeliveryReceipts(target2, token, workspaceId2, signalId, options = {}) {
29713
+ const readOptions = typeof options === "function" ? { fetcher: options } : options;
29714
+ const now = readOptions.now ?? Date.now;
29715
+ const timeoutMs = readOptions.deadlineMs === void 0 ? SIGNAL_READ_TIMEOUT_MS : Math.min(SIGNAL_READ_TIMEOUT_MS, readOptions.deadlineMs - now());
29716
+ if (timeoutMs <= 0) {
29717
+ throw new SignalReadTimeoutError("receipt read timed out");
29718
+ }
29719
+ const deadlineController = new AbortController();
29720
+ const signal = readOptions.signal === void 0 ? deadlineController.signal : AbortSignal.any([readOptions.signal, deadlineController.signal]);
29721
+ let onAbort = () => {
29722
+ };
29723
+ const aborted = new Promise((_resolve, reject) => {
29724
+ onAbort = () => reject(new SignalReadTimeoutError("receipt read timed out"));
29725
+ if (signal.aborted) onAbort();
29726
+ else signal.addEventListener("abort", onAbort, { once: true });
29727
+ });
29728
+ const timer2 = setTimeout(() => deadlineController.abort(), timeoutMs);
29729
+ try {
29730
+ let response;
29731
+ try {
29732
+ response = await Promise.race([
29733
+ (readOptions.fetcher ?? fetch)(readEndpoint(target2), {
29734
+ method: "POST",
29735
+ headers: {
29736
+ authorization: `Bearer ${token}`,
29737
+ apikey: target2.anonKey,
29738
+ "content-type": "application/json"
29739
+ },
29740
+ body: JSON.stringify({
29741
+ resource: "delivery_receipts",
29742
+ workspace_id: uuid3(workspaceId2, "workspace_id"),
29743
+ signal_id: uuid3(signalId, "signal_id")
29744
+ }),
29745
+ signal
29746
+ }),
29747
+ aborted
29748
+ ]);
29749
+ } catch (error) {
29750
+ if (error instanceof SignalReadTimeoutError || signal.aborted || error?.name === "AbortError") {
29751
+ throw new SignalReadTimeoutError("receipt read timed out");
29752
+ }
29753
+ if (error instanceof DeliveryReceiptReadError) throw error;
29754
+ throw new DeliveryReceiptReadError(
29755
+ "transport",
29756
+ "delivery receipt read could not reach the cloud service"
29757
+ );
29758
+ }
29759
+ let body;
29760
+ try {
29761
+ body = await Promise.race([response.json(), aborted]);
29762
+ } catch (error) {
29763
+ if (error instanceof SignalReadTimeoutError || signal.aborted) {
29764
+ throw new SignalReadTimeoutError("receipt read timed out");
29765
+ }
29766
+ throw new DeliveryReceiptReadError(
29767
+ "protocol",
29768
+ "delivery receipt read returned malformed JSON"
29769
+ );
29770
+ }
29771
+ if (!response.ok) {
29772
+ throw new DeliveryReceiptReadError(
29773
+ "http",
29774
+ `delivery receipt read failed (HTTP ${response.status})`,
29775
+ response.status
29776
+ );
29777
+ }
29778
+ const result = parseDeliveryReceiptResult(body);
29779
+ if (result.addressed === null) {
29780
+ throw new DeliveryReceiptReadError(
29781
+ "not_author",
29782
+ "delivery receipt read did not establish that this caller authored the signal"
29783
+ );
29784
+ }
29785
+ return { addressed: result.addressed, receipts: result.receipts };
29786
+ } finally {
29787
+ clearTimeout(timer2);
29788
+ signal.removeEventListener("abort", onAbort);
29789
+ }
29790
+ }
29791
+
29792
+ // src/cloud/receipts.ts
29793
+ function signalReceiptCliState(receipt, nowMs) {
29794
+ const state = deliveryReceiptState(receipt, nowMs);
29795
+ if (state === "enqueued") return "not_delivered";
29796
+ if (state === "leased") return "working";
29797
+ if (state === "delivered") return "delivered";
29798
+ return "finished";
29799
+ }
29800
+ function receiptCheckCommand(report) {
29801
+ return `cswarm receipt ${report.signalId} --workspace-id ${report.workspaceId}`;
29802
+ }
29803
+ function listenerStatusCommand(report, receipt) {
29804
+ return `cswarm listen status --workspace-id ${report.workspaceId} --principal-id ${receipt.recipient_agent_principal_id}`;
29805
+ }
29806
+ function newAskCommand(report, receipt) {
29807
+ return `cswarm ask "<question>" --to ${receipt.recipient_agent_principal_id} --workspace-id ${report.workspaceId}`;
29808
+ }
29809
+ function renderSignalReceiptReport(report, nowMs = Date.now()) {
29810
+ if (!report.addressed) {
29811
+ return [
29812
+ "This was a broadcast; no agent was addressed and none was woken.",
29813
+ `To wake an agent, send a new ask with: cswarm ask "<text>" --to <agent> --workspace-id ${report.workspaceId}`
29814
+ ].join("\n");
29815
+ }
29816
+ const sections = report.receipts.map((receipt) => {
29817
+ const state = deliveryReceiptState(receipt, nowMs);
29818
+ if (state === "enqueued") {
29819
+ return [
29820
+ `Not yet delivered to agent ${receipt.recipient_agent_principal_id}. CommonSwarm accepted it ${relativeAge(receipt.enqueued_at, nowMs)}.`,
29821
+ `Ask the agent's operator to check its listener with: ${listenerStatusCommand(report, receipt)}`,
29822
+ `Then check again with: ${receiptCheckCommand(report)}`
29823
+ ].join("\n");
29824
+ }
29825
+ if (state === "delivered") {
29826
+ return [
29827
+ `Delivered to agent ${receipt.recipient_agent_principal_id} ${relativeAge(receipt.delivered_at, nowMs)}, and the agent has not acted on it.`,
29828
+ `Check again with: ${receiptCheckCommand(report)}`
29829
+ ].join("\n");
29830
+ }
29831
+ if (state === "leased") {
29832
+ return [
29833
+ `Agent ${receipt.recipient_agent_principal_id} is working on it right now; its current lease ${relativeExpiry(receipt.leased_until, nowMs)}.`,
29834
+ `Check for the outcome with: ${receiptCheckCommand(report)}`
29835
+ ].join("\n");
29836
+ }
29837
+ const finished = `Agent ${receipt.recipient_agent_principal_id} finished with outcome ${state} ${relativeAge(receipt.acked_at, nowMs)}.`;
29838
+ if (state === "replied") {
29839
+ return [
29840
+ finished,
29841
+ `Read the reply with: cswarm inbox --workspace-id ${report.workspaceId} --include-stale`
29842
+ ].join("\n");
29843
+ }
29844
+ if (state === "observed") {
29845
+ return [
29846
+ finished,
29847
+ "The agent acknowledged the signal without sending a reply.",
29848
+ `If you need an answer, send a new ask with: ${newAskCommand(report, receipt)}`
29849
+ ].join("\n");
29850
+ }
29851
+ if (state === "expired") {
29852
+ return [
29853
+ finished,
29854
+ "The signal expired before the agent completed it.",
29855
+ `Send a new ask with: ${newAskCommand(report, receipt)}`
29856
+ ].join("\n");
29857
+ }
29858
+ return [
29859
+ finished,
29860
+ `Delivery will not retry${receipt.last_error_code === null ? "." : `; the last error code was ${receipt.last_error_code}.`}`,
29861
+ `Ask the agent's operator to check its listener with: ${listenerStatusCommand(report, receipt)}`
29862
+ ].join("\n");
29863
+ });
29864
+ return sections.join("\n\n");
29865
+ }
29866
+ function signalReceiptJsonPayload(report, nowMs = Date.now()) {
29867
+ return {
29868
+ workspace_id: report.workspaceId,
29869
+ signal_id: report.signalId,
29870
+ broadcast: !report.addressed,
29871
+ receipts: report.receipts.map((receipt) => ({
29872
+ recipient_agent_principal_id: receipt.recipient_agent_principal_id,
29873
+ state: signalReceiptCliState(receipt, nowMs),
29874
+ outcome: receipt.ack_outcome,
29875
+ enqueued_at: receipt.enqueued_at,
29876
+ delivered_at: receipt.delivered_at,
29877
+ leased_until: receipt.leased_until,
29878
+ acked_at: receipt.acked_at,
29879
+ attempt_count: receipt.attempt_count,
29880
+ lease_expiry_count: receipt.lease_expiry_count,
29881
+ last_error_code: receipt.last_error_code
29882
+ }))
29883
+ };
29884
+ }
29885
+
29574
29886
  // src/host/opencode.ts
29575
29887
  var import_node_child_process3 = require("node:child_process");
29576
29888
  var import_node_crypto12 = require("node:crypto");
@@ -32160,7 +32472,7 @@ async function resolveBudgetAndPrompt(session, prompt, budget) {
32160
32472
  }
32161
32473
 
32162
32474
  // src/listener/engine.ts
32163
- 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;
32475
+ 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;
32164
32476
  var TERMINAL_STATES = /* @__PURE__ */ new Set(["done", "expired", "failed"]);
32165
32477
  var REPLY_MAX_CODE_UNITS = 2e3;
32166
32478
  var TRUNCATION_SUFFIX = "\n[Reply truncated by CommonSwarm]";
@@ -32168,7 +32480,7 @@ var UNSAFE_CONTROLS_RE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u
32168
32480
  var LISTENER_MAX_PROMPT_ATTEMPTS = 3;
32169
32481
  var LISTENER_MAX_POST_ATTEMPTS = 5;
32170
32482
  function listenerReplyCommandId(signalId, effectOrdinal = 0) {
32171
- if (!UUID_RE8.test(signalId)) {
32483
+ if (!UUID_RE9.test(signalId)) {
32172
32484
  throw new Error("listener signal id must be a UUID");
32173
32485
  }
32174
32486
  if (!Number.isSafeInteger(effectOrdinal) || effectOrdinal < 0) {
@@ -32632,7 +32944,7 @@ var import_node_crypto13 = require("node:crypto");
32632
32944
  var import_node_os5 = require("node:os");
32633
32945
  var import_node_path8 = require("node:path");
32634
32946
  var import_node_util = require("node:util");
32635
- 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;
32947
+ 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;
32636
32948
  var COMMAND_ID_RE2 = /^[A-Za-z0-9_-]{8,72}$/;
32637
32949
  var MAX_EFFECT_BYTES = 1024 * 1024;
32638
32950
  var STATES = /* @__PURE__ */ new Set([
@@ -32670,7 +32982,7 @@ function defaultListenerStateDirectory() {
32670
32982
  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");
32671
32983
  }
32672
32984
  function listenerInstanceKey(input) {
32673
- if (!UUID_RE9.test(input.workspaceId) || !UUID_RE9.test(input.principalId)) {
32985
+ if (!UUID_RE10.test(input.workspaceId) || !UUID_RE10.test(input.principalId)) {
32674
32986
  throw new Error("listener workspace and principal ids must be UUIDs");
32675
32987
  }
32676
32988
  if (!input.profileId || input.profileId.includes("\0")) {
@@ -32702,7 +33014,7 @@ function parseListenerEffectRecord(raw, expectedId) {
32702
33014
  throw new Error("stored listener effect is malformed");
32703
33015
  }
32704
33016
  const row = value;
32705
- if (typeof row.version !== "number" || row.version !== 1 && row.version !== 2 || typeof row.signalId !== "string" || row.signalId.toLowerCase() !== expectedId || !UUID_RE9.test(row.signalId)) {
33017
+ if (typeof row.version !== "number" || row.version !== 1 && row.version !== 2 || typeof row.signalId !== "string" || row.signalId.toLowerCase() !== expectedId || !UUID_RE10.test(row.signalId)) {
32706
33018
  throw new Error("stored listener effect is malformed");
32707
33019
  }
32708
33020
  if (row.version === 1) {
@@ -32719,7 +33031,7 @@ function upcastV1Ask(row) {
32719
33031
  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))) {
32720
33032
  throw new Error("stored listener effect is malformed");
32721
33033
  }
32722
- if (row.replySignalId !== null && !UUID_RE9.test(row.replySignalId)) {
33034
+ if (row.replySignalId !== null && !UUID_RE10.test(row.replySignalId)) {
32723
33035
  throw new Error("stored listener effect is malformed");
32724
33036
  }
32725
33037
  return {
@@ -32758,7 +33070,7 @@ function parseV2Record(row) {
32758
33070
  if (typeof row.commandId !== "string" || !COMMAND_ID_RE2.test(row.commandId) || row.state === "observed") {
32759
33071
  throw new Error("stored listener effect is malformed");
32760
33072
  }
32761
- if (row.replySignalId !== null && !UUID_RE9.test(row.replySignalId)) {
33073
+ if (row.replySignalId !== null && !UUID_RE10.test(row.replySignalId)) {
32762
33074
  throw new Error("stored listener effect is malformed");
32763
33075
  }
32764
33076
  }
@@ -32782,7 +33094,7 @@ function parseV2Record(row) {
32782
33094
  };
32783
33095
  }
32784
33096
  function newObservedNoteRecord(input) {
32785
- if (!UUID_RE9.test(input.signalId)) {
33097
+ if (!UUID_RE10.test(input.signalId)) {
32786
33098
  throw new Error("listener note signal id must be a UUID");
32787
33099
  }
32788
33100
  if (input.body.length < 1) {
@@ -32916,7 +33228,7 @@ var FileListenerEffectStore = class {
32916
33228
  );
32917
33229
  }
32918
33230
  checkedId(signalId) {
32919
- if (!UUID_RE9.test(signalId)) {
33231
+ if (!UUID_RE10.test(signalId)) {
32920
33232
  throw new Error("listener signal id must be a UUID");
32921
33233
  }
32922
33234
  return signalId.toLowerCase();
@@ -34007,7 +34319,7 @@ var CodexListenerModel = class {
34007
34319
  var import_node_crypto17 = require("node:crypto");
34008
34320
 
34009
34321
  // src/cloud/delivery.ts
34010
- 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;
34322
+ 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;
34011
34323
  var RFC3339_TIMESTAMP_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))$/i;
34012
34324
  var DELIVERY_KINDS = /* @__PURE__ */ new Set(["ask", "note"]);
34013
34325
  var SENDER_OWNER_RELATIONS2 = /* @__PURE__ */ new Set([
@@ -34089,7 +34401,7 @@ var DeliveryProtocolError = class extends Error {
34089
34401
  }
34090
34402
  };
34091
34403
  function checkedUuid3(value, field) {
34092
- if (typeof value !== "string" || !UUID_RE10.test(value)) {
34404
+ if (typeof value !== "string" || !UUID_RE11.test(value)) {
34093
34405
  throw new DeliveryProtocolError(
34094
34406
  `delivery response returned a malformed ${field}`
34095
34407
  );
@@ -34200,7 +34512,7 @@ function checkedClaimCapabilities(value) {
34200
34512
  }
34201
34513
  function checkedOptionalUuidArray(value, field) {
34202
34514
  if (value === void 0) return;
34203
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE10.test(item))) {
34515
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE11.test(item))) {
34204
34516
  throw new DeliveryProtocolError(
34205
34517
  `delivery response returned a malformed ${field}`
34206
34518
  );
@@ -34347,7 +34659,7 @@ function checkedCommandId(value) {
34347
34659
  return value;
34348
34660
  }
34349
34661
  function checkedUuidRequest(value, field) {
34350
- if (!UUID_RE10.test(value)) {
34662
+ if (!UUID_RE11.test(value)) {
34351
34663
  throw new Error(`${field} must be a UUID for an agent delivery command`);
34352
34664
  }
34353
34665
  }
@@ -34556,7 +34868,7 @@ var DeliveryCommandClient = class {
34556
34868
 
34557
34869
  // src/listener/main-routing.ts
34558
34870
  var import_node_path14 = require("node:path");
34559
- 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;
34871
+ 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;
34560
34872
  var MAX_QUEUE_BYTES = 1024 * 1024;
34561
34873
  var QUEUE_FILE = "pending-for-main.json";
34562
34874
  var QUEUE_LOCK = "pending-for-main";
@@ -34610,7 +34922,7 @@ function parseEntry(value) {
34610
34922
  if (Object.keys(row).some((key2) => !allowed.has(key2))) {
34611
34923
  throw new Error("stored pending-for-main entry is malformed");
34612
34924
  }
34613
- if (typeof row.signalId !== "string" || !UUID_RE11.test(row.signalId) || typeof row.workspaceId !== "string" || !UUID_RE11.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE11.test(row.principalId) || typeof row.fromId !== "string" || !UUID_RE11.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)) {
34925
+ 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)) {
34614
34926
  throw new Error("stored pending-for-main entry is malformed");
34615
34927
  }
34616
34928
  return {
@@ -34746,7 +35058,7 @@ var LISTENER_REPLY_ONLY_MINIMUM_MS = SIGNAL_REQUEST_TIMEOUT_MS + LISTENER_ACK_ON
34746
35058
  var LISTENER_PROMPT_START_MINIMUM_MS = SIGNAL_READ_TIMEOUT_MS + ACP_DEFAULT_REQUEST_TIMEOUT_MS + LISTENER_REPLY_ONLY_MINIMUM_MS;
34747
35059
  var LISTENER_DELIVERY_RETRY_INITIAL_MS = 500;
34748
35060
  var LISTENER_DELIVERY_RETRY_MAX_MS = 3e4;
34749
- 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;
35061
+ 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;
34750
35062
  var ListenerCapabilityError = class extends Error {
34751
35063
  code;
34752
35064
  constructor(code, message) {
@@ -35021,7 +35333,7 @@ async function runListenerRuntime(options) {
35021
35333
  new Error("listener instance id and delivery journal must be configured together")
35022
35334
  );
35023
35335
  }
35024
- if (hasInstanceId && !UUID_RE12.test(options.listenerInstanceId)) {
35336
+ if (hasInstanceId && !UUID_RE13.test(options.listenerInstanceId)) {
35025
35337
  return await closeBeforeStart(
35026
35338
  options.model,
35027
35339
  new Error("listener instance id must be a UUID")
@@ -35844,7 +36156,7 @@ async function runListenerRuntime(options) {
35844
36156
  var import_node_net = require("node:net");
35845
36157
  var import_promises9 = require("node:fs/promises");
35846
36158
  var import_node_path15 = require("node:path");
35847
- 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;
36159
+ 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;
35848
36160
  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-]+)*)?$/;
35849
36161
  var MAX_STATUS_BYTES = 16 * 1024;
35850
36162
  var MAX_CONTROL_BYTES = 8 * 1024;
@@ -35950,10 +36262,10 @@ function parseStatus(raw) {
35950
36262
  throw new Error("stored listener status is malformed");
35951
36263
  }
35952
36264
  }
35953
- const nullableUuid2 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE13.test(candidate);
36265
+ const nullableUuid2 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE14.test(candidate);
35954
36266
  const nullableCount = (candidate) => candidate === null || typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate >= 0;
35955
- const nullableTimestamp = (candidate) => candidate === null || typeof candidate === "string" && Number.isFinite(Date.parse(candidate));
35956
- if (row.version !== 1 || typeof row.instanceId !== "string" || !UUID_RE13.test(row.instanceId) || row.provider !== "grok" && row.provider !== "opencode" && row.provider !== "claude" && row.provider !== "codex" || typeof row.profileId !== "string" || typeof row.workspaceId !== "string" || !UUID_RE13.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE13.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 || nullableTimestamp(row.lastTerminalDeliveryFailureAt)) || !(row.lastClaimAt === void 0 || nullableTimestamp(row.lastClaimAt)) || !(row.lastAckAt === void 0 || nullableTimestamp(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)) {
36267
+ const nullableTimestamp2 = (candidate) => candidate === null || typeof candidate === "string" && Number.isFinite(Date.parse(candidate));
36268
+ 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)) {
35957
36269
  throw new Error("stored listener status is malformed");
35958
36270
  }
35959
36271
  const routeMode = row.routeMode ?? "worker";
@@ -36302,7 +36614,7 @@ async function queryListenerControl(paths, command2, timeoutMs = CONTROL_TIMEOUT
36302
36614
 
36303
36615
  // src/listener/supervisor.ts
36304
36616
  var import_node_crypto18 = require("node:crypto");
36305
- 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;
36617
+ 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;
36306
36618
  var LISTENER_RESTART_MAX_ATTEMPTS = 5;
36307
36619
  var LISTENER_RESTART_INITIAL_MS = 1e3;
36308
36620
  var LISTENER_RESTART_MAX_MS = 6e4;
@@ -36431,7 +36743,7 @@ async function runListenerSupervisor(options) {
36431
36743
  // before the socket can answer, before any status/event persistence.
36432
36744
  initialize: prepare ? async () => {
36433
36745
  const selected = await prepare(proposedInstanceId);
36434
- if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE14.test(selected.instanceId)) {
36746
+ if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE15.test(selected.instanceId)) {
36435
36747
  throw new Error("listener prepare returned an invalid instance id");
36436
36748
  }
36437
36749
  status = { ...status, instanceId: selected.instanceId };
@@ -36789,7 +37101,7 @@ async function waitForListenerReady(paths, options = {}) {
36789
37101
  // src/listener/delivery-journal.ts
36790
37102
  var import_node_path16 = require("node:path");
36791
37103
  var import_node_util2 = require("node:util");
36792
- 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}$/;
37104
+ 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}$/;
36793
37105
  var COMMAND_ID_RE3 = /^[A-Za-z0-9_-]{8,72}$/;
36794
37106
  var SIGNAL_FINGERPRINT_RE = /^[0-9a-f]{64}$/;
36795
37107
  var MAX_JOURNAL_BYTES = 8192;
@@ -36883,7 +37195,7 @@ var ALLOWED_ERROR_CODES = /* @__PURE__ */ new Set([
36883
37195
  "credential_unavailable"
36884
37196
  ]);
36885
37197
  function claimCommandId(listenerInstanceId, claimOrdinal) {
36886
- if (!UUID_RE15.test(listenerInstanceId)) {
37198
+ if (!UUID_RE16.test(listenerInstanceId)) {
36887
37199
  throw new Error("stored delivery journal is malformed");
36888
37200
  }
36889
37201
  if (!Number.isSafeInteger(claimOrdinal) || claimOrdinal < 0) {
@@ -36898,7 +37210,7 @@ function claimCommandId(listenerInstanceId, claimOrdinal) {
36898
37210
  return id;
36899
37211
  }
36900
37212
  function ackCommandId(leaseId) {
36901
- if (!UUID_RE15.test(leaseId)) {
37213
+ if (!UUID_RE16.test(leaseId)) {
36902
37214
  throw new Error("stored delivery journal is malformed");
36903
37215
  }
36904
37216
  const cleanLease = leaseId.toLowerCase().replace(/-/g, "");
@@ -36981,19 +37293,19 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId) {
36981
37293
  if (row.version !== 1) {
36982
37294
  throw new Error("stored delivery journal is malformed");
36983
37295
  }
36984
- if (typeof row.workspaceId !== "string" || !UUID_RE15.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
37296
+ if (typeof row.workspaceId !== "string" || !UUID_RE16.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
36985
37297
  throw new Error("stored delivery journal is malformed");
36986
37298
  }
36987
37299
  if (expectedWorkspaceId && row.workspaceId !== expectedWorkspaceId.toLowerCase()) {
36988
37300
  throw new Error("stored delivery journal is malformed");
36989
37301
  }
36990
- if (typeof row.principalId !== "string" || !UUID_RE15.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
37302
+ if (typeof row.principalId !== "string" || !UUID_RE16.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
36991
37303
  throw new Error("stored delivery journal is malformed");
36992
37304
  }
36993
37305
  if (expectedPrincipalId && row.principalId !== expectedPrincipalId.toLowerCase()) {
36994
37306
  throw new Error("stored delivery journal is malformed");
36995
37307
  }
36996
- if (typeof row.listenerInstanceId !== "string" || !UUID_RE15.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
37308
+ if (typeof row.listenerInstanceId !== "string" || !UUID_RE16.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
36997
37309
  throw new Error("stored delivery journal is malformed");
36998
37310
  }
36999
37311
  if (!Number.isSafeInteger(row.nextClaimOrdinal) || row.nextClaimOrdinal < 0) {
@@ -37057,10 +37369,10 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId) {
37057
37369
  if (active.claimLastAttemptAt === null) {
37058
37370
  throw new Error("stored delivery journal is malformed");
37059
37371
  }
37060
- if (typeof active.signalId !== "string" || !UUID_RE15.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
37372
+ if (typeof active.signalId !== "string" || !UUID_RE16.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
37061
37373
  throw new Error("stored delivery journal is malformed");
37062
37374
  }
37063
- if (typeof active.leaseId !== "string" || !UUID_RE15.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
37375
+ if (typeof active.leaseId !== "string" || !UUID_RE16.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
37064
37376
  throw new Error("stored delivery journal is malformed");
37065
37377
  }
37066
37378
  if (!isValidIsoTimestamp(active.leasedUntil) || Date.parse(active.leasedUntil) <= Date.parse(active.claimCreatedAt)) {
@@ -37132,7 +37444,7 @@ var FileListenerDeliveryJournal = class {
37132
37444
  ["profileId", "workspaceId", "principalId"],
37133
37445
  "delivery journal configuration rejected"
37134
37446
  );
37135
- if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE15.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE15.test(options.principalId)) {
37447
+ 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)) {
37136
37448
  throw new Error("delivery journal configuration rejected");
37137
37449
  }
37138
37450
  if (options.stateDirectory !== void 0) {
@@ -37253,7 +37565,7 @@ var FileListenerDeliveryJournal = class {
37253
37565
  ["signalId", "leaseId", "leasedUntil"],
37254
37566
  "delivery journal mutation rejected"
37255
37567
  );
37256
- if (typeof input.signalId !== "string" || !UUID_RE15.test(input.signalId) || typeof input.leaseId !== "string" || !UUID_RE15.test(input.leaseId) || !isValidIsoTimestamp(input.leasedUntil) || input.signalFingerprint !== void 0 && (typeof input.signalFingerprint !== "string" || !SIGNAL_FINGERPRINT_RE.test(input.signalFingerprint))) {
37568
+ 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))) {
37257
37569
  throw new Error("delivery journal mutation rejected");
37258
37570
  }
37259
37571
  const canonicalSignalId = input.signalId.toLowerCase();
@@ -37385,7 +37697,7 @@ async function openListenerDeliveryJournal(options) {
37385
37697
  ["profileId", "workspaceId", "principalId", "proposedListenerInstanceId"],
37386
37698
  "delivery journal configuration rejected"
37387
37699
  );
37388
- if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE15.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE15.test(options.principalId) || typeof options.proposedListenerInstanceId !== "string" || !UUID_RE15.test(options.proposedListenerInstanceId)) {
37700
+ 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)) {
37389
37701
  throw new Error("delivery journal configuration rejected");
37390
37702
  }
37391
37703
  if (options.stateDirectory !== void 0) {
@@ -37600,7 +37912,7 @@ async function spawnDetachedListener(options) {
37600
37912
  // src/listener/hook.ts
37601
37913
  var import_promises10 = require("node:fs/promises");
37602
37914
  var import_node_path18 = require("node:path");
37603
- 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;
37915
+ 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;
37604
37916
  var TOKEN_RE = /^swm_agt_[A-Za-z0-9_-]{43}$/;
37605
37917
  var INSTANCE_KEY_RE = /^[0-9a-f]{64}$/;
37606
37918
  var MAX_HOOK_CREDENTIAL_BYTES = 8 * 1024;
@@ -37641,7 +37953,7 @@ function parseListenerCredential(raw) {
37641
37953
  "principalId",
37642
37954
  "credential",
37643
37955
  "updatedAt"
37644
- ]) || 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_RE16.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE16.test(row.principalId) || typeof row.credential !== "string" || !TOKEN_RE.test(row.credential) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt))) {
37956
+ ]) || 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))) {
37645
37957
  throw new Error("stored listener hook credential is malformed");
37646
37958
  }
37647
37959
  const target2 = cloudTarget(row.targetUrl, row.anonKey);
@@ -37701,7 +38013,7 @@ function parseSurface(raw) {
37701
38013
  const row = value;
37702
38014
  if (Object.keys(row).some(
37703
38015
  (key2) => key2 !== "version" && key2 !== "surfacedSignalIds" && key2 !== "reportedDroppedCount" && key2 !== "credentialFailureReported"
37704
- ) || row.version !== 1 || !Array.isArray(row.surfacedSignalIds) || row.surfacedSignalIds.length > HOOK_SURFACED_IDS_MAX || row.surfacedSignalIds.some((id) => typeof id !== "string" || !UUID_RE16.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")) {
38016
+ ) || 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")) {
37705
38017
  throw new Error("stored listener hook surface state is malformed");
37706
38018
  }
37707
38019
  const ids = row.surfacedSignalIds.map((id) => String(id).toLowerCase());
@@ -37738,7 +38050,7 @@ var FileHookSurfaceStore = class {
37738
38050
  const unseen = [];
37739
38051
  for (const item of items) {
37740
38052
  const signalId = item.signalId.toLowerCase();
37741
- if (!UUID_RE16.test(signalId) || seen.has(signalId)) continue;
38053
+ if (!UUID_RE17.test(signalId) || seen.has(signalId)) continue;
37742
38054
  seen.add(signalId);
37743
38055
  unseen.push(item);
37744
38056
  }
@@ -37761,7 +38073,7 @@ var FileHookSurfaceStore = class {
37761
38073
  const seen = new Set(state.surfacedSignalIds);
37762
38074
  for (const signalId of options.signalIds ?? []) {
37763
38075
  const checked = signalId.toLowerCase();
37764
- if (UUID_RE16.test(checked)) seen.add(checked);
38076
+ if (UUID_RE17.test(checked)) seen.add(checked);
37765
38077
  }
37766
38078
  await writeSecureJsonFile(
37767
38079
  this.path,
@@ -37864,7 +38176,17 @@ async function discoverContexts(stateDirectory2, isListenerLive = listenerIsLive
37864
38176
  instanceDirectory
37865
38177
  );
37866
38178
  const statusIsLive = storedStatus === null ? null : await isListenerLive(storedStatus);
37867
- if (statusIsLive === false) continue;
38179
+ if (statusIsLive === false) {
38180
+ contexts.push({
38181
+ instanceDirectory,
38182
+ paths: storedStatus.paths,
38183
+ status: storedStatus.status,
38184
+ listenerLive: false,
38185
+ credential: null,
38186
+ credentialReadFailed: false
38187
+ });
38188
+ continue;
38189
+ }
37868
38190
  await deleteSecureJsonFile(
37869
38191
  (0, import_node_path18.join)(instanceDirectory, RETIRED_HOOK_CREDENTIAL_FILE)
37870
38192
  ).catch(() => void 0);
@@ -37874,6 +38196,7 @@ async function discoverContexts(stateDirectory2, isListenerLive = listenerIsLive
37874
38196
  instanceDirectory,
37875
38197
  paths: storedStatus?.paths ?? null,
37876
38198
  status: storedStatus?.status ?? null,
38199
+ listenerLive: statusIsLive,
37877
38200
  credential,
37878
38201
  credentialReadFailed: credential === null && storedStatus !== null
37879
38202
  });
@@ -37883,6 +38206,7 @@ async function discoverContexts(stateDirectory2, isListenerLive = listenerIsLive
37883
38206
  instanceDirectory,
37884
38207
  paths: storedStatus.paths,
37885
38208
  status: storedStatus.status,
38209
+ listenerLive: statusIsLive,
37886
38210
  credential: null,
37887
38211
  credentialReadFailed: true
37888
38212
  });
@@ -37923,6 +38247,24 @@ function renderHookSignal(item) {
37923
38247
  `${replyLabel} cswarm reply ${item.signalId} "<answer>" --workspace-id ${item.workspaceId}`
37924
38248
  ].join("\n");
37925
38249
  }
38250
+ function listenerRestartCommand(status) {
38251
+ const routeMode = status.routeMode ?? "worker";
38252
+ return [
38253
+ "cswarm listen start",
38254
+ "--agent-token-stdin",
38255
+ `--workspace-id ${status.workspaceId}`,
38256
+ `--provider ${status.provider}`,
38257
+ ...status.permissionMode ? [`--permissions ${status.permissionMode}`] : [],
38258
+ `--route ${routeMode}`,
38259
+ ...routeMode === "split" && status.deferOverChars !== null && status.deferOverChars !== void 0 ? [`--defer-over ${status.deferOverChars}`] : []
38260
+ ].join(" ");
38261
+ }
38262
+ function renderStrandedQueue(context, count2) {
38263
+ const status = context.status;
38264
+ const noun = count2 === 1 ? "message" : "messages";
38265
+ const verb = count2 === 1 ? "was" : "were";
38266
+ return `[CommonSwarm] ${count2} ${noun} ${verb} waiting for agent ${status.principalId} in listener ${status.instanceId}, but that listener is no longer running. Restart it by piping the same agent credential into: ` + listenerRestartCommand(status);
38267
+ }
37926
38268
  async function inboxItems(context, options) {
37927
38269
  const stored = context.credential;
37928
38270
  const target2 = cloudTarget(stored.targetUrl, stored.anonKey);
@@ -37982,11 +38324,11 @@ async function checkListenerHooks(options) {
37982
38324
  options.isListenerLive ?? listenerIsLive
37983
38325
  );
37984
38326
  if (contexts.length === 0) return "";
37985
- const networkAllowed = await reserveCheck(
38327
+ const networkAllowed = contexts.some((context) => context.listenerLive !== false) ? await reserveCheck(
37986
38328
  stateDirectory2,
37987
38329
  cooldownSeconds * 1e3,
37988
38330
  now()
37989
- );
38331
+ ) : false;
37990
38332
  const checks = await Promise.all(contexts.map(async (context) => {
37991
38333
  const queue = new FilePendingMainQueue(context.instanceDirectory);
37992
38334
  const pending = await queue.read();
@@ -38011,7 +38353,7 @@ async function checkListenerHooks(options) {
38011
38353
  context,
38012
38354
  queue,
38013
38355
  pending,
38014
- droppedCount: stats.droppedCount,
38356
+ droppedCount: context.listenerLive === false ? 0 : stats.droppedCount,
38015
38357
  network,
38016
38358
  credentialFailure,
38017
38359
  credentialHealthy
@@ -38027,6 +38369,11 @@ async function checkListenerHooks(options) {
38027
38369
  check.droppedCount
38028
38370
  );
38029
38371
  blocks.push(...staged.unseen.map(renderHookSignal));
38372
+ const pendingSignalIds = new Set(check.pending.map((entry) => entry.signalId));
38373
+ const unseenPending = staged.unseen.filter((item) => pendingSignalIds.has(item.signalId));
38374
+ if (check.context.listenerLive === false && unseenPending.length > 0) {
38375
+ blocks.push(renderStrandedQueue(check.context, unseenPending.length));
38376
+ }
38030
38377
  const reportDrops = staged.droppedSinceLastCheck > 0;
38031
38378
  if (reportDrops) blocks.push(renderDroppedAsks(staged.droppedSinceLastCheck));
38032
38379
  const reportCredentialFailure = check.credentialFailure !== null && !staged.credentialFailureReported;
@@ -38037,12 +38384,14 @@ async function checkListenerHooks(options) {
38037
38384
  blocks.push(warning);
38038
38385
  }
38039
38386
  }
38040
- const pendingSignalIds = new Set(check.pending.map((entry) => entry.signalId));
38041
38387
  commits.push({
38042
38388
  check,
38043
38389
  store: store2,
38044
38390
  signalIds: staged.unseen.map((item) => item.signalId),
38045
- printedPendingSignalIds: staged.unseen.map((item) => item.signalId).filter((signalId) => pendingSignalIds.has(signalId)),
38391
+ // Every staged queue entry is either written by this run or was committed
38392
+ // after an earlier successful write. Removing both keeps the queue bounded
38393
+ // without re-printing entries below the exactly-once high-water.
38394
+ settledPendingSignalIds: check.pending.map((item) => item.signalId),
38046
38395
  reportDrops,
38047
38396
  reportCredentialFailure
38048
38397
  });
@@ -38056,7 +38405,7 @@ async function checkListenerHooks(options) {
38056
38405
  ...commit.reportCredentialFailure ? { credentialFailureReported: true } : commit.check.credentialHealthy ? { credentialFailureReported: false } : {}
38057
38406
  });
38058
38407
  const remainingCount = await commit.check.queue.remove(
38059
- new Set(commit.printedPendingSignalIds),
38408
+ new Set(commit.settledPendingSignalIds),
38060
38409
  HOOK_LOCK_TIMEOUT_MS
38061
38410
  );
38062
38411
  if (commit.check.context.paths !== null && commit.check.context.status !== null) {
@@ -38181,7 +38530,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
38181
38530
  "reveal-anon-key",
38182
38531
  "write"
38183
38532
  ]);
38184
- 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;
38533
+ 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;
38185
38534
  var AGENT_CREDENTIAL_MESSAGE = "Agent credential minted. It is bound to this task and run so the agent's work stays scoped and attributable.";
38186
38535
  var AGENT_CREDENTIAL_MESSAGE_D088 = "Agent credential minted. It is bound to this run, so the agent's work is attributable to it.";
38187
38536
  var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
@@ -38189,8 +38538,8 @@ var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
38189
38538
  AGENT_CREDENTIAL_MESSAGE_D088
38190
38539
  ];
38191
38540
  function packageVersion() {
38192
- if ("0.1.30".length > 0) {
38193
- return "0.1.30";
38541
+ if ("0.1.32".length > 0) {
38542
+ return "0.1.32";
38194
38543
  }
38195
38544
  try {
38196
38545
  const value = JSON.parse(
@@ -38309,6 +38658,7 @@ Usage:
38309
38658
  cswarm note "<text>" [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--to <member|agent>] [--about <ref>] [--until <dur>] [--json] # text: 1..8000 characters
38310
38659
  cswarm ask "<text>" [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--to <member|agent>] [--about <ref>] [--until <dur>] [--wait <seconds>] [--json] # text: 1..8000 characters
38311
38660
  cswarm reply <signal-id> "<text>" [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--until <dur>] [--json]
38661
+ cswarm receipt <signal-id> --agent-token-stdin [--url <url> --anon-key <key>] --workspace-id <uuid> [--json]
38312
38662
  cswarm feed [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--about <ref>] [--kind <kind>] [--since <timestamp>] [--limit <n>] [--include-stale] [--json]
38313
38663
  cswarm inbox [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--kind <kind>] [--about <ref>] [--since <timestamp>] [--limit <n>] [--include-stale] [--wait <seconds>] [--json]
38314
38664
  cswarm inbox --follow --ndjson [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--kind <kind>] [--about <ref>] [--since <timestamp>] [--limit <n>] [--include-stale]
@@ -38355,6 +38705,7 @@ Credential selection for command/dogfood:
38355
38705
  One that persists or references the credential needs the complete
38356
38706
  JSON artifact, because it needs a field a bare secret does not carry:
38357
38707
  members reads only -- either form
38708
+ receipt reads only -- either form
38358
38709
  file put, file ls, file get, file rm, file restore
38359
38710
  read and command, nothing persisted -- either form
38360
38711
  feedback command only, nothing persisted -- either form
@@ -38524,7 +38875,7 @@ function parsedAgentCredential(value) {
38524
38875
  const withExpiry = [...requiredKeys, "expires_at"].sort();
38525
38876
  const actualKeys = Object.keys(artifact).sort();
38526
38877
  const shape = actualKeys.length === requiredKeys.length ? requiredKeys : withExpiry;
38527
- 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_RE17.test(artifact.principal_id) || typeof artifact.token_id !== "string" || !UUID_RE17.test(artifact.token_id) || typeof artifact.run_id !== "string" || !UUID_RE17.test(artifact.run_id) || typeof artifact.agent_token !== "string") {
38878
+ 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") {
38528
38879
  throw new Error("agent credential JSON is malformed");
38529
38880
  }
38530
38881
  let expiresAt = null;
@@ -38641,7 +38992,7 @@ async function workspaceId(args, cloud, human, options = {}) {
38641
38992
  warn: options.warn ?? writeWorkspaceWarning
38642
38993
  });
38643
38994
  }
38644
- function uuid3(value, field) {
38995
+ function uuid4(value, field) {
38645
38996
  if (value === void 0 || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
38646
38997
  throw new Error(`server returned a malformed ${field}`);
38647
38998
  }
@@ -38746,7 +39097,7 @@ async function runNew(args) {
38746
39097
  throw error;
38747
39098
  }
38748
39099
  const response = acceptedConnect("workspace creation", result);
38749
- const created = uuid3(response.workspace_id, "workspace_id");
39100
+ const created = uuid4(response.workspace_id, "workspace_id");
38750
39101
  if (created !== proposedId) {
38751
39102
  throw new Error(
38752
39103
  "the server confirmed a different workspace than this command created; run cswarm workspaces before doing anything else"
@@ -38762,7 +39113,7 @@ async function runNew(args) {
38762
39113
  project: {
38763
39114
  workspace_id: created,
38764
39115
  name,
38765
- stream_id: typeof response.stream_id === "string" && UUID_RE17.test(response.stream_id) ? response.stream_id : null
39116
+ stream_id: typeof response.stream_id === "string" && UUID_RE18.test(response.stream_id) ? response.stream_id : null
38766
39117
  }
38767
39118
  });
38768
39119
  return;
@@ -39019,7 +39370,7 @@ async function runInvite(args) {
39019
39370
  );
39020
39371
  }
39021
39372
  assertInvitationToken(response.invitation_token);
39022
- const responseWorkspaceId = uuid3(response.workspace_id, "workspace_id");
39373
+ const responseWorkspaceId = uuid4(response.workspace_id, "workspace_id");
39023
39374
  if (typeof response.workspace_name !== "string" || typeof response.inviter_display_name !== "string") {
39024
39375
  throw new Error(
39025
39376
  "the invitation was created without its fresh display labels; run invite again to issue a complete link"
@@ -39039,7 +39390,7 @@ async function runInvite(args) {
39039
39390
  printJson({
39040
39391
  message: "Invitation created. Share the one-time link below with its intended recipient. It can be accepted once before it expires; use a GitHub account with a distinct verified email for a second person.",
39041
39392
  status: response.status,
39042
- invitation_id: uuid3(response.invitation_id, "invitation_id"),
39393
+ invitation_id: uuid4(response.invitation_id, "invitation_id"),
39043
39394
  invite_link: inviteLink
39044
39395
  });
39045
39396
  }
@@ -39151,7 +39502,7 @@ async function runLegacyAccept(args) {
39151
39502
  { kind: "accept_invitation", token: invitationToken }
39152
39503
  )
39153
39504
  );
39154
- const acceptedWorkspace = uuid3(response.workspace_id, "workspace_id");
39505
+ const acceptedWorkspace = uuid4(response.workspace_id, "workspace_id");
39155
39506
  await writeWorkspaceDefault(human.store, human.userId, acceptedWorkspace);
39156
39507
  await writeCurrentTarget(cloud);
39157
39508
  printJson({
@@ -39297,7 +39648,7 @@ async function runPrincipal(args) {
39297
39648
  "Agent identity created. It makes this machine's agent auditable inside the shared workspace. Its name is visible to everyone in the workspace, so avoid naming it after anything private."
39298
39649
  ),
39299
39650
  status: response.status,
39300
- principal_id: uuid3(response.principal_id, "principal_id")
39651
+ principal_id: uuid4(response.principal_id, "principal_id")
39301
39652
  });
39302
39653
  return;
39303
39654
  }
@@ -39405,8 +39756,8 @@ async function runToken(args) {
39405
39756
  );
39406
39757
  printJson(agentCredentialArtifact({
39407
39758
  principalId,
39408
- tokenId: uuid3(response.token_id, "token_id"),
39409
- runId: uuid3(response.run_id, "run_id"),
39759
+ tokenId: uuid4(response.token_id, "token_id"),
39760
+ runId: uuid4(response.run_id, "run_id"),
39410
39761
  token: response.agent_token,
39411
39762
  expiresAt
39412
39763
  }));
@@ -39536,7 +39887,7 @@ async function runLinkNew(args) {
39536
39887
  2
39537
39888
  );
39538
39889
  const taskId = args.required("task-id");
39539
- if (!UUID_RE17.test(taskId)) {
39890
+ if (!UUID_RE18.test(taskId)) {
39540
39891
  throw new Error("--task-id must be the work item's UUID");
39541
39892
  }
39542
39893
  const site = capabilitySiteOrigin(
@@ -39566,11 +39917,11 @@ async function runLinkNew(args) {
39566
39917
  );
39567
39918
  if (response.capability_token === void 0) {
39568
39919
  throw new Error(
39569
- `this link was created on a prior attempt, and its credential is shown only in a fresh response \u2014 the server keeps just a hash, so it cannot be shown again; run cswarm link new to issue another, then run cswarm link revoke --capability-id ${uuid3(response.capability_id, "capability_id")} to withdraw the one you cannot see`
39920
+ `this link was created on a prior attempt, and its credential is shown only in a fresh response \u2014 the server keeps just a hash, so it cannot be shown again; run cswarm link new to issue another, then run cswarm link revoke --capability-id ${uuid4(response.capability_id, "capability_id")} to withdraw the one you cannot see`
39570
39921
  );
39571
39922
  }
39572
39923
  assertCapabilityToken(response.capability_token);
39573
- const capabilityId = uuid3(response.capability_id, "capability_id");
39924
+ const capabilityId = uuid4(response.capability_id, "capability_id");
39574
39925
  const expiresAt = capabilityTimestamp(response.expires_at, "expires_at");
39575
39926
  const url = capabilityUrl(site, response.capability_token);
39576
39927
  if (args.has("json")) {
@@ -39596,7 +39947,7 @@ async function runLinkRevoke(args) {
39596
39947
  2
39597
39948
  );
39598
39949
  const capabilityId = args.required("capability-id");
39599
- if (!UUID_RE17.test(capabilityId)) {
39950
+ if (!UUID_RE18.test(capabilityId)) {
39600
39951
  throw new Error(
39601
39952
  "--capability-id must be the id printed when the link was created"
39602
39953
  );
@@ -39614,7 +39965,7 @@ async function runLinkRevoke(args) {
39614
39965
  { kind: "revoke_capability_url", capability_id: capabilityId }
39615
39966
  )
39616
39967
  );
39617
- const revoked = uuid3(response.capability_id, "capability_id");
39968
+ const revoked = uuid4(response.capability_id, "capability_id");
39618
39969
  const revokedAt = capabilityTimestamp(response.revoked_at, "revoked_at");
39619
39970
  const message = renderCapabilityRevoke(revoked, revokedAt);
39620
39971
  if (args.has("json")) {
@@ -40175,7 +40526,7 @@ async function runReply(args) {
40175
40526
  "json"
40176
40527
  ], 3);
40177
40528
  const signalId = args.positionals[1];
40178
- if (signalId === void 0 || !UUID_RE17.test(signalId)) {
40529
+ if (signalId === void 0 || !UUID_RE18.test(signalId)) {
40179
40530
  throw new Error("reply requires the signal UUID being answered");
40180
40531
  }
40181
40532
  const body = args.positionals[2];
@@ -40405,6 +40756,52 @@ async function runSignalRead(args, inbox) {
40405
40756
  })}
40406
40757
  `);
40407
40758
  }
40759
+ async function runReceipt(args) {
40760
+ args.assertShape([
40761
+ ...TARGET_FLAGS,
40762
+ "workspace-id",
40763
+ ...CREDENTIAL_FLAGS,
40764
+ "json"
40765
+ ], 2);
40766
+ const signalId = args.positionals[1];
40767
+ if (!UUID_RE18.test(signalId)) {
40768
+ throw new Error("signal-id must be a UUID");
40769
+ }
40770
+ if (!args.has("agent-token-stdin")) {
40771
+ throw new Error(
40772
+ "receipt reads signals sent by an agent; provide --agent-token-stdin and --workspace-id"
40773
+ );
40774
+ }
40775
+ const cloud = await target(args);
40776
+ const selected = await commandWorkspaceAndCredential(args, cloud, {
40777
+ validateHumanWorkspace: true
40778
+ });
40779
+ let result;
40780
+ try {
40781
+ result = await readAgentDeliveryReceipts(
40782
+ cloud,
40783
+ selected.bearer,
40784
+ selected.selectedWorkspace,
40785
+ signalId
40786
+ );
40787
+ } catch (error) {
40788
+ const reason = error instanceof SignalReadTimeoutError ? `the read reached its ${SIGNAL_READ_TIMEOUT_MS / 1e3}-second deadline` : error instanceof DeliveryReceiptReadError && error.status !== null ? `the read service refused it with HTTP ${error.status}` : error instanceof DeliveryReceiptReadError && error.code === "not_author" ? "the service could not verify that this agent sent the signal" : error instanceof DeliveryReceiptReadError && error.code === "protocol" ? "the read service returned an invalid receipt response" : "the read service could not be reached";
40789
+ throw new Error(
40790
+ `Delivery receipt lookup failed because ${reason}. No delivery state was shown, so do not treat this signal as pending, delivered, or failed. Retry with: cswarm receipt ${signalId.toLowerCase()} --workspace-id ${selected.selectedWorkspace}`
40791
+ );
40792
+ }
40793
+ const report = {
40794
+ ...result,
40795
+ workspaceId: selected.selectedWorkspace,
40796
+ signalId: signalId.toLowerCase()
40797
+ };
40798
+ if (args.has("json")) {
40799
+ printJson(signalReceiptJsonPayload(report));
40800
+ return;
40801
+ }
40802
+ process.stdout.write(`${renderSignalReceiptReport(report)}
40803
+ `);
40804
+ }
40408
40805
  async function runInboxFollowCommand(args) {
40409
40806
  const cloud = await target(args);
40410
40807
  const selected = await commandWorkspaceAndCredential(args, cloud, {
@@ -40505,7 +40902,7 @@ async function runInboxFollowCommand(args) {
40505
40902
  }
40506
40903
  }
40507
40904
  function listenerUuid(value, flag) {
40508
- if (!value || !UUID_RE17.test(value)) {
40905
+ if (!value || !UUID_RE18.test(value)) {
40509
40906
  throw new Error(`--${flag} must be a UUID`);
40510
40907
  }
40511
40908
  return value.toLowerCase();
@@ -40741,7 +41138,7 @@ function renderListenerStatus(status) {
40741
41138
  }
40742
41139
  if (pendingForMainCount > 0) {
40743
41140
  lines.push(
40744
- `${pendingForMainCount} asks waiting for this session; they surface at your next prompt, or run cswarm hook check.`
41141
+ status.state === "stopped" || status.state === "failed" ? `${pendingForMainCount} asks are stranded because this listener is not running. Restart it by piping the same agent credential into: ${listenerRestartCommand(status)}` : `${pendingForMainCount} asks waiting for this session; they surface at your next prompt, or run cswarm hook check.`
40745
41142
  );
40746
41143
  }
40747
41144
  }
@@ -40757,6 +41154,20 @@ function renderListenerStatus(status) {
40757
41154
  }
40758
41155
  return lines.join("\n");
40759
41156
  }
41157
+ async function unsurfacedPendingMainStats(instanceDirectory, fallback) {
41158
+ try {
41159
+ const queue = new FilePendingMainQueue(instanceDirectory);
41160
+ const pending = await queue.read();
41161
+ const stats = await queue.stats();
41162
+ const staged = await new FileHookSurfaceStore(instanceDirectory).stage(
41163
+ pending,
41164
+ stats.droppedCount
41165
+ );
41166
+ return { count: staged.unseen.length, droppedCount: stats.droppedCount };
41167
+ } catch {
41168
+ return fallback;
41169
+ }
41170
+ }
40760
41171
  function listenerFailureMessage(code, provider) {
40761
41172
  if (code === "version_below_floor") {
40762
41173
  if (provider === "codex") {
@@ -41231,9 +41642,10 @@ async function runListenStart(args) {
41231
41642
  if ((status.routeMode ?? "worker") !== "worker") {
41232
41643
  const recordedPending = status.pendingForMainCount ?? 0;
41233
41644
  const recordedDropped = status.droppedForMainCount ?? 0;
41234
- const queueStats = await new FilePendingMainQueue(
41235
- paths.instanceDirectory
41236
- ).stats().catch(() => ({ count: recordedPending, droppedCount: recordedDropped }));
41645
+ const queueStats = await unsurfacedPendingMainStats(
41646
+ paths.instanceDirectory,
41647
+ { count: recordedPending, droppedCount: recordedDropped }
41648
+ );
41237
41649
  status = {
41238
41650
  ...status,
41239
41651
  pendingForMainCount: queueStats.count,
@@ -41348,9 +41760,10 @@ async function runListenStatusOrStop(args, command2) {
41348
41760
  if ((status.routeMode ?? "worker") !== "worker") {
41349
41761
  const recordedPending = status.pendingForMainCount ?? 0;
41350
41762
  const recordedDropped = status.droppedForMainCount ?? 0;
41351
- const queueStats = await new FilePendingMainQueue(
41352
- paths.instanceDirectory
41353
- ).stats().catch(() => ({ count: recordedPending, droppedCount: recordedDropped }));
41763
+ const queueStats = await unsurfacedPendingMainStats(
41764
+ paths.instanceDirectory,
41765
+ { count: recordedPending, droppedCount: recordedDropped }
41766
+ );
41354
41767
  status = {
41355
41768
  ...status,
41356
41769
  pendingForMainCount: queueStats.count,
@@ -41552,7 +41965,7 @@ async function fileRows(context) {
41552
41965
  );
41553
41966
  }
41554
41967
  async function resolveFileSelector(context, selector) {
41555
- if (UUID_RE17.test(selector)) return selector.toLowerCase();
41968
+ if (UUID_RE18.test(selector)) return selector.toLowerCase();
41556
41969
  const rows3 = await fileRows(context);
41557
41970
  const match = rows3.find(
41558
41971
  (row) => row.name.toLowerCase() === selector.toLowerCase()
@@ -42064,6 +42477,10 @@ async function main() {
42064
42477
  await runReply(args);
42065
42478
  return;
42066
42479
  }
42480
+ if (verb === "receipt") {
42481
+ await runReceipt(args);
42482
+ return;
42483
+ }
42067
42484
  if (verb === "feed" || verb === "inbox") {
42068
42485
  await runSignalRead(args, verb === "inbox");
42069
42486
  return;
@@ -42140,7 +42557,7 @@ main().catch((error) => {
42140
42557
  if (error instanceof WorkspaceCliError) {
42141
42558
  const structured = error.structured();
42142
42559
  const verb = process.argv[2];
42143
- const json = process.argv.includes("--json") && (verb === "status" || verb === "workspaces" || verb === "use" || verb === "working-on" || verb === "note" || verb === "ask" || verb === "reply" || verb === "feed" || verb === "inbox");
42560
+ const json = process.argv.includes("--json") && (verb === "status" || verb === "workspaces" || verb === "use" || verb === "working-on" || verb === "note" || verb === "ask" || verb === "reply" || verb === "receipt" || verb === "feed" || verb === "inbox");
42144
42561
  if (json) {
42145
42562
  process.stdout.write(`${JSON.stringify(structured, null, 2)}
42146
42563
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commonswarm",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "CommonSwarm CLI — coordination for teams where people and AI agents work side by side.",
5
5
  "bin": {
6
6
  "cswarm": "cswarm.cjs"