You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
session/load returns the config.toml model/effort instead of the thread's, because thread/resume is always sent a modelProvider #343
Setup: codex-acp driven over ACP by Kepler (Electron client, spawns the wrapper via dist/index.js and resumes stored sessions with session/load). Reproduced on codex-acp 1.1.4 and 1.1.7, against codex-cli 0.144.6 app-server.
Problem
session/load returns the model and reasoning effort from ~/.codex/config.toml instead of the ones persisted on the thread. Any in-session model/effort switch is silently lost on resume.
The cause is the modelProvider field that loadSession/resumeSession always pass to thread/resume:
// dist/index.js (1.1.7:26277) — same in 1.1.4:26044constresponse=awaitthis.codexClient.threadResume({config: awaitthis.createSessionConfig(...),cwd: request.cwd,modelProvider: awaitthis.getResumeModelProvider(),// never absentthreadId: request.sessionId,});
getResumeModelProvider() is getCurrentModelProvider() ?? "openai", so the field is always populated even with no gateway configured. Passing it makes the app-server discard the thread's stored model/reasoningEffort and re-resolve them from config.
Reproduction
Create a session and switch it to a model/effort that differs from ~/.codex/config.toml. Mine has model = "gpt-5.5", model_reasoning_effort = "xhigh"; the session was set to gpt-5.6-sol / max.
Send a prompt. The rollout jsonl records the switch: "model":"gpt-5.6-sol", "effort":"max" in turn_context.
Resume that thread with session/load.
Observed on both versions:
currentModelId= gpt-5.5[xhigh]
model => "gpt-5.5"
reasoning_effort => "xhigh"
Expected gpt-5.6-sol / max (what the thread holds).
Isolating it to modelProvider
Calling thread/resume directly on the app-server for the same thread, varying only which params are sent:
params sent
model
reasoningEffort
threadId, cwd
gpt-5.6-sol
max
+ config
gpt-5.6-sol
max
+ modelProvider: "openai"
gpt-5.5
xhigh
+ config + modelProvider (what codex-acp sends)
gpt-5.5
xhigh
config is irrelevant; modelProvider alone flips it. The values it falls back to are exactly the ones in config.toml.
Expected
Resuming a thread should restore the model and reasoning effort stored on that thread. Either don't send modelProvider on thread/resume when no gateway is configured, or have the app-server keep the thread's model when a provider is passed. If the app-server behaviour is the intended contract, this is arguably an openai/codex bug and I'm happy to move it there.
Impact
The client cannot recover the picks on its own: after a client restart there is no live session left to read them from, and the resume response is the only source of truth. Users see the correct model for a moment (from the client's own cache), then it flips to the config default as the load response lands.
Possibly the same root cause as #336, which reports effort reverting between turns of a live session — that one survives without a resume, so it may be a separate path. Filing this separately since the trigger here is isolated to session/load.
I just updated to latest codex-acp, and now whenever we load a session, I get a warning like this
Warning: This session was recorded with model gpt-6.1-terra but is resuming with gpt-6.1-sol. Consider switching back to gpt-6.1-terra as it may affect Codex performance.
which is kind of pointless because my client already sends a config option update for the model right after resume.
Activity
SteffenDE commentedon Nov 5, 2026
I just updated to latest codex-acp, and now whenever we load a session, I get a warning like this
which is kind of pointless because my client already sends a config option update for the model right after resume.
fix: restore a resumed session's own permissions and model
fix: restore a resumed session's own permissions and model (#58)