117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
import { ConfigManager } from '../infrastructure/ConfigManager';
|
|
|
|
import type { CliProviderId, TeamProviderId } from '@shared/types';
|
|
|
|
type RuntimeEnvProviderId = CliProviderId | TeamProviderId;
|
|
|
|
type AnthropicRuntimeBackendProviderId =
|
|
| 'anthropic'
|
|
| 'bedrock'
|
|
| 'vertex'
|
|
| 'foundry'
|
|
| 'claude-platform-aws';
|
|
|
|
const PROVIDER_ROUTING_ENV_KEYS = [
|
|
'CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST',
|
|
'CLAUDE_CODE_ENTRY_PROVIDER',
|
|
'CLAUDE_CODE_USE_OPENAI',
|
|
'CLAUDE_CODE_USE_BEDROCK',
|
|
'CLAUDE_CODE_USE_VERTEX',
|
|
'CLAUDE_CODE_USE_FOUNDRY',
|
|
'CLAUDE_CODE_USE_GEMINI',
|
|
] as const;
|
|
|
|
const BACKEND_SELECTION_ENV_KEYS = [
|
|
'CLAUDE_CODE_GEMINI_BACKEND',
|
|
'CLAUDE_CODE_CODEX_BACKEND',
|
|
] as const;
|
|
|
|
export function applyConfiguredRuntimeBackendsEnv(
|
|
env: NodeJS.ProcessEnv,
|
|
runtimeConfig = ConfigManager.getInstance().getConfig().runtime
|
|
): NodeJS.ProcessEnv {
|
|
for (const key of BACKEND_SELECTION_ENV_KEYS) {
|
|
env[key] = undefined;
|
|
}
|
|
|
|
env.CLAUDE_CODE_GEMINI_BACKEND = runtimeConfig.providerBackends.gemini;
|
|
env.CLAUDE_CODE_CODEX_BACKEND = runtimeConfig.providerBackends.codex;
|
|
return env;
|
|
}
|
|
|
|
function isTruthyEnvValue(value: string | undefined): boolean {
|
|
const normalized = value?.trim().toLowerCase();
|
|
return Boolean(normalized && normalized !== '0' && normalized !== 'false' && normalized !== 'no');
|
|
}
|
|
|
|
function resolveAnthropicRuntimeBackendFromEnv(
|
|
env: NodeJS.ProcessEnv
|
|
): AnthropicRuntimeBackendProviderId {
|
|
if (isTruthyEnvValue(env.CLAUDE_CODE_USE_BEDROCK)) {
|
|
return 'bedrock';
|
|
}
|
|
if (isTruthyEnvValue(env.CLAUDE_CODE_USE_VERTEX)) {
|
|
return 'vertex';
|
|
}
|
|
if (isTruthyEnvValue(env.CLAUDE_CODE_USE_FOUNDRY)) {
|
|
return 'foundry';
|
|
}
|
|
if (env.ANTHROPIC_AWS_WORKSPACE_ID?.trim()) {
|
|
return 'claude-platform-aws';
|
|
}
|
|
return 'anthropic';
|
|
}
|
|
|
|
function applyAnthropicRuntimeBackendEnv(
|
|
env: NodeJS.ProcessEnv,
|
|
backend: AnthropicRuntimeBackendProviderId
|
|
): void {
|
|
if (backend === 'bedrock') {
|
|
env.CLAUDE_CODE_USE_BEDROCK = '1';
|
|
} else if (backend === 'vertex') {
|
|
env.CLAUDE_CODE_USE_VERTEX = '1';
|
|
} else if (backend === 'foundry') {
|
|
env.CLAUDE_CODE_USE_FOUNDRY = '1';
|
|
}
|
|
}
|
|
|
|
export function applyProviderRuntimeEnv(
|
|
env: NodeJS.ProcessEnv,
|
|
providerId: RuntimeEnvProviderId | undefined
|
|
): NodeJS.ProcessEnv {
|
|
const resolvedProvider = resolveRuntimeProviderId(providerId);
|
|
const anthropicBackend =
|
|
resolvedProvider === 'anthropic' ? resolveAnthropicRuntimeBackendFromEnv(env) : 'anthropic';
|
|
|
|
for (const key of PROVIDER_ROUTING_ENV_KEYS) {
|
|
env[key] = undefined;
|
|
}
|
|
|
|
// Provider overrides must be positive pins. In dev and multimodel desktop
|
|
// flows the host process can already be routed to codex or gemini, and the
|
|
// child runtime reapplies settings.env after trust. Mark the env as
|
|
// host-managed and set the exact entry provider so anthropic teammates do not
|
|
// silently fall back into the host's current routing world.
|
|
env.CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST = '1';
|
|
env.CLAUDE_CODE_ENTRY_PROVIDER =
|
|
resolvedProvider === 'anthropic' ? anthropicBackend : resolvedProvider;
|
|
applyAnthropicRuntimeBackendEnv(env, anthropicBackend);
|
|
|
|
return env;
|
|
}
|
|
|
|
export function resolveRuntimeProviderId(
|
|
providerId: RuntimeEnvProviderId | undefined
|
|
): CliProviderId {
|
|
if (providerId === 'codex' || providerId === 'gemini' || providerId === 'opencode') {
|
|
return providerId;
|
|
}
|
|
|
|
return 'anthropic';
|
|
}
|
|
|
|
export function resolveTeamProviderId(providerId: TeamProviderId | undefined): TeamProviderId {
|
|
return providerId === 'codex' || providerId === 'gemini' || providerId === 'opencode'
|
|
? providerId
|
|
: 'anthropic';
|
|
}
|