thinkpool-pair 0.7.299 → 0.7.301

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/codex-session.mjs CHANGED
@@ -577,14 +577,13 @@ export function startCodexSession({ cwd, model, effort: initialEffort = 'high',
577
577
  appServerThreadReady = true
578
578
  pushMappedEvent({ type: 'thread.started', thread_id: sessionId })
579
579
  return true
580
- } catch (error) {
580
+ } catch {
581
581
  // Fallback is safe only here: no turn/start request has been accepted, so
582
582
  // there is no possibility of running the same prompt twice.
583
583
  appServerDisabled = true
584
584
  try { appServer?.end() } catch { /* noop */ }
585
585
  appServer = null
586
586
  appServerThreadReady = false
587
- note(`Codex App Server unavailable; using codex exec: ${error?.message || error}`)
588
587
  return false
589
588
  }
590
589
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.299",
3
+ "version": "0.7.301",
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": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "bundleVersion": 9,
3
+ "bundleVersion": 10,
4
4
  "contracts": [
5
5
  {
6
6
  "id": "room-coordination",
@@ -88,13 +88,13 @@
88
88
  },
89
89
  {
90
90
  "id": "visual-proof",
91
- "version": 1,
91
+ "version": 2,
92
92
  "routes": [
93
93
  {
94
94
  "id": "visual-proof",
95
95
  "tools": ["preview_start", "preview_capture", "preview_inspect", "preview_stop"],
96
96
  "trigger": "\\b(ui|ux|visual|design|frontend|html|css|page|route|mockup|screenshot|responsive|desktop|mobile|preview)\\b",
97
- "prompt": "For built visual work, run the build, use preview_start, preview_capture at desktop and mobile, preview_inspect when rendered state matters, and preview_stop when finished. Surface PNG evidence only when no interactive source-backed Design card is displayed."
97
+ "prompt": "For built visual work, run the build, use preview_start, preview_capture at desktop and mobile, preview_inspect when rendered state matters, and preview_stop when finished. preview_capture uses a fresh isolated browser, so authenticated app routes require an authenticated visual harness; if a room route resolves to the signed-out invitation, the capture is rejected and no mockup card is created. Surface PNG evidence only when no interactive source-backed Design card is displayed."
98
98
  }
99
99
  ],
100
100
  "impact": [
package/viewport.mjs CHANGED
@@ -64,6 +64,12 @@ export function safeSlug(value = 'viewport') {
64
64
  .slice(0, 56) || 'viewport'
65
65
  }
66
66
 
67
+ export function isSignedOutRoomPreview(route, snapshot) {
68
+ const parsed = new URL(normalizeRoute(route), 'http://127.0.0.1')
69
+ if (!parsed.searchParams.get('r')) return false
70
+ return /\bid\s*=\s*["']invitation-room-title["']/i.test(String(snapshot || ''))
71
+ }
72
+
67
73
  export function findBrowserExecutable({ env = process.env, platform = process.platform, exists = fs.existsSync } = {}) {
68
74
  const candidates = [
69
75
  env.TP_BROWSER_PATH,
@@ -425,6 +431,17 @@ export class ViewportManager {
425
431
  if (names.some((name) => !DEFAULT_VIEWPORTS[name])) throw new Error('viewports must be "both", "desktop", or "mobile".')
426
432
  await fsp.mkdir(this.outbox, { recursive: true })
427
433
  const slug = `${safeSlug(title)}-${Date.now().toString(36)}`
434
+ // A preview browser is deliberately isolated and cannot inherit the room
435
+ // member's Supabase session. Catch the production failure mode where an
436
+ // agent requests /?r=ROOM expecting Code, but actually renders the public
437
+ // invitation landing and publishes it under an unrelated feature title.
438
+ // Validate before writing screenshots or a manifest so no misleading card
439
+ // can enter the room.
440
+ const snapshotViewport = names.includes('desktop') ? DEFAULT_VIEWPORTS.desktop : DEFAULT_VIEWPORTS[names[0]]
441
+ const snapshot = await this.browser.snapshot({ url, viewport: snapshotViewport, waitMs })
442
+ if (isSignedOutRoomPreview(normalizedRoute, snapshot)) {
443
+ throw new Error('Preview resolved to the signed-out room invitation instead of the authenticated Code room. preview_capture uses a fresh isolated browser and cannot inherit a person\'s login. Use an authenticated visual harness or signed-in browser evidence; no mockup card was created.')
444
+ }
428
445
  const captures = {}
429
446
  for (const name of names) {
430
447
  const result = await this.browser.capture({ url, viewport: DEFAULT_VIEWPORTS[name], fullPage, waitMs })
@@ -432,8 +449,6 @@ export class ViewportManager {
432
449
  await fsp.writeFile(file, result.png)
433
450
  captures[name] = { ...result, file }
434
451
  }
435
- const snapshotViewport = names.includes('desktop') ? DEFAULT_VIEWPORTS.desktop : DEFAULT_VIEWPORTS[names[0]]
436
- const snapshot = await this.browser.snapshot({ url, viewport: snapshotViewport, waitMs })
437
452
  const snapshotPath = path.join(this.outbox, `${slug}--source.html`)
438
453
  await fsp.writeFile(snapshotPath, snapshot)
439
454
  const workspace = await fsp.realpath(this.workspaceRoot)
@@ -487,7 +502,7 @@ export function createViewportTools({ tool, z, manager }) {
487
502
  ),
488
503
  tool(
489
504
  'preview_capture',
490
- 'Capture this lane preview at exact desktop (1440×900) and mobile (390×844) CSS viewports. Defaults to both and full-page. Returns the PNGs to your vision context and also surfaces a mockup card in the ThinkPool room.',
505
+ 'Capture this lane preview in a fresh isolated browser at exact desktop (1440×900) and mobile (390×844) CSS viewports. Defaults to both and full-page. Authenticated app routes require an authenticated visual harness; a room route that resolves to the signed-out invitation is rejected. Successful captures return PNGs to your vision context and surface a mockup card in the ThinkPool room.',
491
506
  {
492
507
  path: z.string().max(500).optional().describe('route within the preview, e.g. / or /settings; never a full URL'),
493
508
  viewports: z.enum(['both', 'desktop', 'mobile']).optional(),