Revert "Fix Claude PR hyperlinks in terminal" (#5826)

This commit is contained in:
Neil 2026-06-19 12:29:13 -07:00 committed by GitHub
parent 2226e3cbc2
commit 5dbff5d8ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 43 additions and 66 deletions

View File

@ -21,7 +21,6 @@ import { resolveEffectiveWindowsPowerShell } from '../providers/windows-powershe
import { isPwshAvailable } from '../pwsh'
import { isHostCodexHomeForWsl, isWslCodexHomeForHost } from '../pty/codex-home-wsl-env'
import { removeInheritedNoColor } from '../pty/terminal-color-env'
import { buildTerminalCapabilityEnv } from '../../shared/terminal-capability-env'
import { parseWslPath } from '../wsl'
import { addWslEnvKeys } from '../wsl-env'
import { getWslContextFromSessionId } from './wsl-session-context'
@ -402,7 +401,21 @@ export function createPtySubprocess(opts: PtySubprocessOptions): SubprocessHandl
const env: Record<string, string> = {
...process.env,
...opts.env,
...buildTerminalCapabilityEnv(process.env.ORCA_APP_VERSION ?? '0.0.0-dev')
TERM: 'xterm-256color',
COLORTERM: 'truecolor',
TERM_PROGRAM: 'Orca',
// Why: TUIs feature-gate on TERM_PROGRAM_VERSION. The daemon is forked
// by main (daemon-init.ts:93) with the parent's env, so ORCA_APP_VERSION
// — set in src/main/index.ts from app.getVersion() — is inherited here.
TERM_PROGRAM_VERSION: process.env.ORCA_APP_VERSION ?? '0.0.0-dev',
// Why: opt tools (Claude Code, ls --hyperlink, etc.) into emitting OSC 8
// hyperlinks. The `supports-hyperlinks` npm package gates on a hard-coded
// TERM_PROGRAM allowlist (iTerm.app / WezTerm / vscode) and returns false
// for TERM_PROGRAM=Orca, so callers drop OSC 8 output entirely and emit
// bare text instead. xterm.js in Orca parses OSC 8 and the pane's
// linkHandler routes clicks, so forcing the advertisement is safe and
// restores clickable refs like `owner/repo#123` / `PR#123`.
FORCE_HYPERLINK: '1'
} as Record<string, string>
for (const key of opts.envToDelete ?? []) {
delete env[key]

View File

@ -629,30 +629,31 @@ describe('registerPtyHandlers', () => {
expect(env.LANG).toBe('fr_FR.UTF-8')
})
it('advertises xterm.js-compatible terminal capabilities while preserving Orca identity', async () => {
it('always sets TERM and COLORTERM regardless of env', async () => {
const env = await spawnAndGetEnv()
expect(env.TERM).toBe('xterm-256color')
expect(env.COLORTERM).toBe('truecolor')
expect(env.TERM_PROGRAM).toBe('vscode')
expect(env.TERM_PROGRAM_VERSION).toBe('1.100.0')
expect(env.ORCA_TERM_PROGRAM).toBe('Orca')
expect(env.TERM_PROGRAM).toBe('Orca')
})
it('advertises OSC 8 hyperlink support via FORCE_HYPERLINK', async () => {
// Why: some hyperlink detectors still miss Electron embedders even with
// xterm.js-compatible TERM_PROGRAM values; Orca routes OSC 8 natively.
// Why: the supports-hyperlinks npm package hard-codes a TERM_PROGRAM
// allowlist (iTerm.app / WezTerm / vscode) and reports false for
// TERM_PROGRAM=Orca, so tools like Claude Code emit plain text instead
// of ESC]8;; wrappers. Setting FORCE_HYPERLINK=1 forces the detector to
// return true; xterm.js + our linkHandler handle the sequences natively.
const env = await spawnAndGetEnv()
expect(env.FORCE_HYPERLINK).toBe('1')
})
it('surfaces ORCA_APP_VERSION as ORCA_TERM_PROGRAM_VERSION for Orca identity', async () => {
it('surfaces ORCA_APP_VERSION as TERM_PROGRAM_VERSION for TUI feature gating', async () => {
const env = await spawnAndGetEnv(undefined, { ORCA_APP_VERSION: '1.2.3-test' })
expect(env.ORCA_TERM_PROGRAM_VERSION).toBe('1.2.3-test')
expect(env.TERM_PROGRAM_VERSION).toBe('1.2.3-test')
})
it('falls back to a placeholder Orca version when ORCA_APP_VERSION is unset', async () => {
it('falls back to a placeholder version when ORCA_APP_VERSION is unset', async () => {
const env = await spawnAndGetEnv(undefined, { ORCA_APP_VERSION: undefined })
expect(env.ORCA_TERM_PROGRAM_VERSION).toBe('0.0.0-dev')
expect(env.TERM_PROGRAM_VERSION).toBe('0.0.0-dev')
})
it('injects the selected Codex home into Orca terminal PTYs', async () => {

View File

@ -31,7 +31,6 @@ import {
STARTUP_COMMAND_READY_MAX_WAIT_MS
} from './local-pty-shell-ready'
import { removeInheritedNoColor } from '../pty/terminal-color-env'
import { buildTerminalCapabilityEnv } from '../../shared/terminal-capability-env'
import { isHostCodexHomeForWsl, isWslCodexHomeForHost } from '../pty/codex-home-wsl-env'
import { addWslEnvKeys } from '../wsl-env'
import {
@ -407,7 +406,22 @@ export class LocalPtyProvider implements IPtyProvider {
const spawnEnv: Record<string, string> = {
...process.env,
...args.env,
...buildTerminalCapabilityEnv(process.env.ORCA_APP_VERSION ?? '0.0.0-dev')
TERM: 'xterm-256color',
COLORTERM: 'truecolor',
TERM_PROGRAM: 'Orca',
// Why: TUIs feature-gate on TERM_PROGRAM_VERSION (Neovim's termcap
// autodetection, bat/delta paging hints). Sourced from ORCA_APP_VERSION
// which main/index.ts seeds from app.getVersion() at startup; the
// fallback keeps tests and non-Electron runs working.
TERM_PROGRAM_VERSION: process.env.ORCA_APP_VERSION ?? '0.0.0-dev',
// Why: opt tools (Claude Code, ls --hyperlink, etc.) into emitting OSC 8
// hyperlinks. The `supports-hyperlinks` npm package gates on a hard-coded
// TERM_PROGRAM allowlist (iTerm.app / WezTerm / vscode) and returns false
// for TERM_PROGRAM=Orca, so callers drop OSC 8 output entirely and emit
// bare text instead. xterm.js in Orca parses OSC 8 and the pane's
// linkHandler routes clicks, so forcing the advertisement is safe and
// restores clickable refs like `owner/repo#123` / `PR#123`.
FORCE_HYPERLINK: '1'
} as Record<string, string>
// Why: Orca can be launched from an Orca terminal while developing. Pane
// identity belongs to the child PTY, not the parent shell that spawned app.

View File

@ -162,15 +162,6 @@ describe('PtyHandler', () => {
const result = await dispatcher.callRequest('pty.spawn', { cols: 80, rows: 24 })
expect(result).toEqual({ id: 'pty-1' })
expect(mockPtySpawn).toHaveBeenCalled()
const spawnOptions = mockPtySpawn.mock.calls[0]?.[2]
expect(spawnOptions?.env).toMatchObject({
TERM: 'xterm-256color',
COLORTERM: 'truecolor',
TERM_PROGRAM: 'vscode',
TERM_PROGRAM_VERSION: '1.100.0',
ORCA_TERM_PROGRAM: 'Orca',
FORCE_HYPERLINK: '1'
})
expect(handler.activePtyCount).toBe(1)
})

View File

@ -13,7 +13,6 @@ import {
import { getRelayShellLaunchConfig } from './pty-shell-launch'
import { DEFAULT_SSH_RELAY_GRACE_PERIOD_SECONDS } from '../shared/ssh-types'
import { shouldUseShellReadyStartupDelivery } from '../shared/codex-startup-delivery'
import { buildTerminalCapabilityEnv } from '../shared/terminal-capability-env'
// Why: node-pty is a native addon that may not be installed on the remote.
// Dynamic import keeps the require() lazy so loadPty() returns null gracefully
@ -209,11 +208,7 @@ export class PtyHandler {
rendererEnv: Record<string, string> | undefined,
ctx: { id: string; paneKey?: string; shell: string; command?: string }
): Record<string, string> {
const baseEnv = {
...process.env,
...rendererEnv,
...buildTerminalCapabilityEnv(process.env.ORCA_APP_VERSION ?? '0.0.0-dev')
} as Record<string, string>
const baseEnv = { ...process.env, ...rendererEnv } as Record<string, string>
const augmented: Record<string, string> = {}
for (const augmenter of this.envAugmenters) {
try {

View File

@ -1,18 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildTerminalCapabilityEnv } from './terminal-capability-env'
describe('buildTerminalCapabilityEnv', () => {
it('advertises xterm.js-compatible hyperlink capabilities and Orca identity', () => {
const env = buildTerminalCapabilityEnv('1.2.3')
expect(env).toEqual({
TERM: 'xterm-256color',
COLORTERM: 'truecolor',
TERM_PROGRAM: 'vscode',
TERM_PROGRAM_VERSION: '1.100.0',
ORCA_TERM_PROGRAM: 'Orca',
ORCA_TERM_PROGRAM_VERSION: '1.2.3',
FORCE_HYPERLINK: '1'
})
})
})

View File

@ -1,19 +0,0 @@
const XTERM_JS_COMPATIBLE_TERM_PROGRAM = 'vscode'
const XTERM_JS_COMPATIBLE_TERM_PROGRAM_VERSION = '1.100.0'
export function buildTerminalCapabilityEnv(appVersion: string): Record<string, string> {
return {
TERM: 'xterm-256color',
COLORTERM: 'truecolor',
// Why: Claude Code and other CLIs gate OSC 8 links on known xterm.js
// embedders. Do not change this back to "Orca": that makes PR links
// render as plain text. ORCA_* keeps our real app identity available.
TERM_PROGRAM: XTERM_JS_COMPATIBLE_TERM_PROGRAM,
TERM_PROGRAM_VERSION: XTERM_JS_COMPATIBLE_TERM_PROGRAM_VERSION,
ORCA_TERM_PROGRAM: 'Orca',
ORCA_TERM_PROGRAM_VERSION: appVersion,
// Why: supports-hyperlinks can still miss Electron embedders; force OSC 8
// output because Orca parses and routes those links natively.
FORCE_HYPERLINK: '1'
}
}