thinkpool-pair 0.7.67 → 0.7.68

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/bridge.mjs +29 -0
  2. package/package.json +1 -1
package/bridge.mjs CHANGED
@@ -454,8 +454,37 @@ const webPeerPresent = () => {
454
454
  return false
455
455
  }
456
456
 
457
+ // Realtime broadcast silently DROPS frames over its size limit AND can break the
458
+ // socket for the rest of the tick — the 2026-06-26 reload-freeze (a 5.4MB replay).
459
+ // This is the universal backstop: ANY oversized frame (replay OR a giant live
460
+ // tool_result/assistant blob) is (a) LOGGED loudly so it can never be a silent black
461
+ // hole again, and (b) defanged by truncating the largest string field so the frame
462
+ // still delivers instead of taking the channel down. capReplayEvents bounds bulk
463
+ // replays before they reach here; this catches the single-event case + is the alarm.
464
+ const FRAME_SOFT_LIMIT = 200000
465
+ const defendFrame = (event, payload) => {
466
+ let json
467
+ try { json = JSON.stringify(payload) } catch { return payload }
468
+ if (!json || json.length <= FRAME_SOFT_LIMIT) return payload
469
+ process.stderr.write(`\n ⚠ oversized ${event} frame: ${json.length}B (term ${String(payload?.term || '?').slice(0, 8)}) — truncating to fit so delivery isn't dropped\n`)
470
+ try {
471
+ const p = JSON.parse(json)
472
+ const evt = p.evt
473
+ if (evt && typeof evt === 'object') {
474
+ for (const k of ['text', 'content', 'output', 'stdout', 'stderr']) {
475
+ if (typeof evt[k] === 'string' && evt[k].length > 20000) {
476
+ const orig = evt[k].length
477
+ evt[k] = evt[k].slice(0, 20000) + `\n…[truncated ${orig - 20000} bytes — too large to broadcast]`
478
+ }
479
+ }
480
+ }
481
+ return p
482
+ } catch { return payload }
483
+ }
484
+
457
485
  const bcast = (event, payload) => {
458
486
  if (event === 'pty-out' || event === 'code-event') lastActivity = Date.now()
487
+ payload = defendFrame(event, payload)
459
488
  try {
460
489
  if (channel.channelAdapter?.canPush?.() ?? true) {
461
490
  channel.send({ type: 'broadcast', event, payload })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.67",
3
+ "version": "0.7.68",
4
4
  "description": "Share a local coding-agent CLI (Claude Code, Codex, Gemini, Aider, …) into a ThinkPool Code room, live.",
5
5
  "type": "module",
6
6
  "bin": {