feat(codex): Add support for codex /fast mode#393
feat(codex): Add support for codex /fast mode#393paulcalcraft wants to merge 1 commit intotiann:mainfrom
Conversation
There was a problem hiding this comment.
Findings
- [Major]
--service-tieris parsed but never reaches terminal-started Codex sessions. The new branch incli/src/commands/codex.ts:81stores the value in HAPI state, but local launches only forwardsession.codexArgsto the native Codex CLI (cli/src/codex/codexLocalLauncher.ts:18-49), sohapi codex --service-tier fastsilently runs at the default tier. - [Major] Fast mode is not persisted for inactive-session resume. Initial spawn now threads
serviceTierthroughhub/src/sync/syncEngine.ts:318-337, but resume still hardcodesundefinedfor both reasoning effort and service tier inhub/src/sync/syncEngine.ts:404-410, and the session schema still stores onlymodel/effort/collaborationMode(shared/src/schemas.ts:161-180). A resumed Codex session will therefore drop back to the default tier.
Summary
Review mode: initial. 2 issues found in the new Codex fast-mode plumbing: terminal-started sessions ignore the new CLI flag, and resumed inactive Codex sessions lose the selected service tier.
Testing
Not run (bun is not installed in this environment).
HAPI Bot
| throw new Error('Missing --model-reasoning-effort value') | ||
| } | ||
| options.modelReasoningEffort = parseReasoningEffort(effort) | ||
| } else if (arg === '--service-tier') { |
There was a problem hiding this comment.
[MAJOR] --service-tier is swallowed in local/terminal mode.
This new branch parses the flag into options.serviceTier, but it never adds the original CLI args back into unknownArgs. The local launcher only forwards session.codexArgs to the native codex process (cli/src/codex/codexLocalLauncher.ts:18-49), so hapi codex --service-tier fast will silently start at the default tier.
Suggested fix:
} else if (arg === '--service-tier') {
const serviceTier = commandArgs[++i]
if (!serviceTier) {
throw new Error('Missing --service-tier value')
}
options.serviceTier = parseServiceTier(serviceTier)
unknownArgs.push('--service-tier', serviceTier)
}| agent: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode' = 'claude', | ||
| model?: string, | ||
| modelReasoningEffort?: string, | ||
| serviceTier?: string, |
There was a problem hiding this comment.
[MAJOR] Fast mode is wired for initial spawn only; inactive-session resume still drops it.
spawnSession() now accepts serviceTier, but resumeSession() still calls rpcGateway.spawnSession() with undefined for both modelReasoningEffort and serviceTier. Since the persisted session shape also lacks fields for those values (shared/src/schemas.ts:161-180), a resumed Codex session will come back on the default tier instead of the tier selected at creation time.
Suggested fix:
const spawnResult = await this.rpcGateway.spawnSession(
targetMachine.id,
metadata.path,
flavor,
session.model ?? undefined,
session.modelReasoningEffort ?? undefined,
session.serviceTier ?? undefined,
undefined,
undefined,
resumeToken,
session.effort ?? undefined
)Persist modelReasoningEffort/serviceTier alongside the existing session model settings before replaying them here.
hqhq1025
left a comment
There was a problem hiding this comment.
The feature implementation is thorough — the web UI → hub → CLI → Codex data flow for the primary (remote) path is complete and correct. Good i18n coverage and test additions.
However, there's a critical bug that breaks session resume:
Critical: Positional argument misalignment in syncEngine.resumeSession
The PR inserts serviceTier as a new positional parameter in rpcGateway.spawnSession() (between modelReasoningEffort and yolo), but syncEngine.resumeSession() (line ~402) calls spawnSession() with positional args and is not updated.
After this PR, the resume call passes:
resumeToken→worktreeName(wrong!)session.effort→resumeSessionId(wrong!)effort→ undefined (lost!)
TypeScript won't catch this because all misaligned params are string?. The result: all inactive session resumes silently fail — they create a new session instead of resuming.
Fix: add undefined for serviceTier at position 6 in the resume call. Or better yet, refactor spawnSession to accept an options object instead of 11 positional parameters — this class of bug will recur every time a parameter is added.
Other issues
Local mode ignores --service-tier: commands/codex.ts parses the flag but doesn't forward it to the Codex child process args in local mode. Running hapi codex --service-tier fast locally does nothing. Consider at minimum logging a warning.
serviceTier not persisted in session schema: SessionSchema doesn't include serviceTier, so even after fixing the resume args, a resumed session loses the fast mode selection. (modelReasoningEffort has the same issue, but fast mode costs 2x usage so silent loss has higher impact.)
Codex has a fast inference mode that uses tokens at a higher rate. I've added support for that when creating a new session. I also added the full set of reasoning levels for codex to the dropdown.
GPT 5.4 xhigh in codex wrote the code, I've tested that it doesn't break the flow and it seems to work, but hard to know for certain that the fast mode is applied correctly (it seems fast at least!). Despite docs saying that serviceTier should be 'priority' for fast mode, if you pass that param, you actually get an error saying that it should be 'fast', so this patch uses 'fast'.