Keep ChatGPT Official activation metadata-only until OAuth runtime lands

Task 1 should only persist the built-in provider selection. The generic managed env and proxy paths remain reserved for saved Anthropic-compatible providers until the dedicated OpenAI OAuth runtime is wired in a later task.

Constraint: Task 1 must not write managed provider env for openai-official
Rejected: Reuse buildManagedEnv for openai-official | writes placeholder Anthropic env before Task 3 runtime exists
Rejected: Return generic proxy config for openai-official | lets empty-key proxy resolution masquerade as a working runtime
Confidence: high
Scope-risk: narrow
Directive: Do not route openai-official through managed settings or generic proxy lookup until the dedicated OAuth runtime is implemented
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "ChatGPT Official"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun run check:server
This commit is contained in:
程序员阿江(Relakkes) 2026-05-18 22:46:36 +08:00
parent b3cc32e43d
commit 072b913fd2
2 changed files with 45 additions and 0 deletions

View File

@ -313,6 +313,18 @@ describe('ProviderService', () => {
},
})
})
test('activating ChatGPT Official only persists activeId for Task 1', async () => {
const svc = new ProviderService()
await svc.activateProvider('openai-official')
const config = await readProvidersConfig()
expect(config.activeId).toBe('openai-official')
await expect(
fs.readFile(path.join(tmpDir, 'cc-haha', 'settings.json'), 'utf-8'),
).rejects.toThrow()
})
})
test('should throw 404 for non-existent id', async () => {
@ -740,6 +752,14 @@ describe('ProviderService', () => {
expect(active).toBeNull()
})
test('should return null for explicit ChatGPT Official proxy lookup', async () => {
const svc = new ProviderService()
const active = await svc.getProviderForProxy('openai-official')
expect(active).toBeNull()
})
test('should return the active provider proxy config', async () => {
const svc = new ProviderService()
const provider = await svc.addProvider(sampleInput())
@ -751,6 +771,15 @@ describe('ProviderService', () => {
expect(active!.apiKey).toBe(provider.apiKey)
expect(active!.apiFormat).toBe('anthropic')
})
test('should return null when ChatGPT Official is the active provider', async () => {
const svc = new ProviderService()
await svc.activateProvider('openai-official')
const active = await svc.getProviderForProxy()
expect(active).toBeNull()
})
})
describe('testProvider', () => {

View File

@ -358,6 +358,10 @@ export class ProviderService {
index.activeId = id
await this.writeIndex(index)
if (isOpenAIOfficialProviderId(id)) {
return
}
if (provider.presetId === 'official') {
await this.clearProviderFromSettings()
} else {
@ -418,6 +422,12 @@ export class ProviderService {
}
async getProviderRuntimeEnv(id: string): Promise<Record<string, string>> {
if (isOpenAIOfficialProviderId(id)) {
// Task 1 only persists the built-in provider selection. Task 3 wires the
// dedicated OAuth runtime env for ChatGPT Official sessions.
return {}
}
const provider = await this.getProvider(id)
return this.buildManagedEnv(provider, {
proxyPath: `/proxy/providers/${provider.id}`,
@ -528,6 +538,9 @@ export class ProviderService {
apiFormat: ApiFormat
} | null> {
if (providerId) {
if (isOpenAIOfficialProviderId(providerId)) {
return null
}
const provider = await this.getProvider(providerId)
return {
baseUrl: provider.baseUrl,
@ -538,6 +551,9 @@ export class ProviderService {
const index = await this.readIndex()
if (!index.activeId) return null
if (isOpenAIOfficialProviderId(index.activeId)) {
return null
}
const provider = await this.getProvider(index.activeId).catch(() => null)
if (!provider) return null
return {