Skip to content

feat(codex): choose reasoning effort and fast mode per turn - #8

Merged
doublepi123 merged 2 commits into
mainfrom
feat/codex-reasoning-fast
Oct 17, 2026
Merged

doublepi123 merged 2 commits into
mainfrom
feat/codex-reasoning-fast

Conversation

@doublepi123

Copy link
Copy Markdown
Owner

Codex could not set reasoning effort or fast mode: model/list was read for id/name only and turn/start carried neither setting.

  • CodexModels fills variants from supportedReasoningEfforts (server order), and records the fast tier (serviceTiers "Fast"/priority, fallback additionalSpeedTiers), its description, and each model's defaultReasoningEffort / defaultServiceTier
  • Every turn sends explicit effort and serviceTier (resolveCodexTurnSettings): the app-server applies both to subsequent turns as well, so omitting them would keep the previous turn's value (e.g. ultra carried onto another model, or fast left on after switching to a model without it)
  • Global fast-mode choice codexFastMode: Boolean? (null = follow each model's default), persisted; ChatUiState.fastModeAvailable/Enabled/Description, ChatViewModel.setFastMode; wired in both the AndCodeApp factory and Koin
  • UI: Fast chip (bolt) next to the thinking chip in the composer row, only for Codex models with a fast tier; effort labels for none/minimal/ultra; small fast marker in the model picker; strings in all 8 locales
  • Tests: CodexModelsTest (real 0.163.0 shape), CodexTurnStartParamsTest, CodexServiceTierTest, ChatViewModelTest fast cases
  • Protocol verified against codex 0.163.0 (codex app-server generate-ts + a live model/list)

Follow-up (not in this PR): a way to return fast mode to "follow model default" from the UI, and/or per-model storage.

Note: written without a local JDK; CI is the first compile.

Pre-PR review

Final review (approved at the brace fix). Earlier rounds requested changes: test package for codexServiceTier, explicit per-turn effort/serviceTier, then a brace mismatch in CodexTarget.sendMessage; all fixed. The one follow-up commit after approval applies the reviewer's first suggestion only (set modelsRefreshed on success).

判定: APPROVE

ブロッカー

なし

提案(非ブロッキング)

  • CodexTarget.kt:131,253-258:modelsRefreshed は CodexTarget インスタンスの生存期間中ずっと立ったままです。このインスタンスは AndCodeApplication で1つだけ作られ、アプリ終了まで残ります。そのため、最初の再取得が失敗すると(app-server の起動直後など)、その後は1度も再取得しません。
    • 通常は listProviders が呼ばれれば knownModels が埋まるので、実害は小さいです。
    • 気になる場合は、成功したときだけフラグを立てる形にできます(runCatching { ... }.onSuccess { modelsRefreshed = true })。あるいは listProviders が成功したタイミングでリセットする方法もあります。
  • 持ち越し(見送りで了解済み):Fast を「モデル既定に戻す」UI と、モデル単位での保存。

チェック済み項目

  • 前提:shell 権限が無いため、git diff/git status と Gradle は実行していません。変更箇所は grep と Read で追跡しました。
  • CodexTarget.kt:246-273 の構造:
    • sendMessage は 269 行目で withContext を閉じ、270 行目で関数本体を閉じています。
    • resolveKnownModel はクラスのメンバー関数です。
    • 旧 refreshModels への参照が残っていないことを grep で確認しました。
  • コンパイル可能性:
    • var model は OpenCodeModel? 型として推論されます。
    • runtime.modelList() は suspend 関数で、withContext のブロック内(suspend 文脈)から呼ばれています。
    • (modelId ?: knownDefaultModelId)?.let(knownModels::get) は、bound reference で Map<String, OpenCodeModel>.get を指しており、正しい形です。
    • @Volatile private var はクラスのメンバーなので有効です。
    • 行長は 140 未満です。
  • 挙動:
    • modelId が null でも、再取得で knownDefaultModelId が埋まり、その後の resolveKnownModel で既定モデルが解決されます。
    • turn/start の model は従来どおり request.modelId を送ります。モデルを指定しない場合は Codex 側の既定モデルに任せます。
    • resolveCodexTurnSettings の決め方と、それに対応するテストは前回確認した内容から変わっていません。
  • CodexTurnSettings の KDoc(CodexRuntime.kt:672)が型と一致していることを確認しました(effort だけが nullable)。
  • docs/CODEX.md:233-242 に、effort を省略したときは前のターンの値を継承すること、再取得は target ごとに最大1回であること、isDefault が生成型で確認済みであることが書かれていることを確認しました。
  • 前回までの確認事項は今回の差分の影響を受けていません。対象は i18n(全8ロケール)、Koin と AndCodeApp の配線、CodexServiceTierTest のパッケージ、ChatViewModelTest の fast 関連ケース、PromptRequest が OpenCode に漏れないこと、OpenCodeModel の新フィールドの既定値です。

Codex's model/list reports each model's supported reasoning efforts and
service tiers, but the app only read id and name, and turn/start carried
neither setting, so the thinking chip never appeared for Codex and fast
mode could not be turned on.

- CodexModels fills variants from supportedReasoningEfforts (server order)
  and records the fast tier, its description, and each model's default
  effort and service tier
- every turn sends explicit effort and serviceTier: the app-server applies
  them to subsequent turns too, so an omitted value would silently keep the
  previous turn's (resolveCodexTurnSettings)
- a global fast-mode choice (null = follow each model's default) is
  persisted and exposed to the chat as fastModeAvailable/Enabled
- composer gets a Fast chip next to the thinking chip; labels for the
  none/minimal/ultra efforts in all locales
- verified against codex 0.163.0 generated app-server types and a live
  model/list response
@doublepi123
doublepi123 merged commit 98b1169 into main Oct 17, 2026
6 checks passed
@doublepi123
doublepi123 deleted the feat/codex-reasoning-fast branch October 17, 2026 06:39
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.

1 participant