@botbuddy/cli 1.64.16 → 1.64.17

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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.64.16",
3
- "source_commit": "6690f94e4c3d385159ca315713a6eab3560289fb",
4
- "source_sha256": "81838b2e5024a22f62c4b55a75c3113c26cfe88f0047f0048f28f5800d0693d3",
2
+ "release_version": "1.64.17",
3
+ "source_commit": "d2fabc08d075fc51a591dd0ce38dc0ec9d66c168",
4
+ "source_sha256": "a21dcce44a33eddc1392ae4604533ee412d1c0c2bed64a26f52e99a2e2feed30",
5
5
  "target": "darwin-arm64",
6
- "sha256": "9ca9db33cdee03687c26d5e162f4d936d44b7c1c23028c78566a61b90f7c40ad"
6
+ "sha256": "f8f98b5bc212ed676fe2e97381b5a0c548331602ed7165360a331c3e8ff309fd"
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.64.16",
3
- "source_commit": "6690f94e4c3d385159ca315713a6eab3560289fb",
4
- "source_sha256": "81838b2e5024a22f62c4b55a75c3113c26cfe88f0047f0048f28f5800d0693d3",
2
+ "release_version": "1.64.17",
3
+ "source_commit": "d2fabc08d075fc51a591dd0ce38dc0ec9d66c168",
4
+ "source_sha256": "a21dcce44a33eddc1392ae4604533ee412d1c0c2bed64a26f52e99a2e2feed30",
5
5
  "target": "linux-x64",
6
- "sha256": "b1a73bbd5bc7d78a13a3ec6f547436cc780163687bb5162e230d5796291e7689"
6
+ "sha256": "f4a8fd0904f99e688e857b3674400b3e088fbca7f557bdea7cd1f14abcd84f31"
7
7
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "release_version": "1.64.16",
4
- "source_commit": "6690f94e4c3d385159ca315713a6eab3560289fb",
5
- "source_sha256": "81838b2e5024a22f62c4b55a75c3113c26cfe88f0047f0048f28f5800d0693d3",
3
+ "release_version": "1.64.17",
4
+ "source_commit": "d2fabc08d075fc51a591dd0ce38dc0ec9d66c168",
5
+ "source_sha256": "a21dcce44a33eddc1392ae4604533ee412d1c0c2bed64a26f52e99a2e2feed30",
6
6
  "targets": {
7
7
  "darwin-arm64": {
8
8
  "goos": "darwin",
9
9
  "goarch": "arm64",
10
10
  "binary": "daemon/bin/darwin-arm64/botbuddy-daemon",
11
- "sha256": "9ca9db33cdee03687c26d5e162f4d936d44b7c1c23028c78566a61b90f7c40ad",
11
+ "sha256": "f8f98b5bc212ed676fe2e97381b5a0c548331602ed7165360a331c3e8ff309fd",
12
12
  "mode": "0755"
13
13
  },
14
14
  "linux-x64": {
15
15
  "goos": "linux",
16
16
  "goarch": "amd64",
17
17
  "binary": "daemon/bin/linux-x64/botbuddy-daemon",
18
- "sha256": "b1a73bbd5bc7d78a13a3ec6f547436cc780163687bb5162e230d5796291e7689",
18
+ "sha256": "f4a8fd0904f99e688e857b3674400b3e088fbca7f557bdea7cd1f14abcd84f31",
19
19
  "mode": "0755"
20
20
  }
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbuddy/cli",
3
- "version": "1.64.16",
3
+ "version": "1.64.17",
4
4
  "description": "BotBuddy \u2014 Swarm coordination CLI for multi-agent workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -185,6 +185,9 @@ export function buildStackRunOutcomePayload({ fields = {}, exitCode, runId = ran
185
185
  const signal = pick(fields.stop_signal?.signal, SIGNAL_RE);
186
186
  // BOT-2880: sent only when present, because an older server refuses an unknown key.
187
187
  const callbackAuthorizationReason = pick(fields.callback_authorization_reason, AUTHORIZATION_REASON_RE);
188
+ const failureMechanism = code === "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE" &&
189
+ ["origin_config_missing", "origin_digest_missing"].includes(fields.failure_mechanism)
190
+ ? fields.failure_mechanism : null;
188
191
  return {
189
192
  run_id: runId,
190
193
  lease_id: validStackLeaseId(fields.lease_id),
@@ -208,6 +211,7 @@ export function buildStackRunOutcomePayload({ fields = {}, exitCode, runId = ran
208
211
  signal_parent: pick(fields.stop_signal.parent, TOKEN_RE),
209
212
  } : {}),
210
213
  ...(callbackAuthorizationReason ? { callback_authorization_reason: callbackAuthorizationReason } : {}),
214
+ ...(failureMechanism ? { failure_mechanism: failureMechanism } : {}),
211
215
  };
212
216
  }
213
217
 
@@ -236,7 +240,19 @@ export async function reportStackRunOutcome({ fields, exitCode, runId, opts, env
236
240
  timer = setTimeout(() => { ac.abort(); resolve(TIMED_OUT); }, timeoutMs);
237
241
  });
