Use bundled ConPTY for LocalPtyProvider spawns on Windows

The daemon spawn path already passes useConptyDll: true (bundled modern
ConPTY); LocalPtyProvider spawns - degraded mode and fresh-local routing -
silently ran on the legacy system ConPTY, which the daemon path's own
comment blames for full-width TUI scrollback corruption.
This commit is contained in:
Jinwoo Hong
2026-07-02 15:28:20 -04:00
parent 8a5c1625f9
commit c2222b447b
2 changed files with 20 additions and 4 deletions
@@ -76,13 +76,13 @@ describe('spawnShellWithFallback on Windows', () => {
1,
PWSH7,
attempts[0].shellArgs,
expect.objectContaining({ cwd: 'C:\\repo' })
expect.objectContaining({ cwd: 'C:\\repo', useConptyDll: true })
)
expect(ptySpawn).toHaveBeenNthCalledWith(
2,
WINDOWS_POWERSHELL,
attempts[1].shellArgs,
expect.objectContaining({ cwd: 'C:\\repo' })
expect.objectContaining({ cwd: 'C:\\repo', useConptyDll: true })
)
})
+18 -2
View File
@@ -160,6 +160,14 @@ export type ShellSpawnResult = {
* executables with per-shell args, so when the primary fails we retry with the
* next safe shell instead of leaving the user with no terminal.
*/
// Why: match the daemon spawn path (pty-subprocess.ts) — the bundled ConPTY
// has the modern wrap-marker behavior xterm expects; legacy system ConPTY can
// corrupt full-width TUI rows in scrollback. Without this, degraded-mode and
// fresh-local spawns silently behave differently from daemon terminals.
function windowsConptyDllOptions(): { useConptyDll: true } | Record<string, never> {
return process.platform === 'win32' ? { useConptyDll: true } : {}
}
function spawnWindowsFallbackChain(
params: ShellSpawnParams,
primaryError: string
@@ -174,7 +182,8 @@ function spawnWindowsFallbackChain(
cols,
rows,
cwd: attempt.effectiveCwd,
env
env,
...windowsConptyDllOptions()
})
console.warn(
`[pty] Primary shell "${params.shellPath}" failed (${primaryError}), fell back to "${attempt.shellPath}"`
@@ -217,7 +226,14 @@ export function spawnShellWithFallback(params: ShellSpawnParams): ShellSpawnResu
if (!primaryError) {
try {
return {
process: ptySpawn(shellPath, shellArgs, { name: termName, cols, rows, cwd, env }),
process: ptySpawn(shellPath, shellArgs, {
name: termName,
cols,
rows,
cwd,
env,
...windowsConptyDllOptions()
}),
shellPath
}
} catch (err) {