commonswarm 0.1.31 → 0.1.33

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 +521 -75
  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,327 @@ 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
+ "queued",
29590
+ "expired",
29591
+ "failed_terminal"
29592
+ ]);
29593
+ function uuid3(value, field) {
29594
+ if (typeof value !== "string" || !UUID_RE8.test(value)) {
29595
+ throw new DeliveryReceiptReadError(
29596
+ "protocol",
29597
+ `delivery receipt returned a malformed ${field}`
29598
+ );
29599
+ }
29600
+ return value.toLowerCase();
29601
+ }
29602
+ function timestamp2(value, field) {
29603
+ if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) {
29604
+ throw new DeliveryReceiptReadError(
29605
+ "protocol",
29606
+ `delivery receipt returned a malformed ${field}`
29607
+ );
29608
+ }
29609
+ return value;
29610
+ }
29611
+ function nullableTimestamp(value, field) {
29612
+ return value === null ? null : timestamp2(value, field);
29613
+ }
29614
+ function nonNegativeInteger(value, field) {
29615
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
29616
+ throw new DeliveryReceiptReadError(
29617
+ "protocol",
29618
+ `delivery receipt returned a malformed ${field}`
29619
+ );
29620
+ }
29621
+ return value;
29622
+ }
29623
+ function parseDeliveryReceipt(value) {
29624
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29625
+ throw new DeliveryReceiptReadError(
29626
+ "protocol",
29627
+ "delivery receipt returned a malformed row"
29628
+ );
29629
+ }
29630
+ const row = value;
29631
+ const ackedAt = nullableTimestamp(row.acked_at, "acked_at");
29632
+ const ackOutcome = row.ack_outcome === null ? null : typeof row.ack_outcome === "string" && ACK_OUTCOMES.has(row.ack_outcome) ? row.ack_outcome : (() => {
29633
+ throw new DeliveryReceiptReadError(
29634
+ "protocol",
29635
+ "delivery receipt returned a malformed ack_outcome"
29636
+ );
29637
+ })();
29638
+ if (ackedAt === null !== (ackOutcome === null)) {
29639
+ throw new DeliveryReceiptReadError(
29640
+ "protocol",
29641
+ "delivery receipt returned an inconsistent acknowledgement"
29642
+ );
29643
+ }
29644
+ return {
29645
+ recipient_agent_principal_id: uuid3(
29646
+ row.recipient_agent_principal_id,
29647
+ "recipient_agent_principal_id"
29648
+ ),
29649
+ enqueued_at: timestamp2(row.enqueued_at, "enqueued_at"),
29650
+ delivered_at: nullableTimestamp(row.delivered_at, "delivered_at"),
29651
+ leased_until: nullableTimestamp(row.leased_until, "leased_until"),
29652
+ acked_at: ackedAt,
29653
+ ack_outcome: ackOutcome,
29654
+ attempt_count: nonNegativeInteger(row.attempt_count, "attempt_count"),
29655
+ lease_expiry_count: nonNegativeInteger(
29656
+ row.lease_expiry_count,
29657
+ "lease_expiry_count"
29658
+ ),
29659
+ 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 : (() => {
29660
+ throw new DeliveryReceiptReadError(
29661
+ "protocol",
29662
+ "delivery receipt returned a malformed last_error_code"
29663
+ );
29664
+ })()
29665
+ };
29666
+ }
29667
+ function parseDeliveryReceiptResult(value) {
29668
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29669
+ throw new DeliveryReceiptReadError(
29670
+ "protocol",
29671
+ "delivery receipt read returned malformed JSON"
29672
+ );
29673
+ }
29674
+ const body = value;
29675
+ if (!(body.addressed === null || typeof body.addressed === "boolean") || !Array.isArray(body.receipts)) {
29676
+ throw new DeliveryReceiptReadError(
29677
+ "protocol",
29678
+ "delivery receipt read returned malformed JSON"
29679
+ );
29680
+ }
29681
+ const receipts = body.receipts.map(parseDeliveryReceipt);
29682
+ if (body.addressed === false && receipts.length !== 0) {
29683
+ throw new DeliveryReceiptReadError(
29684
+ "protocol",
29685
+ "delivery receipt read returned recipients for a broadcast"
29686
+ );
29687
+ }
29688
+ if (body.addressed === true && receipts.length === 0) {
29689
+ throw new DeliveryReceiptReadError(
29690
+ "protocol",
29691
+ "delivery receipt read returned no recipient for an addressed signal"
29692
+ );
29693
+ }
29694
+ const recipientIds = new Set(
29695
+ receipts.map((row) => row.recipient_agent_principal_id)
29696
+ );
29697
+ if (recipientIds.size !== receipts.length) {
29698
+ throw new DeliveryReceiptReadError(
29699
+ "protocol",
29700
+ "delivery receipt read returned duplicate recipients"
29701
+ );
29702
+ }
29703
+ return { addressed: body.addressed, receipts };
29704
+ }
29705
+ function deliveryReceiptState(receipt, nowMs = Date.now()) {
29706
+ if (receipt.ack_outcome !== null) return receipt.ack_outcome;
29707
+ if (receipt.leased_until !== null && Date.parse(receipt.leased_until) > nowMs) {
29708
+ return "leased";
29709
+ }
29710
+ if (receipt.delivered_at !== null) return "delivered";
29711
+ return "enqueued";
29712
+ }
29713
+ async function readAgentDeliveryReceipts(target2, token, workspaceId2, signalId, options = {}) {
29714
+ const readOptions = typeof options === "function" ? { fetcher: options } : options;
29715
+ const now = readOptions.now ?? Date.now;
29716
+ const timeoutMs = readOptions.deadlineMs === void 0 ? SIGNAL_READ_TIMEOUT_MS : Math.min(SIGNAL_READ_TIMEOUT_MS, readOptions.deadlineMs - now());
29717
+ if (timeoutMs <= 0) {
29718
+ throw new SignalReadTimeoutError("receipt read timed out");
29719
+ }
29720
+ const deadlineController = new AbortController();
29721
+ const signal = readOptions.signal === void 0 ? deadlineController.signal : AbortSignal.any([readOptions.signal, deadlineController.signal]);
29722
+ let onAbort = () => {
29723
+ };
29724
+ const aborted = new Promise((_resolve, reject) => {
29725
+ onAbort = () => reject(new SignalReadTimeoutError("receipt read timed out"));
29726
+ if (signal.aborted) onAbort();
29727
+ else signal.addEventListener("abort", onAbort, { once: true });
29728
+ });
29729
+ const timer2 = setTimeout(() => deadlineController.abort(), timeoutMs);
29730
+ try {
29731
+ let response;
29732
+ try {
29733
+ response = await Promise.race([
29734
+ (readOptions.fetcher ?? fetch)(readEndpoint(target2), {
29735
+ method: "POST",
29736
+ headers: {
29737
+ authorization: `Bearer ${token}`,
29738
+ apikey: target2.anonKey,
29739
+ "content-type": "application/json"
29740
+ },
29741
+ body: JSON.stringify({
29742
+ resource: "delivery_receipts",
29743
+ workspace_id: uuid3(workspaceId2, "workspace_id"),
29744
+ signal_id: uuid3(signalId, "signal_id")
29745
+ }),
29746
+ signal
29747
+ }),
29748
+ aborted
29749
+ ]);
29750
+ } catch (error) {
29751
+ if (error instanceof SignalReadTimeoutError || signal.aborted || error?.name === "AbortError") {
29752
+ throw new SignalReadTimeoutError("receipt read timed out");
29753
+ }
29754
+ if (error instanceof DeliveryReceiptReadError) throw error;
29755
+ throw new DeliveryReceiptReadError(
29756
+ "transport",
29757
+ "delivery receipt read could not reach the cloud service"
29758
+ );
29759
+ }
29760
+ let body;
29761
+ try {
29762
+ body = await Promise.race([response.json(), aborted]);
29763
+ } catch (error) {
29764
+ if (error instanceof SignalReadTimeoutError || signal.aborted) {
29765
+ throw new SignalReadTimeoutError("receipt read timed out");
29766
+ }
29767
+ throw new DeliveryReceiptReadError(
29768
+ "protocol",
29769
+ "delivery receipt read returned malformed JSON"
29770
+ );
29771
+ }
29772
+ if (!response.ok) {
29773
+ throw new DeliveryReceiptReadError(
29774
+ "http",
29775
+ `delivery receipt read failed (HTTP ${response.status})`,
29776
+ response.status
29777
+ );
29778
+ }
29779
+ const result = parseDeliveryReceiptResult(body);
29780
+ if (result.addressed === null) {
29781
+ throw new DeliveryReceiptReadError(
29782
+ "not_author",
29783
+ "delivery receipt read did not establish that this caller authored the signal"
29784
+ );
29785
+ }
29786
+ return { addressed: result.addressed, receipts: result.receipts };
29787
+ } finally {
29788
+ clearTimeout(timer2);
29789
+ signal.removeEventListener("abort", onAbort);
29790
+ }
29791
+ }
29792
+
29793
+ // src/cloud/receipts.ts
29794
+ function signalReceiptCliState(receipt, nowMs) {
29795
+ const state = deliveryReceiptState(receipt, nowMs);
29796
+ if (state === "enqueued") return "not_delivered";
29797
+ if (state === "leased") return "working";
29798
+ if (state === "delivered") return "delivered";
29799
+ if (state === "queued") return "queued";
29800
+ return "finished";
29801
+ }
29802
+ function receiptCheckCommand(report) {
29803
+ return `cswarm receipt ${report.signalId} --workspace-id ${report.workspaceId}`;
29804
+ }
29805
+ function listenerStatusCommand(report, receipt) {
29806
+ return `cswarm listen status --workspace-id ${report.workspaceId} --principal-id ${receipt.recipient_agent_principal_id}`;
29807
+ }
29808
+ function newAskCommand(report, receipt) {
29809
+ return `cswarm ask "<question>" --to ${receipt.recipient_agent_principal_id} --workspace-id ${report.workspaceId}`;
29810
+ }
29811
+ function renderSignalReceiptReport(report, nowMs = Date.now()) {
29812
+ if (!report.addressed) {
29813
+ return [
29814
+ "This was a broadcast; no agent was addressed and none was woken.",
29815
+ `To wake an agent, send a new ask with: cswarm ask "<text>" --to <agent> --workspace-id ${report.workspaceId}`
29816
+ ].join("\n");
29817
+ }
29818
+ const sections = report.receipts.map((receipt) => {
29819
+ const state = deliveryReceiptState(receipt, nowMs);
29820
+ if (state === "enqueued") {
29821
+ return [
29822
+ `Not yet delivered to agent ${receipt.recipient_agent_principal_id}. CommonSwarm accepted it ${relativeAge(receipt.enqueued_at, nowMs)}.`,
29823
+ `Ask the agent's operator to check its listener with: ${listenerStatusCommand(report, receipt)}`,
29824
+ `Then check again with: ${receiptCheckCommand(report)}`
29825
+ ].join("\n");
29826
+ }
29827
+ if (state === "delivered") {
29828
+ return [
29829
+ `Delivered to agent ${receipt.recipient_agent_principal_id} ${relativeAge(receipt.delivered_at, nowMs)}, and the agent has not acted on it.`,
29830
+ `Check again with: ${receiptCheckCommand(report)}`
29831
+ ].join("\n");
29832
+ }
29833
+ if (state === "leased") {
29834
+ return [
29835
+ `Agent ${receipt.recipient_agent_principal_id} is working on it right now; its current lease ${relativeExpiry(receipt.leased_until, nowMs)}.`,
29836
+ `Check for the outcome with: ${receiptCheckCommand(report)}`
29837
+ ].join("\n");
29838
+ }
29839
+ if (state === "queued") {
29840
+ return [
29841
+ `Queued for agent ${receipt.recipient_agent_principal_id}'s interactive session ${relativeAge(receipt.acked_at, nowMs)}. The agent has not seen it yet.`,
29842
+ "It will appear at the agent's next prompt.",
29843
+ `Check again with: ${receiptCheckCommand(report)}`
29844
+ ].join("\n");
29845
+ }
29846
+ const finished = `Agent ${receipt.recipient_agent_principal_id} finished with outcome ${state} ${relativeAge(receipt.acked_at, nowMs)}.`;
29847
+ if (state === "replied") {
29848
+ return [
29849
+ finished,
29850
+ `Read the reply with: cswarm inbox --workspace-id ${report.workspaceId} --include-stale`
29851
+ ].join("\n");
29852
+ }
29853
+ if (state === "observed") {
29854
+ return [
29855
+ finished,
29856
+ "The agent saw the signal without sending a reply.",
29857
+ `If you need an answer, send a new ask with: ${newAskCommand(report, receipt)}`
29858
+ ].join("\n");
29859
+ }
29860
+ if (state === "expired") {
29861
+ return [
29862
+ finished,
29863
+ "The signal expired before the agent completed it.",
29864
+ `Send a new ask with: ${newAskCommand(report, receipt)}`
29865
+ ].join("\n");
29866
+ }
29867
+ return [
29868
+ finished,
29869
+ `Delivery will not retry${receipt.last_error_code === null ? "." : `; the last error code was ${receipt.last_error_code}.`}`,
29870
+ `Ask the agent's operator to check its listener with: ${listenerStatusCommand(report, receipt)}`
29871
+ ].join("\n");
29872
+ });
29873
+ return sections.join("\n\n");
29874
+ }
29875
+ function signalReceiptJsonPayload(report, nowMs = Date.now()) {
29876
+ return {
29877
+ workspace_id: report.workspaceId,
29878
+ signal_id: report.signalId,
29879
+ broadcast: !report.addressed,
29880
+ receipts: report.receipts.map((receipt) => ({
29881
+ recipient_agent_principal_id: receipt.recipient_agent_principal_id,
29882
+ state: signalReceiptCliState(receipt, nowMs),
29883
+ outcome: receipt.ack_outcome,
29884
+ enqueued_at: receipt.enqueued_at,
29885
+ delivered_at: receipt.delivered_at,
29886
+ leased_until: receipt.leased_until,
29887
+ acked_at: receipt.acked_at,
29888
+ attempt_count: receipt.attempt_count,
29889
+ lease_expiry_count: receipt.lease_expiry_count,
29890
+ last_error_code: receipt.last_error_code
29891
+ }))
29892
+ };
29893
+ }
29894
+
29574
29895
  // src/host/opencode.ts
