thinkpool-pair 0.7.22 → 0.7.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.
- package/bridge.mjs +21 -4
- package/package.json +1 -1
- package/session-store.mjs +14 -0
package/bridge.mjs
CHANGED
|
@@ -36,7 +36,7 @@ import { spawn } from 'node:child_process'
|
|
|
36
36
|
import { randomUUID } from 'node:crypto'
|
|
37
37
|
import { createClient } from '@supabase/supabase-js'
|
|
38
38
|
import { startClaudeSession } from './claude-session.mjs'
|
|
39
|
-
import { saveSession, flushSession, deleteSession, loadAll, canResume, loadPtyId, savePtyId } from './session-store.mjs'
|
|
39
|
+
import { saveSession, flushSession, deleteSession, loadAll, canResume, loadPtyId, savePtyId, loadNames, saveNames } from './session-store.mjs'
|
|
40
40
|
|
|
41
41
|
// Public client creds (the same anon values the web app ships — safe to embed).
|
|
42
42
|
// Override with TP_SUPABASE_URL / TP_SUPABASE_ANON if you ever need to.
|
|
@@ -331,6 +331,11 @@ const bcast = (event, payload) => {
|
|
|
331
331
|
} catch { /* noop */ }
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
// Per-room terminal display names (id -> label), set by the web's `term-rename`.
|
|
335
|
+
// Persisted on the host so a rename is cross-device + survives a bridge restart;
|
|
336
|
+
// every announce carries them so a late-joining or second device sees them too.
|
|
337
|
+
const termNames = loadNames(room)
|
|
338
|
+
|
|
334
339
|
const announce = () =>
|
|
335
340
|
bcast('bridge', {
|
|
336
341
|
v: 2, name, repo: repoLabel, branch,
|
|
@@ -352,10 +357,12 @@ const announce = () =>
|
|
|
352
357
|
// cols/rows: the PTY's one true size — web viewers render this grid and
|
|
353
358
|
// scale it to their own page instead of voting to reflow it.
|
|
354
359
|
terms: [
|
|
355
|
-
...[...terms.entries()].map(([id, t]) => ({ id, cmd: t.cmd, alive: true, cols: t.term.cols, rows: t.term.rows })),
|
|
360
|
+
...[...terms.entries()].map(([id, t]) => ({ id, cmd: t.cmd, alive: true, cols: t.term.cols, rows: t.term.rows, name: termNames[id] || undefined })),
|
|
356
361
|
// Structured sessions advertise kind:'structured' so the web renders the
|
|
357
|
-
// reader (not xterm) and drives them with code-turn / code-perm.
|
|
358
|
-
|
|
362
|
+
// reader (not xterm) and drives them with code-turn / code-perm. `mode` +
|
|
363
|
+
// `name` ride along so a second device shows the live permission mode and
|
|
364
|
+
// the chosen label instead of defaulting to Normal / unnamed.
|
|
365
|
+
...[...sessions.entries()].map(([id, s]) => ({ id, cmd: s.cmd, kind: 'structured', alive: true, commands: s.commands, mode: s.mode || undefined, name: termNames[id] || undefined })),
|
|
359
366
|
],
|
|
360
367
|
})
|
|
361
368
|
|
|
@@ -820,6 +827,16 @@ channel
|
|
|
820
827
|
.on('broadcast', { event: 'code-close' }, ({ payload }) => {
|
|
821
828
|
endStructured(payload?.id)
|
|
822
829
|
})
|
|
830
|
+
// Persist + re-announce terminal renames. The web also echoes term-rename to
|
|
831
|
+
// online peers directly; storing it here is what reaches a device that joins
|
|
832
|
+
// LATER (or a second machine) — those only ever see the announce.
|
|
833
|
+
.on('broadcast', { event: 'term-rename' }, ({ payload }) => {
|
|
834
|
+
if (!payload?.id) return
|
|
835
|
+
if (payload.name) termNames[payload.id] = String(payload.name).slice(0, 80)
|
|
836
|
+
else delete termNames[payload.id]
|
|
837
|
+
saveNames(room, termNames)
|
|
838
|
+
announce()
|
|
839
|
+
})
|
|
823
840
|
.on('broadcast', { event: 'who' }, announce)
|
|
824
841
|
.subscribe(status => {
|
|
825
842
|
if (status === 'SUBSCRIBED') {
|
package/package.json
CHANGED
package/session-store.mjs
CHANGED
|
@@ -83,3 +83,17 @@ export function loadPtyId(room) {
|
|
|
83
83
|
export function savePtyId(room, id) {
|
|
84
84
|
try { ensureDir(room); fs.writeFileSync(ptyFile(room), String(id)) } catch { /* noop */ }
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
// Per-room terminal display names (terminal id -> label), set via the web's
|
|
88
|
+
// `term-rename` broadcast. This is what makes a rename CROSS-DEVICE + survive a
|
|
89
|
+
// bridge restart: names were previously web-localStorage only + a live broadcast,
|
|
90
|
+
// so a device that joined later (or a second machine) saw none of them. The bridge
|
|
91
|
+
// stores them here and includes them in every announce. Stored as a single dotfile
|
|
92
|
+
// (NOT *.json) so it never lands in listRecs/loadAll.
|
|
93
|
+
const namesFile = (room) => path.join(dir(room), '.names')
|
|
94
|
+
export function loadNames(room) {
|
|
95
|
+
try { return JSON.parse(fs.readFileSync(namesFile(room), 'utf8')) || {} } catch { return {} }
|
|
96
|
+
}
|
|
97
|
+
export function saveNames(room, names) {
|
|
98
|
+
try { ensureDir(room); fs.writeFileSync(namesFile(room), JSON.stringify(names || {})) } catch { /* noop */ }
|
|
99
|
+
}
|