@dfosco/storyboard 0.6.0-beta.8 → 0.6.0-beta.9
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
|
@@ -549,7 +549,9 @@ export class HotPool {
|
|
|
549
549
|
const poll = setInterval(() => {
|
|
550
550
|
try {
|
|
551
551
|
const paneContent = execSync(
|
|
552
|
-
|
|
552
|
+
// H1: include scrollback so the readiness echo can still be
|
|
553
|
+
// matched after the agent's TUI repaints over it.
|
|
554
|
+
`tmux capture-pane -t "${tmuxName}" -p -S -200`,
|
|
553
555
|
{ encoding: 'utf8', timeout: 1000 }
|
|
554
556
|
)
|
|
555
557
|
// Strip ANSI escape sequences — agent CLIs use heavy formatting
|
|
@@ -3148,7 +3148,8 @@ export function Default() {
|
|
|
3148
3148
|
const poll = setInterval(() => {
|
|
3149
3149
|
if (sent) { clearInterval(poll); return }
|
|
3150
3150
|
try {
|
|
3151
|
-
|
|
3151
|
+
// H1: include scrollback so the echo survives Copilot's TUI repaint.
|
|
3152
|
+
const pane = execSync(`tmux capture-pane -t "${tmuxName}" -p -S -200`, { encoding: 'utf8', timeout: 1000 })
|
|
3152
3153
|
if (pane.includes(readinessSignal)) {
|
|
3153
3154
|
sent = true
|
|
3154
3155
|
clearInterval(poll)
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import { execSync } from 'node:child_process'
|
|
26
|
-
import { readFileSync, mkdirSync, writeFileSync, renameSync, existsSync, unlinkSync } from 'node:fs'
|
|
26
|
+
import { readFileSync, mkdirSync, writeFileSync, renameSync, existsSync, unlinkSync, rmSync } from 'node:fs'
|
|
27
27
|
import { resolve, join, dirname } from 'node:path'
|
|
28
28
|
import { fileURLToPath } from 'node:url'
|
|
29
29
|
import { tmpdir } from 'node:os'
|
|
@@ -1164,7 +1164,15 @@ function handleConnection(ws, widgetId, canvasId, prettyName, widgetStartupComma
|
|
|
1164
1164
|
// pool-keyed for the life of the warm process, so the user-level
|
|
1165
1165
|
// hook always writes there, not to the widget-keyed file.)
|
|
1166
1166
|
const postStartup = resolvedAgentCfg?.postStartup || null
|
|
1167
|
-
|
|
1167
|
+
// ── H2 fix: skip readiness re-poll on warm handoff.
|
|
1168
|
+
// The hot pool already verified readiness when it warmed this session.
|
|
1169
|
+
// Re-polling for a one-shot signal like Copilot's "Environment loaded:"
|
|
1170
|
+
// against an already-running TUI always misses (the echo has long
|
|
1171
|
+
// since scrolled off the visible pane, and `tmux capture-pane -p`
|
|
1172
|
+
// returns only the visible region). Falling through to the 30s
|
|
1173
|
+
// timeout fallback was delaying /allow-all, identity, role, and
|
|
1174
|
+
// bindWidget by ~30s for every warm Copilot widget.
|
|
1175
|
+
const readinessSignal = null
|
|
1168
1176
|
setTimeout(() => {
|
|
1169
1177
|
let completed = false
|
|
1170
1178
|
const finalize = () => {
|
|
@@ -1244,12 +1252,20 @@ function handleConnection(ws, widgetId, canvasId, prettyName, widgetStartupComma
|
|
|
1244
1252
|
const envScriptDir = join(cwd, '.storyboard', 'terminals')
|
|
1245
1253
|
try { mkdirSync(envScriptDir, { recursive: true }) } catch { /* empty */ }
|
|
1246
1254
|
const envScriptPath = join(envScriptDir, `${widgetId}.env.sh`)
|
|
1255
|
+
// ── H4: file marker for readiness. Terminal-state-independent —
|
|
1256
|
+
// `existsSync` doesn't care if Copilot's TUI repainted the pane,
|
|
1257
|
+
// entered alt-screen, or scrolled the echo away.
|
|
1258
|
+
const readyFilePath = join(envScriptDir, `${widgetId}.ready`)
|
|
1259
|
+
try { rmSync(readyFilePath, { force: true }) } catch { /* empty */ }
|
|
1247
1260
|
try {
|
|
1248
|
-
//
|
|
1249
|
-
//
|
|
1250
|
-
//
|
|
1251
|
-
|
|
1252
|
-
|
|
1261
|
+
// `touch` fires before the echo so the marker is set the instant
|
|
1262
|
+
// the env script finishes exporting. Echo kept for backwards-
|
|
1263
|
+
// compatible pane-scanning fallback (H1).
|
|
1264
|
+
writeFileSync(
|
|
1265
|
+
envScriptPath,
|
|
1266
|
+
envParts.join('\n') +
|
|
1267
|
+
`\ntouch ${JSON.stringify(readyFilePath)}\necho "Environment loaded:"\n`
|
|
1268
|
+
)
|
|
1253
1269
|
} catch { /* empty */ }
|
|
1254
1270
|
// Source env script; the trailing readiness echo MUST remain on
|
|
1255
1271
|
// the pane so the post-startup poller can match it. Don't append
|
|
@@ -1338,6 +1354,7 @@ function handleConnection(ws, widgetId, canvasId, prettyName, widgetStartupComma
|
|
|
1338
1354
|
if (sent) return
|
|
1339
1355
|
sent = true
|
|
1340
1356
|
clearInterval(pollInterval)
|
|
1357
|
+
try { rmSync(readyFilePath, { force: true }) } catch { /* empty */ }
|
|
1341
1358
|
setTimeout(() => {
|
|
1342
1359
|
if (postStartup) {
|
|
1343
1360
|
try {
|
|
@@ -1366,14 +1383,21 @@ function handleConnection(ws, widgetId, canvasId, prettyName, widgetStartupComma
|
|
|
1366
1383
|
}
|
|
1367
1384
|
const pollInterval = setInterval(() => {
|
|
1368
1385
|
if (sent) { clearInterval(pollInterval); return }
|
|
1386
|
+
// ── H4: marker file is set the instant env script finishes
|
|
1387
|
+
// exporting, before any TUI starts. Terminal-state-independent.
|
|
1388
|
+
if (existsSync(readyFilePath)) { finalize('file'); return }
|
|
1369
1389
|
try {
|
|
1390
|
+
// ── H1: include 200 lines of scrollback so the echo
|
|
1391
|
+
// can be matched after Copilot's full-screen TUI
|
|
1392
|
+
// repaints over it. `-p` alone returns only the
|
|
1393
|
+
// visible region.
|
|
1370
1394
|
const paneContent = execSync(
|
|
1371
|
-
`tmux capture-pane -t "${tmuxName}" -p`,
|
|
1395
|
+
`tmux capture-pane -t "${tmuxName}" -p -S -200`,
|
|
1372
1396
|
{ encoding: 'utf8', timeout: 1000 }
|
|
1373
1397
|
)
|
|
1374
1398
|
if (paneContent.includes(readinessSignal)) finalize('signal')
|
|
1375
1399
|
} catch { /* empty */ }
|
|
1376
|
-
},
|
|
1400
|
+
}, 1000)
|
|
1377
1401
|
// Fallback: if readiness signal never matches (e.g. resume mode
|
|
1378
1402
|
// doesn't print "Environment loaded:", or the agent shows a
|
|
1379
1403
|
// prompt we can't detect), bind anyway after 30s so the widget
|