mirror of
https://github.com/stablyai/orca.git
synced 2026-10-19 00:03:20 +00:00
124 lines
4.3 KiB
TypeScript
124 lines
4.3 KiB
TypeScript
import type { ClaudeRuntimeAuthPreparation } from '../claude-accounts/runtime-auth-service'
|
|
import { applyClaudeEnvPatch } from '../claude-accounts/environment'
|
|
import { readShellStartupEnvVar } from '../pty/shell-startup-env'
|
|
import { parseWslUncPath } from '../../shared/wsl-paths'
|
|
|
|
export type CommitMessageAgentEnvironmentResolvers = {
|
|
prepareForCodexLaunch?: (target?: CommitMessageAgentRuntimeTarget) => string | null
|
|
prepareForClaudeLaunch?: (
|
|
target?: CommitMessageAgentRuntimeTarget
|
|
) => Promise<ClaudeRuntimeAuthPreparation>
|
|
}
|
|
|
|
export type CommitMessageAgentRuntimeTarget = {
|
|
runtime?: 'host' | 'wsl'
|
|
wslDistro?: string | null
|
|
}
|
|
|
|
function cloneProcessEnv(): Record<string, string> {
|
|
const env: Record<string, string> = {}
|
|
for (const [key, value] of Object.entries(process.env)) {
|
|
if (value !== undefined) {
|
|
env[key] = value
|
|
}
|
|
}
|
|
return env
|
|
}
|
|
|
|
function readInheritedOrShellEnvVar(name: string, sourceName?: string): string | undefined {
|
|
return (
|
|
(sourceName ? process.env[sourceName] : undefined) ??
|
|
process.env[name] ??
|
|
readShellStartupEnvVar(name, process.env.HOME, process.env.SHELL)
|
|
)
|
|
}
|
|
|
|
function prepareShellConfigDirEnv(agentId: string): { ok: true; env?: NodeJS.ProcessEnv } | null {
|
|
const configVar =
|
|
agentId === 'opencode'
|
|
? 'OPENCODE_CONFIG_DIR'
|
|
: agentId === 'pi' || agentId === 'omp'
|
|
? 'PI_CODING_AGENT_DIR'
|
|
: null
|
|
if (!configVar) {
|
|
return null
|
|
}
|
|
// Why: each kind owns a distinct ORCA_*_SOURCE_* shadow so a headless commit
|
|
// run from inside a legacy OMP overlay restores the OMP source dir, never
|
|
// the Pi one (and vice versa). PI_CODING_AGENT_DIR is the binary-facing var
|
|
// both kinds consume — see src/main/pi/titlebar-extension-service.ts.
|
|
const sourceVar =
|
|
agentId === 'opencode'
|
|
? 'ORCA_OPENCODE_SOURCE_CONFIG_DIR'
|
|
: agentId === 'pi'
|
|
? 'ORCA_PI_SOURCE_AGENT_DIR'
|
|
: agentId === 'omp'
|
|
? 'ORCA_OMP_SOURCE_AGENT_DIR'
|
|
: undefined
|
|
|
|
const value = readInheritedOrShellEnvVar(configVar, sourceVar)
|
|
if (!value) {
|
|
return { ok: true }
|
|
}
|
|
|
|
// Why: GUI-launched Orca may not inherit shell startup exports, but these
|
|
// vars point the headless CLI at the user's auth/config root. Nested Orca
|
|
// launches inherit PTY overlays, so prefer ORCA_*_SOURCE_* when present.
|
|
return { ok: true, env: { ...cloneProcessEnv(), [configVar]: value } }
|
|
}
|
|
|
|
export async function prepareLocalCommitMessageAgentEnv(
|
|
agentId: string,
|
|
resolvers: CommitMessageAgentEnvironmentResolvers | undefined,
|
|
target?: CommitMessageAgentRuntimeTarget
|
|
): Promise<{ ok: true; env?: NodeJS.ProcessEnv } | { ok: false; error: string }> {
|
|
const shellConfigEnv = target?.runtime === 'wsl' ? null : prepareShellConfigDirEnv(agentId)
|
|
if (shellConfigEnv) {
|
|
return shellConfigEnv
|
|
}
|
|
if (!resolvers) {
|
|
return { ok: true }
|
|
}
|
|
|
|
try {
|
|
if (agentId === 'codex' && resolvers.prepareForCodexLaunch) {
|
|
const codexHomePath = resolvers.prepareForCodexLaunch(target)
|
|
const wslCodexHome = codexHomePath ? parseWslUncPath(codexHomePath) : null
|
|
if (target?.runtime === 'wsl') {
|
|
const codexHomeForTarget = wslCodexHome?.linuxPath ?? null
|
|
return {
|
|
ok: true,
|
|
env: codexHomeForTarget
|
|
? { ...cloneProcessEnv(), CODEX_HOME: codexHomeForTarget }
|
|
: undefined
|
|
}
|
|
}
|
|
if (codexHomePath && wslCodexHome) {
|
|
// Why: this local generation path spawns the host Codex binary. A WSL
|
|
// managed home is only valid when the process is routed through wsl.exe.
|
|
return { ok: true }
|
|
}
|
|
return {
|
|
ok: true,
|
|
env: codexHomePath ? { ...cloneProcessEnv(), CODEX_HOME: codexHomePath } : undefined
|
|
}
|
|
}
|
|
|
|
if (agentId === 'claude' && resolvers.prepareForClaudeLaunch) {
|
|
const preparation = await resolvers.prepareForClaudeLaunch(target)
|
|
const env = applyClaudeEnvPatch(cloneProcessEnv(), preparation.envPatch, {
|
|
stripAuthEnv: preparation.stripAuthEnv
|
|
})
|
|
return { ok: true, env }
|
|
}
|
|
} catch (error) {
|
|
console.error('[commit-message] Failed to prepare agent environment:', error)
|
|
return {
|
|
ok: false,
|
|
error: 'Failed to prepare the selected agent account for commit message generation.'
|
|
}
|
|
}
|
|
|
|
return { ok: true }
|
|
}
|