Skip to content

fix(subagent): move per-role model fallback into opencodex config (#1190) - #1210

Closed
Yuxin-Qiao wants to merge 5 commits into
lidge-jun:devfrom
Yuxin-Qiao:fix/1190-subagent-model-fallback-config
Closed

fix(subagent): move per-role model fallback into opencodex config (#1190)#1210
Yuxin-Qiao wants to merge 5 commits into
lidge-jun:devfrom
Yuxin-Qiao:fix/1190-subagent-model-fallback-config

Conversation

@Yuxin-Qiao

@Yuxin-Qiao Yuxin-Qiao commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes [Bug] Per-role model_fallback causes Codex 0.146.0 to reject custom agent TOML #1190: Codex 0.146+ strictly deserializes $CODEX_HOME/agents/*.toml and rejects model_fallback as an unknown field, which skips the entire custom-agent role definition (the role never enters the multi_agent_v1 registry).
  • Per-role fallback chains now live in opencodex config as subagentModelFallbackByModel (Record<primaryModelId, string[]>), consulted after the requested primary model and before the global subagentModelFallback list — the same slot the TOML field used to occupy.
  • The legacy TOML model_fallback read is kept for backwards compatibility (config-keyed chains take precedence on duplicates), but ocx doctor now scans $CODEX_HOME/agents/*.toml and warns for every role file still carrying the field, pointing at the new config home. The scan shares one TOML-aware, presence-aware parser with the reader: quoted keys are detected, text inside (multi)line strings is not, escaped delimiters stay inside strings, and malformed array values still trigger the doctor WARN while yielding no fallback entries.
  • Docs updated in all locales (en, ja, ko, ru, zh-cn): fallback-chain order, the new config field, the Codex 0.146 incompatibility warning, and the JSON example.

Closes #1190

Verification

  • Branch rebased onto the latest origin/dev (0 commits behind).
  • bun run typecheck — clean.
  • bun test tests/subagent-model-fallback.test.ts — 50 pass / 0 fail. New coverage: config-keyed resolution, cross-key dedupe with account selectors, config-over-TOML precedence, doctor scan presence including empty arrays, quoted model_fallback keys, single-line and multiline strings containing model_fallback text, escaped triple quotes inside multiline strings, and malformed arrays (missing/leading commas, trailing tokens) that stay reported by the scan while producing no fallback entries.
  • bun test tests/doctor.test.ts tests/doctor-provider-apikey.test.ts tests/codex-plugins-doctor.test.ts tests/doctor-oauth.test.ts tests/config.test.ts tests/config-user-edits.test.ts — 222 pass / 0 fail.
  • bun run privacy:scan — passed.
  • Full bun run test (9079 tests): 12 failures in tests/management-provider-validation.test.ts, crash-guard, and a process-serialization test; re-ran the same files on a clean origin/dev worktree and got the identical failures — pre-existing on dev, unrelated to this change.
  • All CodeRabbit review threads resolved (3 review rounds; last review on 6b1ce0cd completed with no new findings).

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I fixed all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds subagentModelFallbackByModel to OpenCodex configuration, applies model-specific chains before global fallbacks, preserves legacy TOML reads, adds ocx doctor detection, and updates tests and multilingual documentation.

Changes

Sub-agent fallback compatibility

Layer / File(s) Summary
Fallback configuration contract
src/types.ts, src/config.ts, docs-site/src/content/docs/**/reference/configuration/agents.md, docs-site/src/content/docs/**/guides/sub-agent-surface.md
Defines and validates subagentModelFallbackByModel. Documents fallback precedence and legacy model_fallback behavior.
Model-keyed fallback resolution
src/codex/subagent-model-fallback.ts, tests/subagent-model-fallback.test.ts
Resolves chains by primary model, trims and deduplicates entries, and gives configured chains precedence over legacy TOML fallbacks.
Legacy role diagnostics
src/codex/subagent-model-fallback.ts, src/cli/doctor.ts, tests/subagent-model-fallback.test.ts
Parses TOML fields with presence-aware handling, scans affected roles, and reports migration guidance. Tests cover quoted keys, multiline values, empty arrays, malformed arrays, and embedded text.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Subagent
  participant OpenCodex
  participant Config
  participant CodexRole
  participant Doctor
  Subagent->>OpenCodex: request with primary model
  OpenCodex->>Config: resolve subagentModelFallbackByModel
  Config-->>OpenCodex: model-specific fallback chain
  OpenCodex->>CodexRole: read legacy model_fallback
  CodexRole-->>OpenCodex: compatibility entries
  Doctor->>CodexRole: scan agent TOML files
  CodexRole-->>Doctor: roles containing model_fallback
  OpenCodex-->>Subagent: apply ordered fallback candidates
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: wibias, chrisae9, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue [#1190] by adding per-model fallbacks, preserving legacy reads, adding doctor warnings, updating documentation, and testing compatibility behavior.
Out of Scope Changes check ✅ Passed The code, tests, doctor diagnostics, and localized documentation all directly support the fallback compatibility objectives in [#1190].
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: moving per-role model fallback configuration into OpenCodex configuration for subagents.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ⬜ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

Hygiene

Deterministic PR hygiene checks passed.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 7, 2026
@Yuxin-Qiao
Yuxin-Qiao force-pushed the fix/1190-subagent-model-fallback-config branch from 9320131 to 63f31ae Compare August 7, 2026 15:15
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/ru/reference/configuration/agents.md`:
- Line 21: Update the Russian table entry for subagentModelFallbackByModel to
identify this OpenCodex configuration field as the supported location for
per-role fallback metadata. Describe model_fallback in $CODEX_HOME/agents/*.toml
as legacy-only and state that Codex 0.146+ skips the role when it is used,
keeping the wording consistent with the English documentation and referenced
guidance.

In `@src/cli/doctor.ts`:
- Around line 926-932: Update the scanner used by the doctor flow around
scanCodexAgentRolesWithTomlModelFallback so it reports every readable
model_fallback TOML key, including model_fallback = [], while excluding roles
without the key; do not base detection solely on
readCodexAgentModelFallback(...).length. In
tests/subagent-model-fallback.test.ts lines 990-1004, add an empty-array
model_fallback role and assert it is reported, while retaining coverage that
roles without the key are excluded.

In `@src/codex/subagent-model-fallback.ts`:
- Around line 567-570: Update scanCodexAgentRolesWithTomlModelFallback to detect
the presence of the model_fallback key rather than requiring
readCodexAgentModelFallback to return a non-empty list; add or use
hasCodexAgentModelFallbackField with the same TOML parser while preserving
readCodexAgentModelFallback for fallback execution, and add a focused Bun
regression test under tests/ covering model_fallback = [].
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4fb8111f-cb52-4927-bac7-5d9056e41ae8

📥 Commits

Reviewing files that changed from the base of the PR and between 3e60b1d and 63f31ae.

📒 Files selected for processing (15)
  • docs-site/src/content/docs/guides/sub-agent-surface.md
  • docs-site/src/content/docs/ja/guides/sub-agent-surface.md
  • docs-site/src/content/docs/ja/reference/configuration/agents.md
  • docs-site/src/content/docs/ko/guides/sub-agent-surface.md
  • docs-site/src/content/docs/ko/reference/configuration/agents.md
  • docs-site/src/content/docs/reference/configuration/agents.md
  • docs-site/src/content/docs/ru/guides/sub-agent-surface.md
  • docs-site/src/content/docs/ru/reference/configuration/agents.md
  • docs-site/src/content/docs/zh-cn/guides/sub-agent-surface.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/agents.md
  • src/cli/doctor.ts
  • src/codex/subagent-model-fallback.ts
  • src/config.ts
  • src/types.ts
  • tests/subagent-model-fallback.test.ts

Comment thread docs-site/src/content/docs/ru/reference/configuration/agents.md Outdated
Comment thread src/cli/doctor.ts
Comment thread src/codex/subagent-model-fallback.ts Outdated
@Yuxin-Qiao
Yuxin-Qiao force-pushed the fix/1190-subagent-model-fallback-config branch from 210e372 to c476e83 Compare August 8, 2026 04:25
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Addressed all three CodeRabbit findings:

  1. model_fallback = [] now counts as the field being present: added hasCodexAgentModelFallbackField (key-presence scan) and switched scanCodexAgentRolesWithTomlModelFallback to it, with a regression test covering an empty-array role while roles without the key stay excluded.
  2. Russian config table wording now states subagentModelFallbackByModel is the supported location and TOML model_fallback is legacy-only.
  3. Verified: bun run typecheck clean, focused suite 46 pass / 0 fail.

@coderabbitai re-review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

@Yuxin-Qiao I will review the updated changes, including the empty-array TOML field detection and the Russian configuration documentation.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/codex/subagent-model-fallback.ts`:
- Around line 567-572: Update hasCodexAgentModelFallbackField and the
fallback-reading path to reuse one TOML-aware, presence-aware parser instead of
matching raw text. Ensure it recognizes quoted model_fallback keys, ignores
occurrences inside multiline strings, and preserves distinction between an
absent field and a present field with an empty value; add coverage for both
cases in the existing subagent model fallback tests.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a404ca17-a237-47ea-b4f2-bcc687bfa453

📥 Commits

Reviewing files that changed from the base of the PR and between 63f31ae and c476e83.

📒 Files selected for processing (3)
  • docs-site/src/content/docs/ru/reference/configuration/agents.md
  • src/codex/subagent-model-fallback.ts
  • tests/subagent-model-fallback.test.ts

Comment thread src/codex/subagent-model-fallback.ts Outdated
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@coderabbitai please re-review

Addressed the TOML-awareness finding in c29ade17:

  • hasCodexAgentModelFallbackField and the fallback-reading path now share one TOML-aware, presence-aware parser (parseTomlModelFallbackField).
  • Quoted keys ("model_fallback", 'model_fallback') are recognized; text inside single-line and multiline strings is never treated as a key; array continuation lines are not scanned as statements.\n- The absent-field vs. present-with-empty-array distinction is preserved: present is set whenever the key exists, and the reader still returns the parsed array only when it is readable.\n- New regression tests cover quoted keys, empty arrays, single-line strings, and multiline strings containing model_fallback = [].\n\nVerification on the branch:\n- bun run typecheck passes.\n- bun test tests/subagent-model-fallback.test.ts -> 48 pass.\n- doctor suites: tests/doctor.test.ts, tests/doctor-provider-apikey.test.ts, tests/codex-plugins-doctor.test.ts, tests/doctor-oauth.test.ts -> 61 pass.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- PR diff summary ---'
git diff --stat origin/dev...HEAD || git diff --stat HEAD~1...HEAD

echo
echo '--- Changed files ---'
git diff --name-only origin/dev...HEAD || git diff --name-only HEAD~1...HEAD

echo
echo '--- Relevant symbol map ---'
fd -a -t f '^(subagent-model-fallback|doctor)\.ts$' src tests | while IFS= read -r f; do
  echo "### $f"
  ast-grep outline "$f" --items all --type function --match 'parseTomlModelFallbackField|hasCodexAgentModelFallbackField|scanCodexAgentRolesWithTomlModelFallback|read.*ModelFallback|applySubagentModelFallback' || true
done

echo
echo '--- Implementation references with context ---'
rg -n -C 8 'parseTomlModelFallbackField|hasCodexAgentModelFallbackField|scanCodexAgentRolesWithTomlModelFallback|model_fallback' src/codex/subagent-model-fallback.ts tests/subagent-model-fallback.test.ts

echo
echo '--- Incremental commit diff ---'
git show --format=fuller --find-renames c29ade17 -- src/codex/subagent-model-fallback.ts tests/subagent-model-fallback.test.ts

Length of output: 38871


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Parser with line numbers ---'
nl -ba src/codex/subagent-model-fallback.ts | sed -n '520,725p'

echo
echo '--- TOML dependencies and parser usage ---'
rg -n -i -C 3 '"[^"]*toml[^"]*"|from ["'\''][^"'\'']*toml|require\(["'\''][^"'\'']*toml' \
  package.json bun.lockb bun.lock tests src 2>/dev/null || true

echo
echo '--- Escaped multiline-delimiter coverage ---'
rg -n -i -C 5 'escaped.*multiline|multiline.*escaped|\\{1,}""".*model_fallback|model_fallback.*\\{1,}"""' \
  tests src || true

echo
echo '--- All parser call sites ---'
rg -n -C 3 '\bparseTomlModelFallbackField\b|\bscanTomlLine\b|\bfindTomlMultilineStringEnd\b' src tests

Length of output: 1056


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Parser with line numbers ---'
sed -n '520,725p' src/codex/subagent-model-fallback.ts | awk '{ printf "%6d  %s\n", NR + 519, $0 }'

echo
echo '--- TOML dependencies and parser usage ---'
for f in package.json bun.lockb bun.lock; do
  if [ -f "$f" ]; then
    echo "### $f"
    rg -n -i -C 3 'toml' "$f" || true
  fi
done
rg -n -i -C 3 'from ["'\''][^"'\'']*toml|require\(["'\''][^"'\'']*toml|parse.*toml|toml.*parse' src tests || true

echo
echo '--- Escaped multiline-delimiter coverage ---'
rg -n -i -C 5 'escaped.*multiline|multiline.*escaped|\\{1,}""".*model_fallback|model_fallback.*\\{1,}"""' tests src || true

echo
echo '--- All parser call sites ---'
rg -n -C 3 '\bparseTomlModelFallbackField\b|\bscanTomlLine\b|\bfindTomlMultilineStringEnd\b' src tests

Length of output: 49739


@Yuxin-Qiao, I found one remaining TOML-awareness issue.

Medium — preserve multiline basic-string state across escaped delimiters

In src/codex/subagent-model-fallback.ts, Lines 545 and 663 use indexOf('"""') to find a multiline-string terminator. This treats an escaped triple quote in a TOML multiline basic string as a closing delimiter.

findTomlMultilineStringEnd at Lines 601-612 already contains the required odd-backslash check. However, the scanner does not use it.

As a result, this valid pattern can cause a false positive:

description = """
An escaped delimiter: \"""
model_fallback = []
"""

The scanner exits string mode at \""". It then processes model_fallback = [] as a top-level key. ocx doctor reports the role even though the field is only string content.

Use the same delimiter-aware helper in both scanner paths:

  • Replace the indexOf call in scanTomlLine.
  • Replace the indexOf call in the state.inMultilineString branch of parseTomlModelFallbackField.
  • Add a regression test for an escaped """ before model_fallback = [] inside a multiline basic string.

The shared parser and the existing quoted-key, empty-array, and basic string tests otherwise address the prior finding.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…dge-jun#1190)

Codex 0.146+ strictly deserializes $CODEX_HOME/agents/*.toml and rejects
model_fallback as an unknown field, skipping the entire role definition.
Per-role fallback chains now live in config.json as
subagentModelFallbackByModel, keyed by the requested primary model id, and
are consulted before the legacy TOML read (kept for backwards
compatibility). ocx doctor scans agent role files and warns when any
still carries model_fallback, pointing at the new config home.

Docs updated in all locales.
CodeRabbit review: Codex >= 0.146 rejects the unknown field regardless of
value, so the doctor scan must report model_fallback = [] roles too. Add
hasCodexAgentModelFallbackField and a regression test; clarify the Russian
config table wording.
CodeRabbit review: hasCodexAgentModelFallbackField matched raw text, so
quoted keys like "model_fallback" were missed and the same text inside a
multiline string literal was a false positive. Share one TOML-aware,
presence-aware parser between the doctor scan and the fallback-reading
path; it recognizes quoted keys, skips string contents, and keeps absent
vs. empty-array distinct. Add quoted-key and multiline-string tests.
@Yuxin-Qiao
Yuxin-Qiao force-pushed the fix/1190-subagent-model-fallback-config branch from c29ade1 to 2b6a50f Compare August 8, 2026 04:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/codex/subagent-model-fallback.ts`:
- Around line 637-671: Update parseTomlStringArrayValue so commas are tracked
separately from whitespace and required between successive string elements.
Reject arrays with adjacent strings or a leading comma, while preserving valid
empty and comma-separated arrays; add tests covering missing-comma and
leading-comma inputs.
- Around line 568-574: Replace the raw triple-quote index lookup in both scanner
paths with findTomlMultilineStringEnd, including the path containing the shown
state.inMultilineString handling, so escaped delimiters do not terminate
scanning early. Add a regression test covering an escaped triple quote followed
by model_fallback = [] within the same multiline string, ensuring the embedded
text is not reported as configuration.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bc6a5156-c411-4787-a7e4-888b7b274c97

📥 Commits

Reviewing files that changed from the base of the PR and between c29ade1 and 2b6a50f.

📒 Files selected for processing (3)
  • src/codex/subagent-model-fallback.ts
  • src/config.ts
  • src/types.ts

Comment thread src/codex/subagent-model-fallback.ts Outdated
Comment thread src/codex/subagent-model-fallback.ts Outdated
CodeRabbit review: an escaped triple quote (\""") inside a multiline
basic string closed scanner state early, and string arrays accepted
adjacent elements without commas. Use findTomlMultilineStringEnd in both
scanner paths and require one comma between successive array elements
while keeping empty and trailing-comma arrays valid. Add regression tests
for escaped delimiters and malformed arrays.
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Addressed the two new findings in 7325fbac:

  • Escaped triple quotes (\""") inside multiline basic strings no longer close scanner state early: both the line scanner and the continuation-line path now use findTomlMultilineStringEnd.
  • parseTomlStringArrayValue now requires one comma between successive string elements and rejects leading/doubled commas, while keeping empty arrays and trailing commas valid.
  • Regression tests cover an escaped delimiter on the opening line, an escaped delimiter on a continuation line (both followed by model_fallback = [] inside the string), and missing/leading comma arrays (doctor still reports presence for malformed values).

Verification: bun run typecheck clean; bun test tests/subagent-model-fallback.test.ts -> 50 pass.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Commit summary and changed files ---'
git show --stat --oneline --decorate --find-renames 7325fbac
git show --format='' --name-only 7325fbac

echo
echo '--- Relevant symbol map ---'
ast-grep outline src/codex/subagent-model-fallback.ts \
  --items all --type function \
  --match 'findTomlMultilineStringEnd|scanTomlLine|parseTomlModelFallbackField|parseTomlStringArrayValue|hasCodexAgentModelFallbackField|readAgentModelFallback'
ast-grep outline tests/subagent-model-fallback.test.ts \
  --items all --type function \
  --match 'modelFallback|fallback|Toml|toml'

echo
echo '--- Incremental implementation and test diff ---'
git show --format=fuller --find-renames 7325fbac -- \
  src/codex/subagent-model-fallback.ts \
  tests/subagent-model-fallback.test.ts

echo
echo '--- Current parser and relevant tests with line numbers ---'
rg -n -C 14 \
  'function (findTomlMultilineStringEnd|scanTomlLine|parseTomlModelFallbackField|parseTomlStringArrayValue)|findTomlMultilineStringEnd\(|escaped delimiter|missing comma|leading comma|doubled comma|model_fallback = \[\]' \
  src/codex/subagent-model-fallback.ts \
  tests/subagent-model-fallback.test.ts

Length of output: 27697


@Yuxin-Qiao I reviewed commit 7325fbac. I found no remaining issue in the two addressed areas.

  • In src/codex/subagent-model-fallback.ts, Line 568 now uses findTomlMultilineStringEnd when a multiline string starts on the current line.
  • Line 695 uses the same helper when parsing continues from a prior line.
  • The helper at Lines 624-635 ignores """ after an odd number of backslashes. This preserves multiline basic-string state for \""".
  • parseTomlStringArrayValue at Lines 638-680 now rejects a leading comma, a doubled comma, and adjacent string values without a comma. It still accepts [] and a trailing comma.
  • tests/subagent-model-fallback.test.ts, Lines 1059-1081, cover escaped delimiters on the opening line and continuation lines.
  • The following test covers malformed comma placement and verifies that doctor detection still reports a present but unreadable field.

The reported test results were not independently executed in this inspection environment.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/codex/subagent-model-fallback.ts`:
- Line 663: Update the array parsing logic in readCodexAgentModelFallback() so
encountering ] validates the rest of the current physical line, permitting only
horizontal whitespace, an inline # comment, or end-of-line; reject any other
trailing token without consuming subsequent lines passed by
parseTomlModelFallbackField(). Add a focused Bun regression test under tests/
verifying scanCodexAgentRolesWithTomlModelFallback() reports the malformed field
and returns no fallback entries.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b1676da4-b145-4e4a-93aa-65e94dfadd37

📥 Commits

Reviewing files that changed from the base of the PR and between 2b6a50f and 7325fba.

📒 Files selected for processing (2)
  • src/codex/subagent-model-fallback.ts
  • tests/subagent-model-fallback.test.ts

Comment thread src/codex/subagent-model-fallback.ts Outdated
CodeRabbit review: the value parser returned as soon as it read the
closing bracket, so 'model_fallback = ["kimi/k3"] invalid' produced a
fallback list. After ']' only horizontal whitespace, an inline comment,
or the line end is valid; anything else makes the value malformed while
presence (and thus the doctor WARN) is still reported.
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Addressed the trailing-token finding in 6b1ce0cd: after the closing ] the value parser now accepts only horizontal whitespace, an inline # comment, or the line end. model_fallback = ["kimi/k3"] invalid yields no fallback entries while scanCodexAgentRolesWithTomlModelFallback still reports the role. Regression coverage includes the malformed trailing-token case and a valid inline-comment case. bun run typecheck clean; bun test tests/subagent-model-fallback.test.ts -> 50 pass.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Incremental commit ---'
git show --stat --oneline --find-renames 6b1ce0cd
git show --format=fuller --find-renames 6b1ce0cd -- \
  src/codex/subagent-model-fallback.ts \
  tests/subagent-model-fallback.test.ts

echo
echo '--- Parser and call-site map ---'
ast-grep outline src/codex/subagent-model-fallback.ts --items all --type function \
  --match 'parseTomlStringArrayValue|parseTomlModelFallbackField|scanCodexAgentRolesWithTomlModelFallback|readAgentModelFallback|hasCodexAgentModelFallbackField'
ast-grep outline tests/subagent-model-fallback.test.ts --items all --type function \
  --match 'fallback|Toml|toml'

echo
echo '--- Focused implementation and regression context ---'
rg -n -C 20 \
  'function parseTomlStringArrayValue|parseTomlStringArrayValue\(|trailing token|inline comment|model_fallback = \["kimi/k3"\]' \
  src/codex/subagent-model-fallback.ts \
  tests/subagent-model-fallback.test.ts

Length of output: 12712


@Yuxin-Qiao I reviewed commit 6b1ce0cd. I found no remaining issue in the trailing-token handling.

  • In src/codex/subagent-model-fallback.ts, isValidTomlArrayTail accepts only spaces, tabs, an inline # comment, or a line ending after the closing ].
  • parseTomlStringArrayValue returns null when it finds a trailing token such as invalid.
  • parseTomlModelFallbackField still returns present: true before it parses the value. Therefore, scanCodexAgentRolesWithTomlModelFallback still reports malformed model_fallback fields.
  • tests/subagent-model-fallback.test.ts verifies both required cases:
    • model_fallback = ["kimi/k3"] invalid yields no fallback entries and remains visible to doctor scanning.
    • model_fallback = ["kimi/k3"] # keep yields ["kimi/k3"].

I did not independently run the reported typecheck or test command in this environment.

You are interacting with an AI system.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/codex/subagent-model-fallback.ts (1)

513-523: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Put global configuration before legacy TOML fallbacks.

The new selection path supplies legacy role fallbacks through the chain that normalizedChain() inserts before config.subagentModelFallback at Lines 127-129. A legacy model_fallback can therefore override the global OpenCodex fallback configuration.

Build the chain in this order: requested primary model, model-keyed configuration, global subagentModelFallback, then legacy TOML values. Apply the existing fallbackChainKey de-duplication across all four stages. Add a regression case with distinct model-keyed, global, and legacy entries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/codex/subagent-model-fallback.ts` around lines 513 - 523, Update the
fallback-chain construction around resolveConfiguredModelFallbackForPrimary and
resolveAgentModelFallbackForPrimary so it orders the requested primary model,
model-keyed configuration, global config.subagentModelFallback, then legacy TOML
values. Apply the existing fallbackChainKey de-duplication across all stages,
and add a regression case using distinct model-keyed, global, and legacy entries
to verify that order.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/codex/subagent-model-fallback.ts`:
- Around line 513-523: Update the fallback-chain construction around
resolveConfiguredModelFallbackForPrimary and resolveAgentModelFallbackForPrimary
so it orders the requested primary model, model-keyed configuration, global
config.subagentModelFallback, then legacy TOML values. Apply the existing
fallbackChainKey de-duplication across all stages, and add a regression case
using distinct model-keyed, global, and legacy entries to verify that order.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 87d049d3-7e27-4645-81ce-0921cc5c3df1

📥 Commits

Reviewing files that changed from the base of the PR and between 2b6a50f and 6b1ce0c.

📒 Files selected for processing (2)
  • src/codex/subagent-model-fallback.ts
  • tests/subagent-model-fallback.test.ts

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

CI status for 6b1ce0cd: the only red check is Cross-platform CI, and it is a timeout, not a test failure.

Run 31242590755: test 4/4 was cancelled by GitHub after running the Test step for exactly 14m54s against the job's 15-minute timeout-minutes ceiling; the aggregate ci job then failed its "needed job(s) did not pass: test=cancelled" assertion. Everything else passed: Linux shards 1/4-3/4, the macOS unsharded full suite, gates (typecheck, GUI tests, privacy scan), storage policy, keyring smokes, npm-global smokes, React Doctor, and PR hygiene.

Local checks on the same head: tests/cli-help.test.ts (the last file with output before the silence) passes in ~6s, and the shard 4 command completes in ~135s without an unbounded hang. This looks like runner load / environment noise rather than a code problem.

Could a maintainer re-run the failed jobs (GitHub Actions "Re-run failed jobs" or gh run rerun 31242590755 --failed)? It needs admin rights, which fork PR authors do not have.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Additional local evidence for the same head (6b1ce0cd): I ran the exact Linux shard 4 command outside the sandbox (bun test --isolate tests --path-ignore-patterns 'tests/api-storage-policy*.test.ts' --shard=4/4).\n\n- Completed in ~251s with no unbounded hang: 2439 pass, 2 skip, 2 fail.\n- Both failures are 5s-timeout timing flakes under parallel load: crash-guard diagnostics > dumps recent fetch origins (already in the pre-existing dev failure list) and CLI subcommand help > top-level help forms exit before Codex shim auto-restore can mutate launchers (passes in ~6s when the file runs alone; the macOS CI full-suite run passed it under load).\n- Neither is related to this change, and neither reproduces the CI symptom (a 14-minute silent stall).\n\nThis all points to runner load on the cancelled test 4/4 rather than a code defect. A maintainer rerun of the failed jobs should be sufficient.

@Wibias Wibias linked an issue Aug 9, 2026 that may be closed by this pull request
4 tasks
@lidge-jun

Copy link
Copy Markdown
Owner

Landed on dev as ba52150 plus your four doctor commits, all with your authorship preserved, and one corrective commit on top (fc17327).

The compatibility fix was right: src/codex/subagent-model-fallback.ts:482-492 still read the model_fallback TOML extension that Codex 0.146+ rejects, and the docs still recommended it. The problem was precedence. applySubagentModelFallback passed [configured, legacy] into normalizedChain, which appends the global chain afterward — so execution produced ["primary","keyed","legacy","global"] and legacy TOML silently outranked the supported configuration you were introducing.

The correction reorders to primary → keyed → global → legacy, deduplicating every stage through fallbackChainKey. Verified concretely: before, the chain resolved gpt-5.6-sol, keyed Alibaba, legacy xai/grok-4.5, then global KIMI/K3; after, it resolves global kimi/k3 before the legacy entry. There is now an all-four-stage precedence regression covering it.

Full suite green on the landed head. Thanks — moving this off the unsupported TOML field was the right call, and the doctor warnings make the migration visible to users.

@lidge-jun lidge-jun closed this Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Per-role model_fallback causes Codex 0.146.0 to reject custom agent TOML

2 participants