mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 00:03:20 +00:00
fix(pty): wait for zsh line-init before startup
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user