Skip hidden title terminal renderer writes

This commit is contained in:
Neil
2026-06-09 17:06:14 -07:00
parent 3a91992852
commit 5b8b8d4e99
7 changed files with 156 additions and 10 deletions
@@ -35,6 +35,32 @@ describe('shouldSkipHiddenRendererOutput', () => {
).toBe(false)
})
it('skips complete hidden title OSC chunks when a snapshot restore is available', () => {
for (const data of ['\x1b]0;window title\x07', '\x1b]1;icon title\x07', '\x1b]2;both\x1b\\']) {
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data
})
).toBe(true)
}
})
it('skips hidden title OSC mixed with otherwise restorable plain output', () => {
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: 'line before\r\n\x1b]0;next title\x07line after\r\n'
})
).toBe(true)
})
it('keeps startup query windows and terminal-control chunks live', () => {
expect(
shouldSkipHiddenRendererOutput({
@@ -58,7 +84,7 @@ describe('shouldSkipHiddenRendererOutput', () => {
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
startupRendererQueryWindowActive: true,
synchronizedOutputActive: false,
data: '\x1b]0;title\x07'
})
@@ -74,6 +100,20 @@ describe('shouldSkipHiddenRendererOutput', () => {
).toBe(false)
})
it('keeps non-title OSC and incomplete title OSC chunks live', () => {
for (const data of ['\x1b]52;c;clipboard\x07', '\x1b]9;notify\x07', '\x1b]0;partial-title']) {
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data
})
).toBe(false)
}
})
it('keeps rewrite and unicode chunks live', () => {
expect(
shouldSkipHiddenRendererOutput({
@@ -13,18 +13,51 @@ function isAllowedPlainHiddenOutputCode(code: number): boolean {
return code >= 0x20 && code <= 0x7e
}
function containsOnlyPlainHiddenOutput(data: string): boolean {
for (let index = 0; index < data.length; index++) {
function findTitleOscEnd(data: string, startIndex: number): number | null {
const command = data.charCodeAt(startIndex + 2)
if (
data.charCodeAt(startIndex) !== 0x1b ||
data.charCodeAt(startIndex + 1) !== 0x5d ||
(command !== 0x30 && command !== 0x31 && command !== 0x32) ||
data.charCodeAt(startIndex + 3) !== 0x3b
) {
return null
}
for (let index = startIndex + 4; index < data.length; index++) {
const code = data.charCodeAt(index)
if (code === 0x07) {
return index + 1
}
if (code === 0x1b) {
return data.charCodeAt(index + 1) === 0x5c ? index + 2 : null
}
}
return null
}
function containsOnlyRestorableHiddenOutput(data: string): boolean {
for (let index = 0; index < data.length; ) {
const code = data.charCodeAt(index)
if (code === 0x1b) {
const nextIndex = findTitleOscEnd(data, index)
if (nextIndex === null) {
return false
}
index = nextIndex
continue
}
if (code === 0x0d) {
if (data.charCodeAt(index + 1) !== 0x0a) {
return false
}
index += 1
continue
}
if (!isAllowedPlainHiddenOutputCode(code)) {
return false
}
index += 1
}
return true
}
@@ -45,5 +78,5 @@ export function shouldSkipHiddenRendererOutput({
) {
return false
}
return containsOnlyPlainHiddenOutput(data)
return containsOnlyRestorableHiddenOutput(data)
}
@@ -3358,6 +3358,44 @@ describe('connectPanePty', () => {
disposable.dispose()
})
it('skips hidden title OSC renderer writes while keeping pane title handling wired', async () => {
const { connectPanePty } = await import('./pty-connection')
const transport = createMockTransport('pty-id')
const capturedDataCallback: {
current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null
} = { current: null }
transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => {
capturedDataCallback.current = callbacks.onData ?? null
return 'pty-id'
})
transportFactoryQueue.push(transport)
const pane = createPane(1)
const manager = createManager(1)
const deps = createDeps({
isVisibleRef: { current: false }
})
const disposable = connectPanePty(pane as never, manager as never, deps as never)
await flushAsyncTicks(6)
const hiddenTitle = '\x1b]0;hidden title\x07'
capturedDataCallback.current?.(hiddenTitle, {
seq: hiddenTitle.length,
rawLength: hiddenTitle.length
})
expect(pane.terminal.write).not.toHaveBeenCalledWith(hiddenTitle, expect.any(Function))
const titleHandler = createdTransportOptions[0]?.onTitleChange as
| ((title: string, rawTitle: string) => void)
| undefined
if (!titleHandler) {
throw new Error('Expected onTitleChange to be registered')
}
titleHandler('hidden title', 'hidden title')
expect(deps.setRuntimePaneTitle).toHaveBeenCalledWith('tab-1', pane.id, 'hidden title')
disposable.dispose()
})
it('restores plain hidden remote runtime output from its serialized snapshot', async () => {
const { connectPanePty } = await import('./pty-connection')
const transport = createMockTransport('remote:env-1@@terminal-1')
@@ -93,6 +93,25 @@ describe('createIpcPtyTransport', () => {
transport.disconnect()
})
it('runs title side effects even when the data callback does not render the chunk', async () => {
const { createIpcPtyTransport } = await import('./pty-transport')
const onTitleChange = vi.fn()
const onDataCallback = vi.fn()
const transport = createIpcPtyTransport({ onTitleChange })
await transport.connect({ url: '', callbacks: { onData: onDataCallback } })
onData?.({ id: 'pty-1', data: '\u001b]0;hidden-title\u0007' })
expect(onDataCallback).toHaveBeenCalledWith('\u001b]0;hidden-title\u0007')
expect(onTitleChange).not.toHaveBeenCalled()
await flushPtySideEffects()
expect(onTitleChange).toHaveBeenCalledWith('hidden-title', 'hidden-title')
transport.disconnect()
})
it('does not schedule PTY side-effect drains for ordinary output with no working title', async () => {
vi.useFakeTimers()
try {
@@ -171,7 +171,7 @@ export async function runHiddenRealPtyPressureScenario<
ackGate
)
if (pressureOutputMode === 'plain') {
if (pressureOutputMode === 'plain' || pressureOutputMode === 'title') {
expect(debug?.hiddenRendererSkipCount ?? 0).toBeGreaterThan(0)
expect(debug?.hiddenRendererSkippedChars ?? 0).toBeGreaterThan(0)
} else {
@@ -1,15 +1,17 @@
import { mkdirSync, writeFileSync } from 'node:fs'
import path from 'node:path'
export type HiddenPressureOutputMode = 'tui' | 'plain'
export type HiddenPressureOutputMode = 'tui' | 'plain' | 'title'
export function pressureOutputScript(runId: string, mode: HiddenPressureOutputMode): string {
const headerPrefix = mode === 'plain' ? '' : '\\x1b[0m'
const donePrefix = mode === 'plain' ? '' : '\\x1b[0m'
const headerPrefix = mode === 'tui' ? '\\x1b[0m' : ''
const donePrefix = mode === 'tui' ? '\\x1b[0m' : ''
const chunkExpression =
mode === 'plain'
? "'plain pressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\n'"
: "'\\x1b[?2026h\\x1b[1;1Hpressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\x1b[?2026l\\n'"
: mode === 'title'
? "'\\x1b]0;title pressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\x07'"
: "'\\x1b[?2026h\\x1b[1;1Hpressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\x1b[?2026l\\n'"
return `
const paneIndex = process.argv[2] ?? '0'
const targetChars = Number(process.argv[3] ?? '0')
@@ -21,6 +21,7 @@ import {
waitForTerminalOutput
} from './helpers/terminal'
import { runHiddenRealPtyPressureScenario } from './artificial-opencode-hidden-pressure-scenario'
import type { HiddenPressureOutputMode } from './artificial-opencode-hidden-pressure-script'
import { runMainPressureScenario } from './artificial-opencode-main-pressure-scenario'
import { startSyntheticOpenCodeInjection } from './artificial-opencode-synthetic-injection'
@@ -728,7 +729,7 @@ test.describe('Artificial OpenCode terminal load', () => {
testInfo: TestInfo,
hiddenPaneCount: number,
annotationSuffix?: string,
pressureOutputMode?: 'tui' | 'plain'
pressureOutputMode?: HiddenPressureOutputMode
): Promise<void> {
await runHiddenRealPtyPressureScenario({
orcaPage,
@@ -779,6 +780,19 @@ test.describe('Artificial OpenCode terminal load', () => {
'plain'
)
})
test('skips renderer writes for title-only hidden PTY output while preserving restore', async ({
orcaPage,
testRepoPath
}, testInfo) => {
await runConfiguredHiddenRealPtyPressureScenario(
orcaPage,
testRepoPath,
testInfo,
HIDDEN_PRESSURE_PANES,
'-title',
'title'
)
})
for (const paneCount of SCALE_HIDDEN_PRESSURE_PANES) {
test(`keeps hidden restore responsive with ${paneCount} ACK-backpressured real PTYs`, async ({
orcaPage,