diff --git a/src/main/shell-wrapper-generated-file-snapshot.test.ts b/src/main/shell-wrapper-generated-file-snapshot.test.ts new file mode 100644 index 00000000000..a8e7eb2d20f --- /dev/null +++ b/src/main/shell-wrapper-generated-file-snapshot.test.ts @@ -0,0 +1,89 @@ +/** + * Byte-for-byte snapshots of every shell wrapper file Orca generates, for all + * three transports (local PTY, daemon/SSH, relay overlay). + * + * Why: the zsh generators were unified behind one builder; these fixtures were + * captured from the pre-unification code so any drift shows up as a diff. + */ +import { mkdtempSync, readFileSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { ensureShellReadyWrappersAt } from './providers/local-pty-shell-ready-wrapper-generation' +import { getShellReadyLaunchConfig as getDaemonShellReadyLaunchConfig } from './daemon/shell-ready' +import { ensureOverlayRestoreWrappers } from '../relay/pty-shell-overlay-wrappers' +import { getShellReadyLaunchConfig as getLocalShellReadyLaunchConfig } from './providers/local-pty-shell-ready' + +const WRAPPER_FILES = [ + ['zsh-zshenv', join('zsh', '.zshenv')], + ['zsh-zprofile', join('zsh', '.zprofile')], + ['zsh-zshrc', join('zsh', '.zshrc')], + ['zsh-zlogin', join('zsh', '.zlogin')], + ['bash-rcfile', join('bash', 'rcfile')] +] as const + +const SNAPSHOT_DIR = join(__dirname, 'shell-wrapper-snapshots') + +// Why: the wrapper root is a temp dir per run, and the baked ZDOTDIR literal is +// the only path-dependent byte in the output; pin it to a stable placeholder. +function withStableRoot(content: string, root: string): string { + return content.split(root).join('') +} + +function snapshotPath(transport: string, label: string): string { + return join(SNAPSHOT_DIR, `${transport}-${label}.txt`) +} + +async function expectWrapperFiles(transport: string, root: string): Promise { + for (const [label, relativePath] of WRAPPER_FILES) { + const content = readFileSync(join(root, relativePath), 'utf8') + await expect(withStableRoot(content, root)).toMatchFileSnapshot(snapshotPath(transport, label)) + } +} + +// Why: all three generators are POSIX-only (the launch configs skip wrapping on +// win32), and native Windows path separators would make the fixtures unstable. +const describePosix = process.platform === 'win32' ? describe.skip : describe + +describePosix('generated shell wrapper files', () => { + let root = '' + let previousUserDataPath: string | undefined + + beforeEach(() => { + root = mkdtempSync(join(tmpdir(), 'orca-wrapper-snapshot-')) + previousUserDataPath = process.env.ORCA_USER_DATA_PATH + }) + + afterEach(() => { + if (previousUserDataPath === undefined) { + delete process.env.ORCA_USER_DATA_PATH + } else { + process.env.ORCA_USER_DATA_PATH = previousUserDataPath + } + rmSync(root, { recursive: true, force: true }) + }) + + it('local PTY wrappers', async () => { + ensureShellReadyWrappersAt(root) + await expectWrapperFiles('local', root) + }) + + it('daemon wrappers', async () => { + process.env.ORCA_USER_DATA_PATH = root + getDaemonShellReadyLaunchConfig('/bin/zsh') + await expectWrapperFiles('daemon', join(root, 'shell-ready')) + }) + + it('relay overlay wrappers', async () => { + ensureOverlayRestoreWrappers(root) + await expectWrapperFiles('relay', root) + }) + + it('fish shell-ready init commands', async () => { + process.env.ORCA_USER_DATA_PATH = root + const local = getLocalShellReadyLaunchConfig('/usr/bin/fish') + const daemon = getDaemonShellReadyLaunchConfig('/usr/bin/fish') + await expect(local.args?.[2]).toMatchFileSnapshot(snapshotPath('local', 'fish-init')) + await expect(daemon.args?.[2]).toMatchFileSnapshot(snapshotPath('daemon', 'fish-init')) + }) +}) diff --git a/src/main/shell-wrapper-snapshots/daemon-bash-rcfile.txt b/src/main/shell-wrapper-snapshots/daemon-bash-rcfile.txt new file mode 100644 index 00000000000..c55bde22b68 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/daemon-bash-rcfile.txt @@ -0,0 +1,345 @@ +# Orca daemon bash shell-ready wrapper +if [[ "${ORCA_SHELL_STARTUP_IDENTITY:-0}" == "1" ]]; then + unset ORCA_SHELL_STARTUP_IDENTITY + printf "\033]777;orca-shell-start:%s\007" "$$" +fi +[[ -f /etc/profile ]] && source /etc/profile +if [[ -f "$HOME/.bash_profile" ]]; then + source "$HOME/.bash_profile" +elif [[ -f "$HOME/.bash_login" ]]; then + source "$HOME/.bash_login" +elif [[ -f "$HOME/.profile" ]]; then + source "$HOME/.profile" +fi +# Why: enable bracketed paste so Orca can deliver a multiline startup prompt as +# a single literal paste (ESC[200~…ESC[201~); without it, older readline builds +# treat each embedded newline as Enter and mangle the prompt into PS2 +# continuation. Modern readline defaults this on; force it for the rest. +[[ $- == *i* ]] && bind 'set enable-bracketed-paste on' 2>/dev/null +__orca_restore_agent_teams_path() { + [[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0 + case "$PATH" in + "${ORCA_AGENT_TEAMS_SHIM_DIR}"|"${ORCA_AGENT_TEAMS_SHIM_DIR}:"*) return 0 ;; + esac + export PATH="${ORCA_AGENT_TEAMS_SHIM_DIR}:$PATH" +} +__orca_restore_agent_teams_path +# Why: user startup files may set the default OpenCode config after Orca's +# spawn env; restore the Orca-managed config dir before the first prompt. +[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" +# Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +# Why: Codex must keep using Orca's runtime CODEX_HOME after profile scripts. +[[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}" +# Why: a typed alias expands inside the shell, after pane launch prep. +__orca_codex_binary="$(command -v codex 2>/dev/null || :)" +if [[ -n "${ORCA_CODEX_LAUNCH_PREFLIGHT:-}" && -n "${__orca_codex_binary:-}" && -x "${__orca_codex_binary}" ]]; then + codex() { + "${ORCA_CODEX_LAUNCH_PREFLIGHT}" agent hooks prepare-codex >/dev/null 2>&1 || : + command codex "$@" + } +fi +unset __orca_codex_binary + +# Why: emit OSC 133 C/D so terminal-command-lifecycle can drop stale agent +# status when the foreground command exits — mirrors the zsh daemon wrapper. +# Without this, bash users (default on most Linux distros) keep a stuck +# 'working' spinner after the CLI exits without a Stop/SessionEnd hook. +__orca_initializing_wrapper=1 +__orca_osc133_precmd() { + local exit_code=$? + __orca_in_prompt_command=1 + if [[ -n "${__orca_in_command:-}" ]]; then + printf "\033]133;D;%s\007" "$exit_code" + unset __orca_in_command + fi + printf "\033]133;A\007" + # Why: emit the shell-ready marker here (not a trailing PROMPT_COMMAND entry) + # so a framework that must be last in PROMPT_COMMAND — bash-preexec — is not + # displaced by one of Orca's own hooks. + [[ "${ORCA_SHELL_READY_MARKER:-0}" == "1" ]] && printf "\033]777;orca-shell-ready\007" + return "$exit_code" +} +__orca_osc133_preexec() { + if [[ -n "${__orca_prompt_status_capture_command:-}" && "$BASH_COMMAND" == "$__orca_prompt_status_capture_command" ]]; then + unset __orca_initial_prompt + __orca_in_legacy_prompt_wrapper=1 + return 0 + fi + if [[ -n "${__orca_initializing_wrapper:-}${__orca_in_debug_capture:-}${__orca_initial_prompt:-}${__orca_in_prompt_dispatch:-}${__orca_in_legacy_prompt_wrapper:-}${__orca_in_prompt_command:-}" ]]; then + [[ -z "${__orca_initializing_wrapper:-}${__orca_in_debug_capture:-}" ]] || return 0 + if [[ -n "${__orca_initial_prompt:-}" && "$BASH_COMMAND" == "__orca_osc133_precmd" ]]; then + unset __orca_initial_prompt; return 0 + fi + if [[ -n "${__orca_in_prompt_dispatch:-}" ]]; then + [[ -n "${__orca_dispatching_user_prompt_command:-}" ]] || return 0 + if [[ "${FUNCNAME[1]:-}" == "__orca_run_prompt_command_array" ]]; then + case "$BASH_COMMAND" in + '(( __orca_exit_code == 0 ))'|'__orca_restore_prompt_status "$__orca_exit_code"'|'eval "$__orca_prompt_part"'|'eval "$__orca_final_prompt_command"'|__orca_dispatching_user_prompt_command=*|__orca_osc133_precmd|__orca_osc133_epilogue) return 0 ;; + esac + fi + elif [[ "${FUNCNAME[1]:-}" == "__orca_run_prompt_command_array" || "$BASH_COMMAND" == "__orca_run_prompt_command_array" ]]; then + return 0 + fi + [[ -z "${__orca_in_legacy_prompt_wrapper:-}" || -n "${__orca_dispatching_user_prompt_command:-}" ]] || return 0 + if [[ -n "${__orca_in_prompt_command:-}" && "$BASH_COMMAND" == "__orca_in_debug_capture=1" ]]; then + return 0 + fi + fi + case "${FUNCNAME[1]:-}" in + __orca_osc133_*|__orca_restore_prompt_status|__bp_*) return 0 ;; + esac + case "$BASH_COMMAND" in + __orca_osc133_precmd|__orca_osc133_epilogue) return 0 ;; + # The prefix is only special while bash-preexec prompt hooks run. + __bp_*) [[ -n "${__orca_in_prompt_command:-}" ]] && return 0 ;; + esac + __orca_run_user_debug_trap + # Why: a framework (bash-preexec/starship) may replace our DEBUG trap at the + # first prompt; __orca_osc133_epilogue re-takes it each prompt and stores the + # framework's trap here, so the framework's own preexec still runs while our + # command-start C survives its re-arm. + if [[ -n "${__orca_chained_debug_trap:-}" ]]; then + eval "$__orca_chained_debug_trap" || true + fi + [[ -z "${__orca_in_prompt_command:-}" ]] || return 0 + # Why: a chained trap can invoke us more than once for a single command, so + # emit C only on the first fire (the __orca_in_command gate), and never for a + # prompt-time hook — ours or bash-preexec's __bp_* helpers. + [[ -z "${__orca_in_command:-}" ]] || return 0 + printf "\033]133;C\007" + __orca_in_command=1 +} +# Why: adopt the latest user trap before Orca retakes lifecycle ownership. +__orca_osc133_epilogue() { + unset __orca_in_prompt_command + __orca_adopt_outer_debug_trap + trap '__orca_osc133_preexec' DEBUG +} +__orca_normalize_prompt_command_part() { + local __orca_value="$1" __orca_output_name="$2" __orca_character __orca_chunk + local __orca_value_length=${#1} __orca_suffix_length=0 __orca_backslash_length=0 + local __orca_output_length __orca_scan_start + while (( __orca_value_length - __orca_suffix_length >= 1024 )); do + __orca_scan_start=$(( __orca_value_length - __orca_suffix_length - 1024 )) + __orca_chunk="${__orca_value:__orca_scan_start:1024}" + case "$__orca_chunk" in + *[!$' \t\n;']*) break ;; + *) __orca_suffix_length=$(( __orca_suffix_length + 1024 )) ;; + esac + done + while (( __orca_suffix_length < __orca_value_length )); do + __orca_character="${__orca_value: -__orca_suffix_length - 1:1}" + case "$__orca_character" in + ' '|$'\t'|$'\n'|';') __orca_suffix_length=$(( __orca_suffix_length + 1 )) ;; + *) break ;; + esac + done + __orca_output_length=$(( ${#__orca_value} - __orca_suffix_length )) + while (( __orca_output_length - __orca_backslash_length >= 1024 )); do + __orca_scan_start=$(( __orca_output_length - __orca_backslash_length - 1024 )) + __orca_chunk="${__orca_value:__orca_scan_start:1024}" + case "$__orca_chunk" in + *[!\\]*) break ;; + *) __orca_backslash_length=$(( __orca_backslash_length + 1024 )) ;; + esac + done + while (( __orca_backslash_length < __orca_output_length )); do + __orca_character="${__orca_value:__orca_output_length - __orca_backslash_length - 1:1}" + [[ "$__orca_character" == '\' ]] || break + __orca_backslash_length=$(( __orca_backslash_length + 1 )) + done + # Preserve the first separator when an odd backslash run escapes it. + if (( __orca_suffix_length > 0 && __orca_backslash_length % 2 == 1 )); then + __orca_suffix_length=$(( __orca_suffix_length - 1 )) + __orca_backslash_length=0 + fi + __orca_output_length=$(( ${#__orca_value} - __orca_suffix_length )) + __orca_value="${__orca_value:0:__orca_output_length}" + # Bash 4.4-5.0 scalar prompt evaluation preserves an odd terminal backslash. + if (( __orca_suffix_length == 0 && ((BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4) || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] == 0)) && __orca_backslash_length % 2 == 1 )); then + __orca_value="$__orca_value\\" + fi + printf -v "$__orca_output_name" '%s' "$__orca_value" +} +__orca_restore_prompt_status() { + return "$1" +} +__orca_update_user_debug_trap() { + local __orca_debug_trap_spec="$1" __orca_unchanged_debug_trap_spec="$2" + local __orca_debug_trap_command + [[ "$__orca_debug_trap_spec" != "$__orca_unchanged_debug_trap_spec" ]] || return 0 + [[ "$__orca_debug_trap_spec" != "trap -- '__orca_osc133_preexec' DEBUG" ]] || return 0 + if [[ -z "$__orca_debug_trap_spec" ]]; then + __orca_user_debug_trap="" + unset __orca_chained_debug_trap + return 0 + fi + __orca_debug_trap_command="${__orca_debug_trap_spec#trap -- }" + __orca_debug_trap_command="${__orca_debug_trap_command% DEBUG}" + eval "__orca_user_debug_trap=$__orca_debug_trap_command" + unset __orca_chained_debug_trap +} +__orca_run_user_debug_trap() { + if [[ -n "${__orca_user_debug_trap:-}" ]]; then + eval "$__orca_user_debug_trap" || true + fi +} +__orca_adopt_outer_debug_trap() { + local __orca_debug_trap_spec="${__orca_outer_debug_trap_spec:-}" + unset __orca_outer_debug_trap_spec + __orca_update_user_debug_trap "$__orca_debug_trap_spec" "trap -- '__orca_osc133_preexec' DEBUG" +} +__orca_run_prompt_command_array() { + local __orca_exit_code="${__orca_prompt_status:-$?}" __orca_prompt_part __orca_prompt_index __orca_user_count + local __orca_suffix_part + local __orca_final_prompt_command + local __orca_in_prompt_dispatch=1 __orca_dispatching_user_prompt_command="" + unset __orca_prompt_status + __orca_adopt_outer_debug_trap + trap '__orca_osc133_preexec' DEBUG + for __orca_prompt_part in "${__orca_prompt_command_prefix[@]+"${__orca_prompt_command_prefix[@]}"}"; do + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + done + __orca_user_count=0 + for __orca_prompt_part in "${__orca_prompt_command_array[@]+"${__orca_prompt_command_array[@]}"}"; do + __orca_user_count=$(( __orca_user_count + 1 )) + done + for (( __orca_prompt_index = 0; __orca_prompt_index + 1 < __orca_user_count; __orca_prompt_index++ )); do + __orca_prompt_part="${__orca_prompt_command_array[__orca_prompt_index]}" + __orca_dispatching_user_prompt_command=1 + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + __orca_dispatching_user_prompt_command="" + done + if (( __orca_user_count > 0 )); then + __orca_prompt_part="${__orca_prompt_command_array[__orca_user_count - 1]}" + # Why: keep the final user hook and Orca suffixes in one status-preserving eval. + __orca_final_prompt_command='eval "$__orca_prompt_part"' + for __orca_suffix_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + __orca_final_prompt_command+=$'\n'"$__orca_suffix_part" + done + __orca_dispatching_user_prompt_command=1 + if (( __orca_exit_code == 0 )); then + eval "$__orca_final_prompt_command" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_final_prompt_command" + fi + __orca_dispatching_user_prompt_command="" + else + for __orca_prompt_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + done + fi + return "$__orca_exit_code" +} +__orca_finish_legacy_prompt_dispatch() { + local __orca_suffix_part + if [[ -n "${__orca_in_prompt_command:-}" ]]; then + for __orca_suffix_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + eval "$__orca_suffix_part" + done + fi + trap '__orca_osc133_preexec' DEBUG + unset __orca_in_legacy_prompt_wrapper +} +__orca_normalize_prompt_command() { + [[ -z "${__orca_prompt_command_normalized:-}" ]] || return 0 + local __orca_prompt_part + local -a __orca_normalized=() + for __orca_prompt_part in "${PROMPT_COMMAND[@]+"${PROMPT_COMMAND[@]}"}"; do + __orca_normalize_prompt_command_part "$__orca_prompt_part" __orca_prompt_part + [[ -n "$__orca_prompt_part" ]] && __orca_normalized+=("$__orca_prompt_part") + done + __orca_prompt_command_normalized=1 + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND=("${__orca_normalized[@]+"${__orca_normalized[@]}"}") + else + __orca_prompt_command_array=("${__orca_normalized[@]+"${__orca_normalized[@]}"}") + __orca_prompt_command_prefix=() + __orca_prompt_command_suffix=() + unset PROMPT_COMMAND + # Why: PID scope distinguishes legacy prompt dispatch from ordinary user command text. + __orca_prompt_status_variable="__orca_prompt_status_$$" + __orca_prompt_status_capture_command="$__orca_prompt_status_variable=\$?" + __orca_prompt_status_value="\${$__orca_prompt_status_variable}" + PROMPT_COMMAND="$__orca_prompt_status_capture_command; __orca_prompt_status=$__orca_prompt_status_value"'; __orca_prompt_had_functrace=""; if [[ -o functrace ]]; then __orca_prompt_had_functrace=1; set +T; fi; __orca_outer_debug_trap_spec="$(trap -p DEBUG)"; [[ -z "$__orca_prompt_had_functrace" ]] || set -T; unset __orca_prompt_had_functrace; __orca_run_prompt_command_array; __orca_finish_legacy_prompt_dispatch' + fi +} +__orca_prepend_prompt_command() { + local command="$1" + __orca_normalize_prompt_command + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND=("$command" "${PROMPT_COMMAND[@]+"${PROMPT_COMMAND[@]}"}") + else + __orca_prompt_command_prefix=("$command" "${__orca_prompt_command_prefix[@]+"${__orca_prompt_command_prefix[@]}"}") + fi +} +__orca_append_prompt_command() { + local command="$1" + __orca_normalize_prompt_command + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND+=("$command") + else + __orca_prompt_command_suffix+=("$command") + fi +} +__orca_prepend_prompt_command "__orca_osc133_precmd" +__orca_append_prompt_command '__orca_in_debug_capture=1; __orca_prompt_had_functrace=""; if [[ -o functrace ]]; then __orca_prompt_had_functrace=1; set +T; fi; __orca_outer_debug_trap_spec="$(trap -p DEBUG)"; [[ -z "$__orca_prompt_had_functrace" ]] || set -T; unset __orca_prompt_had_functrace __orca_in_debug_capture' +__orca_append_prompt_command "__orca_osc133_epilogue" +__orca_had_functrace="" +[[ -o functrace ]] && __orca_had_functrace=1 +set +T +__orca_debug_trap_spec="$(trap -p DEBUG)" +[[ -z "$__orca_had_functrace" ]] || set -T +if [[ -n "$__orca_debug_trap_spec" && "$__orca_debug_trap_spec" != "trap -- '__orca_osc133_preexec' DEBUG" ]]; then + __orca_debug_trap_command="${__orca_debug_trap_spec#trap -- }" + __orca_debug_trap_command="${__orca_debug_trap_command% DEBUG}" + eval "__orca_user_debug_trap=$__orca_debug_trap_command" +fi +unset __orca_debug_trap_spec __orca_debug_trap_command __orca_had_functrace +unset -f __orca_normalize_prompt_command_part __orca_normalize_prompt_command __orca_prepend_prompt_command __orca_append_prompt_command +unset __orca_prompt_command_normalized +# Why: arm DEBUG after wrapper setup; otherwise bash treats our own rcfile +# commands as a foreground command and emits a fake C/D before the first prompt. +__orca_initial_prompt=1 +trap '__orca_osc133_preexec' DEBUG +unset __orca_initializing_wrapper diff --git a/src/main/shell-wrapper-snapshots/daemon-fish-init.txt b/src/main/shell-wrapper-snapshots/daemon-fish-init.txt new file mode 100644 index 00000000000..94381e52c1a --- /dev/null +++ b/src/main/shell-wrapper-snapshots/daemon-fish-init.txt @@ -0,0 +1,12 @@ +if test "$ORCA_SHELL_READY_MARKER" = 1 + function __orca_shell_ready_marker --on-event fish_prompt + builtin printf "\033]777;orca-shell-ready\007" + functions -e __orca_shell_ready_marker + end +end +if test -n "$ORCA_CODEX_LAUNCH_PREFLIGHT"; and test (type -t codex 2>/dev/null) = file + function codex + command "$ORCA_CODEX_LAUNCH_PREFLIGHT" agent hooks prepare-codex >/dev/null 2>&1; or true + command codex $argv + end +end \ No newline at end of file diff --git a/src/main/shell-wrapper-snapshots/daemon-zsh-zlogin.txt b/src/main/shell-wrapper-snapshots/daemon-zsh-zlogin.txt new file mode 100644 index 00000000000..b1a78cdfcfc --- /dev/null +++ b/src/main/shell-wrapper-snapshots/daemon-zsh-zlogin.txt @@ -0,0 +1,109 @@ +# Orca daemon zsh shell-ready wrapper +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -o interactive && -f "$_orca_home/.zlogin" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zlogin" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + +__orca_restore_agent_teams_path() { + [[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0 + case "$PATH" in + "${ORCA_AGENT_TEAMS_SHIM_DIR}"|"${ORCA_AGENT_TEAMS_SHIM_DIR}:"*) return 0 ;; + esac + export PATH="${ORCA_AGENT_TEAMS_SHIM_DIR}:$PATH" +} +__orca_restore_agent_teams_path +# Why: .zlogin is the final login startup file before the prompt is shown. +[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" +# Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +[[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}" +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi +# Why: a typed alias expands inside the shell, after pane launch prep. +__orca_codex_binary="$(command -v codex 2>/dev/null || :)" +if [[ -n "${ORCA_CODEX_LAUNCH_PREFLIGHT:-}" && -n "${__orca_codex_binary:-}" && -x "${__orca_codex_binary}" ]]; then + codex() { + "${ORCA_CODEX_LAUNCH_PREFLIGHT}" agent hooks prepare-codex >/dev/null 2>&1 || : + command codex "$@" + } +fi +unset __orca_codex_binary + +if [[ "${ORCA_SHELL_READY_MARKER:-0}" == "1" ]]; then + # Why: capture the prior zle-line-init so the marker chains to it. On a + # re-source we are already the bound widget, so keep the function captured + # the first time instead of clobbering it to empty (which would silently + # drop the user's widget on every prompt after the second source). Only + # user-defined widgets are chainable as plain functions; builtin/completion + # forms (rare for zle-line-init) are left unchained. + if [[ "${widgets[zle-line-init]:-}" == "user:__orca_prompt_mark" ]]; then + : + elif (( ${+widgets[zle-line-init]} )) && [[ "${widgets[zle-line-init]}" == user:* ]]; then + __orca_prev_line_init_fn="${widgets[zle-line-init]#user:}" + else + __orca_prev_line_init_fn="" + fi + __orca_prompt_mark() { + printf "\033]777;orca-shell-ready\007" + # 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. + if [[ -n "${__orca_prev_line_init_fn:-}" ]]; then + "${__orca_prev_line_init_fn}" "$@" + fi + } + zle -N zle-line-init __orca_prompt_mark +fi + +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +# Why: after Orca's last wrapper file has loaded, the interactive shell should +# expose the same ZDOTDIR a normal zsh startup would expose. +export ZDOTDIR="$_orca_home" +unset _orca_home + diff --git a/src/main/shell-wrapper-snapshots/daemon-zsh-zprofile.txt b/src/main/shell-wrapper-snapshots/daemon-zsh-zprofile.txt new file mode 100644 index 00000000000..cef7c417cfa --- /dev/null +++ b/src/main/shell-wrapper-snapshots/daemon-zsh-zprofile.txt @@ -0,0 +1,15 @@ +# Orca daemon zsh shell-ready wrapper +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -f "$_orca_home/.zprofile" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zprofile" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + diff --git a/src/main/shell-wrapper-snapshots/daemon-zsh-zshenv.txt b/src/main/shell-wrapper-snapshots/daemon-zsh-zshenv.txt new file mode 100644 index 00000000000..0c95f943fd8 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/daemon-zsh-zshenv.txt @@ -0,0 +1,87 @@ +# Orca daemon zsh shell-ready wrapper +if [[ "${ORCA_SHELL_STARTUP_IDENTITY:-0}" == "1" ]]; then + unset ORCA_SHELL_STARTUP_IDENTITY + printf "\033]777;orca-shell-start:%s\007" "$$" +fi +# Why: capture the runtime wrapper dir before it is unset below. On WSL this +# file is generated with a Windows path but sourced via /mnt/c, so the baked +# literal is unusable there and ZDOTDIR must be restored from this value. +# Derive it from the file being sourced (%x, zsh's internal script name) rather +# than the env-imported $ZDOTDIR: zsh corrupts environment values whose UTF-8 +# bytes fall in its 0x84-0x9D token range (e.g. a non-ASCII Windows username +# such as a Korean login), which would make the self-check below fail and fall +# back to the unusable baked literal, so the user's .zshrc never loads (#8003). +# %x is not subject to that corruption; keep $ZDOTDIR as a fallback for the +# rare shell where %x prompt expansion yields nothing. +_orca_wrapper_zdotdir_self="${${(%):-%x}:h}" +if [[ -z "${_orca_wrapper_zdotdir_self:-}" ]]; then + _orca_wrapper_zdotdir_self="${ZDOTDIR:-}" +fi +while [[ "${_orca_wrapper_zdotdir_self:-}" == */ ]]; do + _orca_wrapper_zdotdir_self="${_orca_wrapper_zdotdir_self%/}" +done +_orca_spawn_orig_zdotdir="${ORCA_ORIG_ZDOTDIR:-}" +_orca_user_zdotdir="${_orca_spawn_orig_zdotdir:-$HOME}" +_orca_zshenv_source_dir="${ORCA_ZSHENV_SOURCE_DIR:-$HOME}" +_orca_zshenv_path="" +unset ORCA_ZSHENV_SOURCE_DIR + +# Normalize fallback and source roots before reading user .zshenv so nested +# Orca PTYs never source another Orca wrapper recursively. +while [[ "${_orca_user_zdotdir}" == */ ]]; do + _orca_user_zdotdir="${_orca_user_zdotdir%/}" +done +case "${_orca_user_zdotdir}" in + ""|*/shell-ready/zsh) _orca_user_zdotdir="$HOME" ;; +esac +while [[ "${_orca_zshenv_source_dir}" == */ ]]; do + _orca_zshenv_source_dir="${_orca_zshenv_source_dir%/}" +done +case "${_orca_zshenv_source_dir}" in + ""|*/shell-ready/zsh) _orca_zshenv_source_dir="$HOME" ;; +esac + +# Why: source at wrapper top level, not in a function/subshell, so .zshenv +# exports, functions, path/fpath typesets, and zsh options keep normal scope. +unset ZDOTDIR +if [[ -n "${_orca_zshenv_source_dir:-}" && -f "${_orca_zshenv_source_dir}/.zshenv" ]]; then + _orca_zshenv_path="${_orca_zshenv_source_dir}/.zshenv" +fi +if [[ -n "${_orca_zshenv_path:-}" ]]; then + source "${_orca_zshenv_path}" +fi + +_orca_discovered_zdotdir="${ZDOTDIR:-}" + +while [[ "${_orca_discovered_zdotdir}" == */ ]]; do + _orca_discovered_zdotdir="${_orca_discovered_zdotdir%/}" +done + +case "${_orca_discovered_zdotdir}" in + *[![:space:]]*) ;; + *) _orca_discovered_zdotdir="" ;; +esac + +if [[ -n "${_orca_discovered_zdotdir}" && ! -d "${_orca_discovered_zdotdir}" ]]; then + [[ "${ORCA_DEBUG:-0}" == "1" ]] && echo "[orca-shell-ready] Discovered ZDOTDIR '${_orca_discovered_zdotdir}' does not exist, falling back" >&2 + _orca_discovered_zdotdir="" +fi + +export ORCA_ORIG_ZDOTDIR="${_orca_discovered_zdotdir:-${_orca_user_zdotdir:-$HOME}}" + +while [[ "${ORCA_ORIG_ZDOTDIR}" == */ ]]; do + ORCA_ORIG_ZDOTDIR="${ORCA_ORIG_ZDOTDIR%/}" +done + +case "${ORCA_ORIG_ZDOTDIR}" in + ""|*/shell-ready/zsh) export ORCA_ORIG_ZDOTDIR="$HOME" ;; +esac + +# Why: use :- after user .zshenv — a pathological unset under set -u must not +# abort the wrapper; empty falls through to the baked-literal branch. +if [[ -n "${_orca_wrapper_zdotdir_self:-}" && -f "${_orca_wrapper_zdotdir_self:-}/.zshenv" ]]; then + export ZDOTDIR="${_orca_wrapper_zdotdir_self:-}" +else + export ZDOTDIR='/zsh' +fi +unset _orca_spawn_orig_zdotdir _orca_user_zdotdir _orca_zshenv_source_dir _orca_zshenv_path _orca_discovered_zdotdir _orca_wrapper_zdotdir_self diff --git a/src/main/shell-wrapper-snapshots/daemon-zsh-zshrc.txt b/src/main/shell-wrapper-snapshots/daemon-zsh-zshrc.txt new file mode 100644 index 00000000000..3e7c78831ce --- /dev/null +++ b/src/main/shell-wrapper-snapshots/daemon-zsh-zshrc.txt @@ -0,0 +1,103 @@ +# Orca daemon zsh shell-ready wrapper +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ "$_orca_home" != "$ZDOTDIR" && -o interactive && -f "$_orca_home/.zshrc" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zshrc" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + +__orca_restore_agent_teams_path() { + [[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0 + case "$PATH" in + "${ORCA_AGENT_TEAMS_SHIM_DIR}"|"${ORCA_AGENT_TEAMS_SHIM_DIR}:"*) return 0 ;; + esac + export PATH="${ORCA_AGENT_TEAMS_SHIM_DIR}:$PATH" +} +[[ ! -o login ]] && __orca_restore_agent_teams_path +if [[ ! -o login ]]; then + # Why: ~/.zshrc can export the user's default OpenCode config after spawn. + [[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" + [[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" + # Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + + [[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}" +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi + # Why: a typed alias expands inside the shell, after pane launch prep. +__orca_codex_binary="$(command -v codex 2>/dev/null || :)" +if [[ -n "${ORCA_CODEX_LAUNCH_PREFLIGHT:-}" && -n "${__orca_codex_binary:-}" && -x "${__orca_codex_binary}" ]]; then + codex() { + "${ORCA_CODEX_LAUNCH_PREFLIGHT}" agent hooks prepare-codex >/dev/null 2>&1 || : + command codex "$@" + } +fi +unset __orca_codex_binary + +fi +__orca_osc133_precmd() { + local exit_code=$? + if [[ -n "${__orca_in_command:-}" ]]; then + printf "\033]133;D;%s\007" "$exit_code" + unset __orca_in_command + fi + printf "\033]133;A\007" +} +__orca_osc133_preexec() { + printf "\033]133;C\007" + __orca_in_command=1 +} +# Why: prepend so Orca captures $? before user prompt hooks can overwrite it. +precmd_functions=(__orca_osc133_precmd ${precmd_functions[@]}) +preexec_functions=(__orca_osc133_preexec ${preexec_functions[@]}) +if [[ ! -o login ]]; then +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +# Why: after Orca's last wrapper file has loaded, the interactive shell should +# expose the same ZDOTDIR a normal zsh startup would expose. +export ZDOTDIR="$_orca_home" +unset _orca_home + +fi diff --git a/src/main/shell-wrapper-snapshots/local-bash-rcfile.txt b/src/main/shell-wrapper-snapshots/local-bash-rcfile.txt new file mode 100644 index 00000000000..b0436f965b7 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/local-bash-rcfile.txt @@ -0,0 +1,339 @@ +# Orca bash shell-ready wrapper +if [[ "${ORCA_SHELL_STARTUP_IDENTITY:-0}" == "1" ]]; then + unset ORCA_SHELL_STARTUP_IDENTITY + printf "\033]777;orca-shell-start:%s\007" "$$" +fi +[[ -f /etc/profile ]] && source /etc/profile +if [[ -f "$HOME/.bash_profile" ]]; then + source "$HOME/.bash_profile" +elif [[ -f "$HOME/.bash_login" ]]; then + source "$HOME/.bash_login" +elif [[ -f "$HOME/.profile" ]]; then + source "$HOME/.profile" +fi +# Why: enable bracketed paste so Orca can deliver a multiline startup prompt as +# a single literal paste (ESC[200~…ESC[201~). Without it, older readline builds +# treat each embedded newline as Enter and mangle the prompt into PS2 +# continuation. Modern readline defaults this on; force it for the rest. +[[ $- == *i* ]] && bind 'set enable-bracketed-paste on' 2>/dev/null +# Why: preserve bash's normal login-shell contract. Many users already source +# ~/.bashrc from ~/.bash_profile; forcing ~/.bashrc again here would duplicate +# PATH edits, hooks, and prompt init in Orca startup-command shells. +__orca_restore_agent_teams_path() { + [[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0 + case "$PATH" in + "${ORCA_AGENT_TEAMS_SHIM_DIR}"|"${ORCA_AGENT_TEAMS_SHIM_DIR}:"*) return 0 ;; + esac + export PATH="${ORCA_AGENT_TEAMS_SHIM_DIR}:$PATH" +} +__orca_restore_agent_teams_path +# Why: user startup files may set the default OpenCode config after Orca's +# spawn env; restore the Orca-managed config dir before the first prompt. +[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" +# Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +# Why: Codex must keep using Orca's runtime CODEX_HOME after profile scripts. +[[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}" +# Why: a typed alias expands inside the shell, after pane launch prep. +__orca_codex_binary="$(command -v codex 2>/dev/null || :)" +if [[ -n "${ORCA_CODEX_LAUNCH_PREFLIGHT:-}" && -n "${__orca_codex_binary:-}" && -x "${__orca_codex_binary}" ]]; then + codex() { + "${ORCA_CODEX_LAUNCH_PREFLIGHT}" agent hooks prepare-codex >/dev/null 2>&1 || : + command codex "$@" + } +fi +unset __orca_codex_binary + +# Why: emit OSC 133 C/D so terminal-command-lifecycle can drop stale agent +# status when the foreground command (e.g. an interrupted Claude/Codex CLI) +# exits — mirrors the zsh wrapper. Without this, bash users (default on most +# Linux distros) keep a stuck 'working' spinner for up to 30 min after the +# CLI exits without sending a Stop/SessionEnd hook. +__orca_initializing_wrapper=1 +__orca_osc133_precmd() { + local exit_code=$? + __orca_in_prompt_command=1 + if [[ -n "${__orca_in_command:-}" ]]; then + printf "\033]133;D;%s\007" "$exit_code" + unset __orca_in_command + fi + printf "\033]133;A\007" + return "$exit_code" +} +__orca_osc133_prompt_done() { + unset __orca_in_prompt_command + __orca_adopt_outer_debug_trap + trap '__orca_osc133_preexec' DEBUG +} +__orca_osc133_preexec() { + if [[ -n "${__orca_prompt_status_capture_command:-}" && "$BASH_COMMAND" == "$__orca_prompt_status_capture_command" ]]; then + unset __orca_initial_prompt + __orca_in_legacy_prompt_wrapper=1 + return 0 + fi + if [[ -n "${__orca_initializing_wrapper:-}${__orca_in_debug_capture:-}${__orca_initial_prompt:-}${__orca_in_prompt_dispatch:-}${__orca_in_legacy_prompt_wrapper:-}${__orca_in_prompt_command:-}" ]]; then + [[ -z "${__orca_initializing_wrapper:-}${__orca_in_debug_capture:-}" ]] || return 0 + if [[ -n "${__orca_initial_prompt:-}" && "$BASH_COMMAND" == "__orca_osc133_precmd" ]]; then + unset __orca_initial_prompt; return 0 + fi + if [[ -n "${__orca_in_prompt_dispatch:-}" ]]; then + [[ -n "${__orca_dispatching_user_prompt_command:-}" ]] || return 0 + if [[ "${FUNCNAME[1]:-}" == "__orca_run_prompt_command_array" ]]; then + case "$BASH_COMMAND" in + '(( __orca_exit_code == 0 ))'|'__orca_restore_prompt_status "$__orca_exit_code"'|'eval "$__orca_prompt_part"'|'eval "$__orca_final_prompt_command"'|__orca_dispatching_user_prompt_command=*|__orca_osc133_precmd|__orca_osc133_prompt_done|__orca_prompt_mark) return 0 ;; + esac + fi + elif [[ "${FUNCNAME[1]:-}" == "__orca_run_prompt_command_array" || "$BASH_COMMAND" == "__orca_run_prompt_command_array" ]]; then + return 0 + fi + [[ -z "${__orca_in_legacy_prompt_wrapper:-}" || -n "${__orca_dispatching_user_prompt_command:-}" ]] || return 0 + if [[ -n "${__orca_in_prompt_command:-}" && "$BASH_COMMAND" == "__orca_in_debug_capture=1" ]]; then + return 0 + fi + fi + case "${FUNCNAME[1]:-}" in __orca_osc133_*|__orca_prompt_mark|__orca_restore_prompt_status) return 0 ;; esac + case "$BASH_COMMAND" in __orca_osc133_precmd|__orca_osc133_prompt_done|__orca_prompt_mark) return 0 ;; esac + __orca_run_user_debug_trap + [[ -z "${__orca_in_prompt_command:-}" ]] || return 0 + [[ -z "${__orca_in_command:-}" ]] || return 0 + # Why: bash DEBUG fires for every simple command, including PROMPT_COMMAND + # bodies and chained traps can call us repeatedly for one command. + printf "\033]133;C\007" + __orca_in_command=1 +} +# Why: prepend so we capture $? before the user's PROMPT_COMMAND chain mutates it. +__orca_normalize_prompt_command_part() { + local __orca_value="$1" __orca_output_name="$2" __orca_character __orca_chunk + local __orca_value_length=${#1} __orca_suffix_length=0 __orca_backslash_length=0 + local __orca_output_length __orca_scan_start + while (( __orca_value_length - __orca_suffix_length >= 1024 )); do + __orca_scan_start=$(( __orca_value_length - __orca_suffix_length - 1024 )) + __orca_chunk="${__orca_value:__orca_scan_start:1024}" + case "$__orca_chunk" in + *[!$' \t\n;']*) break ;; + *) __orca_suffix_length=$(( __orca_suffix_length + 1024 )) ;; + esac + done + while (( __orca_suffix_length < __orca_value_length )); do + __orca_character="${__orca_value: -__orca_suffix_length - 1:1}" + case "$__orca_character" in + ' '|$'\t'|$'\n'|';') __orca_suffix_length=$(( __orca_suffix_length + 1 )) ;; + *) break ;; + esac + done + __orca_output_length=$(( ${#__orca_value} - __orca_suffix_length )) + while (( __orca_output_length - __orca_backslash_length >= 1024 )); do + __orca_scan_start=$(( __orca_output_length - __orca_backslash_length - 1024 )) + __orca_chunk="${__orca_value:__orca_scan_start:1024}" + case "$__orca_chunk" in + *[!\\]*) break ;; + *) __orca_backslash_length=$(( __orca_backslash_length + 1024 )) ;; + esac + done + while (( __orca_backslash_length < __orca_output_length )); do + __orca_character="${__orca_value:__orca_output_length - __orca_backslash_length - 1:1}" + [[ "$__orca_character" == '\' ]] || break + __orca_backslash_length=$(( __orca_backslash_length + 1 )) + done + # Preserve the first separator when an odd backslash run escapes it. + if (( __orca_suffix_length > 0 && __orca_backslash_length % 2 == 1 )); then + __orca_suffix_length=$(( __orca_suffix_length - 1 )) + __orca_backslash_length=0 + fi + __orca_output_length=$(( ${#__orca_value} - __orca_suffix_length )) + __orca_value="${__orca_value:0:__orca_output_length}" + # Bash 4.4-5.0 scalar prompt evaluation preserves an odd terminal backslash. + if (( __orca_suffix_length == 0 && ((BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4) || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] == 0)) && __orca_backslash_length % 2 == 1 )); then + __orca_value="$__orca_value\\" + fi + printf -v "$__orca_output_name" '%s' "$__orca_value" +} +__orca_restore_prompt_status() { + return "$1" +} +__orca_update_user_debug_trap() { + local __orca_debug_trap_spec="$1" __orca_unchanged_debug_trap_spec="$2" + local __orca_debug_trap_command + [[ "$__orca_debug_trap_spec" != "$__orca_unchanged_debug_trap_spec" ]] || return 0 + [[ "$__orca_debug_trap_spec" != "trap -- '__orca_osc133_preexec' DEBUG" ]] || return 0 + if [[ -z "$__orca_debug_trap_spec" ]]; then + __orca_user_debug_trap="" + unset __orca_chained_debug_trap + return 0 + fi + __orca_debug_trap_command="${__orca_debug_trap_spec#trap -- }" + __orca_debug_trap_command="${__orca_debug_trap_command% DEBUG}" + eval "__orca_user_debug_trap=$__orca_debug_trap_command" + unset __orca_chained_debug_trap +} +__orca_run_user_debug_trap() { + if [[ -n "${__orca_user_debug_trap:-}" ]]; then + eval "$__orca_user_debug_trap" || true + fi +} +__orca_adopt_outer_debug_trap() { + local __orca_debug_trap_spec="${__orca_outer_debug_trap_spec:-}" + unset __orca_outer_debug_trap_spec + __orca_update_user_debug_trap "$__orca_debug_trap_spec" "trap -- '__orca_osc133_preexec' DEBUG" +} +__orca_run_prompt_command_array() { + local __orca_exit_code="${__orca_prompt_status:-$?}" __orca_prompt_part __orca_prompt_index __orca_user_count + local __orca_suffix_part + local __orca_final_prompt_command + local __orca_in_prompt_dispatch=1 __orca_dispatching_user_prompt_command="" + unset __orca_prompt_status + __orca_adopt_outer_debug_trap + trap '__orca_osc133_preexec' DEBUG + for __orca_prompt_part in "${__orca_prompt_command_prefix[@]+"${__orca_prompt_command_prefix[@]}"}"; do + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + done + __orca_user_count=0 + for __orca_prompt_part in "${__orca_prompt_command_array[@]+"${__orca_prompt_command_array[@]}"}"; do + __orca_user_count=$(( __orca_user_count + 1 )) + done + for (( __orca_prompt_index = 0; __orca_prompt_index + 1 < __orca_user_count; __orca_prompt_index++ )); do + __orca_prompt_part="${__orca_prompt_command_array[__orca_prompt_index]}" + __orca_dispatching_user_prompt_command=1 + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + __orca_dispatching_user_prompt_command="" + done + if (( __orca_user_count > 0 )); then + __orca_prompt_part="${__orca_prompt_command_array[__orca_user_count - 1]}" + # Why: keep the final user hook and Orca suffixes in one status-preserving eval. + __orca_final_prompt_command='eval "$__orca_prompt_part"' + for __orca_suffix_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + __orca_final_prompt_command+=$'\n'"$__orca_suffix_part" + done + __orca_dispatching_user_prompt_command=1 + if (( __orca_exit_code == 0 )); then + eval "$__orca_final_prompt_command" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_final_prompt_command" + fi + __orca_dispatching_user_prompt_command="" + else + for __orca_prompt_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + done + fi + return "$__orca_exit_code" +} +__orca_finish_legacy_prompt_dispatch() { + local __orca_suffix_part + if [[ -n "${__orca_in_prompt_command:-}" ]]; then + for __orca_suffix_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + eval "$__orca_suffix_part" + done + fi + trap '__orca_osc133_preexec' DEBUG + unset __orca_in_legacy_prompt_wrapper +} +__orca_normalize_prompt_command() { + [[ -z "${__orca_prompt_command_normalized:-}" ]] || return 0 + local __orca_prompt_part + local -a __orca_normalized=() + for __orca_prompt_part in "${PROMPT_COMMAND[@]+"${PROMPT_COMMAND[@]}"}"; do + __orca_normalize_prompt_command_part "$__orca_prompt_part" __orca_prompt_part + [[ -n "$__orca_prompt_part" ]] && __orca_normalized+=("$__orca_prompt_part") + done + __orca_prompt_command_normalized=1 + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND=("${__orca_normalized[@]+"${__orca_normalized[@]}"}") + else + __orca_prompt_command_array=("${__orca_normalized[@]+"${__orca_normalized[@]}"}") + __orca_prompt_command_prefix=() + __orca_prompt_command_suffix=() + unset PROMPT_COMMAND + # Why: PID scope distinguishes legacy prompt dispatch from ordinary user command text. + __orca_prompt_status_variable="__orca_prompt_status_$$" + __orca_prompt_status_capture_command="$__orca_prompt_status_variable=\$?" + __orca_prompt_status_value="\${$__orca_prompt_status_variable}" + PROMPT_COMMAND="$__orca_prompt_status_capture_command; __orca_prompt_status=$__orca_prompt_status_value"'; __orca_prompt_had_functrace=""; if [[ -o functrace ]]; then __orca_prompt_had_functrace=1; set +T; fi; __orca_outer_debug_trap_spec="$(trap -p DEBUG)"; [[ -z "$__orca_prompt_had_functrace" ]] || set -T; unset __orca_prompt_had_functrace; __orca_run_prompt_command_array; __orca_finish_legacy_prompt_dispatch' + fi +} +__orca_prepend_prompt_command() { + local command="$1" + __orca_normalize_prompt_command + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND=("$command" "${PROMPT_COMMAND[@]+"${PROMPT_COMMAND[@]}"}") + else + __orca_prompt_command_prefix=("$command" "${__orca_prompt_command_prefix[@]+"${__orca_prompt_command_prefix[@]}"}") + fi +} +__orca_append_prompt_command() { + local command="$1" + __orca_normalize_prompt_command + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND+=("$command") + else + __orca_prompt_command_suffix+=("$command") + fi +} +__orca_prepend_prompt_command "__orca_osc133_precmd" +# Why: append the marker through PROMPT_COMMAND so it fires after the login +# startup files have rebuilt the prompt, without re-running user rc files. +if [[ "${ORCA_SHELL_READY_MARKER:-0}" == "1" ]]; then + __orca_prompt_mark() { + printf "\033]777;orca-shell-ready\007" + } + __orca_append_prompt_command "__orca_prompt_mark" +fi +__orca_append_prompt_command '__orca_in_debug_capture=1; __orca_prompt_had_functrace=""; if [[ -o functrace ]]; then __orca_prompt_had_functrace=1; set +T; fi; __orca_outer_debug_trap_spec="$(trap -p DEBUG)"; [[ -z "$__orca_prompt_had_functrace" ]] || set -T; unset __orca_prompt_had_functrace __orca_in_debug_capture' +__orca_append_prompt_command "__orca_osc133_prompt_done" +__orca_had_functrace="" +[[ -o functrace ]] && __orca_had_functrace=1 +set +T +__orca_debug_trap_spec="$(trap -p DEBUG)" +[[ -z "$__orca_had_functrace" ]] || set -T +if [[ -n "$__orca_debug_trap_spec" && "$__orca_debug_trap_spec" != "trap -- '__orca_osc133_preexec' DEBUG" ]]; then + __orca_debug_trap_command="${__orca_debug_trap_spec#trap -- }" + __orca_debug_trap_command="${__orca_debug_trap_command% DEBUG}" + eval "__orca_user_debug_trap=$__orca_debug_trap_command" +fi +unset __orca_debug_trap_spec __orca_debug_trap_command __orca_had_functrace +unset -f __orca_normalize_prompt_command_part __orca_normalize_prompt_command __orca_prepend_prompt_command __orca_append_prompt_command +unset __orca_prompt_command_normalized +# Why: arm DEBUG after wrapper setup; otherwise bash treats our own rcfile +# commands as a foreground command and emits a fake C/D before the first prompt. +__orca_initial_prompt=1 +trap '__orca_osc133_preexec' DEBUG +unset __orca_initializing_wrapper diff --git a/src/main/shell-wrapper-snapshots/local-fish-init.txt b/src/main/shell-wrapper-snapshots/local-fish-init.txt new file mode 100644 index 00000000000..94381e52c1a --- /dev/null +++ b/src/main/shell-wrapper-snapshots/local-fish-init.txt @@ -0,0 +1,12 @@ +if test "$ORCA_SHELL_READY_MARKER" = 1 + function __orca_shell_ready_marker --on-event fish_prompt + builtin printf "\033]777;orca-shell-ready\007" + functions -e __orca_shell_ready_marker + end +end +if test -n "$ORCA_CODEX_LAUNCH_PREFLIGHT"; and test (type -t codex 2>/dev/null) = file + function codex + command "$ORCA_CODEX_LAUNCH_PREFLIGHT" agent hooks prepare-codex >/dev/null 2>&1; or true + command codex $argv + end +end \ No newline at end of file diff --git a/src/main/shell-wrapper-snapshots/local-zsh-zlogin.txt b/src/main/shell-wrapper-snapshots/local-zsh-zlogin.txt new file mode 100644 index 00000000000..7e0ae1a5131 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/local-zsh-zlogin.txt @@ -0,0 +1,109 @@ +# Orca zsh shell-ready wrapper +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -o interactive && -f "$_orca_home/.zlogin" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zlogin" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + +__orca_restore_agent_teams_path() { + [[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0 + case "$PATH" in + "${ORCA_AGENT_TEAMS_SHIM_DIR}"|"${ORCA_AGENT_TEAMS_SHIM_DIR}:"*) return 0 ;; + esac + export PATH="${ORCA_AGENT_TEAMS_SHIM_DIR}:$PATH" +} +__orca_restore_agent_teams_path +# Why: .zlogin is the final login startup file before the prompt is shown. +[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" +# Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +[[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}" +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi +# Why: a typed alias expands inside the shell, after pane launch prep. +__orca_codex_binary="$(command -v codex 2>/dev/null || :)" +if [[ -n "${ORCA_CODEX_LAUNCH_PREFLIGHT:-}" && -n "${__orca_codex_binary:-}" && -x "${__orca_codex_binary}" ]]; then + codex() { + "${ORCA_CODEX_LAUNCH_PREFLIGHT}" agent hooks prepare-codex >/dev/null 2>&1 || : + command codex "$@" + } +fi +unset __orca_codex_binary + +if [[ "${ORCA_SHELL_READY_MARKER:-0}" == "1" ]]; then + # Why: capture the prior zle-line-init so the marker chains to it. On a + # re-source we are already the bound widget, so keep the function captured + # the first time instead of clobbering it to empty (which would silently + # drop the user's widget on every prompt after the second source). Only + # user-defined widgets are chainable as plain functions; builtin/completion + # forms (rare for zle-line-init) are left unchained. + if [[ "${widgets[zle-line-init]:-}" == "user:__orca_prompt_mark" ]]; then + : + elif (( ${+widgets[zle-line-init]} )) && [[ "${widgets[zle-line-init]}" == user:* ]]; then + __orca_prev_line_init_fn="${widgets[zle-line-init]#user:}" + else + __orca_prev_line_init_fn="" + fi + __orca_prompt_mark() { + printf "\033]777;orca-shell-ready\007" + # 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. + if [[ -n "${__orca_prev_line_init_fn:-}" ]]; then + "${__orca_prev_line_init_fn}" "$@" + fi + } + zle -N zle-line-init __orca_prompt_mark +fi + +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +# Why: after Orca's last wrapper file has loaded, the interactive shell should +# expose the same ZDOTDIR a normal zsh startup would expose. +export ZDOTDIR="$_orca_home" +unset _orca_home + diff --git a/src/main/shell-wrapper-snapshots/local-zsh-zprofile.txt b/src/main/shell-wrapper-snapshots/local-zsh-zprofile.txt new file mode 100644 index 00000000000..6382e9b97e1 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/local-zsh-zprofile.txt @@ -0,0 +1,15 @@ +# Orca zsh shell-ready wrapper +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -f "$_orca_home/.zprofile" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zprofile" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + diff --git a/src/main/shell-wrapper-snapshots/local-zsh-zshenv.txt b/src/main/shell-wrapper-snapshots/local-zsh-zshenv.txt new file mode 100644 index 00000000000..c5a0bcbd0d9 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/local-zsh-zshenv.txt @@ -0,0 +1,87 @@ +# Orca zsh shell-ready wrapper +if [[ "${ORCA_SHELL_STARTUP_IDENTITY:-0}" == "1" ]]; then + unset ORCA_SHELL_STARTUP_IDENTITY + printf "\033]777;orca-shell-start:%s\007" "$$" +fi +# Why: capture the runtime wrapper dir before it is unset below. On WSL this +# file is generated with a Windows path but sourced via /mnt/c, so the baked +# literal is unusable there and ZDOTDIR must be restored from this value. +# Derive it from the file being sourced (%x, zsh's internal script name) rather +# than the env-imported $ZDOTDIR: zsh corrupts environment values whose UTF-8 +# bytes fall in its 0x84-0x9D token range (e.g. a non-ASCII Windows username +# such as a Korean login), which would make the self-check below fail and fall +# back to the unusable baked literal, so the user's .zshrc never loads (#8003). +# %x is not subject to that corruption; keep $ZDOTDIR as a fallback for the +# rare shell where %x prompt expansion yields nothing. +_orca_wrapper_zdotdir_self="${${(%):-%x}:h}" +if [[ -z "${_orca_wrapper_zdotdir_self:-}" ]]; then + _orca_wrapper_zdotdir_self="${ZDOTDIR:-}" +fi +while [[ "${_orca_wrapper_zdotdir_self:-}" == */ ]]; do + _orca_wrapper_zdotdir_self="${_orca_wrapper_zdotdir_self%/}" +done +_orca_spawn_orig_zdotdir="${ORCA_ORIG_ZDOTDIR:-}" +_orca_user_zdotdir="${_orca_spawn_orig_zdotdir:-$HOME}" +_orca_zshenv_source_dir="${ORCA_ZSHENV_SOURCE_DIR:-$HOME}" +_orca_zshenv_path="" +unset ORCA_ZSHENV_SOURCE_DIR + +# Normalize fallback and source roots before reading user .zshenv so nested +# Orca PTYs never source another Orca wrapper recursively. +while [[ "${_orca_user_zdotdir}" == */ ]]; do + _orca_user_zdotdir="${_orca_user_zdotdir%/}" +done +case "${_orca_user_zdotdir}" in + ""|*/shell-ready/zsh) _orca_user_zdotdir="$HOME" ;; +esac +while [[ "${_orca_zshenv_source_dir}" == */ ]]; do + _orca_zshenv_source_dir="${_orca_zshenv_source_dir%/}" +done +case "${_orca_zshenv_source_dir}" in + ""|*/shell-ready/zsh) _orca_zshenv_source_dir="$HOME" ;; +esac + +# Why: source at wrapper top level, not in a function/subshell, so .zshenv +# exports, functions, path/fpath typesets, and zsh options keep normal scope. +unset ZDOTDIR +if [[ -n "${_orca_zshenv_source_dir:-}" && -f "${_orca_zshenv_source_dir}/.zshenv" ]]; then + _orca_zshenv_path="${_orca_zshenv_source_dir}/.zshenv" +fi +if [[ -n "${_orca_zshenv_path:-}" ]]; then + source "${_orca_zshenv_path}" +fi + +_orca_discovered_zdotdir="${ZDOTDIR:-}" + +while [[ "${_orca_discovered_zdotdir}" == */ ]]; do + _orca_discovered_zdotdir="${_orca_discovered_zdotdir%/}" +done + +case "${_orca_discovered_zdotdir}" in + *[![:space:]]*) ;; + *) _orca_discovered_zdotdir="" ;; +esac + +if [[ -n "${_orca_discovered_zdotdir}" && ! -d "${_orca_discovered_zdotdir}" ]]; then + [[ "${ORCA_DEBUG:-0}" == "1" ]] && echo "[orca-shell-ready] Discovered ZDOTDIR '${_orca_discovered_zdotdir}' does not exist, falling back" >&2 + _orca_discovered_zdotdir="" +fi + +export ORCA_ORIG_ZDOTDIR="${_orca_discovered_zdotdir:-${_orca_user_zdotdir:-$HOME}}" + +while [[ "${ORCA_ORIG_ZDOTDIR}" == */ ]]; do + ORCA_ORIG_ZDOTDIR="${ORCA_ORIG_ZDOTDIR%/}" +done + +case "${ORCA_ORIG_ZDOTDIR}" in + ""|*/shell-ready/zsh) export ORCA_ORIG_ZDOTDIR="$HOME" ;; +esac + +# Why: use :- after user .zshenv — a pathological unset under set -u must not +# abort the wrapper; empty falls through to the baked-literal branch. +if [[ -n "${_orca_wrapper_zdotdir_self:-}" && -f "${_orca_wrapper_zdotdir_self:-}/.zshenv" ]]; then + export ZDOTDIR="${_orca_wrapper_zdotdir_self:-}" +else + export ZDOTDIR='/zsh' +fi +unset _orca_spawn_orig_zdotdir _orca_user_zdotdir _orca_zshenv_source_dir _orca_zshenv_path _orca_discovered_zdotdir _orca_wrapper_zdotdir_self diff --git a/src/main/shell-wrapper-snapshots/local-zsh-zshrc.txt b/src/main/shell-wrapper-snapshots/local-zsh-zshrc.txt new file mode 100644 index 00000000000..1e9bbf79365 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/local-zsh-zshrc.txt @@ -0,0 +1,104 @@ +# Orca zsh shell-ready wrapper +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ "$_orca_home" != "$ZDOTDIR" && -o interactive && -f "$_orca_home/.zshrc" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zshrc" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + +__orca_restore_agent_teams_path() { + [[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0 + case "$PATH" in + "${ORCA_AGENT_TEAMS_SHIM_DIR}"|"${ORCA_AGENT_TEAMS_SHIM_DIR}:"*) return 0 ;; + esac + export PATH="${ORCA_AGENT_TEAMS_SHIM_DIR}:$PATH" +} +[[ ! -o login ]] && __orca_restore_agent_teams_path +if [[ ! -o login ]]; then + # Why: ~/.zshrc can export the user's default OpenCode config after spawn. + [[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" + # Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + + # Why: Codex must keep using Orca's runtime CODEX_HOME after rc files. + [[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}" +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi + # Why: a typed alias expands inside the shell, after pane launch prep. +__orca_codex_binary="$(command -v codex 2>/dev/null || :)" +if [[ -n "${ORCA_CODEX_LAUNCH_PREFLIGHT:-}" && -n "${__orca_codex_binary:-}" && -x "${__orca_codex_binary}" ]]; then + codex() { + "${ORCA_CODEX_LAUNCH_PREFLIGHT}" agent hooks prepare-codex >/dev/null 2>&1 || : + command codex "$@" + } +fi +unset __orca_codex_binary + +fi +__orca_osc133_precmd() { + local exit_code=$? + if [[ -n "${__orca_in_command:-}" ]]; then + printf "\033]133;D;%s\007" "$exit_code" + unset __orca_in_command + fi + printf "\033]133;A\007" +} +__orca_osc133_preexec() { + printf "\033]133;C\007" + __orca_in_command=1 +} +# Why: prepend so Orca captures $? before user prompt hooks can overwrite it. +precmd_functions=(__orca_osc133_precmd ${precmd_functions[@]}) +preexec_functions=(__orca_osc133_preexec ${preexec_functions[@]}) +if [[ ! -o login ]]; then +_orca_home="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +# Why: after Orca's last wrapper file has loaded, the interactive shell should +# expose the same ZDOTDIR a normal zsh startup would expose. +export ZDOTDIR="$_orca_home" +unset _orca_home + +fi diff --git a/src/main/shell-wrapper-snapshots/relay-bash-rcfile.txt b/src/main/shell-wrapper-snapshots/relay-bash-rcfile.txt new file mode 100644 index 00000000000..14fd56d6836 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/relay-bash-rcfile.txt @@ -0,0 +1,319 @@ +# Orca relay bash overlay wrapper +if [[ "${ORCA_SHELL_STARTUP_IDENTITY:-0}" == "1" ]]; then + unset ORCA_SHELL_STARTUP_IDENTITY + printf "\033]777;orca-shell-start:%s\007" "$$" +fi +[[ -f /etc/profile ]] && source /etc/profile +if [[ -f "$HOME/.bash_profile" ]]; then + source "$HOME/.bash_profile" +elif [[ -f "$HOME/.bash_login" ]]; then + source "$HOME/.bash_login" +elif [[ -f "$HOME/.profile" ]]; then + source "$HOME/.profile" +fi +# Why: enable bracketed paste so Orca can deliver a multiline startup prompt as +# a single literal paste (ESC[200~…ESC[201~); without it, older readline builds +# treat each embedded newline as Enter and mangle the prompt into PS2 +# continuation. Modern readline defaults this on; force it for the rest. +[[ $- == *i* ]] && bind 'set enable-bracketed-paste on' 2>/dev/null +# Why: remote startup files can re-export user defaults after relay spawn. +[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" +[[ -n "${ORCA_REMOTE_CLI_BIN_DIR:-}" ]] && case ":$PATH:" in *:"${ORCA_REMOTE_CLI_BIN_DIR}":*) ;; *) export PATH="${ORCA_REMOTE_CLI_BIN_DIR}:$PATH" ;; esac +# Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi +# Why: SSH bash sessions need the same command lifecycle markers as local +# bash so agent rows stop showing "working" when the foreground command exits. +__orca_initializing_wrapper=1 +__orca_osc133_precmd() { + local exit_code=$? + __orca_in_prompt_command=1 + if [[ -n "${__orca_in_command:-}" ]]; then + printf "\033]133;D;%s\007" "$exit_code" + unset __orca_in_command + fi + printf "\033]133;A\007" + return "$exit_code" +} +__orca_osc133_prompt_done() { + unset __orca_in_prompt_command; __orca_adopt_outer_debug_trap + trap '__orca_osc133_preexec' DEBUG +} +__orca_osc133_preexec() { + if [[ -n "${__orca_prompt_status_capture_command:-}" && "$BASH_COMMAND" == "$__orca_prompt_status_capture_command" ]]; then + unset __orca_initial_prompt + __orca_in_legacy_prompt_wrapper=1 + return 0 + fi + if [[ -n "${__orca_initializing_wrapper:-}${__orca_in_debug_capture:-}${__orca_initial_prompt:-}${__orca_in_prompt_dispatch:-}${__orca_in_legacy_prompt_wrapper:-}${__orca_in_prompt_command:-}" ]]; then + [[ -z "${__orca_initializing_wrapper:-}${__orca_in_debug_capture:-}" ]] || return 0 + if [[ -n "${__orca_initial_prompt:-}" && "$BASH_COMMAND" == "__orca_osc133_precmd" ]]; then + unset __orca_initial_prompt; return 0 + fi + if [[ -n "${__orca_in_prompt_dispatch:-}" ]]; then + [[ -n "${__orca_dispatching_user_prompt_command:-}" ]] || return 0 + if [[ "${FUNCNAME[1]:-}" == "__orca_run_prompt_command_array" ]]; then + case "$BASH_COMMAND" in + '(( __orca_exit_code == 0 ))'|'__orca_restore_prompt_status "$__orca_exit_code"'|'eval "$__orca_prompt_part"'|'eval "$__orca_final_prompt_command"'|__orca_dispatching_user_prompt_command=*|__orca_osc133_precmd|__orca_osc133_prompt_done|__orca_prompt_mark) return 0 ;; + esac + fi + elif [[ "${FUNCNAME[1]:-}" == "__orca_run_prompt_command_array" || "$BASH_COMMAND" == "__orca_run_prompt_command_array" ]]; then + return 0 + fi + [[ -z "${__orca_in_legacy_prompt_wrapper:-}" || -n "${__orca_dispatching_user_prompt_command:-}" ]] || return 0 + if [[ -n "${__orca_in_prompt_command:-}" && "$BASH_COMMAND" == "__orca_in_debug_capture=1" ]]; then + return 0 + fi + fi + case "${FUNCNAME[1]:-}" in __orca_osc133_*|__orca_prompt_mark|__orca_restore_prompt_status) return 0 ;; esac + case "$BASH_COMMAND" in __orca_osc133_precmd|__orca_osc133_prompt_done|__orca_prompt_mark) return 0 ;; esac + __orca_run_user_debug_trap + [[ -z "${__orca_in_prompt_command:-}" ]] || return 0 + [[ -z "${__orca_in_command:-}" ]] || return 0 + printf "\033]133;C\007" + __orca_in_command=1 +} +__orca_normalize_prompt_command_part() { + local __orca_value="$1" __orca_output_name="$2" __orca_character __orca_chunk + local __orca_value_length=${#1} __orca_suffix_length=0 __orca_backslash_length=0 + local __orca_output_length __orca_scan_start + while (( __orca_value_length - __orca_suffix_length >= 1024 )); do + __orca_scan_start=$(( __orca_value_length - __orca_suffix_length - 1024 )) + __orca_chunk="${__orca_value:__orca_scan_start:1024}" + case "$__orca_chunk" in + *[!$' \t\n;']*) break ;; + *) __orca_suffix_length=$(( __orca_suffix_length + 1024 )) ;; + esac + done + while (( __orca_suffix_length < __orca_value_length )); do + __orca_character="${__orca_value: -__orca_suffix_length - 1:1}" + case "$__orca_character" in + ' '|$'\t'|$'\n'|';') __orca_suffix_length=$(( __orca_suffix_length + 1 )) ;; + *) break ;; + esac + done + __orca_output_length=$(( ${#__orca_value} - __orca_suffix_length )) + while (( __orca_output_length - __orca_backslash_length >= 1024 )); do + __orca_scan_start=$(( __orca_output_length - __orca_backslash_length - 1024 )) + __orca_chunk="${__orca_value:__orca_scan_start:1024}" + case "$__orca_chunk" in + *[!\\]*) break ;; + *) __orca_backslash_length=$(( __orca_backslash_length + 1024 )) ;; + esac + done + while (( __orca_backslash_length < __orca_output_length )); do + __orca_character="${__orca_value:__orca_output_length - __orca_backslash_length - 1:1}" + [[ "$__orca_character" == '\' ]] || break + __orca_backslash_length=$(( __orca_backslash_length + 1 )) + done + # Preserve the first separator when an odd backslash run escapes it. + if (( __orca_suffix_length > 0 && __orca_backslash_length % 2 == 1 )); then + __orca_suffix_length=$(( __orca_suffix_length - 1 )) + __orca_backslash_length=0 + fi + __orca_output_length=$(( ${#__orca_value} - __orca_suffix_length )) + __orca_value="${__orca_value:0:__orca_output_length}" + # Bash 4.4-5.0 scalar prompt evaluation preserves an odd terminal backslash. + if (( __orca_suffix_length == 0 && ((BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4) || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] == 0)) && __orca_backslash_length % 2 == 1 )); then + __orca_value="$__orca_value\\" + fi + printf -v "$__orca_output_name" '%s' "$__orca_value" +} +__orca_restore_prompt_status() { + return "$1" +} +__orca_update_user_debug_trap() { + local __orca_debug_trap_spec="$1" __orca_unchanged_debug_trap_spec="$2" + local __orca_debug_trap_command + [[ "$__orca_debug_trap_spec" != "$__orca_unchanged_debug_trap_spec" ]] || return 0 + [[ "$__orca_debug_trap_spec" != "trap -- '__orca_osc133_preexec' DEBUG" ]] || return 0 + if [[ -z "$__orca_debug_trap_spec" ]]; then + __orca_user_debug_trap="" + unset __orca_chained_debug_trap + return 0 + fi + __orca_debug_trap_command="${__orca_debug_trap_spec#trap -- }" + __orca_debug_trap_command="${__orca_debug_trap_command% DEBUG}" + eval "__orca_user_debug_trap=$__orca_debug_trap_command" + unset __orca_chained_debug_trap +} +__orca_run_user_debug_trap() { + if [[ -n "${__orca_user_debug_trap:-}" ]]; then + eval "$__orca_user_debug_trap" || true + fi +} +__orca_adopt_outer_debug_trap() { + local __orca_debug_trap_spec="${__orca_outer_debug_trap_spec:-}" + unset __orca_outer_debug_trap_spec + __orca_update_user_debug_trap "$__orca_debug_trap_spec" "trap -- '__orca_osc133_preexec' DEBUG" +} +__orca_run_prompt_command_array() { + local __orca_exit_code="${__orca_prompt_status:-$?}" __orca_prompt_part __orca_prompt_index __orca_user_count + local __orca_suffix_part + local __orca_final_prompt_command + local __orca_in_prompt_dispatch=1 __orca_dispatching_user_prompt_command="" + unset __orca_prompt_status + __orca_adopt_outer_debug_trap + trap '__orca_osc133_preexec' DEBUG + for __orca_prompt_part in "${__orca_prompt_command_prefix[@]+"${__orca_prompt_command_prefix[@]}"}"; do + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + done + __orca_user_count=0 + for __orca_prompt_part in "${__orca_prompt_command_array[@]+"${__orca_prompt_command_array[@]}"}"; do + __orca_user_count=$(( __orca_user_count + 1 )) + done + for (( __orca_prompt_index = 0; __orca_prompt_index + 1 < __orca_user_count; __orca_prompt_index++ )); do + __orca_prompt_part="${__orca_prompt_command_array[__orca_prompt_index]}" + __orca_dispatching_user_prompt_command=1 + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + __orca_dispatching_user_prompt_command="" + done + if (( __orca_user_count > 0 )); then + __orca_prompt_part="${__orca_prompt_command_array[__orca_user_count - 1]}" + # Why: keep the final user hook and Orca suffixes in one status-preserving eval. + __orca_final_prompt_command='eval "$__orca_prompt_part"' + for __orca_suffix_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + __orca_final_prompt_command+=$'\n'"$__orca_suffix_part" + done + __orca_dispatching_user_prompt_command=1 + if (( __orca_exit_code == 0 )); then + eval "$__orca_final_prompt_command" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_final_prompt_command" + fi + __orca_dispatching_user_prompt_command="" + else + for __orca_prompt_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + if (( __orca_exit_code == 0 )); then + eval "$__orca_prompt_part" + else + __orca_restore_prompt_status "$__orca_exit_code" || eval "$__orca_prompt_part" + fi + done + fi + return "$__orca_exit_code" +} +__orca_finish_legacy_prompt_dispatch() { + local __orca_suffix_part + if [[ -n "${__orca_in_prompt_command:-}" ]]; then + for __orca_suffix_part in "${__orca_prompt_command_suffix[@]+"${__orca_prompt_command_suffix[@]}"}"; do + eval "$__orca_suffix_part" + done + fi + trap '__orca_osc133_preexec' DEBUG + unset __orca_in_legacy_prompt_wrapper +} +__orca_normalize_prompt_command() { + [[ -z "${__orca_prompt_command_normalized:-}" ]] || return 0 + local __orca_prompt_part + local -a __orca_normalized=() + for __orca_prompt_part in "${PROMPT_COMMAND[@]+"${PROMPT_COMMAND[@]}"}"; do + __orca_normalize_prompt_command_part "$__orca_prompt_part" __orca_prompt_part + [[ -n "$__orca_prompt_part" ]] && __orca_normalized+=("$__orca_prompt_part") + done + __orca_prompt_command_normalized=1 + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND=("${__orca_normalized[@]+"${__orca_normalized[@]}"}") + else + __orca_prompt_command_array=("${__orca_normalized[@]+"${__orca_normalized[@]}"}") + __orca_prompt_command_prefix=() + __orca_prompt_command_suffix=() + unset PROMPT_COMMAND + # Why: PID scope distinguishes legacy prompt dispatch from ordinary user command text. + __orca_prompt_status_variable="__orca_prompt_status_$$" + __orca_prompt_status_capture_command="$__orca_prompt_status_variable=\$?" + __orca_prompt_status_value="\${$__orca_prompt_status_variable}" + PROMPT_COMMAND="$__orca_prompt_status_capture_command; __orca_prompt_status=$__orca_prompt_status_value"'; __orca_prompt_had_functrace=""; if [[ -o functrace ]]; then __orca_prompt_had_functrace=1; set +T; fi; __orca_outer_debug_trap_spec="$(trap -p DEBUG)"; [[ -z "$__orca_prompt_had_functrace" ]] || set -T; unset __orca_prompt_had_functrace; __orca_run_prompt_command_array; __orca_finish_legacy_prompt_dispatch' + fi +} +__orca_prepend_prompt_command() { + local command="$1" + __orca_normalize_prompt_command + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND=("$command" "${PROMPT_COMMAND[@]+"${PROMPT_COMMAND[@]}"}") + else + __orca_prompt_command_prefix=("$command" "${__orca_prompt_command_prefix[@]+"${__orca_prompt_command_prefix[@]}"}") + fi +} +__orca_append_prompt_command() { + local command="$1" + __orca_normalize_prompt_command + if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then + PROMPT_COMMAND+=("$command") + else + __orca_prompt_command_suffix+=("$command") + fi +} +__orca_prepend_prompt_command "__orca_osc133_precmd" +# Why: SSH startup commands are renderer-delivered; emit the same internal +# readiness marker as local shells only when that delivery mode asks for it. +if [[ "${ORCA_SHELL_READY_MARKER:-0}" == "1" ]]; then + __orca_prompt_mark() { + printf "\033]777;orca-shell-ready\007" + } + __orca_append_prompt_command "__orca_prompt_mark" +fi +__orca_append_prompt_command '__orca_in_debug_capture=1; __orca_prompt_had_functrace=""; if [[ -o functrace ]]; then __orca_prompt_had_functrace=1; set +T; fi; __orca_outer_debug_trap_spec="$(trap -p DEBUG)"; [[ -z "$__orca_prompt_had_functrace" ]] || set -T; unset __orca_prompt_had_functrace __orca_in_debug_capture' +__orca_append_prompt_command "__orca_osc133_prompt_done" +__orca_had_functrace="" +[[ -o functrace ]] && __orca_had_functrace=1 +set +T +__orca_debug_trap_spec="$(trap -p DEBUG)" +[[ -z "$__orca_had_functrace" ]] || set -T +if [[ -n "$__orca_debug_trap_spec" && "$__orca_debug_trap_spec" != "trap -- '__orca_osc133_preexec' DEBUG" ]]; then + __orca_debug_trap_command="${__orca_debug_trap_spec#trap -- }" + __orca_debug_trap_command="${__orca_debug_trap_command% DEBUG}" + eval "__orca_user_debug_trap=$__orca_debug_trap_command" +fi +unset __orca_debug_trap_spec __orca_debug_trap_command __orca_had_functrace +unset -f __orca_normalize_prompt_command_part __orca_normalize_prompt_command __orca_prepend_prompt_command __orca_append_prompt_command +unset __orca_prompt_command_normalized +# Why: arm DEBUG after wrapper setup so the relay rcfile itself does not emit +# fake command-start/end markers before the first prompt. +__orca_initial_prompt=1 +trap '__orca_osc133_preexec' DEBUG +unset __orca_initializing_wrapper diff --git a/src/main/shell-wrapper-snapshots/relay-zsh-zlogin.txt b/src/main/shell-wrapper-snapshots/relay-zsh-zlogin.txt new file mode 100644 index 00000000000..26fff23cbbc --- /dev/null +++ b/src/main/shell-wrapper-snapshots/relay-zsh-zlogin.txt @@ -0,0 +1,91 @@ +# Orca relay zsh overlay wrapper +_orca_home="${ORCA_USER_ZDOTDIR:-${ORCA_ORIG_ZDOTDIR:-$HOME}}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -o interactive && -f "$_orca_home/.zlogin" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zlogin" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + +# Why: .zlogin is the final zsh login startup file before the prompt. +[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" +[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" +[[ -n "${ORCA_REMOTE_CLI_BIN_DIR:-}" ]] && case ":$PATH:" in *:"${ORCA_REMOTE_CLI_BIN_DIR}":*) ;; *) export PATH="${ORCA_REMOTE_CLI_BIN_DIR}:$PATH" ;; esac +# Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi +_orca_home="${ORCA_USER_ZDOTDIR:-${ORCA_ORIG_ZDOTDIR:-$HOME}}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +# Why: after Orca's last wrapper file has loaded, the interactive shell should +# expose the same ZDOTDIR a normal zsh startup would expose. +export ZDOTDIR="$_orca_home" +unset _orca_home + +if [[ "${ORCA_SHELL_READY_MARKER:-0}" == "1" ]]; then + # Why: capture the prior zle-line-init so the marker chains to it. On a + # re-source we are already the bound widget, so keep the function captured + # the first time instead of clobbering it to empty (which would silently + # drop the user's widget on every prompt after the second source). Only + # user-defined widgets are chainable as plain functions; builtin/completion + # forms (rare for zle-line-init) are left unchained. + if [[ "${widgets[zle-line-init]:-}" == "user:__orca_prompt_mark" ]]; then + : + elif (( ${+widgets[zle-line-init]} )) && [[ "${widgets[zle-line-init]}" == user:* ]]; then + __orca_prev_line_init_fn="${widgets[zle-line-init]#user:}" + else + __orca_prev_line_init_fn="" + fi + __orca_prompt_mark() { + printf "\033]777;orca-shell-ready\007" + # 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. + if [[ -n "${__orca_prev_line_init_fn:-}" ]]; then + "${__orca_prev_line_init_fn}" "$@" + fi + } + zle -N zle-line-init __orca_prompt_mark +fi + diff --git a/src/main/shell-wrapper-snapshots/relay-zsh-zprofile.txt b/src/main/shell-wrapper-snapshots/relay-zsh-zprofile.txt new file mode 100644 index 00000000000..2e14e174e94 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/relay-zsh-zprofile.txt @@ -0,0 +1,15 @@ +# Orca relay zsh overlay wrapper +_orca_home="${ORCA_USER_ZDOTDIR:-${ORCA_ORIG_ZDOTDIR:-$HOME}}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -f "$_orca_home/.zprofile" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zprofile" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + diff --git a/src/main/shell-wrapper-snapshots/relay-zsh-zshenv.txt b/src/main/shell-wrapper-snapshots/relay-zsh-zshenv.txt new file mode 100644 index 00000000000..54eb71abe0d --- /dev/null +++ b/src/main/shell-wrapper-snapshots/relay-zsh-zshenv.txt @@ -0,0 +1,15 @@ +# Orca relay zsh overlay wrapper +if [[ "${ORCA_SHELL_STARTUP_IDENTITY:-0}" == "1" ]]; then + unset ORCA_SHELL_STARTUP_IDENTITY + printf "\033]777;orca-shell-start:%s\007" "$$" +fi +export ORCA_ORIG_ZDOTDIR="${ORCA_ORIG_ZDOTDIR:-$HOME}" +case "${ORCA_ORIG_ZDOTDIR%/}" in + */shell-ready/zsh) export ORCA_ORIG_ZDOTDIR="$HOME" ;; +esac +[[ -f "$ORCA_ORIG_ZDOTDIR/.zshenv" ]] && source "$ORCA_ORIG_ZDOTDIR/.zshenv" +export ORCA_USER_ZDOTDIR="${ZDOTDIR:-${ORCA_ORIG_ZDOTDIR:-$HOME}}" +case "${ORCA_USER_ZDOTDIR%/}" in + */shell-ready/zsh) export ORCA_USER_ZDOTDIR="$HOME" ;; +esac +export ZDOTDIR='/zsh' diff --git a/src/main/shell-wrapper-snapshots/relay-zsh-zshrc.txt b/src/main/shell-wrapper-snapshots/relay-zsh-zshrc.txt new file mode 100644 index 00000000000..d9af197bb17 --- /dev/null +++ b/src/main/shell-wrapper-snapshots/relay-zsh-zshrc.txt @@ -0,0 +1,70 @@ +# Orca relay zsh overlay wrapper +_orca_home="${ORCA_USER_ZDOTDIR:-${ORCA_ORIG_ZDOTDIR:-$HOME}}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +if [[ -o interactive && -f "$_orca_home/.zshrc" ]]; then + _orca_wrapper_zdotdir="$ZDOTDIR" + # Why: user startup files resolve plugin/config paths from their own ZDOTDIR; + # Orca restores its wrapper dir afterward so zsh still loads wrapper files. + export ZDOTDIR="$_orca_home" + source "$_orca_home/.zshrc" + export ZDOTDIR="$_orca_wrapper_zdotdir" + unset _orca_wrapper_zdotdir +fi + +if [[ ! -o login ]]; then + # Why: remote startup files can re-export user defaults after relay spawn. + [[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}" + [[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}" + [[ -n "${ORCA_REMOTE_CLI_BIN_DIR:-}" ]] && case ":$PATH:" in *:"${ORCA_REMOTE_CLI_BIN_DIR}":*) ;; *) export PATH="${ORCA_REMOTE_CLI_BIN_DIR}:$PATH" ;; esac + # Why: OMP does not auto-load Orca's managed status extension; wrap only +# interactive launch invocations so subcommands such as `omp config` keep +# their normal argv shape. +__orca_omp_should_skip_extension() { + case "${1:-}" in + help|--help|-h|--version|-v) return 0 ;; + __complete|acp|agents|auth-broker|auth-gateway|bench|commit|completions|config|dry-balance|gallery|grep|grievances|install|join|models|plugin|read|say|search|setup|shell|ssh|stats|tiny-models|token|ttsr|update|usage|worktree|q|wt) return 0 ;; + esac + return 1 +} +__orca_omp() { + local __orca_use_extension=1 + __orca_omp_should_skip_extension "${1:-}" && __orca_use_extension=0 + if [[ $__orca_use_extension -eq 1 && -n "${ORCA_OMP_STATUS_EXTENSION:-}" && -f "${ORCA_OMP_STATUS_EXTENSION}" ]]; then + if [[ "${1:-}" == "launch" ]]; then + shift + command omp launch --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + else + command omp --extension "${ORCA_OMP_STATUS_EXTENSION}" "$@" + fi + else + command omp "$@" + fi +} +if [[ -n "${ORCA_OMP_STATUS_EXTENSION:-}" ]]; then + omp() { __orca_omp "$@"; } +fi + +if [[ -n "${ORCA_HISTFILE:-}" ]]; then + HISTFILE="$ORCA_HISTFILE" +elif [[ "${HISTFILE:-}" == "$ZDOTDIR/.zsh_history" ]]; then + # Why also when Orca injected nothing: /etc/zshrc derived this from Orca's + # wrapper ZDOTDIR, so history would accumulate INSIDE the wrapper dir and the + # user's real history would be invisible — the plain #11044 bug, with no + # per-worktree scoping involved. Matching the exact clobbered value means a + # HISTFILE the user set deliberately is never touched. + HISTFILE="${ORCA_ORIG_ZDOTDIR:-$HOME}/.zsh_history" +fi +fi +if [[ ! -o login ]]; then +_orca_home="${ORCA_USER_ZDOTDIR:-${ORCA_ORIG_ZDOTDIR:-$HOME}}" +case "${_orca_home%/}" in + */shell-ready/zsh) _orca_home="$HOME" ;; +esac +# Why: after Orca's last wrapper file has loaded, the interactive shell should +# expose the same ZDOTDIR a normal zsh startup would expose. +export ZDOTDIR="$_orca_home" +unset _orca_home + +fi