@snowyroad/braid 0.89.0 → 0.89.1

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.
@@ -389,7 +389,7 @@ var InviteExpiredError = class extends Error {
389
389
  }
390
390
  };
391
391
  async function redeemInvite(relayHttpUrl, code) {
392
- const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-6KFDTGLV.js");
392
+ const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-HQIELMJB.js");
393
393
  const r = await boundedJsonFetch2(`${relayHttpUrl.replace(/\/$/, "")}/invites/redeem`, {
394
394
  method: "POST",
395
395
  headers: { "content-type": "application/json" },
@@ -478,7 +478,7 @@ function validateReplacementToken(newToken, currentToken, nowMs = Date.now()) {
478
478
  return { ok: true };
479
479
  }
480
480
  async function mintAccessToken(relayHttpUrl, agentKey, fetchFn = fetch, dpopProof) {
481
- const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-6KFDTGLV.js");
481
+ const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-HQIELMJB.js");
482
482
  const r = await boundedJsonFetch2(`${relayHttpUrl.replace(/\/$/, "")}/agents/token`, {
483
483
  method: "POST",
484
484
  headers: {
@@ -1340,6 +1340,17 @@ function buildAcpEnv(base, extra, stripKeys) {
1340
1340
  return merged;
1341
1341
  }
1342
1342
  var STOP_DRAIN_MS = 3e3;
1343
+ var WARMUP_CEILING_MS = 12e4;
1344
+ var WarmupCeilingError = class extends Error {
1345
+ constructor(ceilingMs) {
1346
+ super(
1347
+ `ACP agent warm-up timed out after ${ceilingMs}ms \u2014 the agent process started but never completed the initialize/session handshake (commonly a stalled login/auth prompt, or a slow first-run adapter download). Aborted.`
1348
+ );
1349
+ this.ceilingMs = ceilingMs;
1350
+ this.name = "WarmupCeilingError";
1351
+ }
1352
+ ceilingMs;
1353
+ };
1343
1354
  function killProcessGroup(child, signal) {
1344
1355
  const pid = child.pid;
1345
1356
  try {
@@ -1371,17 +1382,19 @@ function safeAcpToolName(tc) {
1371
1382
  return tc?.kind ?? "unknown";
1372
1383
  }
1373
1384
  var AcpClient = class {
1374
- constructor(launch, scopeWrap, afterChildExitHook, telemetry) {
1385
+ constructor(launch, scopeWrap, afterChildExitHook, telemetry, warmupCeilingMs = WARMUP_CEILING_MS) {
1375
1386
  this.launch = launch;
1376
1387
  this.scopeWrap = scopeWrap;
1377
1388
  this.afterChildExitHook = afterChildExitHook;
1378
1389
  this.telemetry = telemetry;
1390
+ this.warmupCeilingMs = warmupCeilingMs;
1379
1391
  this.policy = launch.policy ?? { mode: "readonly", configDirAbs: configDir(process.env) };
1380
1392
  }
1381
1393
  launch;
1382
1394
  scopeWrap;
1383
1395
  afterChildExitHook;
1384
1396
  telemetry;
1397
+ warmupCeilingMs;
1385
1398
  /** The tool permission policy; defaults FAIL-SAFE to readonly (never to approval). */
1386
1399
  policy;
1387
1400
  child = null;
@@ -1449,13 +1462,31 @@ var AcpClient = class {
1449
1462
  this.currentTurnOverrideMode = void 0;
1450
1463
  this.exitRejecters.clear();
1451
1464
  try {
1452
- await this.startInner();
1465
+ await this.withWarmupCeiling(this.startInner());
1453
1466
  } catch (err) {
1454
1467
  await this.stop().catch(() => {
1455
1468
  });
1456
1469
  throw err;
1457
1470
  }
1458
1471
  }
1472
+ /** Race the warm-up against the fixed ceiling so start() can never hang unbounded
1473
+ * (G1). On timeout it rejects with WarmupCeilingError; the caller's catch reaps the
1474
+ * subprocess (G2). The timer is cleared on every path (no leak), and a late inner
1475
+ * rejection after the ceiling already won is swallowed so it cannot surface as an
1476
+ * unhandledRejection. */
1477
+ async withWarmupCeiling(inner) {
1478
+ inner.catch(() => {
1479
+ });
1480
+ let timer;
1481
+ const ceiling = new Promise((_, reject) => {
1482
+ timer = setTimeout(() => reject(new WarmupCeilingError(this.warmupCeilingMs)), this.warmupCeilingMs);
1483
+ });
1484
+ try {
1485
+ await Promise.race([inner, ceiling]);
1486
+ } finally {
1487
+ if (timer) clearTimeout(timer);
1488
+ }
1489
+ }
1459
1490
  async startInner() {
1460
1491
  const spec = this.scopeWrap ? await this.scopeWrap(this.launch) : this.launch;
1461
1492
  const child = spawn(spec.command, spec.args, {
package/dist/cli.js CHANGED
@@ -70,7 +70,7 @@ import {
70
70
  toolStatusLine,
71
71
  validateRelayWsUrl,
72
72
  wsToHttp
73
- } from "./chunk-JALMGUEK.js";
73
+ } from "./chunk-EST67K7A.js";
74
74
  import {
75
75
  externalSourceLabel,
76
76
  externalUntrustedPreamble,
@@ -4,7 +4,7 @@ import {
4
4
  boundedJsonFetch,
5
5
  resetHttpMetricsForTest,
6
6
  snapshotHttpMetrics
7
- } from "./chunk-JALMGUEK.js";
7
+ } from "./chunk-EST67K7A.js";
8
8
  import "./chunk-BDOF72CL.js";
9
9
  export {
10
10
  assertHttpEndpoint,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowyroad/braid",
3
- "version": "0.89.0",
3
+ "version": "0.89.1",
4
4
  "description": "Braid: connect your own coding agent (Claude Code, Codex, Gemini, Grok) to a Braid channel and collaborate with other agents and humans.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "SnowyRoad",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@snowyroad/braid",
3
- "version": "0.89.0",
3
+ "version": "0.89.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@snowyroad/braid",
9
- "version": "0.89.0",
9
+ "version": "0.89.1",
10
10
  "license": "SEE LICENSE IN LICENSE.md",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "0.25.1",
@@ -2506,9 +2506,9 @@
2506
2506
  "license": "ISC"
2507
2507
  },
2508
2508
  "node_modules/jose": {
2509
- "version": "6.2.5",
2510
- "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.5.tgz",
2511
- "integrity": "sha512-2E5L2yRp03FnwreJLJX8/r7mHiZICCf8kG7fAsTWkSQTDAcc46NIZoQLKy+EJ8sPoJlxyS4OQR5H70LjIZZlIQ==",
2509
+ "version": "6.2.6",
2510
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.6.tgz",
2511
+ "integrity": "sha512-HwMtbJjMw8rC8dUTwCNilHJD+fxTeKM3JV1eprSmTjS41qwXSSt6exJXgyPK1QOu0jB9eDYLESRDkB3qaT3jnw==",
2512
2512
  "license": "MIT",
2513
2513
  "funding": {
2514
2514
  "url": "https://github.com/sponsors/panva"