thinkpool-pair 0.7.218 → 0.7.220
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 +4 -1
- package/claude-session.mjs +3 -2
- package/design-edit.mjs +38 -0
- package/package.json +1 -1
- package/thinkpool-room-prompt.mjs +4 -2
package/bridge.mjs
CHANGED
|
@@ -65,7 +65,7 @@ import { writeLaneArtifact, digestSlice, appendDigest, resumeLane } from './flow
|
|
|
65
65
|
import { createFlowWorktree, worktreeSpec } from './flow-worktree.mjs'
|
|
66
66
|
import { startPreview, stopAllPreviews, previews } from './flow-preview.mjs'
|
|
67
67
|
import { ViewportManager, createViewportTools, sharedViewportBrowser } from './viewport.mjs'
|
|
68
|
-
import { designPrompt, resolveDesignSource, syncRealtimeAuth, validateDesignRequest } from './design-edit.mjs'
|
|
68
|
+
import { designPrompt, resolveDesignSource, restoreDesignSources, syncRealtimeAuth, validateDesignRequest } from './design-edit.mjs'
|
|
69
69
|
// FL-M9 — per-lane preview servers leak (one per done lane, never stopped until shutdown).
|
|
70
70
|
// Lane previews are keyed `lane:<flowId>:<laneId>`; stop a whole flow's set when it assembles
|
|
71
71
|
// (the assembled preview supersedes them) or when a lane is reverted.
|
|
@@ -1862,6 +1862,9 @@ function openStructured({ id, runtime = 'claude', model, effort, resume, log, co
|
|
|
1862
1862
|
// they land on this session even after other terminals open/close.
|
|
1863
1863
|
const mockupOutbox = ownerOutbox('sessions', id)
|
|
1864
1864
|
entry.mockupWatcher = watchOutbox(mockupOutbox, () => id, true)
|
|
1865
|
+
const restoredDesigns = restoreDesignSources(mockupOutbox, cwd || process.cwd(), id)
|
|
1866
|
+
for (const record of restoredDesigns) designArtifacts.set(record.previewId, record)
|
|
1867
|
+
if (restoredDesigns.length) process.stderr.write(`\n ◆ restored ${restoredDesigns.length} Thinkpool Design artifact${restoredDesigns.length === 1 ? '' : 's'} (${id.slice(0, 8)}).\n`)
|
|
1865
1868
|
// Visual QA runs in the bridge process, outside either agent runtime's sandbox.
|
|
1866
1869
|
// It remains scoped to this lane's cwd and private mockup outbox.
|
|
1867
1870
|
entry.viewport = new ViewportManager({ workspaceRoot: cwd || process.cwd(), ownerId: id, outbox: mockupOutbox })
|
package/claude-session.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import { sanitizeSession } from './transcript-sanitize.mjs'
|
|
|
21
21
|
import { reviewGatePreToolDecision } from './flow-review-gate.mjs'
|
|
22
22
|
import { crossPostNeedsCard } from './cross-terminal.mjs'
|
|
23
23
|
import { correctContext } from './context-windows.mjs'
|
|
24
|
-
import { THINKPOOL_REMOTE_DELIVERY_RULES } from './thinkpool-room-prompt.mjs'
|
|
24
|
+
import { THINKPOOL_DESIGN_DELIVERY_RULE, THINKPOOL_REMOTE_DELIVERY_RULES } from './thinkpool-room-prompt.mjs'
|
|
25
25
|
import { stallDecision, stallEvent, isCompactTurn } from './turn-stall.mjs'
|
|
26
26
|
|
|
27
27
|
// The caret-pulled SDK's real version (^0.3.x auto-upgrades on restart). Resolved
|
|
@@ -196,7 +196,8 @@ const MODES = new Set(['default', 'acceptEdits', 'plan', 'bypassPermissions'])
|
|
|
196
196
|
// the bridge's roomContext callback — see roomReminder() inside startClaudeSession.
|
|
197
197
|
const TP_ROOM_REMINDER = [
|
|
198
198
|
'You are Claude in a ThinkPool Code room, driven live from a phone or browser — NOT a local terminal. Keep using the room\'s features.',
|
|
199
|
-
'ARTIFACTS: never hand the room a local path, a file:// URL, a localhost address, an `open …`/Preview reference, or "it\'s in ~/claude-shots/" — the room cannot see the host. Surface every image by reading the PNG into your turn so it renders inline
|
|
199
|
+
'ARTIFACTS: never hand the room a local path, a file:// URL, a localhost address, an `open …`/Preview reference, or "it\'s in ~/claude-shots/" — the room cannot see the host. Surface every image by reading the PNG into your turn so it renders inline.',
|
|
200
|
+
THINKPOOL_DESIGN_DELIVERY_RULE,
|
|
200
201
|
'REMOTE USER: the people here may have no terminal and no access to this host — never ask them to run a local command, open a local file, or check something on the machine. Anything host-side, YOU run, and show the result.',
|
|
201
202
|
'SHOW, don\'t narrate: a picture of the result beats a wall of text on a phone — err toward more screenshots.',
|
|
202
203
|
'ENSEMBLE: delegated work goes through the room — fan parallel work out with spawn_terminal (your own fresh lanes, visible and steerable by the people here), NOT the built-in invisible Task/Agent subagents; never hijack a busy sibling.',
|
package/design-edit.mjs
CHANGED
|
@@ -48,6 +48,44 @@ export function resolveDesignSource(file, workspaceRoot) {
|
|
|
48
48
|
return { previewId, revision, sourcePath, workspaceRoot: root, source }
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// Design provenance is intentionally host-only, but it must survive a bridge
|
|
52
|
+
// restart. Rebuild the in-memory registry from manifests already written by the
|
|
53
|
+
// trusted lane render workflow; do not re-upload or re-broadcast old cards.
|
|
54
|
+
export function restoreDesignSources(box, workspaceRoot, term, limit = 100) {
|
|
55
|
+
if (!box || !workspaceRoot || !term) return []
|
|
56
|
+
let files
|
|
57
|
+
try {
|
|
58
|
+
files = fs.readdirSync(box, { withFileTypes: true })
|
|
59
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.json') && !entry.name.endsWith('.receipt.json'))
|
|
60
|
+
.map((entry) => {
|
|
61
|
+
const file = path.join(box, entry.name)
|
|
62
|
+
return { file, mtimeMs: fs.statSync(file).mtimeMs }
|
|
63
|
+
})
|
|
64
|
+
.sort((a, b) => b.mtimeMs - a.mtimeMs)
|
|
65
|
+
.slice(0, Math.max(0, limit))
|
|
66
|
+
} catch { return [] }
|
|
67
|
+
const restored = []
|
|
68
|
+
for (const { file } of files) {
|
|
69
|
+
try {
|
|
70
|
+
const manifest = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
71
|
+
if (!manifest?.source) continue
|
|
72
|
+
const record = resolveDesignSource(manifest.source, workspaceRoot)
|
|
73
|
+
if (!record) continue
|
|
74
|
+
Object.assign(record, {
|
|
75
|
+
term,
|
|
76
|
+
slug: String(manifest.slug || ''),
|
|
77
|
+
title: String(manifest.title || manifest.slug || ''),
|
|
78
|
+
desktop: manifest.desktop || null,
|
|
79
|
+
mobile: manifest.mobile || null,
|
|
80
|
+
})
|
|
81
|
+
const backupPath = path.join(box, '.design-revisions', `${record.revision}.html`)
|
|
82
|
+
if (fs.existsSync(backupPath)) record.backupPath = backupPath
|
|
83
|
+
restored.push(record)
|
|
84
|
+
} catch { /* stale or malformed manifests are ignored */ }
|
|
85
|
+
}
|
|
86
|
+
return restored
|
|
87
|
+
}
|
|
88
|
+
|
|
51
89
|
function safeTarget(value) {
|
|
52
90
|
if (!value || typeof value !== 'object') return null
|
|
53
91
|
const rect = value.rect && typeof value.rect === 'object' ? {
|
package/package.json
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
// the first human turn in each fresh native thread. Keep the runtime-specific
|
|
4
4
|
// orchestration rules in their own drivers — these are the cross-runtime truths
|
|
5
5
|
// about where the people are and how finished work must reach them.
|
|
6
|
+
export const THINKPOOL_DESIGN_DELIVERY_RULE = 'THINKPOOL DESIGN (mandatory for HTML): save the editable HTML source in the workspace, then use the $TP_MOCKUP_OUTBOX render helper so the room receives a Thinkpool Design card with both desktop (1440×900) and mobile (390×844) previews. Never paste raw HTML into chat, send an .html file as the room deliverable, or substitute a bare URL or single screenshot for this card. A shareable browser URL may accompany the card, but never replaces it.'
|
|
7
|
+
|
|
6
8
|
export const THINKPOOL_REMOTE_DELIVERY_RULES = Object.freeze([
|
|
7
9
|
'REMOTE USER (authoritative default for ThinkPool Code rooms): unless a person explicitly says they are at the host machine, assume everyone driving this room is remote — possibly on a phone — with no terminal and no access to the host filesystem. Never ask them to run a local command, open a local file, or "go check" something on the machine. Anything host-side, you run yourself and show the result in the room. Only suggest actions they can actually do from the room UI or a browser.',
|
|
8
10
|
'LINKS & ARTIFACTS: a local filesystem path, file:// URL, localhost/127.0.0.1 address, or host-only preview is useless to a remote room. Every link you surface must be reachable by the people in the room.',
|
|
9
|
-
'Whenever you produce HTML or shareable markup — a demo, mockup, preview, report, or page — publish it to a browser-renderable GitHub-shareable URL, normally GitHub Pages (or an equivalent URL that actually renders; raw.githubusercontent.com serves HTML as plain text). Give the room that shareable URL, never only a local path. If you cannot publish it, say so
|
|
11
|
+
'Whenever you produce HTML or shareable markup — a demo, mockup, preview, report, or page — publish it to a browser-renderable GitHub-shareable URL, normally GitHub Pages (or an equivalent URL that actually renders; raw.githubusercontent.com serves HTML as plain text). Give the room that shareable URL in addition to the Thinkpool Design card, never instead of it and never only as a local path. If you cannot publish it, say so instead of falling back to a host-only path.',
|
|
10
12
|
'SHOW VISUAL WORK: whenever you build, change, or fix anything visual — UI, page, HTML artifact, chart, diagram, or rendered result — capture a PNG and surface the image in your turn so it appears inline in the room; the room auto-uploads surfaced images. Prefer showing the result over describing it.',
|
|
11
13
|
'BRIDGE PREVIEWS: for a built web UI, use preview_start (default root: dist), then preview_capture for exact desktop 1440x900 and mobile 390x844 PNGs, and preview_inspect when DOM text or selector geometry helps. Run the project build first and stop the preview server with preview_stop when done.',
|
|
12
|
-
|
|
14
|
+
THINKPOOL_DESIGN_DELIVERY_RULE,
|
|
13
15
|
'VERIFY BEFORE CLAIMING: run or serve what you changed, observe it, and show the evidence in the room — the PNG, passing test output, or real response. If something could not be verified, say exactly what remains unverified.',
|
|
14
16
|
])
|
|
15
17
|
|