thinkpool-pair 0.7.55 → 0.7.56
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/account.mjs +12 -1
- package/bridge.mjs +21 -2
- package/package.json +1 -1
package/account.mjs
CHANGED
|
@@ -186,6 +186,9 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
186
186
|
}
|
|
187
187
|
const { sb, session } = auth
|
|
188
188
|
const email = session.user?.email || 'your account'
|
|
189
|
+
// Current owner JWT, handed to each room-bridge child for authed web writes
|
|
190
|
+
// (code-mockup, whip L16). Refreshed below; pushed to live children on rotation.
|
|
191
|
+
let currentAccessToken = session.access_token || null
|
|
189
192
|
|
|
190
193
|
// Owner-gate (Contract C-CODE-2): hosting a code session — spawning the agent and
|
|
191
194
|
// burning compute on this machine — requires Pro or Enterprise. This is the layer
|
|
@@ -253,7 +256,13 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
253
256
|
const keepFresh = scheduleTokenRefresh({
|
|
254
257
|
sb,
|
|
255
258
|
session,
|
|
256
|
-
onRefreshed: (s) => {
|
|
259
|
+
onRefreshed: (s) => {
|
|
260
|
+
saveAuth(s); pushPresence()
|
|
261
|
+
// Push the rotated owner token to every live child so their authed writes
|
|
262
|
+
// (code-mockup) never go stale on a long session (whip L16).
|
|
263
|
+
currentAccessToken = s.access_token || currentAccessToken
|
|
264
|
+
for (const c of children.values()) { try { c.send({ t: 'token', accessToken: currentAccessToken }) } catch { /* child not ready */ } }
|
|
265
|
+
},
|
|
257
266
|
forceMs: parseInt(process.env.TP_TOKEN_REFRESH_FORCE_MS, 10) || 0,
|
|
258
267
|
})
|
|
259
268
|
|
|
@@ -287,6 +296,8 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
287
296
|
// can't make a child self-exit; flag it as an account child instead.
|
|
288
297
|
const env = { ...process.env, THINKPOOL_PAIR_ACCOUNT_CHILD: '1' }
|
|
289
298
|
delete env.THINKPOOL_PAIR_AUTOUPDATE
|
|
299
|
+
// Hand the child the owner JWT for authed web writes (code-mockup, L16).
|
|
300
|
+
if (currentAccessToken) env.TP_ACCESS_TOKEN = currentAccessToken
|
|
290
301
|
const child = spawn(process.execPath, [BRIDGE, room, '--headless', '--auto=claude'], { cwd: dir, stdio: ['inherit', 'inherit', 'inherit', 'ipc'], env })
|
|
291
302
|
children.set(room, child)
|
|
292
303
|
childIdle.set(room, false) // unknown until it reports → never restart a fresh child
|
package/bridge.mjs
CHANGED
|
@@ -47,6 +47,14 @@ const SUPABASE_URL = process.env.TP_SUPABASE_URL || 'https://daytvtakmlixpfbbq
|
|
|
47
47
|
const WEB_BASE = process.env.TP_WEB_BASE || 'https://thinkpool.io'
|
|
48
48
|
const SUPABASE_ANON = process.env.TP_SUPABASE_ANON || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImRheXR2dGFrbWxpeHBmYmJxempkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzgwNTMxNzEsImV4cCI6MjA5MzYyOTE3MX0.zYmz8bHUNEY4STUr2JuXChAsKwxNwkwFHe1Hd0Betqo'
|
|
49
49
|
|
|
50
|
+
// Owner access token for AUTHED web writes (currently /api/code-mockup, whip L16).
|
|
51
|
+
// The room-bridge is anon by design; the account supervisor (account.mjs) owns the
|
|
52
|
+
// session, so it hands a fresh owner token in at spawn (TP_ACCESS_TOKEN) and pushes
|
|
53
|
+
// a rotated one over IPC ({ t:'token' }) on each refresh. Stays null for a
|
|
54
|
+
// directly-started bridge with no account login — those writes go unattributed,
|
|
55
|
+
// never owner-spoofed (the server treats a missing/!owner token accordingly).
|
|
56
|
+
let codeAuthToken = process.env.TP_ACCESS_TOKEN || null
|
|
57
|
+
|
|
50
58
|
// Per-terminal rolling scrollback (raw chars). Replayed to joining clients.
|
|
51
59
|
// Kept comfortably under realtime payload limits once base64'd.
|
|
52
60
|
const SCROLLBACK_MAX = 120_000
|
|
@@ -518,9 +526,14 @@ const handleManifest = async (box, file, term) => {
|
|
|
518
526
|
const readTxt = (p) => { try { return p && fs.readFileSync(p, 'utf8') } catch { return null } }
|
|
519
527
|
const cid = randomUUID()
|
|
520
528
|
try {
|
|
529
|
+
const mockupHeaders = { 'Content-Type': 'application/json' }
|
|
530
|
+
// Authenticate as the owner so the server can attribute the persisted row to a
|
|
531
|
+
// verified user instead of trusting "knows the code" (whip L16). Omitted when
|
|
532
|
+
// we have no token (direct bridge, no login) → server persists it unattributed.
|
|
533
|
+
if (codeAuthToken) mockupHeaders.Authorization = `Bearer ${codeAuthToken}`
|
|
521
534
|
const res = await fetch(`${WEB_BASE}/api/code-mockup`, {
|
|
522
535
|
method: 'POST',
|
|
523
|
-
headers:
|
|
536
|
+
headers: mockupHeaders,
|
|
524
537
|
body: JSON.stringify({
|
|
525
538
|
code: room, slug: m.slug, title: m.title, cid, ts: m.ts, term,
|
|
526
539
|
desktopPng: readB64(m.desktop), mobilePng: readB64(m.mobile), html: readTxt(m.html),
|
|
@@ -1206,7 +1219,13 @@ if (process.env.THINKPOOL_PAIR_AUTOUPDATE === '1' && VERSION) {
|
|
|
1206
1219
|
// Contract #1) + `idle` (the quiet window, for the unattended fallback) + whether a
|
|
1207
1220
|
// web peer is present, so the supervisor restarts on an explicit click between turns
|
|
1208
1221
|
// and otherwise waits for true idle with nobody watching (Slice 3).
|
|
1209
|
-
process.on('message', (m) => {
|
|
1222
|
+
process.on('message', (m) => {
|
|
1223
|
+
if (!m) return
|
|
1224
|
+
if (m.t === 'update-available') surfaceUpdate(m.version)
|
|
1225
|
+
// Supervisor rotated the owner JWT (account.mjs scheduleTokenRefresh) — adopt
|
|
1226
|
+
// it so our authed writes (code-mockup) never go stale on a long session (L16).
|
|
1227
|
+
else if (m.t === 'token') codeAuthToken = m.accessToken || null
|
|
1228
|
+
})
|
|
1210
1229
|
setInterval(() => { try { process.send({ t: 'idle', idle: idleNow(), between: betweenTurns(), webPeer: webPeerPresent() }) } catch { /* parent gone */ } }, 5000).unref()
|
|
1211
1230
|
} else if (VERSION) {
|
|
1212
1231
|
// Foreground run (not the supervised service): it can't self-restart, but
|