Fix terminal shell integration and DEBUG trap chaining in bash

Chain external DEBUG traps (e.g., starship, bash-preexec) dynamically
in a prompt epilogue rather than using static hooks. This ensures our
own DEBUG trap survives re-arming by third-party frameworks and reliably
emits OSC 133 sequences.

Additionally:
- Print the shell-ready marker inside the precmd hook to avoid modifying
  and displacing hooks at the end of PROMPT_COMMAND.
- Skip redundant foreground state checks in the PTY connection when a
  shell prompt is already active and no background agent is expected.
This commit is contained in:
Jinjing
2026-07-05 22:05:06 -07:00
parent 5c9247c658
commit fe5cd52fc7
+33
View File
@@ -589,6 +589,39 @@ describePosix('daemon shell-ready launch config', () => {
}
)
itWithBash(
'dispatches bash-preexec callbacks against the real command, not Orca hooks',
async () => {
const { getDaemonBashShellReadyRcfileContent } = await importFreshShellReady()
// Why: Orca's epilogue captures bash-preexec's re-armed DEBUG trap and
// chains it. A non-empty preexec_functions must still see the user's real
// command as $BASH_COMMAND — not __orca_osc133_epilogue or a __bp_* helper.
writeFileSync(
join(userDataPath, '.bash_profile'),
[
'preexec_functions=(__user_preexec)',
'__user_preexec() { printf \'USER_PREEXEC:%s\\n\' "$1"; }',
'__bp_preexec_invoke_exec() {',
' [[ -n "${__bp_interactive_mode:-}" ]] || return',
' __bp_interactive_mode=""',
' local f',
' for f in "${preexec_functions[@]}"; do "$f" "$BASH_COMMAND"; done',
'}',
"__bp_arm() { __bp_interactive_mode=1; trap '__bp_preexec_invoke_exec' DEBUG; }",
'PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND;}__bp_arm"'
].join('\n')
)
const output = runInteractiveBashRcfile(getDaemonBashShellReadyRcfileContent(), userDataPath)
expectBashOsc133Lifecycle(output)
expect(output).toContain('USER_PREEXEC:true')
expect(output).toContain('USER_PREEXEC:false')
expect(output).not.toContain('USER_PREEXEC:__orca_osc133')
expect(output).not.toContain('USER_PREEXEC:__bp_')
}
)
itWithBash('normalizes array PROMPT_COMMAND hooks so bash 3.2 still runs cleanup', async () => {
const { getDaemonBashShellReadyRcfileContent } = await importFreshShellReady()
writeFileSync(