mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-11-06 12:50:54 -04:00
fix(providers): keep saved Requesty keys off shell-retargeted launches
A relaunch with a shell OPENAI_BASE_URL that points a saved Requesty profile at a non-canonical URL still carried the profile's persisted OPENAI_API_KEY to that URL. Drop persisted generic credentials for that retarget, as the Merge and Runcrate guards already do; explicit shell credentials still apply. Also require the persisted profile to be a Requesty profile before its generic key is recovered as REQUESTY_API_KEY, so a shell retarget of another profile to Requesty no longer adopts that profile's key over a shell REQUESTY_API_KEY. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3811,3 +3811,63 @@ test('OpenAI profile builder materializes the canonical Orca key only at its rou
|
|||||||
})
|
})
|
||||||
assert.equal(custom?.ORCAROUTER_API_KEY, undefined)
|
assert.equal(custom?.ORCAROUTER_API_KEY, undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('a shell URL retarget does not carry a saved Requesty key to the new endpoint', async () => {
|
||||||
|
const persisted = profile('openai', {
|
||||||
|
OPENAI_BASE_URL: 'https://router.requesty.ai/v1',
|
||||||
|
OPENAI_MODEL: 'openai/gpt-5-mini',
|
||||||
|
OPENAI_API_KEY: 'saved-requesty-key',
|
||||||
|
REQUESTY_API_KEY: 'saved-requesty-key',
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const shellBaseUrl of [
|
||||||
|
'https://example.test/v1',
|
||||||
|
'http://router.requesty.ai/v1',
|
||||||
|
]) {
|
||||||
|
const env = await buildLaunchEnv({
|
||||||
|
profile: 'openai',
|
||||||
|
persisted,
|
||||||
|
goal: 'balanced',
|
||||||
|
processEnv: { OPENAI_BASE_URL: shellBaseUrl },
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.equal(env.OPENAI_BASE_URL, shellBaseUrl)
|
||||||
|
assert.equal(env.OPENAI_API_KEY, undefined)
|
||||||
|
assert.equal(env.REQUESTY_API_KEY, undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
const regional = await buildLaunchEnv({
|
||||||
|
profile: 'openai',
|
||||||
|
persisted,
|
||||||
|
goal: 'balanced',
|
||||||
|
processEnv: { OPENAI_BASE_URL: 'https://router.eu.requesty.ai/v1' },
|
||||||
|
})
|
||||||
|
assert.equal(regional.OPENAI_API_KEY, 'saved-requesty-key')
|
||||||
|
assert.equal(regional.REQUESTY_API_KEY, 'saved-requesty-key')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('a shell URL retarget to Requesty does not adopt another profile key as the Requesty key', async () => {
|
||||||
|
const env = await buildLaunchEnv({
|
||||||
|
profile: 'openai',
|
||||||
|
persisted: profile('openai', {
|
||||||
|
OPENAI_BASE_URL: 'https://api.openai.com/v1',
|
||||||
|
OPENAI_MODEL: 'gpt-4o',
|
||||||
|
OPENAI_API_KEY: 'sk-saved-openai',
|
||||||
|
}),
|
||||||
|
goal: 'balanced',
|
||||||
|
processEnv: {
|
||||||
|
OPENAI_BASE_URL: 'https://router.requesty.ai/v1',
|
||||||
|
REQUESTY_API_KEY: 'shell-requesty-key',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.equal(env.REQUESTY_API_KEY, 'shell-requesty-key')
|
||||||
|
assert.equal(
|
||||||
|
resolveRouteCredentialValue({
|
||||||
|
routeId: 'requesty',
|
||||||
|
baseUrl: env.OPENAI_BASE_URL,
|
||||||
|
processEnv: env,
|
||||||
|
}),
|
||||||
|
'shell-requesty-key',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|||||||
@@ -2260,6 +2260,14 @@ export async function buildLaunchEnv(options: {
|
|||||||
(persistedEnv.CLAUDE_CODE_PROVIDER_ROUTE_ID === 'merge-gateway' ||
|
(persistedEnv.CLAUDE_CODE_PROVIDER_ROUTE_ID === 'merge-gateway' ||
|
||||||
isCanonicalMergeGatewayInferenceBaseUrl(persistedOpenAIBaseUrl)) &&
|
isCanonicalMergeGatewayInferenceBaseUrl(persistedOpenAIBaseUrl)) &&
|
||||||
!isCanonicalMergeGatewayInferenceBaseUrl(env.OPENAI_BASE_URL)
|
!isCanonicalMergeGatewayInferenceBaseUrl(env.OPENAI_BASE_URL)
|
||||||
|
// Same for a saved Requesty profile: its key is valid only on the canonical
|
||||||
|
// Requesty inference URLs, so a shell retarget elsewhere drops it.
|
||||||
|
const persistedRequestyProfileIdentity =
|
||||||
|
persistedEnv.CLAUDE_CODE_PROVIDER_ROUTE_ID === 'requesty' ||
|
||||||
|
isCanonicalRequestyInferenceBaseUrl(persistedOpenAIBaseUrl)
|
||||||
|
const retargetedRequestyProfile =
|
||||||
|
persistedRequestyProfileIdentity &&
|
||||||
|
!isCanonicalRequestyInferenceBaseUrl(env.OPENAI_BASE_URL)
|
||||||
// A saved Runcrate profile mirrors its dedicated key into the generic
|
// A saved Runcrate profile mirrors its dedicated key into the generic
|
||||||
// OPENAI_API_KEY alias. A shell URL retarget must not hand that saved key to
|
// OPENAI_API_KEY alias. A shell URL retarget must not hand that saved key to
|
||||||
// the new endpoint; only an explicit shell credential may follow the URL.
|
// the new endpoint; only an explicit shell credential may follow the URL.
|
||||||
@@ -2283,7 +2291,11 @@ export async function buildLaunchEnv(options: {
|
|||||||
: processEnv
|
: processEnv
|
||||||
const openAICredential = resolveOpenAICredentialEnvOverride(
|
const openAICredential = resolveOpenAICredentialEnvOverride(
|
||||||
shellCredentialSource,
|
shellCredentialSource,
|
||||||
retargetedMergeProfile || retargetedRuncrateProfile ? {} : persistedEnv,
|
retargetedMergeProfile ||
|
||||||
|
retargetedRuncrateProfile ||
|
||||||
|
retargetedRequestyProfile
|
||||||
|
? {}
|
||||||
|
: persistedEnv,
|
||||||
)
|
)
|
||||||
if (openAICredential) {
|
if (openAICredential) {
|
||||||
env[openAICredential.envVar] = openAICredential.value
|
env[openAICredential.envVar] = openAICredential.value
|
||||||
@@ -2632,10 +2644,13 @@ export async function buildLaunchEnv(options: {
|
|||||||
: undefined)
|
: undefined)
|
||||||
: undefined
|
: undefined
|
||||||
// Same ownership rule for a selected canonical Requesty profile, including
|
// Same ownership rule for a selected canonical Requesty profile, including
|
||||||
// startup files that only persisted the saved key as OPENAI_API_KEY.
|
// startup files that only persisted the saved key as OPENAI_API_KEY. Only
|
||||||
|
// a persisted Requesty profile owns that key; another profile's generic
|
||||||
|
// key is not a Requesty credential.
|
||||||
const persistedRequestyProfileKey =
|
const persistedRequestyProfileKey =
|
||||||
dedicatedKey === 'REQUESTY_API_KEY' &&
|
dedicatedKey === 'REQUESTY_API_KEY' &&
|
||||||
effectiveOpenAIRouteId === 'requesty' &&
|
effectiveOpenAIRouteId === 'requesty' &&
|
||||||
|
persistedRequestyProfileIdentity &&
|
||||||
!!dedicatedBaseUrl &&
|
!!dedicatedBaseUrl &&
|
||||||
isCanonicalRequestyInferenceBaseUrl(dedicatedBaseUrl)
|
isCanonicalRequestyInferenceBaseUrl(dedicatedBaseUrl)
|
||||||
? sanitizeApiKey(persistedEnv.REQUESTY_API_KEY) ||
|
? sanitizeApiKey(persistedEnv.REQUESTY_API_KEY) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user