thinkpool-pair 0.6.21 → 0.6.23

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 +25 -4
  2. package/package.json +1 -1
package/bridge.mjs CHANGED
@@ -536,6 +536,16 @@ channel
536
536
  const t = terms.get(payload.term)
537
537
  if (t && !t.attached) { try { t.term.resize(Math.max(payload.cols, 80), Math.max(payload.rows, 20)); announce() } catch { /* noop */ } }
538
538
  })
539
+ .on('broadcast', { event: 'session-deleted' }, async () => {
540
+ // The room was deleted from the dashboard. Close the bridge — and if we're a
541
+ // background service, uninstall ourselves first so the supervisor doesn't
542
+ // restart us into a room that no longer exists.
543
+ process.stderr.write('\n ◆ this room was deleted — closing the bridge.\n')
544
+ if (process.env.THINKPOOL_PAIR_AUTOUPDATE === '1') {
545
+ try { const svc = await import('./service.mjs'); svc.uninstallService(room) } catch { /* noop */ }
546
+ }
547
+ shutdown()
548
+ })
539
549
  .on('broadcast', { event: 'term-open' }, ({ payload }) => {
540
550
  if (!payload?.id || !payload?.cmd) return
541
551
  // Multi-bridge rooms: a targeted open is for ONE machine. Untargeted
@@ -770,12 +780,18 @@ if (process.env.THINKPOOL_PAIR_AUTOUPDATE === '1' && VERSION) {
770
780
  const a = core(latest), b = core(VERSION)
771
781
  let newer = false
772
782
  for (let i = 0; i < 3; i++) { if ((a[i] || 0) > (b[i] || 0)) { newer = true; break } if ((a[i] || 0) < (b[i] || 0)) break }
773
- if (newer) process.stderr.write(`\n ◆ thinkpool-pair ${latest} is out (you're on ${VERSION}) — restart with: npx thinkpool-pair@latest ${room}\n`)
783
+ if (newer) process.stderr.write(
784
+ `\n ◆ thinkpool-pair ${latest} is out (you're on ${VERSION}).\n` +
785
+ ` To update: stop this bridge (Ctrl-C), then rerun:\n` +
786
+ ` npx thinkpool-pair@latest ${room}\n` +
787
+ ` Your session resumes on restart (you'll be asked to continue it).\n` +
788
+ ` For hands-off updates with no interruption, install the background\n` +
789
+ ` service: npx thinkpool-pair@latest install-service ${room}\n`)
774
790
  } catch { /* offline — never block the session */ }
775
791
  }, 60000).unref()
776
792
  }
777
793
 
778
- function shutdown() {
794
+ async function shutdown() {
779
795
  if (shuttingDown) return
780
796
  shuttingDown = true
781
797
  clearInterval(flushTimer)
@@ -783,11 +799,16 @@ function shutdown() {
783
799
  const bye = Buffer.from('\r\n[ shared session ended ]\r\n', 'utf8').toString('base64')
784
800
  for (const id of terms.keys()) bcast('pty-out', { term: id, b64: bye })
785
801
  } catch { /* noop */ }
786
- try { supabase.removeChannel(channel) } catch { /* noop */ }
802
+ // Leave presence EXPLICITLY before exiting so the web room flips to dormant
803
+ // immediately. Previously we removeChannel()'d and process.exit()'d on the next
804
+ // line — the leave frame never flushed, so the web only noticed via the realtime
805
+ // heartbeat timeout (tens of seconds later) and looked stuck "live".
806
+ try { await channel.untrack() } catch { /* noop */ }
807
+ try { await supabase.removeChannel(channel) } catch { /* noop */ }
787
808
  for (const t of terms.values()) { try { t.term.kill() } catch { /* noop */ } }
788
809
  for (const s of sessions.values()) { try { s.session.end() } catch { /* noop */ } }
789
810
  detachLocal()
790
- process.exit(0)
811
+ setTimeout(() => process.exit(0), 250) // small grace for the leave/close frames to flush over the socket
791
812
  }
792
813
  process.on('SIGINT', shutdown)
793
814
  process.on('SIGTERM', shutdown)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.6.21",
3
+ "version": "0.6.23",
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": {