thinkpool-pair 0.7.33 → 0.7.35
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.
- package/bridge.mjs +20 -2
- package/package.json +1 -1
package/bridge.mjs
CHANGED
|
@@ -650,7 +650,13 @@ function openStructured({ id, model, resume, log, commands, mode }) {
|
|
|
650
650
|
if (entry.log.length) process.stderr.write(`\n ◆ restored ${entry.log.length} prior events (${id.slice(0, 8)})${resume ? ' + resuming live context' : ''}.\n`)
|
|
651
651
|
// Persist the permission mode alongside the transcript so a bridge restart
|
|
652
652
|
// restores the session in the SAME mode (a bypass room stays bypass on resume).
|
|
653
|
-
const
|
|
653
|
+
const sessionData = () => ({ sessionId: entry.session?.sessionId || resume || null, log: entry.log, commands: entry.commands, mode: entry.mode })
|
|
654
|
+
const persist = () => saveSession(room, id, sessionData())
|
|
655
|
+
// Synchronous flush of this session's record. Used on open (so a brand-new session
|
|
656
|
+
// has a file under its id BEFORE its first event — surviving a restart inside the
|
|
657
|
+
// 1.5s saveSession debounce window) and on shutdown (so events since the last
|
|
658
|
+
// debounced write aren't lost). Contract #2: restart resumes, no lost messages.
|
|
659
|
+
entry.flush = () => flushSession(room, id, sessionData())
|
|
654
660
|
entry.session = startClaudeSession({
|
|
655
661
|
cwd: process.cwd(), model, resume, mode,
|
|
656
662
|
env: { ...process.env, TP_MOCKUP_OUTBOX: mockupOutbox },
|
|
@@ -708,6 +714,10 @@ function openStructured({ id, model, resume, log, commands, mode }) {
|
|
|
708
714
|
: `\n ${A.yel}● permission: ${req.toolName}${argStr(req.input)} — approve in the room.${A.rst}\n`)
|
|
709
715
|
}),
|
|
710
716
|
})
|
|
717
|
+
// Brand-new session (no restored log): write its record now so a restart that lands
|
|
718
|
+
// before the first debounced save still restores this id instead of dropping it (the
|
|
719
|
+
// room would otherwise show a fresh empty terminal + strand the transcript).
|
|
720
|
+
if (!entry.log.length) entry.flush()
|
|
711
721
|
announce()
|
|
712
722
|
if (!entry.log.length) process.stderr.write(`\n ◆ structured Claude session (${id.slice(0, 8)}) — driven from the room.\n`)
|
|
713
723
|
return entry
|
|
@@ -1002,7 +1012,11 @@ channel
|
|
|
1002
1012
|
// only runs on a fresh start (guard above), so a network re-subscribe
|
|
1003
1013
|
// with live sessions won't re-spawn them.
|
|
1004
1014
|
if (wantStructured(startCmd)) {
|
|
1005
|
-
|
|
1015
|
+
// Restore EVERY saved rec — a freshly opened session (persisted on open) may
|
|
1016
|
+
// have an empty log + no sessionId yet and must still come back under its id.
|
|
1017
|
+
// Closed sessions are unlinked by deleteSession, so a file existing on disk ==
|
|
1018
|
+
// a session that was live at shutdown (never an explicitly closed one).
|
|
1019
|
+
const all = loadAll(room)
|
|
1006
1020
|
if (all.length) for (const rec of all) openStructured({ id: rec.id, resume: canResume(rec) ? rec.sessionId : undefined, log: rec.log, commands: rec.commands, mode: rec.mode })
|
|
1007
1021
|
// Fresh open: ONLY for an explicit `-- <claude>` share. In account mode
|
|
1008
1022
|
// (autoAgent set, no attachedCmd) the web's `?new=1` flow opens the first
|
|
@@ -1171,6 +1185,10 @@ async function shutdown(code = 0, farewell = true) {
|
|
|
1171
1185
|
// correct and must not hang on the (possibly dead) realtime socket. This is the
|
|
1172
1186
|
// bug behind the watchdog/auto-update raw process.exit() paths, which skipped
|
|
1173
1187
|
// teardown entirely and orphaned agent processes + left stale presence.
|
|
1188
|
+
// Flush structured session state synchronously BEFORE ending sessions. saveSession
|
|
1189
|
+
// debounces ~1.5s, so without this any events since the last write are lost on exit
|
|
1190
|
+
// (Contract #2). writeFileSync, well inside the 1500ms hard-exit backstop above.
|
|
1191
|
+
for (const s of sessions.values()) { try { s.flush?.() } catch { /* noop */ } }
|
|
1174
1192
|
for (const t of terms.values()) { try { t.term.kill() } catch { /* noop */ } }
|
|
1175
1193
|
for (const s of sessions.values()) { try { s.session.end() } catch { /* noop */ } }
|
|
1176
1194
|
detachLocal()
|