29575
29896
  var import_node_child_process3 = require("node:child_process");
29576
29897
  var import_node_crypto12 = require("node:crypto");
@@ -32160,7 +32481,7 @@ async function resolveBudgetAndPrompt(session, prompt, budget) {
32160
32481
  }
32161
32482
 
32162
32483
  // 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;
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;
32164
32485
  var TERMINAL_STATES = /* @__PURE__ */ new Set(["done", "expired", "failed"]);
32165
32486
  var REPLY_MAX_CODE_UNITS = 2e3;
32166
32487
  var TRUNCATION_SUFFIX = "\n[Reply truncated by CommonSwarm]";
@@ -32168,7 +32489,7 @@ var UNSAFE_CONTROLS_RE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u
32168
32489
  var LISTENER_MAX_PROMPT_ATTEMPTS = 3;
32169
32490
  var LISTENER_MAX_POST_ATTEMPTS = 5;
32170
32491
  function listenerReplyCommandId(signalId, effectOrdinal = 0) {
32171
- if (!UUID_RE8.test(signalId)) {
32492
+ if (!UUID_RE9.test(signalId)) {
32172
32493
  throw new Error("listener signal id must be a UUID");
32173
32494
  }
32174
32495
  if (!Number.isSafeInteger(effectOrdinal) || effectOrdinal < 0) {
@@ -32632,7 +32953,7 @@ var import_node_crypto13 = require("node:crypto");
32632
32953
  var import_node_os5 = require("node:os");
32633
32954
  var import_node_path8 = require("node:path");
32634
32955
  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;
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;
32636
32957
  var COMMAND_ID_RE2 = /^[A-Za-z0-9_-]{8,72}$/;
32637
32958
  var MAX_EFFECT_BYTES = 1024 * 1024;
32638
32959
  var STATES = /* @__PURE__ */ new Set([
@@ -32670,7 +32991,7 @@ function defaultListenerStateDirectory() {
32670
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");
32671
32992
  }
32672
32993
  function listenerInstanceKey(input) {
32673
- if (!UUID_RE9.test(input.workspaceId) || !UUID_RE9.test(input.principalId)) {
32994
+ if (!UUID_RE10.test(input.workspaceId) || !UUID_RE10.test(input.principalId)) {
32674
32995
  throw new Error("listener workspace and principal ids must be UUIDs");
32675
32996
  }
32676
32997
  if (!input.profileId || input.profileId.includes("\0")) {
@@ -32702,7 +33023,7 @@ function parseListenerEffectRecord(raw, expectedId) {
32702
33023
  throw new Error("stored listener effect is malformed");
32703
33024
  }
32704
33025
  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)) {
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)) {
32706
33027
  throw new Error("stored listener effect is malformed");
32707
33028
  }
32708
33029
  if (row.version === 1) {
@@ -32719,7 +33040,7 @@ function upcastV1Ask(row) {
32719
33040
  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
33041
  throw new Error("stored listener effect is malformed");
32721
33042
  }
32722
- if (row.replySignalId !== null && !UUID_RE9.test(row.replySignalId)) {
33043
+ if (row.replySignalId !== null && !UUID_RE10.test(row.replySignalId)) {
32723
33044
  throw new Error("stored listener effect is malformed");
32724
33045
  }
32725
33046
  return {
@@ -32758,7 +33079,7 @@ function parseV2Record(row) {
32758
33079
  if (typeof row.commandId !== "string" || !COMMAND_ID_RE2.test(row.commandId) || row.state === "observed") {
32759
33080
  throw new Error("stored listener effect is malformed");
32760
33081
  }
32761
- if (row.replySignalId !== null && !UUID_RE9.test(row.replySignalId)) {
33082
+ if (row.replySignalId !== null && !UUID_RE10.test(row.replySignalId)) {
32762
33083
  throw new Error("stored listener effect is malformed");
32763
33084
  }
32764
33085
  }
@@ -32782,7 +33103,7 @@ function parseV2Record(row) {
32782
33103
  };
32783
33104
  }
32784
33105
  function newObservedNoteRecord(input) {
32785
- if (!UUID_RE9.test(input.signalId)) {
33106
+ if (!UUID_RE10.test(input.signalId)) {
32786
33107
  throw new Error("listener note signal id must be a UUID");
32787
33108
  }
32788
33109
  if (input.body.length < 1) {
@@ -32916,7 +33237,7 @@ var FileListenerEffectStore = class {
32916
33237
  );
32917
33238
  }
32918
33239
  checkedId(signalId) {
32919
- if (!UUID_RE9.test(signalId)) {
33240
+ if (!UUID_RE10.test(signalId)) {
32920
33241
  throw new Error("listener signal id must be a UUID");
32921
33242
  }
32922
33243
  return signalId.toLowerCase();
@@ -34007,7 +34328,7 @@ var CodexListenerModel = class {
34007
34328
  var import_node_crypto17 = require("node:crypto");
34008
34329
 
34009
34330
  // 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;
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;
34011
34332
  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
34333
  var DELIVERY_KINDS = /* @__PURE__ */ new Set(["ask", "note"]);
34013
34334
  var SENDER_OWNER_RELATIONS2 = /* @__PURE__ */ new Set([
@@ -34018,6 +34339,7 @@ var SENDER_OWNER_RELATIONS2 = /* @__PURE__ */ new Set([
34018
34339
  var DELIVERY_ACK_OUTCOMES = /* @__PURE__ */ new Set([
34019
34340
  "replied",
34020
34341
  "observed",
34342
+ "queued",
34021
34343
  "expired",
34022
34344
  "failed_terminal"
34023
34345
  ]);
@@ -34064,6 +34386,10 @@ var DELIVERY_SERVER_ERROR_CODES = Object.freeze([
34064
34386
  "internal_error"
34065
34387
  ]);
34066
34388
  var DELIVERY_UNKNOWN_ERROR_CODE = "unknown_error";
34389
+ function observationCommandId(signalId) {
34390
+ checkedUuidRequest(signalId, "signalId");
34391
+ return `observe_${signalId.toLowerCase().replaceAll("-", "")}`;
34392
+ }
34067
34393
  var DeliveryTransportError = class extends Error {
34068
34394
  constructor(message) {
34069
34395
  super(message);
@@ -34089,7 +34415,7 @@ var DeliveryProtocolError = class extends Error {
34089
34415
  }
34090
34416
  };
34091
34417
  function checkedUuid3(value, field) {
34092
- if (typeof value !== "string" || !UUID_RE10.test(value)) {
34418
+ if (typeof value !== "string" || !UUID_RE11.test(value)) {
34093
34419
  throw new DeliveryProtocolError(
34094
34420
  `delivery response returned a malformed ${field}`
34095
34421
  );
@@ -34200,7 +34526,7 @@ function checkedClaimCapabilities(value) {
34200
34526
  }
34201
34527
  function checkedOptionalUuidArray(value, field) {
34202
34528
  if (value === void 0) return;
34203
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE10.test(item))) {
34529
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE11.test(item))) {
34204
34530
  throw new DeliveryProtocolError(
34205
34531
  `delivery response returned a malformed ${field}`
34206
34532
  );
@@ -34347,7 +34673,7 @@ function checkedCommandId(value) {
34347
34673
  return value;
34348
34674
  }
34349
34675
  function checkedUuidRequest(value, field) {
34350
- if (!UUID_RE10.test(value)) {
34676
+ if (!UUID_RE11.test(value)) {
34351
34677
  throw new Error(`${field} must be a UUID for an agent delivery command`);
34352
34678
  }
34353
34679
  }
@@ -34360,7 +34686,7 @@ function assertAckRequest(request) {
34360
34686
  checkedUuidRequest(request.listenerInstanceId, "listenerInstanceId");
34361
34687
  if (!DELIVERY_ACK_OUTCOMES.has(request.outcome)) {
34362
34688
  throw new Error(
34363
- "a delivery outcome must be replied, observed, expired, or failed_terminal"
34689
+ "a delivery outcome must be replied, observed, queued, expired, or failed_terminal"
34364
34690
  );
34365
34691
  }
34366
34692
  if (request.outcome === "failed_terminal") {
@@ -34552,11 +34878,39 @@ var DeliveryCommandClient = class {
34552
34878
  outcome: request.outcome
34553
34879
  };
34554
34880
  }
34881
+ /** Mark a queued delivery observed only after the interactive hook surfaced it. */
34882
+ async observeQueuedAgentDelivery(request) {
34883
+ checkedCommandId(request.commandId);
34884
+ assertAgentToken(request.credential);
34885
+ checkedUuidRequest(request.workspaceId, "workspaceId");
34886
+ checkedUuidRequest(request.signalId, "signalId");
34887
+ const { response, text } = await this.post(request, {
34888
+ kind: "ack_agent_delivery",
34889
+ signal_id: request.signalId.toLowerCase(),
34890
+ lease_id: null,
34891
+ listener_instance_id: null,
34892
+ outcome: "observed",
34893
+ last_error_code: null
34894
+ }, "delivery observation");
34895
+ if (!response.ok) throw refusal(response, text);
34896
+ parseAckSuccess(
34897
+ successBody(response, text, "delivery observation"),
34898
+ {
34899
+ signalId: request.signalId.toLowerCase(),
34900
+ outcome: "observed"
34901
+ }
34902
+ );
34903
+ return {
34904
+ httpStatus: response.status,
34905
+ signalId: request.signalId.toLowerCase(),
34906
+ outcome: "observed"
34907
+ };
34908
+ }
34555
34909
  };
34556
34910
 
34557
34911
  // src/listener/main-routing.ts
34558
34912
  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;
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;
34560
34914
  var MAX_QUEUE_BYTES = 1024 * 1024;
34561
34915
  var QUEUE_FILE = "pending-for-main.json";
34562
34916
  var QUEUE_LOCK = "pending-for-main";
@@ -34605,12 +34959,13 @@ function parseEntry(value) {
34605
34959
  "senderName",
34606
34960
  "body",
34607
34961
  "createdAt",
34608
- "queuedAt"
34962
+ "queuedAt",
34963
+ "observationPending"
34609
34964
  ]);
34610
34965
  if (Object.keys(row).some((key2) => !allowed.has(key2))) {
34611
34966
  throw new Error("stored pending-for-main entry is malformed");
34612
34967
  }
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)) {
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)) {
34614
34969
  throw new Error("stored pending-for-main entry is malformed");
34615
34970
  }
34616
34971
  return {
@@ -34623,7 +34978,8 @@ function parseEntry(value) {
34623
34978
  senderName: row.senderName,
34624
34979
  body: row.body,
34625
34980
  createdAt: row.createdAt,
34626
- queuedAt: row.queuedAt
34981
+ queuedAt: row.queuedAt,
34982
+ ...row.observationPending === true ? { observationPending: true } : {}
34627
34983
  };
34628
34984
  }
34629
34985
  function parseFile(raw) {
@@ -34719,7 +35075,7 @@ var FilePendingMainQueue = class {
34719
35075
  }, lockTimeoutMs === void 0 ? {} : { timeoutMs: lockTimeoutMs });
34720
35076
  }
34721
35077
  };
34722
- function pendingMainEntry(signal, principalId, provenance, now) {
35078
+ function pendingMainEntry(signal, principalId, provenance, now, options = {}) {
34723
35079
  if (signal.kind !== "ask") {
34724
35080
  throw new Error("only directed asks can enter the pending-for-main queue");
34725
35081
  }
@@ -34732,7 +35088,8 @@ function pendingMainEntry(signal, principalId, provenance, now) {
34732
35088
  senderName: provenance.senderName,
34733
35089
  body: signal.body,
34734
35090
  createdAt: signal.created_at,
34735
- queuedAt: new Date(now).toISOString()
35091
+ queuedAt: new Date(now).toISOString(),
35092
+ ...options.observationPending ? { observationPending: true } : {}
34736
35093
  });
34737
35094
  }
34738
35095
 
@@ -34746,7 +35103,7 @@ var LISTENER_REPLY_ONLY_MINIMUM_MS = SIGNAL_REQUEST_TIMEOUT_MS + LISTENER_ACK_ON
34746
35103
  var LISTENER_PROMPT_START_MINIMUM_MS = SIGNAL_READ_TIMEOUT_MS + ACP_DEFAULT_REQUEST_TIMEOUT_MS + LISTENER_REPLY_ONLY_MINIMUM_MS;
34747
35104
  var LISTENER_DELIVERY_RETRY_INITIAL_MS = 500;
34748
35105
  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;
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;
34750
35107
  var ListenerCapabilityError = class extends Error {
34751
35108
  code;
34752
35109
  constructor(code, message) {
@@ -34826,7 +35183,7 @@ function ackForTerminalEffect(record, now) {
34826
35183
  return { outcome: "observed", lastErrorCode: null };
34827
35184
  }
34828
35185
  if (record.state === "routed_main" && record.signalKind === "ask") {
34829
- return { outcome: "observed", lastErrorCode: null };
35186
+ return { outcome: "queued", lastErrorCode: null };
34830
35187
  }
34831
35188
  if (record.state === "expired" && record.signalKind === "ask" && Date.parse(record.askUntil) <= now()) {
34832
35189
  return { outcome: "expired", lastErrorCode: null };
@@ -35021,7 +35378,7 @@ async function runListenerRuntime(options) {
35021
35378
  new Error("listener instance id and delivery journal must be configured together")
35022
35379
  );
35023
35380
  }
35024
- if (hasInstanceId && !UUID_RE12.test(options.listenerInstanceId)) {
35381
+ if (hasInstanceId && !UUID_RE13.test(options.listenerInstanceId)) {
35025
35382
  return await closeBeforeStart(
35026
35383
  options.model,
35027
35384
  new Error("listener instance id must be a UUID")
@@ -35109,7 +35466,9 @@ async function runListenerRuntime(options) {
35109
35466
  }
35110
35467
  }
35111
35468
  const queued = await options.pendingMainQueue.enqueue(
35112
- pendingMainEntry(signal, options.principalId, provenance, now())
35469
+ pendingMainEntry(signal, options.principalId, provenance, now(), {
35470
+ observationPending: deliveryMode === "durable_claim"
35471
+ })
35113
35472
  );
35114
35473
  options.onEvent?.({
35115
35474
  type: "main_queue",
@@ -35844,7 +36203,7 @@ async function runListenerRuntime(options) {
35844
36203
  var import_node_net = require("node:net");
35845
36204
  var import_promises9 = require("node:fs/promises");
35846
36205
  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;
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;
35848
36207
  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
36208
  var MAX_STATUS_BYTES = 16 * 1024;
35850
36209
  var MAX_CONTROL_BYTES = 8 * 1024;
@@ -35950,10 +36309,10 @@ function parseStatus(raw) {
35950
36309
  throw new Error("stored listener status is malformed");
35951
36310
  }
35952
36311
  }
35953
- const nullableUuid2 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE13.test(candidate);
36312
+ const nullableUuid2 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE14.test(candidate);
35954
36313
  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)) {
36314
+ 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)) {
35957
36316
  throw new Error("stored listener status is malformed");
35958
36317
  }
35959
36318
  const routeMode = row.routeMode ?? "worker";
@@ -36029,6 +36388,7 @@ async function appendListenerEvent(paths, event) {
36029
36388
  const deliveryOutcomes = /* @__PURE__ */ new Set([
36030
36389
  "replied",
36031
36390
  "observed",
36391
+ "queued",
36032
36392
  "expired",
36033
36393
  "failed_terminal"
36034
36394
  ]);
@@ -36302,7 +36662,7 @@ async function queryListenerControl(paths, command2, timeoutMs = CONTROL_TIMEOUT
36302
36662
 
36303
36663
  // src/listener/supervisor.ts
36304
36664
  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;
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;
36306
36666
  var LISTENER_RESTART_MAX_ATTEMPTS = 5;
36307
36667
  var LISTENER_RESTART_INITIAL_MS = 1e3;
36308
36668
  var LISTENER_RESTART_MAX_MS = 6e4;
@@ -36431,7 +36791,7 @@ async function runListenerSupervisor(options) {
36431
36791
  // before the socket can answer, before any status/event persistence.
36432
36792
  initialize: prepare ? async () => {
36433
36793
  const selected = await prepare(proposedInstanceId);
36434
- if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE14.test(selected.instanceId)) {
36794
+ if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE15.test(selected.instanceId)) {
36435
36795
  throw new Error("listener prepare returned an invalid instance id");
36436
36796
  }
36437
36797
  status = { ...status, instanceId: selected.instanceId };
@@ -36789,7 +37149,7 @@ async function waitForListenerReady(paths, options = {}) {
36789
37149
  // src/listener/delivery-journal.ts
36790
37150
  var import_node_path16 = require("node:path");
36791
37151
  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}$/;
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}$/;
36793
37153
  var COMMAND_ID_RE3 = /^[A-Za-z0-9_-]{8,72}$/;
36794
37154
  var SIGNAL_FINGERPRINT_RE = /^[0-9a-f]{64}$/;
36795
37155
  var MAX_JOURNAL_BYTES = 8192;
@@ -36873,6 +37233,7 @@ var ALLOWED_PHASES = /* @__PURE__ */ new Set(["claim_pending", "leased", "ack_pe
36873
37233
  var ALLOWED_OUTCOMES = /* @__PURE__ */ new Set([
36874
37234
  "replied",
36875
37235
  "observed",
37236
+ "queued",
36876
37237
  "expired",
36877
37238
  "failed_terminal"
36878
37239
  ]);
@@ -36883,7 +37244,7 @@ var ALLOWED_ERROR_CODES = /* @__PURE__ */ new Set([
36883
37244
  "credential_unavailable"
36884
37245
  ]);
36885
37246
  function claimCommandId(listenerInstanceId, claimOrdinal) {
36886
- if (!UUID_RE15.test(listenerInstanceId)) {
37247
+ if (!UUID_RE16.test(listenerInstanceId)) {
36887
37248
  throw new Error("stored delivery journal is malformed");
36888
37249
  }
36889
37250
  if (!Number.isSafeInteger(claimOrdinal) || claimOrdinal < 0) {
@@ -36898,7 +37259,7 @@ function claimCommandId(listenerInstanceId, claimOrdinal) {
36898
37259
  return id;
36899
37260
  }
36900
37261
  function ackCommandId(leaseId) {
36901
- if (!UUID_RE15.test(leaseId)) {
37262
+ if (!UUID_RE16.test(leaseId)) {
36902
37263
  throw new Error("stored delivery journal is malformed");
36903
37264
  }
36904
37265
  const cleanLease = leaseId.toLowerCase().replace(/-/g, "");
@@ -36981,19 +37342,19 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId) {
36981
37342
  if (row.version !== 1) {
36982
37343
  throw new Error("stored delivery journal is malformed");
36983
37344
  }
36984
- if (typeof row.workspaceId !== "string" || !UUID_RE15.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
37345
+ if (typeof row.workspaceId !== "string" || !UUID_RE16.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
36985
37346
  throw new Error("stored delivery journal is malformed");
36986
37347
  }
36987
37348
  if (expectedWorkspaceId && row.workspaceId !== expectedWorkspaceId.toLowerCase()) {
36988
37349
  throw new Error("stored delivery journal is malformed");
36989
37350
  }
36990
- if (typeof row.principalId !== "string" || !UUID_RE15.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
37351
+ if (typeof row.principalId !== "string" || !UUID_RE16.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
36991
37352
  throw new Error("stored delivery journal is malformed");
36992
37353
  }
36993
37354
  if (expectedPrincipalId && row.principalId !== expectedPrincipalId.toLowerCase()) {
36994
37355
  throw new Error("stored delivery journal is malformed");
36995
37356
  }
36996
- if (typeof row.listenerInstanceId !== "string" || !UUID_RE15.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
37357
+ if (typeof row.listenerInstanceId !== "string" || !UUID_RE16.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
36997
37358
  throw new Error("stored delivery journal is malformed");
36998
37359
  }
36999
37360
  if (!Number.isSafeInteger(row.nextClaimOrdinal) || row.nextClaimOrdinal < 0) {
@@ -37057,10 +37418,10 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId) {
37057
37418
  if (active.claimLastAttemptAt === null) {
37058
37419
  throw new Error("stored delivery journal is malformed");
37059
37420
  }
37060
- if (typeof active.signalId !== "string" || !UUID_RE15.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
37421
+ if (typeof active.signalId !== "string" || !UUID_RE16.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
37061
37422
  throw new Error("stored delivery journal is malformed");
37062
37423
  }
37063
- if (typeof active.leaseId !== "string" || !UUID_RE15.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
37424
+ if (typeof active.leaseId !== "string" || !UUID_RE16.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
37064
37425
  throw new Error("stored delivery journal is malformed");
37065
37426
  }
37066
37427
  if (!isValidIsoTimestamp(active.leasedUntil) || Date.parse(active.leasedUntil) <= Date.parse(active.claimCreatedAt)) {
@@ -37132,7 +37493,7 @@ var FileListenerDeliveryJournal = class {
37132
37493
  ["profileId", "workspaceId", "principalId"],
37133
37494
  "delivery journal configuration rejected"
37134
37495
  );
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)) {
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)) {
37136
37497
  throw new Error("delivery journal configuration rejected");
37137
37498
  }
37138
37499
  if (options.stateDirectory !== void 0) {
@@ -37253,7 +37614,7 @@ var FileListenerDeliveryJournal = class {
37253
37614
  ["signalId", "leaseId", "leasedUntil"],
37254
37615
  "delivery journal mutation rejected"
37255
37616
  );
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))) {
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))) {
37257
37618
  throw new Error("delivery journal mutation rejected");
37258
37619
  }
37259
37620
  const canonicalSignalId = input.signalId.toLowerCase();
@@ -37385,7 +37746,7 @@ async function openListenerDeliveryJournal(options) {
37385
37746
  ["profileId", "workspaceId", "principalId", "proposedListenerInstanceId"],
37386
37747
  "delivery journal configuration rejected"
37387
37748
  );
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)) {
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)) {
37389
37750
  throw new Error("delivery journal configuration rejected");
37390
37751
  }
37391
37752
  if (options.stateDirectory !== void 0) {
@@ -37600,7 +37961,7 @@ async function spawnDetachedListener(options) {
37600
37961
  // src/listener/hook.ts
37601
37962
  var import_promises10 = require("node:fs/promises");
37602
37963
  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;
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;
37604
37965
  var TOKEN_RE = /^swm_agt_[A-Za-z0-9_-]{43}$/;
37605
37966
  var INSTANCE_KEY_RE = /^[0-9a-f]{64}$/;
37606
37967
  var MAX_HOOK_CREDENTIAL_BYTES = 8 * 1024;
@@ -37641,7 +38002,7 @@ function parseListenerCredential(raw) {
37641
38002
  "principalId",
37642
38003
  "credential",
37643
38004
  "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))) {
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))) {
37645
38006
  throw new Error("stored listener hook credential is malformed");
37646
38007
  }
37647
38008
  const target2 = cloudTarget(row.targetUrl, row.anonKey);
@@ -37701,7 +38062,7 @@ function parseSurface(raw) {
37701
38062
  const row = value;
37702
38063
  if (Object.keys(row).some(
37703
38064
  (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")) {
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")) {
37705
38066
  throw new Error("stored listener hook surface state is malformed");
37706
38067
  }
37707
38068
  const ids = row.surfacedSignalIds.map((id) => String(id).toLowerCase());
@@ -37738,7 +38099,7 @@ var FileHookSurfaceStore = class {
37738
38099
  const unseen = [];
37739
38100
  for (const item of items) {
37740
38101
  const signalId = item.signalId.toLowerCase();
37741
- if (!UUID_RE16.test(signalId) || seen.has(signalId)) continue;
38102
+ if (!UUID_RE17.test(signalId) || seen.has(signalId)) continue;
37742
38103
  seen.add(signalId);
37743
38104
  unseen.push(item);
37744
38105
  }
@@ -37761,7 +38122,7 @@ var FileHookSurfaceStore = class {
37761
38122
  const seen = new Set(state.surfacedSignalIds);
37762
38123
  for (const signalId of options.signalIds ?? []) {
37763
38124
  const checked = signalId.toLowerCase();
37764
- if (UUID_RE16.test(checked)) seen.add(checked);
38125
+ if (UUID_RE17.test(checked)) seen.add(checked);
37765
38126
  }
37766
38127
  await writeSecureJsonFile(
37767
38128
  this.path,
@@ -37998,6 +38359,32 @@ function renderDroppedAsks(count2) {
37998
38359
  }
37999
38360
  var CREDENTIAL_READ_WARNING = "CommonSwarm could not read the configured listener credential safely. The hook is not checking routed asks. Restart the listener with a fresh credential; any credential state file must be mode 0600. Then run cswarm listen status.";
38000
38361
  var CREDENTIAL_401_WARNING = "CommonSwarm could not authenticate a listener credential (HTTP 401). The hook is not checking routed asks. Restart the listener with a fresh credential, then run cswarm listen status.";
38362
+ async function recordQueuedObservations(check, signalIds, options, now) {
38363
+ const stored = check.context.credential;
38364
+ const remainingMs = options.deadlineMs - now();
38365
+ if (signalIds.length === 0 || stored === null || options.signal.aborted || remainingMs <= 0) {
38366
+ return /* @__PURE__ */ new Set();
38367
+ }
38368
+ const client = new DeliveryCommandClient(
38369
+ cloudTarget(stored.targetUrl, stored.anonKey),
38370
+ options.fetcher ?? fetch,
38371
+ { deadlineMs: remainingMs, now }
38372
+ );
38373
+ const results = await Promise.all(signalIds.map(async (signalId) => {
38374
+ try {
38375
+ await client.observeQueuedAgentDelivery({
38376
+ workspaceId: stored.workspaceId,
38377
+ credential: stored.credential,
38378
+ commandId: observationCommandId(signalId),
38379
+ signalId
38380
+ });
38381
+ return signalId;
38382
+ } catch {
38383
+ return null;
38384
+ }
38385
+ }));
38386
+ return new Set(results.filter((signalId) => signalId !== null));
38387
+ }
38001
38388
  async function checkListenerHooks(options) {
38002
38389
  try {
38003
38390
  const stateDirectory2 = options.stateDirectory ?? defaultListenerStateDirectory();
@@ -38076,10 +38463,8 @@ async function checkListenerHooks(options) {
38076
38463
  check,
38077
38464
  store: store2,
38078
38465
  signalIds: staged.unseen.map((item) => item.signalId),
38079
- // Every staged queue entry is either written by this run or was committed
38080
- // after an earlier successful write. Removing both keeps the queue bounded
38081
- // without re-printing entries below the exactly-once high-water.
38082
- settledPendingSignalIds: check.pending.map((item) => item.signalId),
38466
+ plainPendingSignalIds: check.pending.filter((item) => item.observationPending !== true).map((item) => item.signalId),
38467
+ observationPendingSignalIds: check.pending.filter((item) => item.observationPending === true).map((item) => item.signalId),
38083
38468
  reportDrops,
38084
38469
  reportCredentialFailure
38085
38470
  });
@@ -38092,8 +38477,17 @@ async function checkListenerHooks(options) {
38092
38477
  ...commit.reportDrops ? { droppedCount: commit.check.droppedCount } : {},
38093
38478
  ...commit.reportCredentialFailure ? { credentialFailureReported: true } : commit.check.credentialHealthy ? { credentialFailureReported: false } : {}
38094
38479
  });
38480
+ const observedSignalIds = await recordQueuedObservations(
38481
+ commit.check,
38482
+ commit.observationPendingSignalIds,
38483
+ options,
38484
+ now
38485
+ );
38095
38486
  const remainingCount = await commit.check.queue.remove(
38096
- new Set(commit.settledPendingSignalIds),
38487
+ /* @__PURE__ */ new Set([
38488
+ ...commit.plainPendingSignalIds,
38489
+ ...observedSignalIds
38490
+ ]),
38097
38491
  HOOK_LOCK_TIMEOUT_MS
38098
38492
  );
38099
38493
  if (commit.check.context.paths !== null && commit.check.context.status !== null) {
@@ -38218,7 +38612,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
38218
38612
  "reveal-anon-key",
38219
38613
  "write"
38220
38614
  ]);
38221
- 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;
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;
38222
38616
  var AGENT_CREDENTIAL_MESSAGE = "Agent credential minted. It is bound to this task and run so the agent's work stays scoped and attributable.";
38223
38617
  var AGENT_CREDENTIAL_MESSAGE_D088 = "Agent credential minted. It is bound to this run, so the agent's work is attributable to it.";
38224
38618
  var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
@@ -38226,8 +38620,8 @@ var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
38226
38620
  AGENT_CREDENTIAL_MESSAGE_D088
38227
38621
  ];
38228
38622
  function packageVersion() {
38229
- if ("0.1.31".length > 0) {
38230
- return "0.1.31";
38623
+ if ("0.1.33".length > 0) {
38624
+ return "0.1.33";
38231
38625
  }
38232
38626
  try {
38233
38627
  const value = JSON.parse(
@@ -38346,6 +38740,7 @@ Usage:
38346
38740
  cswarm note "<text>" [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--to <member|agent>] [--about <ref>] [--until <dur>] [--json] # text: 1..8000 characters
38347
38741
  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
38348
38742
  cswarm reply <signal-id> "<text>" [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--until <dur>] [--json]
38743
+ cswarm receipt <signal-id> --agent-token-stdin [--url <url> --anon-key <key>] --workspace-id <uuid> [--json]
38349
38744
  cswarm feed [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--about <ref>] [--kind <kind>] [--since <timestamp>] [--limit <n>] [--include-stale] [--json]
38350
38745
  cswarm inbox [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--kind <kind>] [--about <ref>] [--since <timestamp>] [--limit <n>] [--include-stale] [--wait <seconds>] [--json]
38351
38746
  cswarm inbox --follow --ndjson [--url <url> --anon-key <key>] [--workspace-id <uuid>] [--kind <kind>] [--about <ref>] [--since <timestamp>] [--limit <n>] [--include-stale]
@@ -38392,6 +38787,7 @@ Credential selection for command/dogfood:
38392
38787
  One that persists or references the credential needs the complete
38393
38788
  JSON artifact, because it needs a field a bare secret does not carry:
38394
38789
  members reads only -- either form
38790
+ receipt reads only -- either form
38395
38791
  file put, file ls, file get, file rm, file restore
38396
38792
  read and command, nothing persisted -- either form
38397
38793
  feedback command only, nothing persisted -- either form
@@ -38561,7 +38957,7 @@ function parsedAgentCredential(value) {
38561
38957
  const withExpiry = [...requiredKeys, "expires_at"].sort();
38562
38958
  const actualKeys = Object.keys(artifact).sort();
38563
38959
  const shape = actualKeys.length === requiredKeys.length ? requiredKeys : withExpiry;
38564
- 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") {
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") {
38565
38961
  throw new Error("agent credential JSON is malformed");
38566
38962
  }
38567
38963
  let expiresAt = null;
@@ -38678,7 +39074,7 @@ async function workspaceId(args, cloud, human, options = {}) {
38678
39074
  warn: options.warn ?? writeWorkspaceWarning
38679
39075
  });
38680
39076
  }
38681
- function uuid3(value, field) {
39077
+ function uuid4(value, field) {
38682
39078
  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)) {
38683
39079
  throw new Error(`server returned a malformed ${field}`);
38684
39080
  }
@@ -38783,7 +39179,7 @@ async function runNew(args) {
38783
39179
  throw error;
38784
39180
  }
38785
39181
  const response = acceptedConnect("workspace creation", result);
38786
- const created = uuid3(response.workspace_id, "workspace_id");
39182
+ const created = uuid4(response.workspace_id, "workspace_id");
38787
39183
  if (created !== proposedId) {
38788
39184
  throw new Error(
38789
39185
  "the server confirmed a different workspace than this command created; run cswarm workspaces before doing anything else"
@@ -38799,7 +39195,7 @@ async function runNew(args) {
38799
39195
  project: {
38800
39196
  workspace_id: created,
38801
39197
  name,
38802
- stream_id: typeof response.stream_id === "string" && UUID_RE17.test(response.stream_id) ? response.stream_id : null
39198
+ stream_id: typeof response.stream_id === "string" && UUID_RE18.test(response.stream_id) ? response.stream_id : null
38803
39199
  }
38804
39200
  });
38805
39201
  return;
@@ -39056,7 +39452,7 @@ async function runInvite(args) {
39056
39452
  );
39057
39453
  }
39058
39454
  assertInvitationToken(response.invitation_token);
39059
- const responseWorkspaceId = uuid3(response.workspace_id, "workspace_id");
39455
+ const responseWorkspaceId = uuid4(response.workspace_id, "workspace_id");
39060
39456
  if (typeof response.workspace_name !== "string" || typeof response.inviter_display_name !== "string") {
39061
39457
  throw new Error(
39062
39458
  "the invitation was created without its fresh display labels; run invite again to issue a complete link"
@@ -39076,7 +39472,7 @@ async function runInvite(args) {
39076
39472
  printJson({
39077
39473
  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.",
39078
39474
  status: response.status,
39079
- invitation_id: uuid3(response.invitation_id, "invitation_id"),
39475
+ invitation_id: uuid4(response.invitation_id, "invitation_id"),
39080
39476
  invite_link: inviteLink
39081
39477
  });
39082
39478
  }
@@ -39188,7 +39584,7 @@ async function runLegacyAccept(args) {
39188
39584
  { kind: "accept_invitation", token: invitationToken }
39189
39585
  )
39190
39586
  );
39191
- const acceptedWorkspace = uuid3(response.workspace_id, "workspace_id");
39587
+ const acceptedWorkspace = uuid4(response.workspace_id, "workspace_id");
39192
39588
  await writeWorkspaceDefault(human.store, human.userId, acceptedWorkspace);
39193
39589
  await writeCurrentTarget(cloud);
39194
39590
  printJson({
@@ -39334,7 +39730,7 @@ async function runPrincipal(args) {
39334
39730
  "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."
39335
39731
  ),
39336
39732
  status: response.status,
39337
- principal_id: uuid3(response.principal_id, "principal_id")
39733
+ principal_id: uuid4(response.principal_id, "principal_id")
39338
39734
  });
39339
39735
  return;
39340
39736
  }
@@ -39442,8 +39838,8 @@ async function runToken(args) {
39442
39838
  );
39443
39839
  printJson(agentCredentialArtifact({
39444
39840
  principalId,
39445
- tokenId: uuid3(response.token_id, "token_id"),
39446
- runId: uuid3(response.run_id, "run_id"),
39841
+ tokenId: uuid4(response.token_id, "token_id"),
39842
+ runId: uuid4(response.run_id, "run_id"),
39447
39843
  token: response.agent_token,
39448
39844
  expiresAt
39449
39845
  }));
@@ -39573,7 +39969,7 @@ async function runLinkNew(args) {
39573
39969
  2
39574
39970
  );
39575
39971
  const taskId = args.required("task-id");
39576
- if (!UUID_RE17.test(taskId)) {
39972
+ if (!UUID_RE18.test(taskId)) {
39577
39973
  throw new Error("--task-id must be the work item's UUID");
39578
39974
  }
39579
39975
  const site = capabilitySiteOrigin(
@@ -39603,11 +39999,11 @@ async function runLinkNew(args) {
39603
39999
  );
39604
40000
  if (response.capability_token === void 0) {
39605
40001
  throw new Error(
39606
- `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`
40002
+ `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`
39607
40003
  );
39608
40004
  }
39609
40005
  assertCapabilityToken(response.capability_token);
39610
- const capabilityId = uuid3(response.capability_id, "capability_id");
40006
+ const capabilityId = uuid4(response.capability_id, "capability_id");
39611
40007
  const expiresAt = capabilityTimestamp(response.expires_at, "expires_at");
39612
40008
  const url = capabilityUrl(site, response.capability_token);
39613
40009
  if (args.has("json")) {
@@ -39633,7 +40029,7 @@ async function runLinkRevoke(args) {
39633
40029
  2
39634
40030
  );
39635
40031
  const capabilityId = args.required("capability-id");
39636
- if (!UUID_RE17.test(capabilityId)) {
40032
+ if (!UUID_RE18.test(capabilityId)) {
39637
40033
  throw new Error(
39638
40034
  "--capability-id must be the id printed when the link was created"
39639
40035
  );
@@ -39651,7 +40047,7 @@ async function runLinkRevoke(args) {
39651
40047
  { kind: "revoke_capability_url", capability_id: capabilityId }
39652
40048
  )
39653
40049
  );
39654
- const revoked = uuid3(response.capability_id, "capability_id");
40050
+ const revoked = uuid4(response.capability_id, "capability_id");
39655
40051
  const revokedAt = capabilityTimestamp(response.revoked_at, "revoked_at");
39656
40052
  const message = renderCapabilityRevoke(revoked, revokedAt);
39657
40053
  if (args.has("json")) {
@@ -40212,7 +40608,7 @@ async function runReply(args) {
40212
40608
  "json"
40213
40609
  ], 3);
40214
40610
  const signalId = args.positionals[1];
40215
- if (signalId === void 0 || !UUID_RE17.test(signalId)) {
40611
+ if (signalId === void 0 || !UUID_RE18.test(signalId)) {
40216
40612
  throw new Error("reply requires the signal UUID being answered");
40217
40613
  }
40218
40614
  const body = args.positionals[2];
@@ -40442,6 +40838,52 @@ async function runSignalRead(args, inbox) {
40442
40838
  })}
40443
40839
  `);
40444
40840
  }
40841
+ async function runReceipt(args) {
40842
+ args.assertShape([
40843
+ ...TARGET_FLAGS,
40844
+ "workspace-id",
40845
+ ...CREDENTIAL_FLAGS,
40846
+ "json"
40847
+ ], 2);
40848
+ const signalId = args.positionals[1];
40849
+ if (!UUID_RE18.test(signalId)) {
40850
+ throw new Error("signal-id must be a UUID");
40851
+ }
40852
+ if (!args.has("agent-token-stdin")) {
40853
+ throw new Error(
40854
+ "receipt reads signals sent by an agent; provide --agent-token-stdin and --workspace-id"
40855
+ );
40856
+ }
40857
+ const cloud = await target(args);
40858
+ const selected = await commandWorkspaceAndCredential(args, cloud, {
40859
+ validateHumanWorkspace: true
40860
+ });
40861
+ let result;
40862
+ try {
40863
+ result = await readAgentDeliveryReceipts(
40864
+ cloud,
40865
+ selected.bearer,
40866
+ selected.selectedWorkspace,
40867
+ signalId
40868
+ );
40869
+ } catch (error) {
40870
+ 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";
40871
+ throw new Error(
40872
+ `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}`
40873
+ );
40874
+ }
40875
+ const report = {
40876
+ ...result,
40877
+ workspaceId: selected.selectedWorkspace,
40878
+ signalId: signalId.toLowerCase()
40879
+ };
40880
+ if (args.has("json")) {
40881
+ printJson(signalReceiptJsonPayload(report));
40882
+ return;
40883
+ }
40884
+ process.stdout.write(`${renderSignalReceiptReport(report)}
40885
+ `);
40886
+ }
40445
40887
  async function runInboxFollowCommand(args) {
40446
40888
  const cloud = await target(args);
40447
40889
  const selected = await commandWorkspaceAndCredential(args, cloud, {
@@ -40542,7 +40984,7 @@ async function runInboxFollowCommand(args) {
40542
40984
  }
40543
40985
  }
40544
40986
  function listenerUuid(value, flag) {
40545
- if (!value || !UUID_RE17.test(value)) {
40987
+ if (!value || !UUID_RE18.test(value)) {
40546
40988
  throw new Error(`--${flag} must be a UUID`);
40547
40989
  }
40548
40990
  return value.toLowerCase();
@@ -41605,7 +42047,7 @@ async function fileRows(context) {
41605
42047
  );
41606
42048
  }
41607
42049
  async function resolveFileSelector(context, selector) {
41608
- if (UUID_RE17.test(selector)) return selector.toLowerCase();
42050
+ if (UUID_RE18.test(selector)) return selector.toLowerCase();
41609
42051
  const rows3 = await fileRows(context);
41610
42052
  const match = rows3.find(
41611
42053
  (row) => row.name.toLowerCase() === selector.toLowerCase()
@@ -42117,6 +42559,10 @@ async function main() {
42117
42559
  await runReply(args);
42118
42560
  return;
42119
42561
  }
42562
+ if (verb === "receipt") {
42563
+ await runReceipt(args);
42564
+ return;
42565
+ }
42120
42566
  if (verb === "feed" || verb === "inbox") {
42121
42567
  await runSignalRead(args, verb === "inbox");
42122
42568
  return;
@@ -42193,7 +42639,7 @@ main().catch((error) => {
42193
42639
  if (error instanceof WorkspaceCliError) {
42194
42640
  const structured = error.structured();
42195
42641
  const verb = process.argv[2];
42196
- 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");
42642
+ 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");
42197
42643
  if (json) {
42198
42644
  process.stdout.write(`${JSON.stringify(structured, null, 2)}
42199
42645
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commonswarm",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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"