mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
fix(frontend): ensure Codex base URLs include /v1
This commit is contained in:
@@ -736,12 +736,14 @@ const currentFiles = computed((): FileConfig[] => {
|
||||
switch (props.platform) {
|
||||
case 'openai':
|
||||
if (activeClientTab.value === 'claude') {
|
||||
return generateAnthropicFiles(baseUrl, apiKey)
|
||||
// Anthropic clients append /v1/messages themselves.
|
||||
return generateAnthropicFiles(baseRoot, apiKey)
|
||||
}
|
||||
if (activeClientTab.value === 'codex-ws') {
|
||||
return generateOpenAIWsFiles(baseUrl, apiKey)
|
||||
return generateOpenAIWsFiles(apiBase, apiKey)
|
||||
}
|
||||
return generateOpenAIFiles(baseUrl, apiKey)
|
||||
// Codex appends /responses directly and does not add /v1.
|
||||
return generateOpenAIFiles(apiBase, apiKey)
|
||||
case 'gemini':
|
||||
if (activeClientTab.value === 'codex') {
|
||||
return generateRoutedCodexFiles(apiBase, apiKey, 'gemini')
|
||||
|
||||
@@ -384,6 +384,45 @@ describe('UseKeyModal', () => {
|
||||
expect(wrapper.find('[data-testid="codex-api-key-restart-notice"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('normalizes OpenAI Codex and Claude base URLs independently', async () => {
|
||||
const wrapper = mount(UseKeyModal, {
|
||||
props: {
|
||||
show: true,
|
||||
apiKey: 'sk-test',
|
||||
baseUrl: 'https://example.com',
|
||||
platform: 'openai',
|
||||
allowMessagesDispatch: true
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
BaseDialog: {
|
||||
template: '<div><slot /><slot name="footer" /></div>'
|
||||
},
|
||||
Icon: {
|
||||
template: '<span />'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const codexConfig = wrapper.findAll('pre code')
|
||||
.map((code) => code.text())
|
||||
.find((content) => content.includes('model_provider = "OpenAI"'))
|
||||
expect(codexConfig).toContain('base_url = "https://example.com/v1"')
|
||||
|
||||
const claudeTab = wrapper.findAll('button').find((button) =>
|
||||
button.text().includes('keys.useKeyModal.cliTabs.claudeCode')
|
||||
)
|
||||
expect(claudeTab).toBeDefined()
|
||||
await claudeTab!.trigger('click')
|
||||
await nextTick()
|
||||
|
||||
const claudeConfig = wrapper.findAll('pre code')
|
||||
.map((code) => code.text())
|
||||
.find((content) => content.startsWith('export ANTHROPIC_BASE_URL'))
|
||||
expect(claudeConfig).toContain('ANTHROPIC_BASE_URL="https://example.com"')
|
||||
})
|
||||
|
||||
it('renders API Key Mode authorization in OpenAI Codex config', async () => {
|
||||
const wrapper = mount(UseKeyModal, {
|
||||
props: {
|
||||
|
||||
@@ -38,11 +38,29 @@ describe('ccswitchImport utils', () => {
|
||||
|
||||
expect(params.get('resource')).toBe('provider')
|
||||
expect(params.get('app')).toBe('codex')
|
||||
expect(params.get('endpoint')).toBe(baseInput.baseUrl)
|
||||
expect(params.get('endpoint')).toBe(`${baseInput.baseUrl}/v1`)
|
||||
expect(params.get('model')).toBe(OPENAI_CC_SWITCH_CODEX_MODEL)
|
||||
expect(atob(params.get('usageScript') || '')).toBe(baseInput.usageScript)
|
||||
})
|
||||
|
||||
it.each([
|
||||
'https://api.example.com',
|
||||
'https://api.example.com/',
|
||||
'https://api.example.com/v1',
|
||||
'https://api.example.com/v1/'
|
||||
])('imports Codex with exactly one /v1 suffix for base URL %s', (baseUrl) => {
|
||||
const params = paramsFromDeeplink(
|
||||
buildCcSwitchImportDeeplink({
|
||||
...baseInput,
|
||||
baseUrl,
|
||||
platform: 'openai',
|
||||
clientType: 'claude'
|
||||
})
|
||||
)
|
||||
|
||||
expect(params.get('endpoint')).toBe('https://api.example.com/v1')
|
||||
})
|
||||
|
||||
it.each([
|
||||
'https://api.example.com',
|
||||
'https://api.example.com/',
|
||||
|
||||
@@ -39,7 +39,7 @@ export function resolveCcSwitchImportConfig(
|
||||
case 'openai':
|
||||
return {
|
||||
app: 'codex',
|
||||
endpoint: baseUrl,
|
||||
endpoint: withV1Endpoint(baseUrl),
|
||||
model: OPENAI_CC_SWITCH_CODEX_MODEL
|
||||
}
|
||||
case 'gemini':
|
||||
|
||||
Reference in New Issue
Block a user