mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 16:02:56 +00:00
fix Claude managed runtime routing and pane environment
This commit is contained in:
@@ -7,6 +7,7 @@ export const CLAUDE_AUTH_ENV_VARS = [
|
||||
|
||||
export type ClaudeEnvPatch = {
|
||||
CLAUDE_CONFIG_DIR?: string
|
||||
ORCA_CLAUDE_CONFIG_DIR?: string
|
||||
ANTHROPIC_CUSTOM_HEADERS?: string
|
||||
}
|
||||
|
||||
@@ -27,6 +28,9 @@ export function applyClaudeEnvPatch(
|
||||
if (patch.CLAUDE_CONFIG_DIR && !baseEnv.CLAUDE_CONFIG_DIR) {
|
||||
baseEnv.CLAUDE_CONFIG_DIR = patch.CLAUDE_CONFIG_DIR
|
||||
}
|
||||
if (patch.ORCA_CLAUDE_CONFIG_DIR && !baseEnv.ORCA_CLAUDE_CONFIG_DIR) {
|
||||
baseEnv.ORCA_CLAUDE_CONFIG_DIR = patch.ORCA_CLAUDE_CONFIG_DIR
|
||||
}
|
||||
if (patch.ANTHROPIC_CUSTOM_HEADERS !== undefined) {
|
||||
baseEnv.ANTHROPIC_CUSTOM_HEADERS = patch.ANTHROPIC_CUSTOM_HEADERS
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import type { Store } from '../persistence'
|
||||
import {
|
||||
getSelectedClaudeAccountIdForTarget,
|
||||
@@ -124,6 +125,17 @@ export class ClaudeRuntimeAuthService extends ClaudeRuntimeAuthSync {
|
||||
process.platform === 'darwin'
|
||||
? () => readActiveClaudeKeychainCredentialsStrict()
|
||||
: undefined,
|
||||
readLegacyOauthAccount: () => {
|
||||
try {
|
||||
const parsed = JSON.parse(readFileSync(paths.configPath, 'utf-8')) as Record<
|
||||
string,
|
||||
unknown
|
||||
>
|
||||
return parsed.oauthAccount ?? null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
},
|
||||
readManagedCredentials: (account) => this.readManagedCredentials(account),
|
||||
writeManagedCredentials: (account, contents) =>
|
||||
this.writeManagedCredentials(account, contents)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { existsSync, lstatSync, mkdirSync, symlinkSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import type { ClaudeManagedAccount } from '../../../shared/managed-account-types'
|
||||
import { resolveLocalAccountRuntimeTarget } from '../../../shared/local-account-runtime'
|
||||
@@ -44,7 +45,10 @@ export class ClaudeRuntimeAuthPreparationService extends ClaudeRuntimeAuthSnapsh
|
||||
runtime: 'wsl',
|
||||
wslDistro: activeAccount.wslDistro ?? null,
|
||||
wslLinuxConfigDir: activeAccount.wslLinuxAuthPath,
|
||||
envPatch: { CLAUDE_CONFIG_DIR: activeAccount.wslLinuxAuthPath },
|
||||
envPatch: {
|
||||
CLAUDE_CONFIG_DIR: activeAccount.wslLinuxAuthPath,
|
||||
ORCA_CLAUDE_CONFIG_DIR: activeAccount.wslLinuxAuthPath
|
||||
},
|
||||
stripAuthEnv: true,
|
||||
provenance: `managed:${activeAccount.id}:wsl:${activeAccount.wslDistro ?? ''}`
|
||||
}
|
||||
@@ -84,12 +88,16 @@ export class ClaudeRuntimeAuthPreparationService extends ClaudeRuntimeAuthSnapsh
|
||||
{ adoptLegacyMarker: true }
|
||||
)
|
||||
if (managedPath) {
|
||||
provisionClaudeManagedHome(paths.configDir, managedPath)
|
||||
return {
|
||||
configDir: managedPath,
|
||||
runtime: 'host',
|
||||
wslDistro: null,
|
||||
wslLinuxConfigDir: null,
|
||||
envPatch: { CLAUDE_CONFIG_DIR: managedPath },
|
||||
envPatch: {
|
||||
CLAUDE_CONFIG_DIR: managedPath,
|
||||
ORCA_CLAUDE_CONFIG_DIR: managedPath
|
||||
},
|
||||
stripAuthEnv: true,
|
||||
provenance: `managed:${activeAccount.id}`
|
||||
}
|
||||
@@ -145,3 +153,26 @@ export class ClaudeRuntimeAuthPreparationService extends ClaudeRuntimeAuthSnapsh
|
||||
return defaultDistro ? { runtime: 'wsl', wslDistro: defaultDistro } : target
|
||||
}
|
||||
}
|
||||
|
||||
// Keep account homes useful without copying credential-bearing runtime state.
|
||||
// Missing user resources are linked once; existing files remain user-owned.
|
||||
function provisionClaudeManagedHome(systemConfigDir: string, managedPath: string): void {
|
||||
if (systemConfigDir === managedPath) {
|
||||
return
|
||||
}
|
||||
const resources = ['settings.json', 'CLAUDE.md', 'projects', 'plugins'] as const
|
||||
for (const name of resources) {
|
||||
const source = join(systemConfigDir, name)
|
||||
const target = join(managedPath, name)
|
||||
if (!existsSync(source) || existsSync(target)) {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
const sourceIsDirectory = lstatSync(source).isDirectory()
|
||||
mkdirSync(managedPath, { recursive: true, mode: 0o700 })
|
||||
symlinkSync(source, target, sourceIsDirectory ? 'dir' : 'file')
|
||||
} catch {
|
||||
// Best effort: auth routing remains safe if an optional resource cannot link.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export class ClaudeRuntimePathResolver {
|
||||
configDir,
|
||||
credentialsPath: join(configDir, '.credentials.json'),
|
||||
configPath: this.resolveConfigPath(configDir, inheritedConfigDir),
|
||||
envPatch: inheritedConfigDir ? { CLAUDE_CONFIG_DIR: configDir } : {}
|
||||
envPatch: { CLAUDE_CONFIG_DIR: configDir, ORCA_CLAUDE_CONFIG_DIR: configDir }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,10 @@ export async function preparePtyIpcSpawnPreflight(ctx: PtyIpcSpawnState): Promis
|
||||
)
|
||||
try {
|
||||
ctx.claudeAuth =
|
||||
ctx.isClaudeLaunch && ctx.deps.prepareClaudeAuth
|
||||
!ctx.preAdoptedStablePane &&
|
||||
!args.connectionId &&
|
||||
(ctx.isClaudeLaunch || !ctx.launchCommand) &&
|
||||
ctx.deps.prepareClaudeAuth
|
||||
? await ctx.deps.prepareClaudeAuth(initialSelectionTarget)
|
||||
: null
|
||||
} catch (error) {
|
||||
|
||||
@@ -131,7 +131,10 @@ export async function prepareRuntimePtySpawn(
|
||||
ctx.launchCommand = codexResumeLaunch.command
|
||||
try {
|
||||
ctx.claudeAuth =
|
||||
ctx.isClaudeLaunch && ctx.deps.prepareClaudeAuth
|
||||
!ctx.preAdoptedStablePane &&
|
||||
!args.connectionId &&
|
||||
(ctx.isClaudeLaunch || !ctx.launchCommand) &&
|
||||
ctx.deps.prepareClaudeAuth
|
||||
? await ctx.deps.prepareClaudeAuth(ctx.codexSelectionTarget)
|
||||
: null
|
||||
} catch (error) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { readLegacySidekickFlag } from '../applying-settings/onboarding-normaliz
|
||||
import type { PersistedState } from '../../../shared/persisted-state-types'
|
||||
import type { PreparedLoadedTerminalSettings } from './prepare-loaded-terminal-settings'
|
||||
import type { PreparedLoadedProfileSettings } from './prepare-loaded-profile-settings'
|
||||
import type { ClaudeManagedAccount } from '../../../shared/managed-account-types'
|
||||
|
||||
export function normalizeLoadedGlobalSettings(
|
||||
parsed: PersistedState,
|
||||
@@ -58,6 +59,9 @@ export function normalizeLoadedGlobalSettings(
|
||||
// old default indistinguishable from a real opt-in. Preserve stored `true`; only
|
||||
// the default changed.
|
||||
...stripRetiredGlobalSettings(parsed.settings),
|
||||
claudeManagedAccounts: normalizeClaudeManagedAccountRuntimes(
|
||||
parsed.settings?.claudeManagedAccounts ?? defaults.settings.claudeManagedAccounts
|
||||
),
|
||||
worktreeVisibilityDefaults: migratedExternalVisibility.defaults,
|
||||
prBotAuthorOverrides: normalizePRBotAuthorOverrides(parsed.settings?.prBotAuthorOverrides),
|
||||
// Why: v1.3.42 renamed the sidekick setting to pet; carry the old flag forward once so enabled users don't lose it.
|
||||
@@ -136,3 +140,11 @@ export function normalizeLoadedGlobalSettings(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeClaudeManagedAccountRuntimes(
|
||||
accounts: readonly ClaudeManagedAccount[]
|
||||
): ClaudeManagedAccount[] {
|
||||
return accounts.map((account) =>
|
||||
account.managedAuthRuntime === undefined ? { ...account, managedAuthRuntime: 'host' } : account
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user