thinkpool-pair 0.7.109 → 0.7.110
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 +10 -2
- package/package.json +1 -1
package/account.mjs
CHANGED
|
@@ -255,6 +255,7 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
255
255
|
let applyRequested = false // a user clicked "apply" in some room (Slice 3)
|
|
256
256
|
let pendingUpdate = null // newest published version once the poll sees it
|
|
257
257
|
const warned = new Set()
|
|
258
|
+
const refused = new Map() // room -> reason ('home'|'none'|'dir-gone'): owned but NOT served, announced in presence so the web shows a precise "attach this session" card instead of spinning
|
|
258
259
|
|
|
259
260
|
// Account presence — so the web dashboard can show "● Bridge active" for this
|
|
260
261
|
// account without per-room probing. We TRACK this machine (name + served room
|
|
@@ -324,7 +325,7 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
324
325
|
// service (always-on, survives reboot) vs a foreground `npx` run that dies with its
|
|
325
326
|
// terminal. THINKPOOL_PAIR_AUTOUPDATE=1 is set ONLY by the install-service plist/unit
|
|
326
327
|
// (service.mjs), so it's the reliable proxy for "running as the managed service".
|
|
327
|
-
const pushPresence = () => trackPresence({ name: machine, version: VERSION, rooms: [...children.keys()], service: process.env.THINKPOOL_PAIR_AUTOUPDATE === '1', ts: Date.now() })
|
|
328
|
+
const pushPresence = () => trackPresence({ name: machine, version: VERSION, rooms: [...children.keys()], refused: [...refused].map(([code, reason]) => ({ code, reason })), service: process.env.THINKPOOL_PAIR_AUTOUPDATE === '1', ts: Date.now() })
|
|
328
329
|
// Re-track on EVERY (re)subscribe, not just the first: a realtime reconnect
|
|
329
330
|
// (network blip, or a token swap mid-flight) rejoins the channel and must
|
|
330
331
|
// re-announce, or the dashboard would read "no bridge" until the next restart.
|
|
@@ -491,18 +492,23 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
491
492
|
// participant's bridge is duplication the UI never even looks at.
|
|
492
493
|
const { data } = await sb.from('code_sessions').select('code,name,last_active_at,owner_id,participants').eq('owner_id', session.user.id).order('last_active_at', { ascending: false }).limit(20)
|
|
493
494
|
rooms = data || []
|
|
495
|
+
// Prune refused entries for rooms we no longer own (only on a SUCCESSFUL fetch,
|
|
496
|
+
// so a transient query error never wipes the set).
|
|
497
|
+
const ownedCodes = new Set(rooms.map((r) => r.code))
|
|
498
|
+
for (const c of [...refused.keys()]) if (!ownedCodes.has(c)) refused.delete(c)
|
|
494
499
|
} catch { /* transient — keep existing children, retry next tick */ }
|
|
495
500
|
const dirs = loadDirs()
|
|
496
501
|
const served = loadServed()
|
|
497
502
|
for (const r of rooms) {
|
|
498
503
|
const room = r.code
|
|
499
|
-
if (!room || children.has(room)) continue
|
|
504
|
+
if (!room || children.has(room)) { if (room) refused.delete(room); continue } // served → not refused
|
|
500
505
|
if (r.owner_id && r.owner_id !== session.user.id) continue // never serve a room we don't own (defense-in-depth behind the .eq above)
|
|
501
506
|
// Resolve the serve dir: explicit bind > last-served memory > launch dir. REFUSE
|
|
502
507
|
// to auto-serve an unbound room from $HOME — that strips the agent's resume context
|
|
503
508
|
// (cwd-keyed SDK sessions) and shows your home folder as the repo (FVIHV1DE).
|
|
504
509
|
const choice = resolveServeDir({ bound: dirs[room], remembered: served[room], defaultDir: DEFAULT_DIR, home: os.homedir() })
|
|
505
510
|
if (choice.refuse) {
|
|
511
|
+
refused.set(room, choice.reason)
|
|
506
512
|
if (!warned.has(room)) {
|
|
507
513
|
warned.add(room)
|
|
508
514
|
const why = choice.reason === 'home'
|
|
@@ -514,10 +520,12 @@ export async function runAccount(SUPABASE_URL, SUPABASE_ANON) {
|
|
|
514
520
|
}
|
|
515
521
|
const dir = choice.dir
|
|
516
522
|
if (!fs.existsSync(dir)) {
|
|
523
|
+
refused.set(room, 'dir-gone')
|
|
517
524
|
if (!warned.has(room)) { warned.add(room); process.stderr.write(`\n ◇ ${room}: bound directory is gone (${dir}) — re-bind it.\n`) }
|
|
518
525
|
continue
|
|
519
526
|
}
|
|
520
527
|
warned.delete(room)
|
|
528
|
+
refused.delete(room) // about to serve → clear any prior refusal
|
|
521
529
|
// Learn this room → dir so a later relaunch from $HOME resumes it HERE (the real
|
|
522
530
|
// repo) instead of the home-dir fallback. Only the auto path is remembered; an
|
|
523
531
|
// explicit bind already persists in dirs.json.
|