@snowyroad/braid 0.80.2 → 0.80.4

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.
@@ -374,7 +374,7 @@ var InviteExpiredError = class extends Error {
374
374
  }
375
375
  };
376
376
  async function redeemInvite(relayHttpUrl, code) {
377
- const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-JUDUFIOQ.js");
377
+ const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-HW3QESWO.js");
378
378
  const r = await boundedJsonFetch2(`${relayHttpUrl.replace(/\/$/, "")}/invites/redeem`, {
379
379
  method: "POST",
380
380
  headers: { "content-type": "application/json" },
@@ -463,7 +463,7 @@ function validateReplacementToken(newToken, currentToken, nowMs = Date.now()) {
463
463
  return { ok: true };
464
464
  }
465
465
  async function mintAccessToken(relayHttpUrl, agentKey, fetchFn = fetch, dpopProof) {
466
- const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-JUDUFIOQ.js");
466
+ const { boundedJsonFetch: boundedJsonFetch2 } = await import("./http-HW3QESWO.js");
467
467
  const r = await boundedJsonFetch2(`${relayHttpUrl.replace(/\/$/, "")}/agents/token`, {
468
468
  method: "POST",
469
469
  headers: {
@@ -970,11 +970,19 @@ var CTRL_RE = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
970
970
  function sanitizeForTty(s) {
971
971
  return s.replace(ANSI_RE, "").replace(CTRL_RE, "");
972
972
  }
973
+ function pipeSanitizedToTty(src, dst = process.stderr) {
974
+ if (!src) return;
975
+ src.setEncoding("utf8");
976
+ src.on("data", (chunk) => {
977
+ const clean = sanitizeForTty(chunk);
978
+ if (clean) dst.write(clean);
979
+ });
980
+ }
973
981
  var ESC = String.fromCharCode(27);
974
982
  function restoreTerminal(out = process.stdout, stdin = process.stdin) {
975
983
  if (!out.isTTY) return;
976
984
  out.write(
977
- `${ESC}[?1l${ESC}>${ESC}[?25h${ESC}[?1049l${ESC}[?2004l${ESC}[>4;0m${ESC}[?1000l${ESC}[?1002l${ESC}[?1003l${ESC}[?1006l`
985
+ `${ESC}[?1l${ESC}>${ESC}[?25h${ESC}[?2004l${ESC}[>4;0m${ESC}[?1000l${ESC}[?1002l${ESC}[?1003l${ESC}[?1006l${ESC}7${ESC}[r${ESC}8`
978
986
  );
979
987
  try {
980
988
  if (stdin.isTTY) stdin.setRawMode?.(false);
@@ -2484,6 +2492,7 @@ export {
2484
2492
  acquireAgentLock,
2485
2493
  pinEndpoint,
2486
2494
  sanitizeForTty,
2495
+ pipeSanitizedToTty,
2487
2496
  restoreTerminal,
2488
2497
  isShellSafeName,
2489
2498
  narrowestMode,
package/dist/cli.js CHANGED
@@ -47,6 +47,7 @@ import {
47
47
  parseRunFlags,
48
48
  pickRejectOptionId,
49
49
  pinEndpoint,
50
+ pipeSanitizedToTty,
50
51
  readPathWithFallback,
51
52
  redeemInvite,
52
53
  relayHostSegment,
@@ -67,7 +68,7 @@ import {
67
68
  validateReplacementToken,
68
69
  verifyCardSignature,
69
70
  wsToHttp
70
- } from "./chunk-M5WUSDQN.js";
71
+ } from "./chunk-ORQHM6RG.js";
71
72
 
72
73
  // src/health.ts
73
74
  var CEILING_STRIKES_TO_DEAD = 3;
@@ -3030,14 +3031,20 @@ var AcpClient = class {
3030
3031
  this.modelOverride ? { ...spec.env, ANTHROPIC_MODEL: this.modelOverride } : spec.env,
3031
3032
  spec.stripEnvKeys
3032
3033
  ),
3033
- stdio: ["pipe", "pipe", "inherit"],
3034
- // stderr passes through for debugging
3034
+ // stderr is PIPED (not inherited) and relayed through pipeSanitizedToTty below.
3035
+ // An inherited stderr fd IS the operator's real terminal, so a misbehaving agent
3036
+ // CLI (Ink apps, spinners, a crashing adapter's EPIPE dump) could clear the screen,
3037
+ // set a scroll region, or enter the alternate buffer directly — the Ctrl-C
3038
+ // terminal-corruption class. Piping + sanitizing makes that impossible by
3039
+ // construction while preserving the diagnostic TEXT.
3040
+ stdio: ["pipe", "pipe", "pipe"],
3035
3041
  // Own process group: Ctrl-C (SIGINT to the bridge's foreground group) does NOT reach
3036
3042
  // the agent subprocess, so the bridge can drain the in-flight turn and shut it down
3037
3043
  // cleanly instead of the SDK tearing down mid-query. stop() kills the whole group.
3038
3044
  detached: true
3039
3045
  });
3040
3046
  this.child = child;
3047
+ pipeSanitizedToTty(child.stderr);
3041
3048
  child.on("error", (err) => {
3042
3049
  this.failPending(new Error(`ACP agent subprocess error: ${err.message}`));
3043
3050
  });
@@ -4,7 +4,7 @@ import {
4
4
  boundedJsonFetch,
5
5
  resetHttpMetricsForTest,
6
6
  snapshotHttpMetrics
7
- } from "./chunk-M5WUSDQN.js";
7
+ } from "./chunk-ORQHM6RG.js";
8
8
  export {
9
9
  assertHttpEndpoint,
10
10
  boundedJsonFetch,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowyroad/braid",
3
- "version": "0.80.2",
3
+ "version": "0.80.4",
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.80.2",
3
+ "version": "0.80.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@snowyroad/braid",
9
- "version": "0.80.2",
9
+ "version": "0.80.4",
10
10
  "license": "SEE LICENSE IN LICENSE.md",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "0.25.1",