238
242
  try {
239
- const call = Promise.resolve().then(() => channel.callTool(STACK_RUN_OUTCOME_TOOL, payload, { auth: channel.auth, signal: ac.signal }));
243
+ const call = Promise.resolve().then(async () => {
244
+ const first = await channel.callTool(STACK_RUN_OUTCOME_TOOL, payload, { auth: channel.auth, signal: ac.signal });
245
+ // Older servers reject unknown keys before writing. Retry only that exact,
246
+ // explicit rejection with the same run id; never retry an uncertain send.
247
+ if (!ac.signal.aborted && payload.failure_mechanism && first?.ok && first?.isError &&
248
+ first?.data?.code === "INVALID_STACK_RUN_OUTCOME" &&
249
+ typeof first?.data?.message === "string" &&
250
+ first.data.message.startsWith("unknown key 'failure_mechanism'")) {
251
+ const { failure_mechanism: _omitted, ...legacyPayload } = payload;
252
+ return await channel.callTool(STACK_RUN_OUTCOME_TOOL, legacyPayload, { auth: channel.auth, signal: ac.signal });
253
+ }
254
+ return first;
255
+ });
240
256
  const result = await Promise.race([call.catch(() => null), timeout]);
241
257
  if (result === TIMED_OUT) return { sent: false, reason: "timeout", payload };
242
258
  const capture = result?.data?.feedback_capture;
package/src/stack.mjs CHANGED
@@ -4250,7 +4250,7 @@ async function runStackLifecycleOnce(opts, childArgv, adapters, incidentBox) {
4250
4250
  let hasDeclaration = false;
4251
4251
  try { hasDeclaration = existsSync(declaration) && lstatSync(declaration).isFile(); } catch { hasDeclaration = false; }
4252
4252
  if (remoteVariant && !originConfigPath) {
4253
- const error = new Error("the requester-origin config variant has no materialized config to replace"); error.code = "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE"; throw error;
4253
+ const error = new Error("the requester-origin config variant has no materialized config to replace"); error.code = "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE"; error.failureMechanism = "origin_config_missing"; throw error;
4254
4254
  }
4255
4255
  return buildBundle(stackDirFor(execution), {
4256
4256
  ...(remoteVariant ? { readFile: (abs, ...rest) => abs === originConfigPath ? Buffer.from(execution.originConfigText, "utf8") : readFileSync(abs, ...rest) } : {}),
@@ -4288,7 +4288,8 @@ async function runStackLifecycleOnce(opts, childArgv, adapters, incidentBox) {
4288
4288
  // hide it — and it happens before any lease exists.
4289
4289
  if (executionRequest === "remote" || bundleInclude.length) {
4290
4290
  const fixable = typeof error?.code === "string" && error.code.startsWith("BUNDLE_");
4291
- return { exitCode: fixable ? EXIT.INVALID : EXIT.INTERNAL, outcome: "error", code: error?.code ?? "BUNDLE_FAILED", error: message };
4291
+ return { exitCode: fixable ? EXIT.INVALID : EXIT.INTERNAL, outcome: "error", code: error?.code ?? "BUNDLE_FAILED", error: message,
4292
+ ...(error?.code === "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE" && error?.failureMechanism === "origin_config_missing" ? { failureMechanism: error.failureMechanism } : {}) };
4292
4293
  }
4293
4294
  // Codex #1077 P2: without a digest, `auto` could still pick a remote host and be
4294
4295
  // refused BUNDLE_REQUIRED instead of queueing here, so ask for this machine.
@@ -4346,7 +4347,7 @@ async function runStackLifecycleOnce(opts, childArgv, adapters, incidentBox) {
4346
4347
  let renewIdentifiedRequest = null;
4347
4348
  if (execution.admissionRequestId) {
4348
4349
  if (!stackDigest || !bundle?.sha256) {
4349
- return { exitCode: EXIT.INTERNAL, outcome: "error", code: "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE", error: "the requester-origin bundle digest could not be computed; no lease was requested" };
4350
+ return { exitCode: EXIT.INTERNAL, outcome: "error", code: "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE", failureMechanism: "origin_digest_missing", error: "the requester-origin bundle digest could not be computed; no lease was requested" };
4350
4351
  }
4351
4352
  leaseArgs.request_id = execution.admissionRequestId;
4352
4353
  // Durable request-to-context association before any request can commit (recovery key).
@@ -5323,6 +5324,8 @@ export function runReceiptFields(result) {
5323
5324
  ...(result.callbackCause ? { callback_cause: result.callbackCause } : {}),
5324
5325
  // BOT-2880: which check refused a CALLBACK_AUTHORIZATION_LOST (a bounded token, never a value).
5325
5326
  ...(result.callbackAuthorizationReason ? { callback_authorization_reason: result.callbackAuthorizationReason } : {}),
5327
+ ...(result.code === "REQUESTER_ORIGIN_DIGEST_UNAVAILABLE" && ["origin_config_missing", "origin_digest_missing"].includes(result.failureMechanism)
5328
+ ? { failure_mechanism: result.failureMechanism } : {}),
5326
5329
  // BOT-2957: the control-plane gaps this run's callback route rode through (never on a run that had none).
5327
5330
  ...(result.callbackOutage ? { callback_outage: result.callbackOutage } : {}),
5328
5331
  // BOT-2780: the reserved requester origin generated auth links name (never a credential).