agent-relay 12.0.0 → 12.1.0

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 (38) hide show
  1. package/README.md +64 -0
  2. package/dist/cli/agent-relay-mcp.d.ts.map +1 -1
  3. package/dist/cli/agent-relay-mcp.js +177 -28
  4. package/dist/cli/agent-relay-mcp.js.map +1 -1
  5. package/dist/cli/commands/core.d.ts +8 -0
  6. package/dist/cli/commands/core.d.ts.map +1 -1
  7. package/dist/cli/commands/core.js +4 -0
  8. package/dist/cli/commands/core.js.map +1 -1
  9. package/dist/cli/commands/fleet-agent.d.ts +5 -1
  10. package/dist/cli/commands/fleet-agent.d.ts.map +1 -1
  11. package/dist/cli/commands/fleet-agent.js +114 -26
  12. package/dist/cli/commands/fleet-agent.js.map +1 -1
  13. package/dist/cli/commands/fleet.d.ts.map +1 -1
  14. package/dist/cli/commands/fleet.js +93 -13
  15. package/dist/cli/commands/fleet.js.map +1 -1
  16. package/dist/cli/commands/node.js +4 -0
  17. package/dist/cli/commands/node.js.map +1 -1
  18. package/dist/cli/commands/status.d.ts +1 -1
  19. package/dist/cli/commands/status.d.ts.map +1 -1
  20. package/dist/cli/commands/status.js +7 -3
  21. package/dist/cli/commands/status.js.map +1 -1
  22. package/dist/cli/lib/broker-lifecycle.d.ts +2 -0
  23. package/dist/cli/lib/broker-lifecycle.d.ts.map +1 -1
  24. package/dist/cli/lib/broker-lifecycle.js +222 -153
  25. package/dist/cli/lib/broker-lifecycle.js.map +1 -1
  26. package/dist/cli/lib/broker-process-identity.d.ts +30 -0
  27. package/dist/cli/lib/broker-process-identity.d.ts.map +1 -0
  28. package/dist/cli/lib/broker-process-identity.js +229 -0
  29. package/dist/cli/lib/broker-process-identity.js.map +1 -0
  30. package/dist/cli/lib/sdk-command.d.ts.map +1 -1
  31. package/dist/cli/lib/sdk-command.js +20 -2
  32. package/dist/cli/lib/sdk-command.js.map +1 -1
  33. package/dist/cli/lib/spawn-lifecycle.d.ts +12 -0
  34. package/dist/cli/lib/spawn-lifecycle.d.ts.map +1 -0
  35. package/dist/cli/lib/spawn-lifecycle.js +89 -0
  36. package/dist/cli/lib/spawn-lifecycle.js.map +1 -0
  37. package/dist/index.cjs +156 -23
  38. package/package.json +9 -9
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-command.js","sourceRoot":"","sources":["../../../src/cli/lib/sdk-command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAwB,MAAM,kBAAkB,CAAC;AAE3F,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAyB,MAAM,iBAAiB,CAAC;AAchG,MAAM,UAAU,eAAe,CAAC,YAAqC,EAAE;IACrE,OAAO;QACL,gBAAgB;QAChB,oBAAoB;QACpB,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACjF,GAAG,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACjD,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QACrD,IAAI,EAAE,WAAW;QACjB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO,CACL,OAAO;SACJ,MAAM,CACL,uBAAuB,EACvB,yEAAyE,CAC1E;SACA,MAAM,CAAC,YAAY,EAAE,2BAA2B,CAAC;SACjD,MAAM,CAAC,iBAAiB,EAAE,6CAA6C,CAAC;SACxE,MAAM,CAAC,kBAAkB,EAAE,wDAAwD,CAAC;QACrF,6EAA6E;QAC7E,iFAAiF;QACjF,8EAA8E;QAC9E,yDAAyD;SACxD,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACxE,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAA6B;IAC9D,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,YAAkC;QACrD,KAAK,EAAE,IAAI,CAAC,KAA2B;QACvC,OAAO,EAAE,IAAI,CAAC,OAA6B;KAC5C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAoB,EAAE,KAAc;IAC5D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAoB,EAAE,EAAuB;IACxE,IAAI,CAAC;QACH,MAAM,EAAE,EAAE,CAAC;IACb,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"sdk-command.js","sourceRoot":"","sources":["../../../src/cli/lib/sdk-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type SpawnLifecycleState = 'accepted' | 'ready' | 'unconfirmed_may_be_running' | 'failed';
2
+ export type SpawnDispatchState = 'dispatched' | 'not_dispatched' | 'unknown';
3
+ export declare function spawnLifecycleState(value: Record<string, unknown>): SpawnLifecycleState;
4
+ /**
5
+ * Project an upstream spawn invocation record down to an allowlisted set of
6
+ * lifecycle-evidence fields, dropping raw error text, task payloads, and any
7
+ * other upstream data that should not cross a CLI/MCP serialization
8
+ * boundary unsanitized.
9
+ */
10
+ export declare function sanitizedSpawnReceipt(value: Record<string, unknown>): Record<string, unknown>;
11
+ export declare function spawnPlacementReceipt(value: Record<string, unknown>): Record<string, unknown>;
12
+ //# sourceMappingURL=spawn-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/spawn-lifecycle.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,OAAO,GAAG,4BAA4B,GAAG,QAAQ,CAAC;AACjG,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,gBAAgB,GAAG,SAAS,CAAC;AA0B7E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAgBvF;AAiBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgB7F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAW7F"}
@@ -0,0 +1,89 @@
1
+ const SUCCESS = new Set(['completed', 'succeeded', 'success']);
2
+ const FAILURE = new Set(['failed', 'error', 'cancelled', 'canceled', 'denied']);
3
+ const DISPATCHED = new Set(['dispatched', 'invoked', 'running']);
4
+ const NOT_DISPATCHED = new Set(['pending', 'queued']);
5
+ function text(value) {
6
+ return typeof value === 'string' && value.trim() ? value : undefined;
7
+ }
8
+ function dispatchEvidence(value) {
9
+ const status = text(value.status)?.toLowerCase();
10
+ if (text(value.dispatchedNodeId) ||
11
+ text(value.dispatched_node_id) ||
12
+ text(value.handlerNodeId) ||
13
+ text(value.handler_node_id) ||
14
+ (status !== undefined && (DISPATCHED.has(status) || SUCCESS.has(status)))) {
15
+ return 'dispatched';
16
+ }
17
+ if (status !== undefined && NOT_DISPATCHED.has(status))
18
+ return 'not_dispatched';
19
+ return 'unknown';
20
+ }
21
+ export function spawnLifecycleState(value) {
22
+ const status = text(value.status)?.toLowerCase();
23
+ if (status && SUCCESS.has(status)) {
24
+ const output = value.output !== null && typeof value.output === 'object'
25
+ ? value.output
26
+ : value;
27
+ // A terminal success status without explicit launch and readiness proof is
28
+ // a failed spawn, not a live-but-uncertain one. Genuine uncertainty is
29
+ // reserved for non-terminal acknowledgements and confirmation timeouts.
30
+ return output.spawned === true && output.ready === true ? 'ready' : 'failed';
31
+ }
32
+ if (status && FAILURE.has(status))
33
+ return 'failed';
34
+ if (status === 'accepted')
35
+ return 'accepted';
36
+ if (status && NOT_DISPATCHED.has(status) && dispatchEvidence(value) === 'not_dispatched')
37
+ return 'accepted';
38
+ return 'unconfirmed_may_be_running';
39
+ }
40
+ // Allowlisted keys for a spawn receipt that crosses a CLI/MCP serialization
41
+ // boundary. Upstream invocation records can carry arbitrary broker/handler
42
+ // output (raw error text, task payloads, environment-derived metadata) that
43
+ // is not safe to echo back verbatim — see relay#1563. Only lifecycle
44
+ // evidence (status/ids/readiness) is allowlisted through.
45
+ const SPAWN_RECEIPT_ALLOWED_KEYS = [
46
+ 'status',
47
+ 'invocation_id',
48
+ 'invocationId',
49
+ 'dispatched_node_id',
50
+ 'dispatchedNodeId',
51
+ 'handler_node_id',
52
+ 'handlerNodeId',
53
+ ];
54
+ /**
55
+ * Project an upstream spawn invocation record down to an allowlisted set of
56
+ * lifecycle-evidence fields, dropping raw error text, task payloads, and any
57
+ * other upstream data that should not cross a CLI/MCP serialization
58
+ * boundary unsanitized.
59
+ */
60
+ export function sanitizedSpawnReceipt(value) {
61
+ const out = {};
62
+ for (const key of SPAWN_RECEIPT_ALLOWED_KEYS) {
63
+ if (value[key] !== undefined)
64
+ out[key] = value[key];
65
+ }
66
+ const output = value.output !== null && typeof value.output === 'object'
67
+ ? value.output
68
+ : undefined;
69
+ if (output && (typeof output.spawned === 'boolean' || typeof output.ready === 'boolean')) {
70
+ out.output = {
71
+ ...(typeof output.spawned === 'boolean' ? { spawned: output.spawned } : {}),
72
+ ...(typeof output.ready === 'boolean' ? { ready: output.ready } : {}),
73
+ };
74
+ }
75
+ return out;
76
+ }
77
+ export function spawnPlacementReceipt(value) {
78
+ const invocationId = text(value.invocationId) ?? text(value.invocation_id);
79
+ const dispatchedNodeId = text(value.dispatchedNodeId) ?? text(value.dispatched_node_id);
80
+ const handlerNodeId = text(value.handlerNodeId) ?? text(value.handler_node_id);
81
+ return {
82
+ state: spawnLifecycleState(value),
83
+ dispatchState: dispatchEvidence(value),
84
+ ...(invocationId ? { invocationId } : {}),
85
+ ...(dispatchedNodeId ? { dispatchedNodeId } : {}),
86
+ ...(handlerNodeId ? { handlerNodeId } : {}),
87
+ };
88
+ }
89
+ //# sourceMappingURL=spawn-lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-lifecycle.js","sourceRoot":"","sources":["../../../src/cli/lib/spawn-lifecycle.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -303,7 +303,7 @@ __export(index_exports, {
303
303
  module.exports = __toCommonJS(index_exports);
304
304
 
305
305
  // ../../node_modules/@relaycast/sdk/dist/version.js
306
- var SDK_VERSION = "8.8.0";
306
+ var SDK_VERSION = "8.9.1";
307
307
 
308
308
  // ../../node_modules/zod/v4/classic/external.js
309
309
  var external_exports = {};
@@ -2868,7 +2868,7 @@ ${content.join("\n")}
2868
2868
  var version = {
2869
2869
  major: 4,
2870
2870
  minor: 6,
2871
- patch: 1
2871
+ patch: 2
2872
2872
  };
2873
2873
 
2874
2874
  // ../../node_modules/zod/v4/core/schemas.js
@@ -3672,7 +3672,7 @@ function handlePropertyResult(result, final, key, input2, optin, optout) {
3672
3672
  return;
3673
3673
  }
3674
3674
  if (result.value === void 0) {
3675
- if (isPresent) {
3675
+ if (isPresent || optin === "defaulted" && !isOptionalOut) {
3676
3676
  final.value[key] = void 0;
3677
3677
  }
3678
3678
  } else {
@@ -3908,16 +3908,16 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
3908
3908
  doc.write(`
3909
3909
  if (${id}.issues.length) {${prefixStr(id, k)}
3910
3910
  }
3911
-
3912
- if (${id}.value === undefined) {
3913
- if (${isPresent}) {
3914
- newResult[${k}] = undefined;
3915
- }
3911
+ `);
3912
+ if (optin === "defaulted") {
3913
+ doc.write(`newResult[${k}] = ${id}.value;`);
3916
3914
  } else {
3915
+ doc.write(`
3916
+ if (${id}.value !== undefined || ${isPresent}) {
3917
3917
  newResult[${k}] = ${id}.value;
3918
3918
  }
3919
-
3920
3919
  `);
3920
+ }
3921
3921
  }
3922
3922
  }
3923
3923
  doc.write(`payload.value = newResult;`);
@@ -13977,7 +13977,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
13977
13977
  }
