Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
parent
b6c0cb4f62
commit
5ac7119c13
|
|
@ -95,6 +95,7 @@ import { isPrimarySelectionEnabled, readPrimarySelectionText } from '@/lib/prima
|
|||
import { APP_MENU_PASTE_EVENT } from '@/lib/app-menu-paste'
|
||||
import { WORKSPACE_FILE_PATH_MIME, WORKSPACE_FILE_PATHS_MIME } from '@/lib/workspace-file-drag'
|
||||
import { isTerminalSessionStateSaveFailure } from '../../../../shared/terminal-session-state-save-failure'
|
||||
import { isTerminalZeroDimensionsDiagnostic } from '../../../../shared/terminal-zero-dimensions-diagnostic'
|
||||
import {
|
||||
isSyntheticSinglePaneTitle,
|
||||
sanitizeTerminalLayoutPaneTitles
|
||||
|
|
@ -612,6 +613,12 @@ export default function TerminalPane({
|
|||
// after first visibility lets inactive agent tabs refit and SIGWINCH.
|
||||
setShouldMeasureHiddenStartup(false)
|
||||
}
|
||||
if (isVisible) {
|
||||
// Why: a hidden pane that connected at 0×0 self-heals via the pane resize
|
||||
// observer once shown, so clear that stale diagnostic. Scoped to the
|
||||
// zero-dimensions message so genuine paste/save-failure errors survive.
|
||||
setTerminalError((prev) => (prev && isTerminalZeroDimensionsDiagnostic(prev) ? null : prev))
|
||||
}
|
||||
}, [isVisible, shouldMeasureHiddenStartup])
|
||||
|
||||
const clearSessionRestoredBannerForPane = useCallback((paneId: number): void => {
|
||||
|
|
|
|||
|
|
@ -667,6 +667,42 @@ describe('connectPanePty', () => {
|
|||
logSpy.mockRestore()
|
||||
}, 30_000)
|
||||
|
||||
// Why: orchestration workers and CLI `terminal create` (no --focus) mount
|
||||
// hidden panes that legitimately connect at 0×0 and refit when shown, so the
|
||||
// zero-dimensions diagnostic must stay silent while the pane is not visible.
|
||||
it('does not surface the zero-dimensions diagnostic for a hidden pane', async () => {
|
||||
const { connectPanePty } = await import('./pty-connection')
|
||||
const transport = createMockTransport()
|
||||
transportFactoryQueue.push(transport)
|
||||
const pane = createPane(1)
|
||||
pane.terminal.cols = 0
|
||||
pane.terminal.rows = 0
|
||||
const deps = createDeps({ isVisibleRef: { current: false } })
|
||||
|
||||
connectPanePty(pane as never, createManager(1) as never, deps as never)
|
||||
await flushAsyncTicks()
|
||||
|
||||
expect(deps.onPtyErrorRef.current).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('still surfaces the zero-dimensions diagnostic for a visible pane', async () => {
|
||||
const { connectPanePty } = await import('./pty-connection')
|
||||
const transport = createMockTransport()
|
||||
transportFactoryQueue.push(transport)
|
||||
const pane = createPane(1)
|
||||
pane.terminal.cols = 0
|
||||
pane.terminal.rows = 0
|
||||
const deps = createDeps({ isVisibleRef: { current: true } })
|
||||
|
||||
connectPanePty(pane as never, createManager(1) as never, deps as never)
|
||||
await flushAsyncTicks()
|
||||
|
||||
expect(deps.onPtyErrorRef.current).toHaveBeenCalledWith(
|
||||
pane.id,
|
||||
expect.stringContaining('Terminal has zero dimensions (0×0)')
|
||||
)
|
||||
})
|
||||
|
||||
it('threads the resolved local project runtime into IPC terminal transport options', async () => {
|
||||
const { connectPanePty } = await import('./pty-connection')
|
||||
const transport = createMockTransport()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { scheduleRuntimeGraphSync } from '@/runtime/sync-runtime-graph'
|
|||
import { useAppStore } from '@/store'
|
||||
import { getWorktreeMapFromState } from '@/store/selectors'
|
||||
import { parseWorkspaceKey } from '../../../../shared/workspace-scope'
|
||||
import { createTerminalZeroDimensionsMessage } from '../../../../shared/terminal-zero-dimensions-diagnostic'
|
||||
import type { PtyBufferSnapshot, PtyConnectResult } from './pty-transport'
|
||||
import { createIpcPtyTransport } from './pty-transport'
|
||||
import { createRemoteRuntimePtyTransport } from './remote-runtime-pty-transport'
|
||||
|
|
@ -2203,11 +2204,12 @@ export function connectPanePty(
|
|||
// Why: if fitAddon resolved to 0×0, the container likely has no layout
|
||||
// dimensions (display:none, unmounted, or zero-size parent). Surface a
|
||||
// diagnostic so the user sees something instead of a blank pane.
|
||||
if (cols === 0 || rows === 0) {
|
||||
deps.onPtyErrorRef?.current?.(
|
||||
pane.id,
|
||||
`Terminal has zero dimensions (${cols}×${rows}). The pane container may not be visible.`
|
||||
)
|
||||
// Gate on visibility: background/hidden tabs (orchestration workers, CLI
|
||||
// `terminal create` without --focus) legitimately connect at 0×0 because
|
||||
// safeFit skips fitting unmeasurable panes; they refit via the pane resize
|
||||
// observer once shown, so the diagnostic must not fire while hidden.
|
||||
if ((cols === 0 || rows === 0) && deps.isVisibleRef.current) {
|
||||
deps.onPtyErrorRef?.current?.(pane.id, createTerminalZeroDimensionsMessage(cols, rows))
|
||||
}
|
||||
|
||||
const reportError = (message: string): void => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
createTerminalZeroDimensionsMessage,
|
||||
isTerminalZeroDimensionsDiagnostic
|
||||
} from './terminal-zero-dimensions-diagnostic'
|
||||
|
||||
describe('terminal zero-dimensions diagnostic', () => {
|
||||
it('round-trips its own message through the matcher', () => {
|
||||
expect(isTerminalZeroDimensionsDiagnostic(createTerminalZeroDimensionsMessage(0, 0))).toBe(true)
|
||||
})
|
||||
|
||||
it('does not match unrelated terminal errors', () => {
|
||||
expect(isTerminalZeroDimensionsDiagnostic('Paste failed.')).toBe(false)
|
||||
expect(isTerminalZeroDimensionsDiagnostic('Failed to save terminal session state')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Why: the zero-dimensions diagnostic is emitted by the renderer's PTY connect
|
||||
// path and later cleared once a hidden pane becomes visible and refits. Keeping
|
||||
// the message text and its matcher together lets both sites stay in sync.
|
||||
|
||||
export function createTerminalZeroDimensionsMessage(cols: number, rows: number): string {
|
||||
return `Terminal has zero dimensions (${cols}×${rows}). The pane container may not be visible.`
|
||||
}
|
||||
|
||||
export function isTerminalZeroDimensionsDiagnostic(message: string): boolean {
|
||||
return message.startsWith('Terminal has zero dimensions (')
|
||||
}
|
||||
Loading…
Reference in New Issue