Skip to content

Commit 54dcc04

Browse files
fix: use configured model provider on session resume (#224)
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 1f58237 commit 54dcc04

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
@@ -195,7 +195,7 @@ export class CodexAcpClient {
195195
return sessionModelProvider;
196196
}
197197
const settingsModelProvider = await this.codexClient.configRead({includeLayers: false});
198-
return settingsModelProvider.config.model_provider ?? null;
198+
return settingsModelProvider?.config?.model_provider ?? null;
199199
}
200200

201201
async logout(): Promise<void> {
@@ -228,7 +228,7 @@ export class CodexAcpClient {
228228
const response = await this.codexClient.threadResume({
229229
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
230230
cwd: request.cwd,
231-
modelProvider: this.getResumeModelProvider(),
231+
modelProvider: await this.getResumeModelProvider(),
232232
threadId: request.sessionId,
233233
});
234234
onSubscribed?.();
@@ -250,7 +250,7 @@ export class CodexAcpClient {
250250
const response = await this.codexClient.threadResume({
251251
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
252252
cwd: request.cwd,
253-
modelProvider: this.getResumeModelProvider(),
253+
modelProvider: await this.getResumeModelProvider(),
254254
threadId: request.sessionId,
255255
});
256256
onSubscribed?.();
@@ -380,10 +380,10 @@ export class CodexAcpClient {
380380
return this.gatewayConfig?.modelProvider ?? this.modelProvider;
381381
}
382382

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

389389
private async refreshSkills(

src/__tests__/CodexACPAgent/CodexAcpClient.test.ts

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

440+
it('uses configured model provider when resuming sessions without an explicit provider', async () => {
441+
const mockFixture = createCodexMockTestFixture();
442+
const codexAcpClient = mockFixture.getCodexAcpClient();
443+
const codexAppServerClient = mockFixture.getCodexAppServerClient();
444+
445+
vi.spyOn(codexAppServerClient, "skillsExtraRootsSet").mockResolvedValue(undefined);
446+
vi.spyOn(codexAppServerClient, "listSkills").mockResolvedValue({data: []});
447+
vi.spyOn(codexAppServerClient, "configRead").mockResolvedValue({
448+
config: {
449+
model_provider: "azure",
450+
},
451+
} as any);
452+
const threadResumeSpy = vi.spyOn(codexAppServerClient, "threadResume").mockResolvedValue({
453+
thread: {id: "thread-id"} as any,
454+
model: "gpt-5",
455+
reasoningEffort: "medium",
456+
serviceTier: null,
457+
} as any);
458+
vi.spyOn(codexAppServerClient, "threadRead").mockResolvedValue({
459+
thread: {id: "thread-id"} as any,
460+
});
461+
vi.spyOn(codexAppServerClient, "listModels").mockResolvedValue({
462+
data: [createTestModel({id: "gpt-5"})],
463+
nextCursor: null,
464+
});
465+
466+
await codexAcpClient.resumeSession({
467+
sessionId: "resume-id",
468+
cwd: "/workspace",
469+
});
470+
await codexAcpClient.loadSession({
471+
sessionId: "load-id",
472+
cwd: "/workspace",
473+
mcpServers: [],
474+
});
475+
476+
expect(threadResumeSpy.mock.calls[0]![0].modelProvider).toBe("azure");
477+
expect(threadResumeSpy.mock.calls[1]![0].modelProvider).toBe("azure");
478+
});
479+
440480
it('rejects malformed ACP additional directories', async () => {
441481
const mockFixture = createCodexMockTestFixture();
442482
const codexAcpClient = mockFixture.getCodexAcpClient();

0 commit comments

Comments
 (0)