@dfosco/storyboard 0.6.0-beta.13 → 0.6.0-beta.14

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.6.0-beta.13",
3
+ "version": "0.6.0-beta.14",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Storyboard prototyping framework — core engine, React integration, and canvas",
@@ -226,7 +226,12 @@ export function buildResumeStartupCommand({ startupCommand, sessionId, agentCfg
226
226
  : `${cmd} || { ${notice}; ${startupCommand}; }`
227
227
 
228
228
  // Primary: per-widget captured sessionId → `resumeCommand` with {id}.
229
- if (sessionId && isResumableSessionId(sessionId, agentCfg)) {
229
+ // We attempt resume whenever a UUID-shaped id is stored, even if the
230
+ // agent's local session-state directory has been GC'd / moved — the
231
+ // shell-level `|| <fresh fallback>` wrapper handles CLI rejection
232
+ // gracefully. This makes resume robust across `tmux kill-server`,
233
+ // disk cleanups, and machine moves.
234
+ if (sessionId && UUID_RE.test(sessionId)) {
230
235
  const template = agentCfg?.resumeCommand
231
236
  if (template && template.includes('{id}')) {
232
237
  return wrapFallback(template.replace('{id}', sessionId))
@@ -235,9 +240,7 @@ export function buildResumeStartupCommand({ startupCommand, sessionId, agentCfg
235
240
 
236
241
  // Fallback: agents like Codex provide a `resumeLastCommand` that
237
242
  // resumes the most recent session in the current cwd without needing
238
- // a captured id (e.g. `codex resume --last`). Useful when the agent's
239
- // sessionStart hook requires manual trust before it can capture ids
240
- // (Codex case — hook needs `/hooks` approval).
243
+ // a captured id (e.g. `codex resume --last`).
241
244
  const lastCmd = agentCfg?.resumeLastCommand
242
245
  if (lastCmd) return wrapFallback(lastCmd)
243
246
 
@@ -323,18 +323,30 @@ async function main() {
323
323
  setTimeout(() => { renderOnce() }, 8000).unref?.()
324
324
  }
325
325
 
326
+ let shuttingDown = false
326
327
  function shutdown() {
328
+ if (shuttingDown) {
329
+ // Second Ctrl+C → hard exit, kill child with SIGKILL.
330
+ try { child.kill('SIGKILL') } catch { /* empty */ }
331
+ process.exit(130)
332
+ }
333
+ shuttingDown = true
327
334
  clearInterval(compactInterval)
328
335
  renameWatcher.close()
329
336
  // Suppress Vite's shutdown-time esbuild noise ("Pre-transform error:
330
- // The service was stopped" for every in-flight transform).
337
+ // The service was stopped" for every in-flight transform) AND the
338
+ // orphan-archive log spam from the storyboard-server plugin teardown.
331
339
  try { child.stdout?.removeAllListeners('data') } catch { /* empty */ }
332
340
  try { child.stderr?.removeAllListeners('data') } catch { /* empty */ }
333
341
  try { child.stdout?.destroy() } catch { /* empty */ }
334
342
  try { child.stderr?.destroy() } catch { /* empty */ }
335
- // SIGINT lets Vite shut down esbuild and HMR cleanly; SIGTERM is harsher
336
- // and tends to leave in-flight transforms aborting noisily.
343
+ // SIGINT first (clean esbuild shutdown), then SIGTERM after 2s if
344
+ // Vite is still alive (handles plugins that loop on session teardown),
345
+ // then SIGKILL after 5s as last resort.
337
346
  try { child.kill('SIGINT') } catch { /* already dead */ }
347
+ const term = setTimeout(() => { try { child.kill('SIGTERM') } catch { /* empty */ } }, 2000)
348
+ const kill = setTimeout(() => { try { child.kill('SIGKILL') } catch { /* empty */ } }, 5000)
349
+ term.unref?.(); kill.unref?.()
338
350
  releasePort(worktreeName)
339
351
  }
340
352
  process.on('SIGINT', shutdown)