mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 10:12:44 +00:00
fix(codex): keep the default effort after a daemon restart (#5686)
A Codex agent created without a thinking option ran on the configured default effort until the daemon restarted. The resumed session never resolved the defaults, so it showed thinking auto and sent turns with no effort. Resolve unset model and effort for a resumed thread the same way a new thread does. Closes #5673 Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1170,6 +1170,36 @@ describe("Codex app-server provider", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps the default effort when a session without one is resumed after a restart", async () => {
|
||||
const beforeRestart = createFakeCodexAppServer();
|
||||
const firstSession = await createProviderWithFakeAppServer(beforeRestart).createSession(
|
||||
createConfig({ thinkingOptionId: undefined }),
|
||||
);
|
||||
await firstSession.startTurn("first turn");
|
||||
await expect(beforeRestart.waitForTurnStart()).resolves.toMatchObject({ effort: "medium" });
|
||||
const handle = firstSession.describePersistence()!;
|
||||
await firstSession.close();
|
||||
|
||||
const afterRestart = createFakeCodexAppServer();
|
||||
// The daemon resumes with the stored agent config, which never recorded an effort.
|
||||
const resumed = await createProviderWithFakeAppServer(afterRestart).resumeSession(handle, {
|
||||
model: "gpt-5.4",
|
||||
thinkingOptionId: undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
await expect(resumed.getRuntimeInfo()).resolves.toMatchObject({
|
||||
thinkingOptionId: "medium",
|
||||
});
|
||||
await resumed.startTurn("turn after restart");
|
||||
await expect(afterRestart.waitForTurnStart()).resolves.toMatchObject({ effort: "medium" });
|
||||
beforeRestart.assertNoErrors();
|
||||
afterRestart.assertNoErrors();
|
||||
} finally {
|
||||
await resumed.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("preapproves only granted tools on the injected Codex MCP server", async () => {
|
||||
const session = createSession({
|
||||
modeId: undefined,
|
||||
|
||||
@@ -3611,6 +3611,7 @@ export class CodexAppServerAgentSession implements AgentSession {
|
||||
if (this.currentThreadId) {
|
||||
await this.ensureThreadLoaded();
|
||||
await this.loadPersistedHistory(this.client);
|
||||
await this.applyDefaultModelAndThinking();
|
||||
}
|
||||
|
||||
if (this.closed) {
|
||||
@@ -5208,13 +5209,20 @@ export class CodexAppServerAgentSession implements AgentSession {
|
||||
return { model, thinkingOptionId };
|
||||
}
|
||||
|
||||
// A session without a model or effort runs on Codex's configured defaults, whether its
|
||||
// thread is new or resumed after a restart.
|
||||
private async applyDefaultModelAndThinking(): Promise<string> {
|
||||
const { model, thinkingOptionId } = await this.resolveModelAndThinking();
|
||||
this.config.model = model;
|
||||
this.config.thinkingOptionId = thinkingOptionId;
|
||||
return model;
|
||||
}
|
||||
|
||||
private async ensureThread(): Promise<void> {
|
||||
if (!this.client) return;
|
||||
if (this.currentThreadId) return;
|
||||
|
||||
const { model, thinkingOptionId } = await this.resolveModelAndThinking();
|
||||
this.config.model = model;
|
||||
this.config.thinkingOptionId = thinkingOptionId;
|
||||
const model = await this.applyDefaultModelAndThinking();
|
||||
|
||||
const { params, approvalPolicy, sandbox } = this.buildThreadStartRequest(model);
|
||||
const rawResponse = await this.client.request("thread/start", params);
|
||||
|
||||
Reference in New Issue
Block a user