diff --git a/src/main/pty/shell-startup/codex-shell-no-daemon.test.ts b/src/main/pty/shell-startup/codex-shell-no-daemon.test.ts index d82bd72c16b..78a70bbd3e7 100644 --- a/src/main/pty/shell-startup/codex-shell-no-daemon.test.ts +++ b/src/main/pty/shell-startup/codex-shell-no-daemon.test.ts @@ -236,7 +236,15 @@ describe('codex wrapper --no-daemon rule', () => { ['0', undefined, undefined, '', '0'], ['1', '', undefined, '', '0'], ['1', '10.0.0.1 5000 10.0.0.2 22', undefined, '10.0.0.1 5000 10.0.0.2 22', '0'], - ['1', undefined, '/dev/ttys004', '', '0'] + ['1', undefined, '/dev/ttys004', '', '0'], + // Pane-level marker from a remote-viewer Codex launch. + [ + '0', + CODEX_REMOTE_VIEWER_SSH_CONNECTION, + undefined, + CODEX_REMOTE_VIEWER_SSH_CONNECTION, + '0' + ] ].filter(([, inherited]) => !isPowerShell(shell) || inherited !== '') )( 'routes manual copies for remote=%s without marking the parent shell', @@ -253,8 +261,13 @@ describe('codex wrapper --no-daemon rule', () => { ...(inheritedTty ? { SSH_TTY: inheritedTty } : {}) }) expect(result.status, result.stderr).toBe(Number(exitCode)) + // Codex keeps the marker for OSC 52, but blanks it for the commands it runs. + const clearMarker = + expected === CODEX_REMOTE_VIEWER_SSH_CONNECTION + ? "-c|shell_environment_policy.set.SSH_CONNECTION=''|" + : '' expect(lines(result.stdout)).toEqual([ - `ARGV|--no-daemon|clipboard|ssh=${expected}`, + `ARGV|--no-daemon|${clearMarker}clipboard|ssh=${expected}`, `ARGV|shell|ssh=${inherited ?? ''}` ]) } diff --git a/src/shared/codex-shell-function.ts b/src/shared/codex-shell-function.ts index dc344821405..c217b2d2109 100644 --- a/src/shared/codex-shell-function.ts +++ b/src/shared/codex-shell-function.ts @@ -19,6 +19,10 @@ export const CODEX_COMMAND_IDENTITY_ENV_KEYS = [ 'ORCA_USER_DATA_PATH' ] as const +// Blank Orca's clipboard marker for commands Codex runs: agy reads SSH_CONNECTION as a remote host and ignores its local login (#37723). +// Why set, not exclude: -c exclude would replace the user's own exclude list. Real SSH never reports port 0. +const CLEAR_SSH_MARKER_ARG = "shell_environment_policy.set.SSH_CONNECTION=''" + // Skip apostrophes: TOML literals cannot hold them and Codex parse fallback may truncate paths; missing identity is safer than wrong identity. const identitySetArg = (key: string, value: string): string => `shell_environment_policy.set.${key}='${value}'` @@ -50,6 +54,7 @@ if [[ -n "\${__orca_codex_binary:-}" && -x "\${__orca_codex_binary}" ]]; then done if [[ "$__orca_codex_identity" != 0 ]]; then ${CODEX_COMMAND_IDENTITY_ENV_KEYS.map((key) => ` [[ -z "\${${key}:-}" || "\${${key}}" == *"'"* ]] || set -- -c "${identitySetArg(key, `\${${key}}`)}" "$@"`).join('\n')} + [[ "\${SSH_CONNECTION:-}" != '${CODEX_REMOTE_VIEWER_SSH_CONNECTION}' ]] || set -- -c "${CLEAR_SSH_MARKER_ARG}" "$@" fi # Why probe every launch: a cached answer goes stale across an upgrade, and 0.155 and older exit 2 on the flag. if [[ "$__orca_codex_isolate" != 0 ]]; then @@ -74,6 +79,9 @@ if test "$__orca_codex_type" = file end if test "$ORCA_CODEX_ISOLATE" != 0; and not string match -qr -- '${CODEX_SHARED_SERVER_ARG_PATTERN}' $argv ${CODEX_COMMAND_IDENTITY_ENV_KEYS.map((key) => ` test -n "$${key}"; and not string match -q -- "*'*" "$${key}"; and set argv -c "${identitySetArg(key, `$${key}`)}" $argv`).join('\n')} + if test "$SSH_CONNECTION" = '${CODEX_REMOTE_VIEWER_SSH_CONNECTION}'; or begin; test "$${REMOTE_VIEWER_CLIPBOARD_ENV}" = 1; and not set -q SSH_CONNECTION; and not set -q SSH_TTY; end + set argv -c "${CLEAR_SSH_MARKER_ARG}" $argv + end end if test "$ORCA_CODEX_ISOLATE" != 0; and not string match -qr -- '${CODEX_NO_DAEMON_SKIP_ARG_PATTERN}' $argv; and command codex --help 2>/dev/null `'${key}'`).join(',')}) { $v = [Environment]::GetEnvironmentVariable($k); if ($v -and -not $v.Contains("'")) { $orcaCodexIdentity += '-c', "${identitySetArg('$k', '$v')}" } } + if ($orcaCodexRemoteClipboard -or $env:SSH_CONNECTION -ceq '${CODEX_REMOTE_VIEWER_SSH_CONNECTION}') { $orcaCodexIdentity += '-c', "${CLEAR_SSH_MARKER_ARG}" } } $orcaCodexArgs = @(__OrcaEscapeNativeArgs $orcaCodexExecutable.Source (@($orcaCodexIdentity) + @($args))) - $orcaCodexRemoteClipboard = $env:${REMOTE_VIEWER_CLIPBOARD_ENV} -eq '1' -and -not (Test-Path Env:SSH_CONNECTION) -and -not (Test-Path Env:SSH_TTY) if ($orcaCodexRemoteClipboard) { $env:SSH_CONNECTION = '${CODEX_REMOTE_VIEWER_SSH_CONNECTION}' } # Why: a native command inside a function never sees the function's pipeline input on its own. try {