@botbuddy/cli 1.29.1 → 1.29.2

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/package.json +1 -1
  2. package/src/stack.mjs +13 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbuddy/cli",
3
- "version": "1.29.1",
3
+ "version": "1.29.2",
4
4
  "description": "BotBuddy — Swarm coordination CLI for multi-agent workflows",
5
5
  "type": "module",
6
6
  "bin": {
package/src/stack.mjs CHANGED
@@ -377,6 +377,16 @@ export async function stackAuthHeader() {
377
377
  return null;
378
378
  }
379
379
 
380
+ // The MCP lease endpoint accepts a session token in x-agent-api-key, whereas
381
+ // the event-stream relay requires that same token in its bearer form too. Keep
382
+ // the lease RPC shape unchanged and derive the relay-compatible form only at
383
+ // the wait boundary; never substitute an ambient OAuth credential.
384
+ function relayAuthHeaders(auth) {
385
+ const sessionToken = auth?.["x-agent-api-key"];
386
+ if (auth?.Authorization || !sessionToken || !AGENT_KEY_RE.test(sessionToken)) return auth;
387
+ return { ...auth, Authorization: `Bearer ${sessionToken}` };
388
+ }
389
+
380
390
  function parseSseFrames(buffer) {
381
391
  const frames = [];
382
392
  let idx, remaining = buffer;
@@ -402,7 +412,7 @@ async function registerLeaseWait(leaseId, timeoutSec, auth, signal, fetchImpl =
402
412
  const deadline = new Date(Date.now() + timeoutSec * 1000).toISOString();
403
413
  const res = await fetchImpl(`${eventStreamBase()}`, {
404
414
  method: "POST",
405
- headers: { ...auth, "Content-Type": "application/json" },
415
+ headers: { ...relayAuthHeaders(auth), "Content-Type": "application/json" },
406
416
  body: JSON.stringify({ action: "register", conditions: [{ type: "lease", params: { id: leaseId } }], deadline, mode: "any" }),
407
417
  signal,
408
418
  });
@@ -435,7 +445,7 @@ export async function waitForLease(leaseId, isDone, isFailed, { timeoutSec, auth
435
445
  const finalizerTimer = setTimeout(() => finalizer.abort(), 5_000);
436
446
  try {
437
447
  const response = await fetchImpl(eventStreamBase(), {
438
- method: "POST", headers: { ...auth, "Content-Type": "application/json" },
448
+ method: "POST", headers: { ...relayAuthHeaders(auth), "Content-Type": "application/json" },
439
449
  body: JSON.stringify({ action: "finalize", wait_session_id: waitSessionId, status, receipt: { outcome: status, lease_id: leaseId } }),
440
450
  signal: finalizer.signal,
441
451
  });
@@ -463,7 +473,7 @@ export async function waitForLease(leaseId, isDone, isFailed, { timeoutSec, auth
463
473
  url.searchParams.set("heartbeat", "1");
464
474
  let res;
465
475
  try {
466
- res = await fetchImpl(url, { headers: { ...auth, Accept: "text/event-stream", "Accept-Encoding": "identity" }, signal: ac.signal });
476
+ res = await fetchImpl(url, { headers: { ...relayAuthHeaders(auth), Accept: "text/event-stream", "Accept-Encoding": "identity" }, signal: ac.signal });
467
477
  } catch (err) {
468
478
  if (ac.signal.aborted) return finish(ac.signal.reason === "interrupted" ? { interrupted: true } : { timeout: true }, ac.signal.reason === "interrupted" ? "error" : "timeout");
469
479
  return finish({ error: `sse connect: ${err?.message ?? err}` }, "error");