From 7cf445778da322adde0afb4d281e32ae25711571 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 7 Jun 2026 13:19:48 -0700 Subject: [PATCH] Slice synthetic OpenCode pane injection (#4827) --- ...artificial-opencode-synthetic-injection.ts | 134 ++++++++++++++++++ .../artificial-opencode-terminal-load.spec.ts | 93 +++--------- 2 files changed, 153 insertions(+), 74 deletions(-) create mode 100644 tests/e2e/artificial-opencode-synthetic-injection.ts diff --git a/tests/e2e/artificial-opencode-synthetic-injection.ts b/tests/e2e/artificial-opencode-synthetic-injection.ts new file mode 100644 index 000000000..4a2f4d9cd --- /dev/null +++ b/tests/e2e/artificial-opencode-synthetic-injection.ts @@ -0,0 +1,134 @@ +import type { Page } from '@stablyai/playwright-test' + +type SyntheticOpenCodeInjectionWindow = Window & { + __terminalPtyDataInjection?: { + inject: (paneKey: string, data: string) => boolean + } + __syntheticOpenCodeLoadState?: SyntheticOpenCodeLoadState +} + +type SyntheticOpenCodeLoadState = { + errorMessage?: string + intervalTimer?: number + pendingTimers: number[] + stopped: boolean +} + +const SYNTHETIC_PANES_PER_TIMER_TASK = 4 + +export async function startSyntheticOpenCodeInjection({ + frameCount, + intervalMs, + page, + paneKeys +}: { + frameCount: number + intervalMs: number + page: Page + paneKeys: string[] +}): Promise<{ stop: () => Promise }> { + await page.evaluate( + ({ frameCount, intervalMs, paneKeys, panesPerTimerTask }) => { + const target = window as SyntheticOpenCodeInjectionWindow + const injector = target.__terminalPtyDataInjection + if (!injector) { + throw new Error('terminal PTY data injection API is unavailable') + } + let frameIndex = 0 + const previousState = target.__syntheticOpenCodeLoadState + if (previousState?.intervalTimer != null) { + window.clearInterval(previousState.intervalTimer) + } + for (const timer of previousState?.pendingTimers ?? []) { + window.clearTimeout(timer) + } + const state: SyntheticOpenCodeLoadState = { + pendingTimers: [], + stopped: false + } + target.__syntheticOpenCodeLoadState = state + state.intervalTimer = window.setInterval(() => { + const frame = frameIndex + frameIndex += 1 + for (let paneOffset = 0; paneOffset < paneKeys.length; paneOffset += panesPerTimerTask) { + const paneBatch = paneKeys.slice(paneOffset, paneOffset + panesPerTimerTask) + // Why: real PTY chunks arrive over several renderer tasks, but not + // necessarily one browser timer per pane. Small batches keep the + // harness from creating either one giant callback or timer storms. + const timer = window.setTimeout(() => { + state.pendingTimers = state.pendingTimers.filter((id) => id !== timer) + if (state.stopped || state.errorMessage) { + return + } + for (const [batchIndex, paneKey] of paneBatch.entries()) { + const paneIndex = paneOffset + batchIndex + try { + const injected = injector.inject( + paneKey, + syntheticOpenCodeFrameSource(paneIndex, frame) + ) + if (!injected) { + state.errorMessage = `no PTY data injector registered for pane key ${paneKey}` + return + } + } catch (error) { + state.errorMessage = error instanceof Error ? error.message : String(error) + return + } + } + }, 0) + state.pendingTimers.push(timer) + } + if (frameIndex >= frameCount && state.intervalTimer != null) { + window.clearInterval(state.intervalTimer) + delete state.intervalTimer + } + }, intervalMs) + + function syntheticOpenCodeFrameSource(paneIndex: number, frame: number): string { + const row = (frame % 18) + 4 + const spinner = ['|', '/', '-', '\\'][frame % 4] + const body = `${'opencode '.repeat(10)}pane=${paneIndex} frame=${frame}` + return [ + '\x1b[?2026h', + '\x1b[?25l', + `\x1b[1;2H\x1b[38;2;255;138;0m${spinner} OpenCode synthetic agent ${paneIndex}\x1b[0m`, + `\x1b[${row};4H\x1b[38;2;231;237;247m${body.padEnd(118, '#')}\x1b[0m`, + `\x1b[23;2H\x1b[38;2;106;169;255mstream ${String(frame).padStart(4, '0')} ${'#'.repeat(96)}\x1b[0m`, + '\x1b[?2026l' + ].join('') + } + }, + { + frameCount, + intervalMs, + paneKeys, + panesPerTimerTask: SYNTHETIC_PANES_PER_TIMER_TASK + } + ) + + return { + stop: async () => { + await page.evaluate(() => { + const target = window as SyntheticOpenCodeInjectionWindow + const state = target.__syntheticOpenCodeLoadState + if (!state) { + return + } + state.stopped = true + if (state.intervalTimer != null) { + window.clearInterval(state.intervalTimer) + delete state.intervalTimer + } + for (const timer of state.pendingTimers) { + window.clearTimeout(timer) + } + const { errorMessage } = state + delete target.__syntheticOpenCodeLoadState + if (errorMessage) { + throw new Error(errorMessage) + } + }) + } + } +} diff --git a/tests/e2e/artificial-opencode-terminal-load.spec.ts b/tests/e2e/artificial-opencode-terminal-load.spec.ts index 578675f26..9b07bc495 100644 --- a/tests/e2e/artificial-opencode-terminal-load.spec.ts +++ b/tests/e2e/artificial-opencode-terminal-load.spec.ts @@ -22,6 +22,7 @@ import { } from './helpers/terminal' import { runHiddenRealPtyPressureScenario } from './artificial-opencode-hidden-pressure-scenario' import { runMainPressureScenario } from './artificial-opencode-main-pressure-scenario' +import { startSyntheticOpenCodeInjection } from './artificial-opencode-synthetic-injection' type TerminalLoadPane = { paneKey: string @@ -279,68 +280,6 @@ function median(values: number[]): number { return sorted[Math.floor(sorted.length / 2)] ?? 0 } -async function startSyntheticOpenCodeInjection( - page: Page, - paneKeys: string[] -): Promise<{ stop: () => Promise }> { - await page.evaluate( - ({ paneKeys, frameCount, intervalMs }) => { - const target = window as SyntheticOpenCodeWindow & { - __syntheticOpenCodeLoadTimer?: number - } - const injector = target.__terminalPtyDataInjection - if (!injector) { - throw new Error('terminal PTY data injection API is unavailable') - } - let frameIndex = 0 - target.__syntheticOpenCodeLoadTimer = window.setInterval(() => { - for (const [paneIndex, paneKey] of paneKeys.entries()) { - const injected = injector.inject( - paneKey, - syntheticOpenCodeFrameSource(paneIndex, frameIndex) - ) - if (!injected) { - throw new Error(`no PTY data injector registered for pane key ${paneKey}`) - } - } - frameIndex += 1 - if (frameIndex >= frameCount && target.__syntheticOpenCodeLoadTimer != null) { - window.clearInterval(target.__syntheticOpenCodeLoadTimer) - delete target.__syntheticOpenCodeLoadTimer - } - }, intervalMs) - - function syntheticOpenCodeFrameSource(paneIndex: number, frame: number): string { - const row = (frame % 18) + 4 - const spinner = ['|', '/', '-', '\\'][frame % 4] - const body = `${'opencode '.repeat(10)}pane=${paneIndex} frame=${frame}` - return [ - '\x1b[?2026h', - '\x1b[?25l', - `\x1b[1;2H\x1b[38;2;255;138;0m${spinner} OpenCode synthetic agent ${paneIndex}\x1b[0m`, - `\x1b[${row};4H\x1b[38;2;231;237;247m${body.padEnd(118, '#')}\x1b[0m`, - `\x1b[23;2H\x1b[38;2;106;169;255mstream ${String(frame).padStart(4, '0')} ${'#'.repeat(96)}\x1b[0m`, - '\x1b[?2026l' - ].join('') - } - }, - { paneKeys, frameCount: FRAME_COUNT, intervalMs: FRAME_INTERVAL_MS } - ) - return { - stop: async () => { - await page.evaluate(() => { - const target = window as SyntheticOpenCodeWindow & { - __syntheticOpenCodeLoadTimer?: number - } - if (target.__syntheticOpenCodeLoadTimer != null) { - window.clearInterval(target.__syntheticOpenCodeLoadTimer) - delete target.__syntheticOpenCodeLoadTimer - } - }) - } - } -} - async function measureTypingDuringLoad( page: Page, scriptPath: string, @@ -532,10 +471,12 @@ async function measureCrossWorkspaceTypingDuringHiddenLoad({ const scriptPath = path.join(testRepoPath, `.orca-opencode-cross-${hiddenPaneCount}-${runId}.mjs`) writeInteractivePromptScript(scriptPath, runId) await resetTerminalPtyOutputDebug(orcaPage) - const load = await startSyntheticOpenCodeInjection( - orcaPage, - hiddenPanes.map((pane) => pane.paneKey) - ) + const load = await startSyntheticOpenCodeInjection({ + frameCount: FRAME_COUNT, + intervalMs: FRAME_INTERVAL_MS, + page: orcaPage, + paneKeys: hiddenPanes.map((pane) => pane.paneKey) + }) try { const measurement = await measureTypingDuringLoad(orcaPage, scriptPath, typingPtyId, runId) const debug = await readTerminalPtyOutputDebug(orcaPage) @@ -660,10 +601,12 @@ test.describe('Artificial OpenCode terminal load', () => { const scriptPath = path.join(testRepoPath, `.orca-opencode-typing-${runId}.mjs`) writeInteractivePromptScript(scriptPath, runId) await resetTerminalPtyOutputDebug(orcaPage) - const load = await startSyntheticOpenCodeInjection( - orcaPage, - loadPanes.map((pane) => pane.paneKey) - ) + const load = await startSyntheticOpenCodeInjection({ + frameCount: FRAME_COUNT, + intervalMs: FRAME_INTERVAL_MS, + page: orcaPage, + paneKeys: loadPanes.map((pane) => pane.paneKey) + }) try { const measurement = await measureTypingDuringLoad( orcaPage, @@ -733,10 +676,12 @@ test.describe('Artificial OpenCode terminal load', () => { const scriptPath = path.join(testRepoPath, `.orca-opencode-scale-${paneCount}-${runId}.mjs`) writeInteractivePromptScript(scriptPath, runId) await resetTerminalPtyOutputDebug(orcaPage) - const load = await startSyntheticOpenCodeInjection( - orcaPage, - loadPanes.map((pane) => pane.paneKey) - ) + const load = await startSyntheticOpenCodeInjection({ + frameCount: FRAME_COUNT, + intervalMs: FRAME_INTERVAL_MS, + page: orcaPage, + paneKeys: loadPanes.map((pane) => pane.paneKey) + }) try { const measurement = await measureTypingDuringLoad( orcaPage,