13978
13978
  }
13979
13979
  const outputVar = newVar(ctx);
13980
- const hasConditionalKeys = allKeys.some((k) => mayOutputUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
13980
+ const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
13981
13981
  if (!buildsValue) {
13982
13982
  if (unknownKeysMode === "schema") {
13983
13983
  const knownSet = keys.length > 0 ? addConstant(ctx, new Set(keys)) : null;
@@ -14004,7 +14004,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
14004
14004
  const out = propOutputs.get(k);
14005
14005
  if (dropsWhenAbsent(propShape[k])) {
14006
14006
  doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
14007
- } else if (mayOutputUndefined(propShape[k])) {
14007
+ } else if (mayOmitUndefined(propShape[k])) {
14008
14008
  doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
14009
14009
  } else {
14010
14010
  doc.write(`${outputVar}[${kx}] = ${out};`);
@@ -14137,6 +14137,9 @@ function fastPathAcceptsAbsence(schema) {
14137
14137
  function dropsWhenAbsent(schema) {
14138
14138
  return schema._zod.optin === "optional" && schema._zod.optout === "optional";
14139
14139
  }
14140
+ function mayOmitUndefined(schema) {
14141
+ return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
14142
+ }
14140
14143
  function mayOutputUndefined(schema) {
14141
14144
  const def = schema._zod.def;
14142
14145
  switch (def.type) {
@@ -20133,6 +20136,9 @@ var ReleaseAgentRequestSchema = external_exports.object({
20133
20136
  delete_agent: external_exports.boolean().optional(),
20134
20137
  expected_token_hash: external_exports.string().regex(AGENT_TOKEN_HASH_PATTERN).optional()
20135
20138
  });
20139
+ var ExactReleaseAgentRequestSchema = ReleaseAgentRequestSchema.extend({
20140
+ expected_agent_id: external_exports.string().min(1)
20141
+ });
20136
20142
 
20137
20143
  // ../../node_modules/@relaycast/types/dist/message.js
20138
20144
  var HeaderBlockSchema = external_exports.object({
@@ -21461,9 +21467,11 @@ var AgentRegisterReplyDataSchema = external_exports.object({
21461
21467
  // Returned only to nodes that advertise FLEET_DELIVERY_CURSOR_CAPABILITY.
21462
21468
  delivery_ack_seq: external_exports.number().int().nonnegative().optional()
21463
21469
  }).strict();
21470
+ var NODE_REGISTRATION_CONTRACT_V1 = "relay:node-registration-v1";
21464
21471
  var NodeRegisterReplyDataSchema = external_exports.object({
21465
21472
  provider: FleetProviderIdentitySchema,
21466
- accepted_capabilities: external_exports.array(FleetCapabilityAcceptanceSchema)
21473
+ accepted_capabilities: external_exports.array(FleetCapabilityAcceptanceSchema),
21474
+ registration_contract: external_exports.literal(NODE_REGISTRATION_CONTRACT_V1).optional()
21467
21475
  }).passthrough();
21468
21476
  var FleetReplyMessageSchema = external_exports.object({
21469
21477
  ...FleetResponseEnvelopeFields,
@@ -22937,6 +22945,7 @@ var RelayError = class extends Error {
22937
22945
  statusCode;
22938
22946
  rawCode;
22939
22947
  status;
22948
+ retryAfterMs;
22940
22949
  constructor(code, message, options = {}) {
22941
22950
  super(message);
22942
22951
  this.name = "RelayError";
@@ -22945,14 +22954,15 @@ var RelayError = class extends Error {
22945
22954
  this.rawCode = options.rawCode;
22946
22955
  this.retryable = options.retryable ?? relayErrorRetryable(code, options.statusCode);
22947
22956
  this.status = options.statusCode ?? 0;
22957
+ this.retryAfterMs = options.retryAfterMs;
22948
22958
  if (options.cause !== void 0) {
22949
22959
  this.cause = options.cause;
22950
22960
  }
22951
22961
  }
22952
22962
  };
22953
- function relayErrorFromApi(rawCode, message, statusCode) {
22963
+ function relayErrorFromApi(rawCode, message, statusCode, retryAfterMs) {
22954
22964
  const code = normalizeRelayErrorCode(rawCode, statusCode);
22955
- return new RelayError(code, message, { statusCode, rawCode });
22965
+ return new RelayError(code, message, { statusCode, rawCode, retryAfterMs });
22956
22966
  }
22957
22967
 
22958
22968
  // ../../node_modules/@relaycast/sdk/dist/client.js
@@ -22980,6 +22990,7 @@ var DEFAULT_RETRY_POLICY = {
22980
22990
  jitter: true,
22981
22991
  retryOn: [429, 500, 502, 503, 504]
22982
22992
  };
22993
+ var MAX_AUTOMATIC_RETRY_DELAY_MS = 6e4;
22983
22994
  function normalizeRetryPolicy(input2) {
22984
22995
  return {
22985
22996
  maxRetries: Number.isFinite(input2?.maxRetries) ? Math.max(0, Math.floor(input2.maxRetries)) : DEFAULT_RETRY_POLICY.maxRetries,
@@ -22997,7 +23008,7 @@ function computeBackoffMs(policy, retryAttempt) {
22997
23008
  return Math.max(0, Math.round(exponential * jitterFactor));
22998
23009
  }
22999
23010
  function parseRetryAfterMs(res) {
23000
- const header = res.headers.get("Retry-After");
23011
+ const header = res.headers?.get("Retry-After");
23001
23012
  if (!header)
23002
23013
  return null;
23003
23014
  const asSeconds = Number(header);
@@ -23115,7 +23126,9 @@ var HttpClient = class _HttpClient {
23115
23126
  if (hasBody)
23116
23127
  headers["Content-Type"] = "application/json";
23117
23128
  const wireBody = hasBody ? decamelizeKeys(body) : void 0;
23118
- const maxRetries = options?.retry === false ? 0 : this._retryPolicy.maxRetries;
23129
+ const idempotencyKey = Object.entries(headers).find(([name]) => name.toLowerCase() === "idempotency-key")?.[1];
23130
+ const isUnsafeMutation = ["POST", "PATCH"].includes(method.toUpperCase()) && !idempotencyKey;
23131
+ const maxRetries = options?.retry === false || isUnsafeMutation ? 0 : this._retryPolicy.maxRetries;
23119
23132
  let attempt = 0;
23120
23133
  while (true) {
23121
23134
  let res;
@@ -23135,7 +23148,7 @@ var HttpClient = class _HttpClient {
23135
23148
  throw new RelayError("transport_error", `Network request failed: ${err instanceof Error ? err.message : "unknown error"}`, { retryable: true, cause: err });
23136
23149
  }
23137
23150
  if (this._retryPolicy.retryOn.includes(res.status) && attempt < maxRetries) {
23138
- const waitMs = res.status === 429 ? parseRetryAfterMs(res) ?? computeBackoffMs(this._retryPolicy, attempt) : computeBackoffMs(this._retryPolicy, attempt);
23151
+ const waitMs = Math.min(parseRetryAfterMs(res) ?? computeBackoffMs(this._retryPolicy, attempt), MAX_AUTOMATIC_RETRY_DELAY_MS);
23139
23152
  attempt += 1;
23140
23153
  await sleep(waitMs);
23141
23154
  continue;
@@ -23160,7 +23173,7 @@ var HttpClient = class _HttpClient {
23160
23173
  const errParsed = ApiErrorSchema.safeParse(json2);
23161
23174
  const code = errParsed.success ? errParsed.data.error.code : "unknown_error";
23162
23175
  const message = errParsed.success ? errParsed.data.error.message : "Unknown error";
23163
- throw relayErrorFromApi(code, message, res.status);
23176
+ throw relayErrorFromApi(code, message, res.status, parseRetryAfterMs(res) ?? void 0);
23164
23177
  }
23165
23178
  const data = envelope.data.data;
23166
23179
  const parsedData = options?.schema ? options.schema.parse(data) : data;
@@ -23678,6 +23691,18 @@ var RelayCast = class _RelayCast {
23678
23691
  resolveIdentity: () => this.resolveIdentity(),
23679
23692
  spawn: (data) => this.client.post("/v1/agents/spawn", data),
23680
23693
  release: (data) => this.client.post("/v1/agents/release", data),
23694
+ /**
23695
+ * Atomically release only the exact immutable agent identity. The key is
23696
+ * deliberately mandatory: callers persist and reuse it across restarts.
23697
+ */
23698
+ releaseExact: (data, options) => {
23699
+ const idempotencyKey = options.idempotencyKey.trim();
23700
+ if (!idempotencyKey)
23701
+ throw new Error("idempotencyKey is required for exact agent release");
23702
+ return this.client.post("/v1/agents/release-exact", data, {
23703
+ headers: { "Idempotency-Key": idempotencyKey }
23704
+ });
23705
+ },
23681
23706
  events: {
23682
23707
  emit: (name, data) => this.client.post(`/v1/agents/${encodeURIComponent(name)}/events`, data),
23683
23708
  list: (name, query) => {
@@ -23719,6 +23744,26 @@ var RelayCast = class _RelayCast {
23719
23744
  params.capability = query.capability;
23720
23745
  if (query?.name)
23721
23746
  params.name = query.name;
23747
+ if (query?.status)
23748
+ params.status = query.status;
23749
+ return this.client.get("/v1/nodes", params);
23750
+ },
23751
+ // Explicit, bounded pagination contract for reading history (e.g. `--all`
23752
+ // in the Relay CLI): pages through every matching row exactly once, no
23753
+ // matter how many the workspace has retained, without silent truncation.
23754
+ // Compatible callers keep using `list()`, which never returns this shape.
23755
+ listHistory: (query) => {
23756
+ const params = { history: "true" };
23757
+ if (query?.capability)
23758
+ params.capability = query.capability;
23759
+ if (query?.name)
23760
+ params.name = query.name;
23761
+ if (query?.status)
23762
+ params.status = query.status;
23763
+ if (query?.cursor)
23764
+ params.cursor = query.cursor;
23765
+ if (query?.limit !== void 0)
23766
+ params.limit = String(query.limit);
23722
23767
  return this.client.get("/v1/nodes", params);
23723
23768
  },
23724
23769
  get: (name) => this.client.get(`/v1/nodes/${encodeURIComponent(name)}`),
@@ -25780,6 +25825,7 @@ function normalizeActionInvocationAck(raw) {
25780
25825
  ...readStr(record2, "handlerNodeId", "handler_node_id") ? { handlerNodeId: readStr(record2, "handlerNodeId", "handler_node_id") } : {},
25781
25826
  ...readStr(record2, "dispatchedNodeId", "dispatched_node_id") ? { dispatchedNodeId: readStr(record2, "dispatchedNodeId", "dispatched_node_id") } : {},
25782
25827
  ...readRecord(record2, "input") ? { input: readRecord(record2, "input") } : {},
25828
+ ...readRecord(record2, "output") ? { output: readRecord(record2, "output") } : {},
25783
25829
  ...readStr(record2, "status") ? { status: readStr(record2, "status") } : {},
25784
25830
  ...readStr(record2, "createdAt", "created_at") ? { createdAt: readStr(record2, "createdAt", "created_at") } : {}
25785
25831
  };
@@ -25859,12 +25905,39 @@ function createRelaycastClient(options) {
25859
25905
  }
25860
25906
 
25861
25907
  // ../sdk/dist/messaging/relaycast-placement.js
25908
+ var DISPATCH_EVIDENT_STATUSES = /* @__PURE__ */ new Set([
25909
+ "dispatched",
25910
+ "invoked",
25911
+ "running",
25912
+ "completed",
25913
+ "succeeded",
25914
+ "success"
25915
+ ]);
25916
+ var NOT_DISPATCHED_STATUSES = /* @__PURE__ */ new Set(["pending", "queued"]);
25917
+ function resolveDispatchState(ack) {
25918
+ if (ack.dispatchedNodeId || ack.handlerNodeId)
25919
+ return "dispatched";
25920
+ const status = ack.status?.toLowerCase();
25921
+ if (status && DISPATCH_EVIDENT_STATUSES.has(status))
25922
+ return "dispatched";
25923
+ if (status && NOT_DISPATCHED_STATUSES.has(status))
25924
+ return "not_dispatched";
25925
+ return "unknown";
25926
+ }
25862
25927
  var RelayPlacementError = class extends Error {
25863
25928
  code;
25864
25929
  capability;
25865
25930
  node;
25866
25931
  repo;
25867
25932
  attempts;
25933
+ /** Stable invocation correlation for accepted/dispatch outcomes. */
25934
+ invocationId;
25935
+ /** Evidence state at the point this placement returned or failed. */
25936
+ state;
25937
+ /** Whether the engine supplied evidence that a node received the dispatch. */
25938
+ dispatchState;
25939
+ /** Original invocation receipt, when a terminal spawn result was observed. */
25940
+ receipt;
25868
25941
  constructor(code, message, context) {
25869
25942
  super(message);
25870
25943
  this.name = "RelayPlacementError";
@@ -25873,6 +25946,10 @@ var RelayPlacementError = class extends Error {
25873
25946
  this.node = context.node;
25874
25947
  this.repo = context.repo;
25875
25948
  this.attempts = context.attempts;
25949
+ this.invocationId = context.invocationId;
25950
+ this.state = context.state;
25951
+ this.dispatchState = context.dispatchState;
25952
+ this.receipt = context.receipt;
25876
25953
  }
25877
25954
  };
25878
25955
  function nonEmptyPlacement(value, label) {
@@ -25918,6 +25995,9 @@ var DEFAULT_CONFIRM_POLL_MS = 500;
25918
25995
  var MAX_CONFIRM_TIMEOUT_MS = 2147483647;
25919
25996
  var CONFIRM_SUCCESS_STATUSES = /* @__PURE__ */ new Set(["completed", "succeeded", "success"]);
25920
25997
  var CONFIRM_FAILURE_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "denied", "cancelled", "canceled"]);
25998
+ function hasExplicitSpawnReadinessProof(value) {
25999
+ return value.output?.spawned === true && value.output?.ready === true;
26000
+ }
25921
26001
  var READ_TIMED_OUT = /* @__PURE__ */ Symbol("relay.confirm.readTimedOut");
25922
26002
  function confirmDurationMs(value, fallback, max) {
25923
26003
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.min(value, max) : fallback;
@@ -26330,6 +26410,32 @@ var RelaycastMessagingClient = class {
26330
26410
  const ack = await this.commands.invoke(actionName, actionInput);
26331
26411
  const placedNode = clientMustTarget ? decision.node : await this.resolvePlacementAckNode(ack, capability);
26332
26412
  const placedNodeLabel = placedNode?.name ?? ack.dispatchedNodeId ?? ack.handlerNodeId ?? "engine-selected node";
26413
+ const ackStatus = ack.status?.toLowerCase();
26414
+ if (ackStatus && CONFIRM_FAILURE_STATUSES.has(ackStatus)) {
26415
+ throw new RelayPlacementError("spawn_failed", `node '${placedNodeLabel}' reported ${ackStatus} for ${actionName} immediately upon dispatch`, {
26416
+ capability,
26417
+ node: placedNodeLabel,
26418
+ repo,
26419
+ attempts,
26420
+ state: "failed",
26421
+ dispatchState: resolveDispatchState(ack),
26422
+ invocationId: ack.invocationId,
26423
+ receipt: ack
26424
+ });
26425
+ }
26426
+ const ackOutput = ack.output;
26427
+ if (!input2.confirm && capability.startsWith("spawn:") && ackStatus && CONFIRM_SUCCESS_STATUSES.has(ackStatus) && !hasExplicitSpawnReadinessProof({ output: ackOutput })) {
26428
+ throw new RelayPlacementError("spawn_failed", `node '${placedNodeLabel}' reported ${ackStatus} for ${actionName} without explicit spawned:true and ready:true proof`, {
26429
+ capability,
26430
+ node: placedNodeLabel,
26431
+ repo,
26432
+ attempts,
26433
+ state: "failed",
26434
+ dispatchState: resolveDispatchState(ack),
26435
+ invocationId: ack.invocationId,
26436
+ receipt: ack
26437
+ });
26438
+ }
26333
26439
  const confirmation = input2.confirm ? await this.confirmPlacementInvocation(actionName, ack, {
26334
26440
  capability,
26335
26441
  node: placedNodeLabel,
@@ -26349,7 +26455,8 @@ var RelaycastMessagingClient = class {
26349
26455
  ...repo ? { repo } : {},
26350
26456
  attempts,
26351
26457
  queued,
26352
- confirmed: Boolean(confirmation)
26458
+ confirmed: Boolean(confirmation),
26459
+ state: confirmation ? "ready" : "accepted"
26353
26460
  },
26354
26461
  ...confirmation ? { confirmation } : {}
26355
26462
  };
@@ -26433,13 +26540,19 @@ var RelaycastMessagingClient = class {
26433
26540
  async confirmPlacementInvocation(actionName, ack, context) {
26434
26541
  const { timeoutMs, pollIntervalMs, ...errorContext } = context;
26435
26542
  const invocationId = ack.invocationId;
26543
+ const dispatchState = resolveDispatchState(ack);
26436
26544
  if (!invocationId) {
26437
- throw new RelayPlacementError("spawn_unconfirmed", `node '${context.node}' accepted ${actionName} without returning an invocation id, so the dispatch cannot be confirmed`, errorContext);
26545
+ throw new RelayPlacementError("spawn_unconfirmed", `node '${context.node}' accepted ${actionName} without returning an invocation id, so the dispatch cannot be confirmed`, { ...errorContext, state: "unconfirmed_may_be_running", dispatchState });
26438
26546
  }
26439
26547
  const budgetMs = confirmDurationMs(timeoutMs, DEFAULT_CONFIRM_TIMEOUT_MS, MAX_CONFIRM_TIMEOUT_MS);
26440
26548
  const cadenceMs = confirmDurationMs(pollIntervalMs, DEFAULT_CONFIRM_POLL_MS, budgetMs);
26441
26549
  if (!this.agentClient?.actions) {
26442
- throw new RelayPlacementError("spawn_unconfirmed", `node '${context.node}' accepted ${actionName} (invocation ${invocationId}), but confirmation requires an agent-scoped client with the actions API, so the dispatch cannot be read back`, errorContext);
26550
+ throw new RelayPlacementError("spawn_unconfirmed", `node '${context.node}' accepted ${actionName} (invocation ${invocationId}), but confirmation requires an agent-scoped client with the actions API, so the dispatch cannot be read back`, {
26551
+ ...errorContext,
26552
+ state: "unconfirmed_may_be_running",
26553
+ invocationId,
26554
+ dispatchState
26555
+ });
26443
26556
  }
26444
26557
  const deadline = Date.now() + budgetMs;
26445
26558
  let lastReadError;
@@ -26454,10 +26567,25 @@ var RelaycastMessagingClient = class {
26454
26567
  const invocation = outcome.value;
26455
26568
  const status = invocation?.status?.toLowerCase();
26456
26569
  if (status && CONFIRM_SUCCESS_STATUSES.has(status)) {
26570
+ if (errorContext.capability.startsWith("spawn:") && !hasExplicitSpawnReadinessProof(invocation)) {
26571
+ throw new RelayPlacementError("spawn_failed", `node '${context.node}' reported ${status} for ${actionName} without explicit spawned:true and ready:true proof`, {
26572
+ ...errorContext,
26573
+ state: "failed",
26574
+ invocationId,
26575
+ dispatchState,
26576
+ receipt: invocation
26577
+ });
26578
+ }
26457
26579
  return invocation;
26458
26580
  }
26459
26581
  if (status && CONFIRM_FAILURE_STATUSES.has(status)) {
26460
- throw new RelayPlacementError("spawn_failed", invocation?.error?.trim() || `node '${context.node}' reported ${status} for ${actionName}`, errorContext);
26582
+ throw new RelayPlacementError("spawn_failed", invocation?.error?.trim() || `node '${context.node}' reported ${status} for ${actionName}`, {
26583
+ ...errorContext,
26584
+ state: "failed",
26585
+ invocationId,
26586
+ dispatchState,
26587
+ receipt: invocation
26588
+ });
26461
26589
  }
26462
26590
  } else {
26463
26591
  lastReadError = outcome.error;
@@ -26465,7 +26593,12 @@ var RelaycastMessagingClient = class {
26465
26593
  }
26466
26594
  }
26467
26595
  if (Date.now() >= deadline) {
26468
- throw new RelayPlacementError("spawn_unconfirmed", `node '${context.node}' accepted ${actionName} (invocation ${invocationId}) but never reported a result within ${budgetMs}ms. The node advertised capacity and acknowledged the dispatch; nothing confirmed that it launched. Check that node's broker version, or re-run without confirmation to accept an unconfirmed dispatch.` + (lastReadError ? ` Last read error: ${lastReadError}` : ""), errorContext);
26596
+ throw new RelayPlacementError("spawn_unconfirmed", `node '${context.node}' accepted ${actionName} (invocation ${invocationId}) but never reported a result within ${budgetMs}ms. The node advertised capacity and acknowledged the dispatch; nothing confirmed that it launched. The invocation may still be running, so do not retry blindly. Check that node's broker version, or re-run without confirmation to accept an unconfirmed dispatch.` + (lastReadError ? ` Last read error: ${lastReadError}` : ""), {
26597
+ ...errorContext,
26598
+ state: "unconfirmed_may_be_running",
26599
+ invocationId,
26600
+ dispatchState
26601
+ });
26469
26602
  }
26470
26603
  await delay(Math.max(0, Math.min(cadenceMs, deadline - Date.now())));
26471
26604
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "12.0.0",
3
+ "version": "12.1.0",
4
4
  "description": "Real-time agent-to-agent communication system",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -43,14 +43,14 @@
43
43
  "pack:validate": "npm pack --dry-run"
44
44
  },
45
45
  "dependencies": {
46
- "@agent-relay/cloud": "12.0.0",
47
- "@agent-relay/config": "12.0.0",
48
- "@agent-relay/fleet": "12.0.0",
49
- "@agent-relay/harness-driver": "12.0.0",
50
- "@agent-relay/harnesses": "12.0.0",
51
- "@agent-relay/sdk": "12.0.0",
52
- "@agent-relay/session": "12.0.0",
53
- "@agent-relay/utils": "12.0.0",
46
+ "@agent-relay/cloud": "12.1.0",
47
+ "@agent-relay/config": "12.1.0",
48
+ "@agent-relay/fleet": "12.1.0",
49
+ "@agent-relay/harness-driver": "12.1.0",
50
+ "@agent-relay/harnesses": "12.1.0",
51
+ "@agent-relay/sdk": "12.1.0",
52
+ "@agent-relay/session": "12.1.0",
53
+ "@agent-relay/utils": "12.1.0",
54
54
  "@modelcontextprotocol/sdk": "^1.23.0",
55
55
  "@relayfile/client": "^0.10.27",
56
56
  "@relayflows/cli": "1.0.1",