thinkpool-pair 0.7.123 → 0.7.125

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 +27 -9
  2. package/package.json +1 -1
package/bridge.mjs CHANGED
@@ -1663,6 +1663,15 @@ function openStructured({ id, model, resume, log, commands, mode, spawnedBy, rol
1663
1663
  // on the entry so the ANNOUNCE can hand it to clients that connect/reload
1664
1664
  // AFTER init (the one-time code-event would miss them), then re-announce.
1665
1665
  if (evt.kind === 'system' && Array.isArray(evt.commands) && evt.commands.length && !entry.commands) { entry.commands = evt.commands; announce(); persist() }
1666
+ // Auto-resume trigger (Max, 2026-07-02): the init `system` event means the SDK session
1667
+ // is LIVE (input stream now consumed). A restored mid-turn plain terminal flagged for
1668
+ // resume gets its single "continue" HERE — not on a blind timer that raced the ~40s
1669
+ // resume and dropped the turn into a dead input stream. Fires exactly once.
1670
+ if (evt.kind === 'system' && entry.pendingAutoResume) {
1671
+ entry.pendingAutoResume = false
1672
+ try { entry.session?.sendTurn('continue') } catch { /* not resumable — stays idle, user can continue manually */ }
1673
+ process.stderr.write(`\n ◆ auto-resumed interrupted turn (${id.slice(0, 8)}) — sent continue.\n`)
1674
+ }
1666
1675
  // Chrome events (mode / usage / clear / compact) are transient state, not
1667
1676
  // transcript — broadcast + print them but keep out of the persisted/replayed log.
1668
1677
  // 'stalled' is transient turn-liveness state (would replay as a stale frozen
@@ -2064,7 +2073,16 @@ channel
2064
2073
  }
2065
2074
  const mm = text.match(/^\/model\b\s*(\S+)?/)
2066
2075
  if (mm) {
2067
- if (mm[1]) { s.session.setModel(mm[1]); ctlLine(`switched model → ${mm[1]}`) }
2076
+ if (mm[1]) {
2077
+ s.session.setModel(mm[1])
2078
+ // Reflect the switch in the announce IMMEDIATELY (before any turn). The SDK
2079
+ // only echoes the resolved full id on the next turn, and meta/ctx model go
2080
+ // stale until then, so without this the chip snapped back to the old model
2081
+ // when you left + returned to the tab. onEvent refines s.model to the full
2082
+ // id on the next turn; the announce carries it to every device meanwhile.
2083
+ s.model = mm[1]; announce()
2084
+ ctlLine(`switched model → ${mm[1]}`)
2085
+ }
2068
2086
  else { ctlLine('use /model <name> to switch — e.g. opus, sonnet, haiku') }
2069
2087
  return
2070
2088
  }
@@ -2177,15 +2195,15 @@ channel
2177
2195
  // Auto-resume (Max, 2026-07-02): a PLAIN terminal (NOT a flow lane — those have their
2178
2196
  // own re-dispatch) that was MID-TURN when the bridge stopped picks the work back up
2179
2197
  // instead of sitting aborted. If its SDK context resumes (canResume), send ONE
2180
- // "continue" once the session is live — like the user typing "continue" after a
2181
- // restart. openStructured already closed the interrupted turn idle, so a continue that
2182
- // can't be delivered just leaves it idle (recoverable) — never a hang or a loop.
2198
+ // "continue" — like the user typing "continue" after a restart. We DON'T fire on a
2199
+ // fixed timer: a resume takes ~40s to become live (MCP boot + sanitizeSession), and a
2200
+ // 2.5s sendTurn pushed into an input stream nothing is consuming yet is silently lost
2201
+ // (the 2026-07-02 "didn't autocontinue" bug). Instead FLAG it here and fire the single
2202
+ // continue when the session's init `system` event actually arrives (onEvent), i.e. the
2203
+ // instant it's live. openStructured already closed the interrupted turn idle, so a
2204
+ // continue that can't be delivered just leaves it idle (recoverable) — never a hang.
2183
2205
  if (re && !rec.flowSessionId && canResume(rec) && restoredTurnOpen(rec.log || [])) {
2184
- const rid = rec.id
2185
- setTimeout(() => {
2186
- const e = sessions.get(rid)
2187
- try { e?.session?.sendTurn('continue') } catch { /* session still starting — stays idle, user can resume manually */ }
2188
- }, 2500)
2206
+ re.pendingAutoResume = true
2189
2207
  }
2190
2208
  }
2191
2209
  // Fresh open: ONLY for an explicit `-- <claude>` share. In account mode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.123",
3
+ "version": "0.7.125",
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": {