Skip to content

Commit 9850118

Browse files
fix: use configured model provider on session resume
When resuming or loading a session, getResumeModelProvider() now reads the model_provider value from Codex config (config/read) before falling back to "openai". This fixes a v1.0.0 regression where sessions resumed via ACP always used OpenAI even when ~/.codex/config.toml specified model_provider = "azure".
1 parent b93225f commit 9850118

2 files changed

Lines changed: 47 additions & 7 deletions

File tree

src/CodexAcpClient.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export class CodexAcpClient {
178178
return sessionModelProvider;
179179
}
180180
const settingsModelProvider = await this.codexClient.configRead({includeLayers: false});
181-
return settingsModelProvider.config.model_provider ?? null;
181+
return settingsModelProvider?.config?.model_provider ?? null;
182182
}
183183

184184
async logout(): Promise<void> {
@@ -211,7 +211,7 @@ export class CodexAcpClient {
211211
const response = await this.codexClient.threadResume({
212212
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
213213
cwd: request.cwd,
214-
modelProvider: this.getResumeModelProvider(),
214+
modelProvider: await this.getResumeModelProvider(),
215215
threadId: request.sessionId,
216216
});
217217
onSubscribed?.();
@@ -233,7 +233,7 @@ export class CodexAcpClient {
233233
const response = await this.codexClient.threadResume({
234234
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
235235
cwd: request.cwd,
236-
modelProvider: this.getResumeModelProvider(),
236+
modelProvider: await this.getResumeModelProvider(),
237237
threadId: request.sessionId,
238238
});
239239
onSubscribed?.();
@@ -363,10 +363,10 @@ export class CodexAcpClient {
363363
return this.gatewayConfig?.modelProvider ?? this.modelProvider;
364364
}
365365

366-
private getResumeModelProvider(): string {
367-
// Passing `null` forces codex to use the persisted provider for resumed session instead of default one
368-
// Explicit fallback to "openai" fixes error `Model provider not found` at least for ChatGPT authentication
369-
return this.getModelProvider() ?? "openai";
366+
private async getResumeModelProvider(): Promise<string> {
367+
// Prefer an explicit/gateway provider, then the provider persisted in Codex config.
368+
// Keep OpenAI as the final fallback for ChatGPT-authenticated sessions without a configured provider.
369+
return (await this.getCurrentModelProvider()) ?? "openai";
370370
}
371371

372372
private async refreshSkills(

src/__tests__/CodexACPAgent/CodexAcpClient.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,46 @@ describe('ACP server test', { timeout: 40_000 }, () => {
365365
});
366366
});
367367

368+
it('uses configured model provider when resuming sessions without an explicit provider', async () => {
369+
const mockFixture = createCodexMockTestFixture();
370+
const codexAcpClient = mockFixture.getCodexAcpClient();
371+
const codexAppServerClient = mockFixture.getCodexAppServerClient();
372+
373+
vi.spyOn(codexAppServerClient, "skillsExtraRootsSet").mockResolvedValue(undefined);
374+
vi.spyOn(codexAppServerClient, "listSkills").mockResolvedValue({data: []});
375+
vi.spyOn(codexAppServerClient, "configRead").mockResolvedValue({
376+
config: {
377+
model_provider: "azure",
378+
},
379+
} as any);
380+
const threadResumeSpy = vi.spyOn(codexAppServerClient, "threadResume").mockResolvedValue({
381+
thread: {id: "thread-id"} as any,
382+
model: "gpt-5",
383+
reasoningEffort: "medium",
384+
serviceTier: null,
385+
} as any);
386+
vi.spyOn(codexAppServerClient, "threadRead").mockResolvedValue({
387+
thread: {id: "thread-id"} as any,
388+
});
389+
vi.spyOn(codexAppServerClient, "listModels").mockResolvedValue({
390+
data: [createTestModel({id: "gpt-5"})],
391+
nextCursor: null,
392+
});
393+
394+
await codexAcpClient.resumeSession({
395+
sessionId: "resume-id",
396+
cwd: "/workspace",
397+
});
398+
await codexAcpClient.loadSession({
399+
sessionId: "load-id",
400+
cwd: "/workspace",
401+
mcpServers: [],
402+
});
403+
404+
expect(threadResumeSpy.mock.calls[0]![0].modelProvider).toBe("azure");
405+
expect(threadResumeSpy.mock.calls[1]![0].modelProvider).toBe("azure");
406+
});
407+
368408
it('rejects malformed ACP additional directories', async () => {
369409
const mockFixture = createCodexMockTestFixture();
370410
const codexAcpClient = mockFixture.getCodexAcpClient();

0 commit comments

Comments
 (0)