diff --git a/src/services/api/openaiShim/requestExecutor.test.ts b/src/services/api/openaiShim/requestExecutor.test.ts index a086c7070..20fc95d1f 100644 --- a/src/services/api/openaiShim/requestExecutor.test.ts +++ b/src/services/api/openaiShim/requestExecutor.test.ts @@ -7,7 +7,6 @@ import { acquireSharedMutationLock, releaseSharedMutationLock } from '../../../t import { asMockFetch } from '../../../test/typedMocks.js' import { _clearRegistryForTesting, ensureIntegrationsLoaded } from '../../../integrations/index.ts' import { applyProviderFlag } from '../../../utils/providerFlag.ts' -import { applyAgentProviderOverrideToEnv } from '../agentRouting.ts' import { categorizeRetryableAPIError, getAssistantMessageFromError, @@ -25,6 +24,7 @@ const originalEnv = { OPENAI_API_KEYS: process.env.OPENAI_API_KEYS, LLMTR_API_KEY: process.env.LLMTR_API_KEY, REQUESTY_API_KEY: process.env.REQUESTY_API_KEY, + XAI_API_KEY: process.env.XAI_API_KEY, API_ROUTE_API_KEY: process.env.API_ROUTE_API_KEY, CMD_API_KEY: process.env.CMD_API_KEY, COMMANDCODE_API_KEY: process.env.COMMANDCODE_API_KEY, @@ -188,6 +188,7 @@ beforeEach(async () => { delete process.env.OPENAI_API_KEYS delete process.env.LLMTR_API_KEY delete process.env.REQUESTY_API_KEY + delete process.env.XAI_API_KEY delete process.env.API_ROUTE_API_KEY delete process.env.CMD_API_KEY delete process.env.COMMANDCODE_API_KEY @@ -243,6 +244,7 @@ afterEach(() => { restoreEnv('OPENAI_API_KEYS', originalEnv.OPENAI_API_KEYS) restoreEnv('LLMTR_API_KEY', originalEnv.LLMTR_API_KEY) restoreEnv('REQUESTY_API_KEY', originalEnv.REQUESTY_API_KEY) + restoreEnv('XAI_API_KEY', originalEnv.XAI_API_KEY) restoreEnv('API_ROUTE_API_KEY', originalEnv.API_ROUTE_API_KEY) restoreEnv('CMD_API_KEY', originalEnv.CMD_API_KEY) restoreEnv('COMMANDCODE_API_KEY', originalEnv.COMMANDCODE_API_KEY) @@ -378,13 +380,12 @@ test('selected LLMTR route prefers its dedicated key over a generic OPENAI_API_K test('a Requesty key mirrored into OPENAI_API_KEY wins over an inherited OPENAI_API_KEYS pool', async () => { // A saved Requesty profile and a Requesty teammate override both mirror // their key into OPENAI_API_KEY; a parent's generic pool must not replace it. + process.env.CLAUDE_CODE_USE_OPENAI = '1' + process.env.OPENAI_BASE_URL = 'https://router.requesty.ai/v1' + process.env.OPENAI_MODEL = 'openai/gpt-5-mini' process.env.OPENAI_API_KEYS = 'parent-pool-key-a,parent-pool-key-b' - process.env.REQUESTY_API_KEY = 'parent-requesty-key' - applyAgentProviderOverrideToEnv({ - model: 'openai/gpt-5-mini', - baseURL: 'https://router.requesty.ai/v1', - apiKey: 'configured-agent-key', - }) + process.env.OPENAI_API_KEY = 'configured-agent-key' + process.env.REQUESTY_API_KEY = 'configured-agent-key' const captured = await captureChatCompletionRequest('openai/gpt-5-mini') @@ -392,6 +393,20 @@ test('a Requesty key mirrored into OPENAI_API_KEY wins over an inherited OPENAI_ expect(captured.authorization).toBe('Bearer configured-agent-key') }) +test('a Requesty key mirrored into OPENAI_API_KEY is not reused on another route', async () => { + process.env.CLAUDE_CODE_USE_OPENAI = '1' + process.env.OPENAI_BASE_URL = 'https://api.x.ai/v1' + process.env.OPENAI_MODEL = 'grok-4' + process.env.XAI_API_KEY = 'xai-key' + process.env.OPENAI_API_KEY = 'requesty-key' + process.env.REQUESTY_API_KEY = 'requesty-key' + + const captured = await captureChatCompletionRequest('grok-4') + + expect(captured.url).toBe('https://api.x.ai/v1/chat/completions') + expect(captured.authorization).toBe('Bearer xai-key') +}) + test('selected Command Code route sends CMD_API_KEY through the generic route credential resolver', async () => { process.env.CMD_API_KEY = 'cmd-key' delete process.env.COMMANDCODE_API_KEY diff --git a/src/services/api/openaiShim/requestExecutor.ts b/src/services/api/openaiShim/requestExecutor.ts index da3be6c8d..529cb56b2 100644 --- a/src/services/api/openaiShim/requestExecutor.ts +++ b/src/services/api/openaiShim/requestExecutor.ts @@ -333,7 +333,11 @@ export async function executeOpenAIRequest( requestProcessEnv.FIREWORKS_API_KEY, requestProcessEnv.LONGCAT_API_KEY, requestProcessEnv.LLMTR_API_KEY, - requestProcessEnv.REQUESTY_API_KEY, + // Requesty's key counts as copied only on its own route, so a stale + // mirror is never reused as another provider's credential. + runtimeShimContext.routeId === 'requesty' + ? requestProcessEnv.REQUESTY_API_KEY + : undefined, requestProcessEnv.CMD_API_KEY, requestProcessEnv.COMMANDCODE_API_KEY, requestProcessEnv.COMMAND_CODE_API_KEY,