@dfosco/storyboard 0.5.0-beta.48 → 0.5.0-beta.49

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dfosco/storyboard",
3
- "version": "0.5.0-beta.48",
3
+ "version": "0.5.0-beta.49",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Storyboard prototyping framework — core engine, React integration, and canvas",
@@ -3015,9 +3015,17 @@ export function Default() {
3015
3015
  }
3016
3016
 
3017
3017
  try {
3018
- const { readTerminalConfig, initTerminalConfig } = await import('./terminal-config.js')
3018
+ const { readTerminalConfig, readTerminalConfigById, initTerminalConfig } = await import('./terminal-config.js')
3019
3019
  initTerminalConfig(root)
3020
- const config = readTerminalConfig({ branch, canvasId, widgetId })
3020
+ let config = readTerminalConfig({ branch, canvasId, widgetId })
3021
+ // Fallback: when canvasId/branch are missing, mismatched, or stale
3022
+ // (e.g. the persisted canvasId only captured the parent folder),
3023
+ // recover via the widget-id-named symlink that writeTerminalConfig
3024
+ // creates next to the hashed config.
3025
+ if (!config?.agentStatus) {
3026
+ const byId = readTerminalConfigById(widgetId)
3027
+ if (byId?.agentStatus) config = byId
3028
+ }
3021
3029
  sendJson(res, 200, { agentStatus: config?.agentStatus || null })
3022
3030
  } catch (err) {
3023
3031
  sendJson(res, 500, { error: `Failed to read agent status: ${err.message}` })
@@ -9,6 +9,27 @@ function getBase() {
9
9
  return (import.meta.env?.BASE_URL || '/').replace(/\/$/, '')
10
10
  }
11
11
 
12
+ /**
13
+ * Resolve the **full** canvas-page id for the currently-mounted canvas.
14
+ * Prefer the live bridge state (set by CanvasPage), which always carries the
15
+ * complete nested id (e.g. `dfosco-explorations/adaptive-threat-view`). Fall
16
+ * back to URL parsing when the bridge isn't ready yet — and crucially, take
17
+ * **every** path segment after `/canvas/`, not just the first one, so nested
18
+ * canvas ids round-trip correctly.
19
+ */
20
+ function resolveCanvasId() {
21
+ if (typeof window !== 'undefined') {
22
+ const fromBridge = window.__storyboardCanvasBridgeState?.canvasId
23
+ if (fromBridge) return fromBridge
24
+ const pathParts = window.location.pathname.split('/').filter(Boolean)
25
+ const canvasIdx = pathParts.indexOf('canvas')
26
+ if (canvasIdx >= 0 && canvasIdx < pathParts.length - 1) {
27
+ return pathParts.slice(canvasIdx + 1).join('/')
28
+ }
29
+ }
30
+ return 'default'
31
+ }
32
+
12
33
  async function spawnPromptAgent({ canvasId, widgetId, prompt }) {
13
34
  const res = await fetch(`${getBase()}/_storyboard/canvas/prompt/spawn`, {
14
35
  method: 'POST',
@@ -163,7 +184,10 @@ const PromptWidget = forwardRef(function PromptWidget({ id, props, onUpdate, res
163
184
 
164
185
  async function pollOnce() {
165
186
  try {
166
- const url = `${getBase()}/_storyboard/canvas/agent/status?widgetId=${encodeURIComponent(id)}`
187
+ const params = new URLSearchParams({ widgetId: id })
188
+ const cid = resolveCanvasId()
189
+ if (cid && cid !== 'default') params.set('canvasId', cid)
190
+ const url = `${getBase()}/_storyboard/canvas/agent/status?${params}`
167
191
  const res = await fetch(url)
168
192
  if (!res.ok) return
169
193
  const json = await res.json().catch(() => null)
@@ -213,9 +237,7 @@ const PromptWidget = forwardRef(function PromptWidget({ id, props, onUpdate, res
213
237
  setExecStatus('pending')
214
238
  setExecError('')
215
239
 
216
- const pathParts = window.location.pathname.split('/')
217
- const canvasIdx = pathParts.indexOf('canvas')
218
- const canvasId = canvasIdx >= 0 ? pathParts[canvasIdx + 1] : 'default'
240
+ const canvasId = resolveCanvasId()
219
241
 
220
242
  onUpdate?.({ text: draftText, status: 'pending' })
221
243
 
@@ -315,9 +337,7 @@ const PromptWidget = forwardRef(function PromptWidget({ id, props, onUpdate, res
315
337
  term.open(termContainerRef.current)
316
338
  termRef.current = term
317
339
 
318
- const pathParts = window.location.pathname.split('/')
319
- const canvasIdx = pathParts.indexOf('canvas')
320
- const canvasId = canvasIdx >= 0 ? pathParts[canvasIdx + 1] : 'default'
340
+ const canvasId = resolveCanvasId()
321
341
 
322
342
  const url = getWsUrl(id, canvasId, true)
323
343
  ws = new WebSocket(url)