refactor(tui): drop redundant native-mode guards

This commit is contained in:
Brooklyn Nicholson
2026-09-25 16:03:37 -05:00
committed by brooklyn!
parent 7e35460ac2
commit 87d1c5b0c3
4 changed files with 37 additions and 30 deletions

View File

@@ -1841,7 +1841,7 @@ def cmd_chat(args):
_launch_tui(
passthrough.pop("resume"),
tui_dev=getattr(args, "tui_dev", False),
native_mode=True if getattr(args, "tui_native", False) else None,
native_mode=getattr(args, "tui_native", False) or None,
model=getattr(args, "model", None),
accept_hooks=getattr(args, "accept_hooks", False),
**passthrough,

View File

@@ -91,7 +91,7 @@ function VirtualHarness({ items, scrollRef }: VirtualProps) {
<Box flexDirection="column" width="100%">
{virtual.topSpacer > 0 ? <Box height={virtual.topSpacer} /> : null}
{items.slice(virtual.start, virtual.end).map(item => (
<Box flexDirection="column" key={item.key} ref={virtual.measureRef(item.key)} minHeight={item.height}>
<Box flexDirection="column" key={item.key} minHeight={item.height} ref={virtual.measureRef(item.key)}>
<Text>{item.text}</Text>
</Box>
))}
@@ -108,6 +108,7 @@ async function runSample(mode: 'native' | 'virtual', itemCount: number): Promise
const scrollRef = { current: null as ScrollBoxHandle | null }
const items = makeItems(itemCount)
const renderHarness = (nextItems: readonly Item[]) =>
mode === 'native' ? (
<NativeHarness items={nextItems} />
@@ -117,23 +118,27 @@ async function runSample(mode: 'native' | 'virtual', itemCount: number): Promise
const heapBefore = process.memoryUsage?.().heapUsed ?? null
const mountStart = performance.now()
const instance = renderSync(renderHarness(items), {
patchConsole: false,
stderr: stderr as unknown as NodeJS.WriteStream,
stdin: stdin as unknown as NodeJS.ReadStream,
stdout: stdout as unknown as NodeJS.WriteStream
})
await settle()
const mountMs = performance.now() - mountStart
const rerenderItems = items.map((item, index) =>
index === items.length - 1 ? { ...item, text: `${item.text} rerender` } : item
)
const rerenderStart = performance.now()
instance.rerender(renderHarness(rerenderItems))
await settle()
const rerenderMs = performance.now() - rerenderStart
const heapAfter = process.memoryUsage?.().heapUsed ?? null
const sample = {
heapDeltaBytes: heapBefore === null || heapAfter === null ? null : heapAfter - heapBefore,
mountMs,
@@ -147,13 +152,16 @@ async function runSample(mode: 'native' | 'virtual', itemCount: number): Promise
stdin.destroy()
stdout.destroy()
stderr.destroy()
return sample
}
function distribution(values: number[]) {
const sorted = [...values].sort((a, b) => a - b)
const percentile = (p: number) =>
sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * p) - 1))] ?? 0
return {
max: sorted.at(-1) ?? 0,
mean: sorted.reduce((sum, value) => sum + value, 0) / Math.max(1, sorted.length),
@@ -168,7 +176,9 @@ function numericArg(name: string, fallback: number) {
.slice(2)
.find(arg => arg.startsWith(`--${name}=`))
?.split('=', 2)[1]
const parsed = Number(raw)
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : fallback
}
@@ -177,11 +187,16 @@ function workloadsArg() {
.slice(2)
.find(arg => arg.startsWith('--items='))
?.split('=', 2)[1]
if (!raw) return DEFAULT_WORKLOADS
if (!raw) {
return DEFAULT_WORKLOADS
}
const parsed = raw.split(',').map(Number)
if (parsed.some(value => !Number.isSafeInteger(value) || value <= 0)) {
throw new Error(`invalid --items workload list: ${raw}`)
}
return parsed
}
@@ -209,6 +224,7 @@ async function main() {
const virtual: Sample[] = []
const native: Sample[] = []
for (let sample = 0; sample < sampleCount; sample++) {
virtual.push(await runSample('virtual', itemCount))
native.push(await runSample('native', itemCount))

View File

@@ -181,14 +181,18 @@ const TranscriptPane = memo(function TranscriptPane({
[transcript.historyItems]
)
const clearBlankSelection = (e: { cellIsBlank?: boolean }) => {
if (e.cellIsBlank) {
actions.clearSelection()
}
}
const transcriptContent = (
<Box flexDirection="column" paddingX={1}>
{!nativeMode && transcript.virtualHistory.topSpacer > 0 ? (
<Box height={transcript.virtualHistory.topSpacer} />
) : null}
{transcript.virtualHistory.topSpacer > 0 ? <Box height={transcript.virtualHistory.topSpacer} /> : null}
{transcript.virtualRows
.slice(nativeMode ? 0 : transcript.virtualHistory.start, nativeMode ? undefined : transcript.virtualHistory.end)
.slice(transcript.virtualHistory.start, transcript.virtualHistory.end)
.map(row => (
<Box flexDirection="column" key={row.key} ref={transcript.virtualHistory.measureRef(row.key)}>
{row.msg.role === 'user' && firstUserIdx >= 0 && row.index > firstUserIdx && (
@@ -236,9 +240,7 @@ const TranscriptPane = memo(function TranscriptPane({
</Box>
))}
{!nativeMode && transcript.virtualHistory.bottomSpacer > 0 ? (
<Box height={transcript.virtualHistory.bottomSpacer} />
) : null}
{transcript.virtualHistory.bottomSpacer > 0 ? <Box height={transcript.virtualHistory.bottomSpacer} /> : null}
<StreamingAssistant
cols={bodyCols}
@@ -258,15 +260,7 @@ const TranscriptPane = memo(function TranscriptPane({
return (
<>
{nativeMode ? (
<Box
flexDirection="column"
flexGrow={1}
onClick={(e: { cellIsBlank?: boolean }) => {
if (e.cellIsBlank) {
actions.clearSelection()
}
}}
>
<Box flexDirection="column" flexGrow={1} onClick={clearBlankSelection}>
{transcriptContent}
</Box>
) : (
@@ -274,11 +268,7 @@ const TranscriptPane = memo(function TranscriptPane({
flexDirection="column"
flexGrow={1}
flexShrink={1}
onClick={(e: { cellIsBlank?: boolean }) => {
if (e.cellIsBlank) {
actions.clearSelection()
}
}}
onClick={clearBlankSelection}
ref={transcript.scrollRef}
stickyScroll
>
@@ -421,10 +411,10 @@ const ComposerPane = memo(function ComposerPane({
<Box
flexDirection="column"
marginTop={nativeMode ? 0 : ui.statusBar === 'top' ? 0 : 1}
marginTop={nativeMode || ui.statusBar === 'top' ? 0 : 1}
position={nativeMode ? undefined : 'relative'}
>
{!nativeMode && <FloatingOverlays {...floatingOverlayProps} nativeMode={false} />}
{!nativeMode && <FloatingOverlays {...floatingOverlayProps} />}
{!nativeMode && composer.input === '?' && !composer.inputBuf.length && <HelpHint t={ui.theme} />}

View File

@@ -21,6 +21,11 @@ export const TERMINAL_MODE_RESET =
'\x1b[0m' + // attributes
'\x1b[?25h' // cursor visible
type ResettableStream = Pick<NodeJS.WriteStream, 'isTTY' | 'write'> & {
fd?: number
}
/** Native mode leaves its frame in the primary buffer; wipe it on exit so the shell prompt starts clean. */
export function clearNativeTuiFrame(stream: ResettableStream = process.stdout): boolean {
if (!stream.isTTY) {
return false
@@ -34,10 +39,6 @@ export function clearNativeTuiFrame(stream: ResettableStream = process.stdout):
}
}
type ResettableStream = Pick<NodeJS.WriteStream, 'isTTY' | 'write'> & {
fd?: number
}
// OSC 10/11 set the terminal's DEFAULT foreground/background — so every cell,
// including text rendered with no explicit color (markdown body, borders,
// third-party output), takes the skin instead of the host profile's defaults.