@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
|
@@ -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
|
-
|
|
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`).
|
|
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
|
|
package/src/core/cli/dev.js
CHANGED
|
@@ -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
|
|
336
|
-
//
|
|
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)
|