@snowyroad/braid 0.88.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,
@@ -118,6 +118,9 @@ function artifactErrorMessage(e, brokerStatusFn) {
118
118
  if (relayCode === "demo_sealed" || msg.includes("demo_sealed")) {
119
119
  return "Artifact writes are not allowed in demo channels.";
120
120
  }
121
+ if (relayCode === "app_artifacts_disabled" || msg.includes("app_artifacts_disabled")) {
122
+ return "Interactive app artifacts are disabled for this channel's organization. An organization admin can enable them in the organization's settings on the website.";
123
+ }
121
124
  return "Artifact write forbidden (403).";
122
125
  }
123
126
  if (status === 404) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowyroad/braid",
3
- "version": "0.88.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",
@@ -51,7 +51,7 @@
51
51
  "@anthropic-ai/sandbox-runtime": "0.0.63",
52
52
  "@anthropic-ai/sdk": "0.104.1",
53
53
  "@modelcontextprotocol/sdk": "1.29.0",
54
- "@snowyroad/braid-tui": "0.0.25",
54
+ "@snowyroad/braid-tui": "0.0.26",
55
55
  "canonicalize": "^3.0.0",
56
56
  "jose": "^6.2.3",
57
57
  "ws": "8.21.0",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@snowyroad/braid",
3
- "version": "0.88.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.88.0",
9
+ "version": "0.89.1",
10
10
  "license": "SEE LICENSE IN LICENSE.md",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "0.25.1",
@@ -14,7 +14,7 @@
14
14
  "@anthropic-ai/sandbox-runtime": "0.0.63",
15
15
  "@anthropic-ai/sdk": "0.104.1",
16
16
  "@modelcontextprotocol/sdk": "1.29.0",
17
- "@snowyroad/braid-tui": "0.0.25",
17
+ "@snowyroad/braid-tui": "0.0.26",
18
18
  "canonicalize": "^3.0.0",
19
19
  "jose": "^6.2.3",
20
20
  "ws": "8.21.0",
@@ -1183,9 +1183,9 @@
1183
1183
  ]
1184
1184
  },
1185
1185
  "node_modules/@snowyroad/braid-tui": {
1186
- "version": "0.0.25",
1187
- "resolved": "https://registry.npmjs.org/@snowyroad/braid-tui/-/braid-tui-0.0.25.tgz",
1188
- "integrity": "sha512-HXtqJ0FBPAOTdR5bZ9zFb3Rcew+1ZlDU44AeOz/PxrDW5a1D+TAdrfVSby32mUk9Z5dVUgWZ2wrnGdbyIX725g==",
1186
+ "version": "0.0.26",
1187
+ "resolved": "https://registry.npmjs.org/@snowyroad/braid-tui/-/braid-tui-0.0.26.tgz",
1188
+ "integrity": "sha512-FTXVV0BB5Ko/gRfbzMjLoh1wG+j7aiBWjEhXp+k0cI67gUuQgxMaykV5gELWepVofUh8t3ZAsRgthZoWoqFVPw==",
1189
1189
  "license": "SEE LICENSE IN LICENSE.md",
1190
1190
  "dependencies": {
1191
1191
  "ink": "^5.2.0",
@@ -1373,9 +1373,9 @@
1373
1373
  }
1374
1374
  },
1375
1375
  "node_modules/acorn": {
1376
- "version": "8.17.0",
1377
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
1378
- "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
1376
+ "version": "8.18.0",
1377
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
1378
+ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
1379
1379
  "dev": true,
1380
1380
  "license": "MIT",
1381
1381
  "bin": {
@@ -2144,9 +2144,9 @@
2144
2144
  "license": "Unlicense"
2145
2145
  },
2146
2146
  "node_modules/fast-uri": {
2147
- "version": "3.1.4",
2148
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
2149
- "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
2147
+ "version": "3.1.5",
2148
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
2149
+ "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
2150
2150
  "funding": [
2151
2151
  {
2152
2152
  "type": "github",
@@ -2338,9 +2338,9 @@
2338
2338
  }
2339
2339
  },
2340
2340
  "node_modules/hono": {
2341
- "version": "4.12.32",
2342
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.32.tgz",
2343
- "integrity": "sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==",
2341
+ "version": "4.12.33",
2342
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.33.tgz",
2343
+ "integrity": "sha512-+SwvkaiJtxsiPjhy9LivY/1m7UsNqCJetM1BrZl9A5DkQhlbHQDU730mMiDPWjnoCYOM8Chf3WrCJw27kNTPFQ==",
2344
2344
  "license": "MIT",
2345
2345
  "engines": {
2346
2346
  "node": ">=16.9.0"
@@ -2449,9 +2449,9 @@
2449
2449
  }
2450
2450
  },
2451
2451
  "node_modules/ip-address": {
2452
- "version": "10.3.1",
2453
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz",
2454
- "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==",
2452
+ "version": "10.4.0",
2453
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
2454
+ "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
2455
2455
  "license": "MIT",
2456
2456
  "engines": {
2457
2457
  "node": ">= 12"
@@ -2506,9 +2506,9 @@
2506
2506
  "license": "ISC"
2507
2507
  },
2508
2508
  "node_modules/jose": {
2509
- "version": "6.2.4",
2510
- "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.4.tgz",
2511
- "integrity": "sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==",
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"
@@ -2913,9 +2913,9 @@
2913
2913
  }
2914
2914
  },
2915
2915
  "node_modules/postcss": {
2916
- "version": "8.5.23",
2917
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
2918
- "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
2916
+ "version": "8.5.25",
2917
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
2918
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
2919
2919
  "dev": true,
2920
2920
  "funding": [
2921
2921
  {