Skip to content

fix: persist and restore Codex modelReasoningEffort across session archive/resume#419

Closed
Copilot wants to merge 3 commits intomainfrom
copilot/fix-archived-session-inference-strength
Closed

fix: persist and restore Codex modelReasoningEffort across session archive/resume#419
Copilot wants to merge 3 commits intomainfrom
copilot/fix-archived-session-inference-strength

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 8, 2026

Codex sessions with a custom reasoning effort (e.g., xhigh) would silently reset to medium after being archived and resumed, with no way to change it on a running resumed session.

Root cause

modelReasoningEffort was never stored in the DB — only held in-memory during the active session lifetime.

Changes

DB (schema v6 → v7)

  • Add model_reasoning_effort TEXT column to sessions table
  • Migration paths: v6→v7, v5→v7, v4→v7; removed now-dead v4→v6 shortcut

Persistence & sync (hub)

  • Thread modelReasoningEffort through getOrCreateSessionStoredSessionSessionCache.refreshSession
  • resumeSession now passes session.modelReasoningEffort to spawnSession, restoring the setting on resume
  • SessionCache.applySessionConfig and mergeSessions handle the new field
  • New REST endpoint POST /sessions/:id/model-reasoning-effort for runtime changes

CLI (codex)

  • bootstrapSession and api.getOrCreateSession accept and forward modelReasoningEffort
  • currentModelReasoningEffort changed from constlet; set-session-config RPC handler now applies it and returns it in applied

Shared

  • Added ModelReasoningEffort capability to flavors.ts; codex now declares it
  • New supportsModelReasoningEffort() helper (mirrors existing supportsEffort)
  • SessionSchema gains modelReasoningEffort?: string | null

Web UI

  • HappyComposer shows a reasoning-effort picker for active Codex sessions (gated on supportsModelReasoningEffort)
  • useSessionActions gains setModelReasoningEffort mutation
  • Added misc.reasoningEffort locale key (EN + ZH-CN)

…esume

- Add model_reasoning_effort column to sessions DB (schema v7 migration)
- Store modelReasoningEffort when bootstrapping a Codex session
- Restore modelReasoningEffort when resuming an archived session
- Allow changing modelReasoningEffort at runtime via set-session-config RPC
- Add REST endpoint POST /sessions/:id/model-reasoning-effort for web UI
- Add supportsModelReasoningEffort capability to codex flavor
- Add web UI controls to change reasoning effort in active Codex sessions

Agent-Logs-Url: https://github.com/tiann/hapi/sessions/9a0417ed-4d43-423d-bd91-0616050c6dbd

Co-authored-by: tiann <4233744+tiann@users.noreply.github.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 8, 2026

Deploying hapi with  Cloudflare Pages  Cloudflare Pages

Latest commit: e1f7465
Status: ✅  Deploy successful!
Preview URL: https://5b35ca40.hapi-bqd.pages.dev
Branch Preview URL: https://copilot-fix-archived-session.hapi-bqd.pages.dev

View logs

Copilot AI changed the title [WIP] Fix inference strength issue in archived sessions fix: persist and restore Codex modelReasoningEffort across session archive/resume Apr 8, 2026
Copilot AI requested a review from tiann April 8, 2026 07:43
Copilot finished work on behalf of tiann April 8, 2026 07:43
@tiann tiann marked this pull request as ready for review April 9, 2026 02:59
Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] modelReasoningEffort is only validated as an arbitrary non-empty string, so invalid values can be persisted and then replayed into Codex on resume. Evidence: hub/src/web/routes/sessions.ts:25, hub/src/web/routes/machines.ts:12, hub/src/web/routes/cli.ts:17, cli/src/codex/runCodex.ts:149.
  • [Minor] The new composer control only renders default/low/medium/high/xhigh, but Codex also accepts none and minimal, so resumed sessions using those values show no selected option. Evidence: web/src/components/AssistantChat/HappyComposer.tsx:642, cli/src/commands/codex.ts:9.

Summary
Review mode: initial. Two correctness issues in the new reasoning-effort persistence path: unsupported values are accepted end to end, and the new composer UI cannot represent all valid persisted Codex values.

Testing
Not run (automation): bun is not installed in this runner (bun: command not found).

HAPI Bot

})

const modelReasoningEffortSchema = z.object({
modelReasoningEffort: z.string().trim().min(1).nullable()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MAJOR] modelReasoningEffort is only checked as z.string().trim().min(1) here, and runCodex() later accepts any string via a cast (cli/src/codex/runCodex.ts:149). That lets values like "foo" get stored in SQLite and then sent back to Codex as model_reasoning_effort / reasoning_effort during resume, which can break the restored session.

Suggested fix:

const codexReasoningEffortSchema = z.enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh']).nullable()

const modelReasoningEffortSchema = z.object({
    modelReasoningEffort: codexReasoningEffortSchema
})

Apply the same schema to /cli/sessions, /machines/:id/spawn, and resolveModelReasoningEffort() so the persisted value set stays consistent.

type="button"
disabled={controlsDisabled}
className={`flex w-full items-center gap-2 px-3 py-2 text-left text-sm transition-colors ${
controlsDisabled
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MINOR] The new settings UI only iterates CODEX_REASONING_EFFORT_OPTIONS, which excludes none and minimal, even though Codex sessions can already persist those values (cli/src/commands/codex.ts:9). After resume, those sessions will render with no selected option, so the UI no longer reflects the stored config.

Suggested fix:

export const CODEX_REASONING_EFFORT_OPTIONS = [
    { value: 'default', label: 'Default' },
    { value: 'none', label: 'None' },
    { value: 'minimal', label: 'Minimal' },
    { value: 'low', label: 'Low' },
    { value: 'medium', label: 'Medium' },
    { value: 'high', label: 'High' },
    { value: 'xhigh', label: 'XHigh' },
]

If none / minimal are intentionally unsupported in the web UI, reject them in the backend instead of persisting them.

@tiann tiann closed this Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

归档后的问题,重新拉起再回复,没法读取之前的推理强度,也没法重新设置推理强度。

2 participants