fix(pty): wait for zsh line-init before startup

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo-H
2026-07-14 22:39:19 -04:00
co-authored by Orca
parent 42ee45f392
commit ff3337ff10
2 changed files with 22 additions and 15 deletions
+16 -10
View File
@@ -378,16 +378,21 @@ describePosix('daemon shell-ready launch config', () => {
)
itWithZsh(
'still runs user add-zle-hook-widget line-init hooks after the marker',
'waits for user add-zle-hook-widget line-init hooks before emitting the marker',
async () => {
const { getShellReadyLaunchConfig } = await importFreshShellReady()
const config = getShellReadyLaunchConfig('/bin/zsh')
const tempHome = mkdtempSync(join(tmpdir(), 'orca-zsh-azhw-'))
const userHookOutput = 'ORCA-TEST-USER-HOOK'
const userHookStarted = 'ORCA-TEST-USER-HOOK-STARTED'
const userHookFinished = 'ORCA-TEST-USER-HOOK-FINISHED'
writeFileSync(
join(tempHome, '.zshrc'),
[
`__orca_test_line_init_hook() { printf "${userHookOutput}" }`,
'__orca_test_line_init_hook() {',
` printf "${userHookStarted}"`,
' sleep 0.1',
` printf "${userHookFinished}"`,
'}',
'autoload -Uz add-zle-hook-widget',
'zle -N __orca_test_line_init_hook',
'add-zle-hook-widget line-init __orca_test_line_init_hook',
@@ -399,14 +404,15 @@ describePosix('daemon shell-ready launch config', () => {
tempHome,
wrapperZdotdir: config.env.ZDOTDIR,
isDone: (current) =>
current.includes(SHELL_READY_MARKER_OUTPUT) && current.includes(userHookOutput)
current.includes(SHELL_READY_MARKER_OUTPUT) && current.includes(userHookFinished)
})
// Why: the marker widget chains to the previously installed widget, so
// an azhw dispatcher registered by user config must keep dispatching.
// a slow azhw dispatcher must finish before Orca can safely type input.
expect(output).toContain(SHELL_READY_MARKER_OUTPUT)
expect(output).toContain(userHookOutput)
expect(output.indexOf(SHELL_READY_MARKER_OUTPUT)).toBeLessThan(
output.indexOf(userHookOutput)
expect(output).toContain(userHookStarted)
expect(output).toContain(userHookFinished)
expect(output.indexOf(userHookFinished)).toBeLessThan(
output.indexOf(SHELL_READY_MARKER_OUTPUT)
)
} finally {
rmSync(tempHome, { recursive: true, force: true })
@@ -445,8 +451,8 @@ describePosix('daemon shell-ready launch config', () => {
})
expect(output).toContain(SHELL_READY_MARKER_OUTPUT)
expect(output).toContain(userHookOutput)
expect(output.indexOf(SHELL_READY_MARKER_OUTPUT)).toBeLessThan(
output.indexOf(userHookOutput)
expect(output.indexOf(userHookOutput)).toBeLessThan(
output.indexOf(SHELL_READY_MARKER_OUTPUT)
)
// Why: idempotent — the marker must fire exactly once per prompt, not
// duplicated by the second registration.
+6 -5
View File
@@ -130,8 +130,8 @@ fi
// when an earlier hook exits non-zero, and a pre-existing raw user widget
// (e.g. oh-my-zsh vi-mode without VI_MODE_SET_CURSOR) is preserved as the
// first hook and fails — silently suppressing the marker and stalling every
// startup command on the pre-ready timeout. Instead, own zle-line-init: emit
// the marker first, then chain to whatever widget was installed before.
// startup command on the pre-ready timeout. Instead, own zle-line-init, run
// the prior widget ourselves, then emit the marker even if that widget fails.
export function getZshShellReadyMarkerRegistrationBlock(escapedMarker: string): string {
return `if [[ "\${ORCA_SHELL_READY_MARKER:-0}" == "1" ]]; then
# Why: capture the prior zle-line-init so the marker chains to it. On a
@@ -148,12 +148,13 @@ export function getZshShellReadyMarkerRegistrationBlock(escapedMarker: string):
__orca_prev_line_init_fn=""
fi
__orca_prompt_mark() {
printf "${escapedMarker}"
# Why: call the prior hook as a plain function, not an aliased widget, so
# $WIDGET stays zle-line-init for add-zle-hook-widget dispatchers.
# $WIDGET stays zle-line-init for add-zle-hook-widget dispatchers. Readiness
# comes afterward because a slow hook means zle cannot accept input yet.
if [[ -n "\${__orca_prev_line_init_fn:-}" ]]; then
"\${__orca_prev_line_init_fn}" "$@"
"\${__orca_prev_line_init_fn}" "$@" || true
fi
printf "${escapedMarker}"
}
zle -N zle-line-init __orca_prompt_mark
fi