thinkpool-pair 0.7.229 → 0.7.230

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 CHANGED
@@ -66,7 +66,7 @@ import { writeLaneArtifact, digestSlice, appendDigest, resumeLane } from './flow
66
66
  import { createFlowWorktree, worktreeSpec } from './flow-worktree.mjs'
67
67
  import { startPreview, stopAllPreviews, previews } from './flow-preview.mjs'
68
68
  import { ViewportManager, createViewportTools, sharedViewportBrowser } from './viewport.mjs'
69
- import { deleteDesignAssetDraft, designPrompt, materializeDesignAsset, resolveDesignSource, resolveManifestDesignSource, restoreDesignSources, syncRealtimeAuth, validateDesignBatchRequest } from './design-edit.mjs'
69
+ import { deleteDesignAssetDraft, designPrompt, designTranscript, materializeDesignAsset, resolveDesignSource, resolveManifestDesignSource, restoreDesignSources, syncRealtimeAuth, validateDesignBatchRequest } from './design-edit.mjs'
70
70
  // FL-M9 — per-lane preview servers leak (one per done lane, never stopped until shutdown).
71
71
  // Lane previews are keyed `lane:<flowId>:<laneId>`; stop a whole flow's set when it assembles
72
72
  // (the assembled preview supersedes them) or when a lane is reverted.
@@ -1283,19 +1283,13 @@ function pumpDesign(term) {
1283
1283
  const active = { ...next, resultOk: false, proof: null, timer: null }
1284
1284
  designActive.set(term, active)
1285
1285
  designStatus({ previewId: next.record.previewId, requestId: next.request.cid, state: 'applying' })
1286
- // Safe transcript summary: never include host paths or the full locator packet.
1287
- const action = next.request.mode === 'text' ? 'replace text'
1288
- : next.request.mode === 'move' ? 'move element'
1289
- : next.request.mode === 'image' ? 'replace image'
1290
- : next.request.intent
1291
- const batchCount = next.request.mode === 'batch' ? next.request.edits.length : 0
1286
+ // Complete room-visible instructions, without host paths or locator packets.
1292
1287
  const visible = {
1293
1288
  kind: 'you',
1294
- text: batchCount
1295
- ? `Design batch · ${batchCount} pooled edit${batchCount === 1 ? '' : 's'}`
1296
- : `Design edit · ${next.request.target.name || next.request.target.tag}: ${action}`,
1289
+ text: designTranscript(next.request, { restore: !!next.restoreRecord }),
1297
1290
  cid: next.request.cid,
1298
1291
  by: next.by,
1292
+ design: true,
1299
1293
  }
1300
1294
  stampEvent(visible); pushLog(lane, visible); bcast('code-event', { term, evt: visible })
1301
1295
  try { lane.session.sendTurn(designPrompt({ record: next.record, request: next.request, by: next.by, restore: !!next.restoreRecord, priorRecord: next.restoreRecord })) }
@@ -4038,7 +4032,8 @@ designChannel
4038
4032
  materializedDrafts.push(edit.asset.path)
4039
4033
  }
4040
4034
  await Promise.all(materializedDrafts.map((assetPath) => deleteDesignAssetDraft({ webBase: WEB_BASE, token: codeAuthToken, room, path: assetPath })))
4041
- queue.push({ ...verdict, by: 'A room member' })
4035
+ const by = String(payload?.by || 'A room member').replace(/\0/g, '').trim().slice(0, 120) || 'A room member'
4036
+ queue.push({ ...verdict, by })
4042
4037
  const batchCount = verdict.request.mode === 'batch' ? verdict.request.edits.length : 1
4043
4038
  designStatus({ previewId, requestId, state: 'queued', message: `${batchCount} edit${batchCount === 1 ? '' : 's'} pooled to the producing lane.` })
4044
4039
  pumpDesign(term)
@@ -4061,7 +4056,8 @@ designChannel
4061
4056
  designStatus({ previewId, requestId, state: 'failed', message: 'Too many Design edits are queued for this lane.' })
4062
4057
  return
4063
4058
  }
4064
- queue.push({ record, restoreRecord: restore.priorRecord, request: { previewId, revision: record.revision, mode: 'restore', intent: 'restore previous verified revision', target: restore.request.target || { selector: 'html', tag: 'artifact', name: `${restore.request.edits?.length || 1} pooled edits` }, cid: requestId }, by: 'A room member' })
4059
+ const by = String(payload?.by || 'A room member').replace(/\0/g, '').trim().slice(0, 120) || 'A room member'
4060
+ queue.push({ record, restoreRecord: restore.priorRecord, request: { previewId, revision: record.revision, mode: 'restore', intent: 'restore previous verified revision', target: restore.request.target || { selector: 'html', tag: 'artifact', name: `${restore.request.edits?.length || 1} pooled edits` }, cid: requestId }, by })
4065
4061
  designStatus({ previewId, requestId, state: 'queued', message: 'Restore queued in the producing lane.' })
4066
4062
  pumpDesign(record.term)
4067
4063
  })
package/design-edit.mjs CHANGED
@@ -223,6 +223,32 @@ function designAction(request) {
223
223
  return `Apply this visual change to only the selected element unless the instruction explicitly requires its immediate context:\n${request.intent}`
224
224
  }
225
225
 
226
+ const designModeLabel = (mode) => ({ text: 'Text', prompt: 'Prompt', move: 'Move', image: 'Image' })[mode] || 'Edit'
227
+
228
+ function visibleDesignAction(request) {
229
+ if (request.mode === 'text') return `Replacement text:\n${clean(request.intent, MAX_TEXT)}`
230
+ if (request.mode === 'prompt') return `Instruction:\n${clean(request.intent, MAX_INTENT)}`
231
+ if (request.mode === 'move') return `Move from position ${request.movement.fromIndex + 1} to position ${request.movement.toIndex + 1}.`
232
+ if (request.mode === 'image') return `Replacement image: ${clean(request.asset?.name || 'uploaded image', 240)}`
233
+ return ''
234
+ }
235
+
236
+ // Complete, room-safe transcript text for the visible Design dispatch. Keep the
237
+ // user instructions and order; omit host-only paths and locator packets.
238
+ export function designTranscript(request, { restore = false } = {}) {
239
+ if (restore) return 'Thinkpool Design · restore the previous verified revision'
240
+ const edits = request?.mode === 'batch' ? request.edits : [request]
241
+ const valid = Array.isArray(edits) ? edits.filter(Boolean).slice(0, MAX_BATCH_EDITS) : []
242
+ const heading = request?.mode === 'batch'
243
+ ? `Thinkpool Design · ${valid.length} pooled edit${valid.length === 1 ? '' : 's'}`
244
+ : 'Thinkpool Design · 1 edit'
245
+ const details = valid.map((edit, index) => {
246
+ const target = clean(edit.target?.name || edit.target?.tag || 'element', 240)
247
+ return `${index + 1}. ${designModeLabel(edit.mode)} · ${target}\n${visibleDesignAction(edit)}`
248
+ })
249
+ return [heading, ...details].join('\n\n')
250
+ }
251
+
226
252
  export function designPrompt({ record, request, by, restore = false, priorRecord = null }) {
227
253
  const batch = request.mode === 'batch' ? request.edits : null
228
254
  const work = restore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.229",
3
+ "version": "0.7.230",
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": {