feat(xai): detect retired May 15 models in doctor/chat startup + hermes migrate xai#29277
Merged
Conversation
Add hermes_cli.xai_retirement module that walks a Hermes config and flags references to models being retired by xAI on May 15, 2026 per the official migration guide. Pure logic + dataclass, no I/O — testable in isolation and reusable from a future hermes migrate xai sub-command. Mappings (per https://docs.x.ai/developers/migration/may-15-retirement): - grok-4 / grok-4-0709 -> grok-4.3 - grok-4-fast{,-reasoning,-non-reasoning} -> grok-4.3 (+reasoning_effort=none for non-reasoning) - grok-4-1-fast{,-reasoning,-non-reasoning} -> grok-4.3 (+reasoning_effort=none for non-reasoning) - grok-code-fast-1 -> grok-4.3 - grok-imagine-image-pro -> grok-imagine-image-quality Slots scanned: principal.model, auxiliary.<any>.model (introspective), delegation.model, tts.xai.model, plugins.image_gen.xai.model. Provider prefix x-ai/ is normalized. 33 unit tests covering edge cases (empty/non-dict config, valid models, ambiguous variants, all retired slots, formatter).
Add a new section in run_doctor that lists retired xAI model references found in the active config and points the user at the official xAI migration guide. Each retired reference shows its config path (principal.model, auxiliary.<slot>.model, delegation.model, tts.xai.model, or plugins.image_gen.xai.model), the recommended replacement, and whether reasoning_effort needs to be set (for non-reasoning variants that map to grok-4.3 + reasoning_effort=none). Findings are appended to manual_issues so the final doctor summary reminds the user to update their config.yaml manually (no automatic YAML rewriting in this PR — preserves comments, key order, types). Wrapped in try/except so doctor still completes if load_config or the retirement module raise unexpectedly.
Print a non-blocking stderr warning at the top of cmd_chat when the active config still references xAI models scheduled for retirement on May 15, 2026. Each line includes the config path, the recommended replacement, and the reasoning_effort to set for non-reasoning variants. Points to hermes doctor for full diagnostic. Wrapped in try/except — never blocks startup. After May 15 the upstream xAI API will return a clear error anyway; this is purely a heads-up to give users time to migrate before that happens.
…round-trip
Extends hermes_cli.xai_retirement with apply_migration(config_path,
issues, backup=True), used by the upcoming `hermes migrate xai`
sub-command.
Uses ruamel.yaml round-trip mode so that comments, key order,
indentation, quoting style, and scalar types are preserved on
rewrite — config.yaml is treated as a user-edited file, not a
data dump.
Behavior:
- Each issue rewrites parent[leaf] to issue.replacement
- When issue.reasoning_effort is set (non-reasoning variants
that map to grok-4.3), a sibling reasoning_effort key is
added/updated alongside the model
- Empty issues list or missing slots are no-ops (no backup,
no rewrite)
- When changes occur, a timestamped backup
(.bak-pre-migrate-xai-YYYYMMDD-HHMMSS) is written first
unless backup=False
17 unit tests cover dry-run/no-op, surgical replacement (each
slot), comment + key-order preservation, backup creation, and
idempotence (apply twice → no-op the second time).
Adds a new `migrate` top-level sub-command that delegates to
`migrate xai` for now. xAI handler:
- Default: dry-run. Lists every retired xAI model reference
found in config.yaml, with the recommended replacement and
reasoning_effort hint, and points to the official xAI
migration guide.
- --apply: rewrites config.yaml in-place (via the ruamel
round-trip apply_migration helper from hermes_cli.xai_retirement).
A timestamped backup is created automatically.
- --no-backup: skips the backup when applying (opt-in only —
the safe default keeps a copy).
Together with the doctor + chat-startup warnings already in
this stack, this gives users three escalating signals before
the May 15, 2026 retirement date: green check / warning at
chat startup / actionable migration command.
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
invalid-argument-type |
5 |
unresolved-import |
4 |
First entries
hermes_cli/xai_retirement.py:190: [unresolved-import] unresolved-import: Cannot resolve imported module `ruamel.yaml`
tests/hermes_cli/test_xai_retirement.py:63: [invalid-argument-type] invalid-argument-type: Argument to function `_looks_like_xai` is incorrect: Expected `str | None`, found `Literal[42]`
tests/hermes_cli/test_xai_retirement.py:76: [invalid-argument-type] invalid-argument-type: Argument to function `find_retired_xai_refs` is incorrect: Expected `dict[str, Any]`, found `None`
hermes_cli/xai_retirement.py:84: [invalid-argument-type] invalid-argument-type: Argument is incorrect: Expected `str`, found `str | None`
tests/hermes_cli/test_xai_retirement.py:4: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/hermes_cli/test_migrate_xai.py:61: [unresolved-import] unresolved-import: Cannot resolve imported module `ruamel.yaml`
tests/hermes_cli/test_xai_retirement.py:64: [invalid-argument-type] invalid-argument-type: Argument to function `_looks_like_xai` is incorrect: Expected `str | None`, found `dict[str, str]`
tests/hermes_cli/test_migrate_xai.py:6: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/hermes_cli/test_xai_retirement.py:77: [invalid-argument-type] invalid-argument-type: Argument to function `find_retired_xai_refs` is incorrect: Expected `dict[str, Any]`, found `Literal["nope"]`
✅ Fixed issues: none
Unchanged: 4731 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
This was referenced May 20, 2026
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
xAI is retiring
grok-4,grok-4-0709,grok-4-fast{,-reasoning,-non-reasoning},grok-4-1-fast{,-reasoning,-non-reasoning},grok-code-fast-1,grok-3, andgrok-imagine-image-proon May 15, 2026. After that date, configs pointing at those names will silently 404 or get rerouted. This PR adds detection at three surfaces and a one-shot migration command so users find out before the cutover, not after.Changes
hermes_cli/xai_retirement.py— single source of truth for retired→replacement mapping with reasoning_effort hints (e.g.*-non-reasoning→grok-4.3+reasoning_effort="none"). Recursively walks any config dict'sprovider/modelslots.hermes doctor— new "xAI Model Retirement (May 15, 2026)" section. Surfaces each retired ref with its recommended replacement and a link to xAI's migration guide.hermes chatstartup — same warning shown at session start so users notice without having to run doctor.hermes migrate xai— new CLI subcommand. Default is dry-run (preview only).--applyrewritesconfig.yamlin place via ruamel.yaml round-trip (preserves comments/formatting), creating a timestamped.bak-pre-migrate-xai-*backup first.--no-backupskips the backup.hermes_cli/models.py— comment note that the xAI static fallback excludes retired models.Salvage
Cherry-picked from #23278 + #23320 (both by @Julientalbot). Conflicts in
hermes_cli/doctor.pyresolved to use the current_section()helper. Duplicate "align toolset defaults and model fallback" commits collapsed since main's wording is already richer.Validation
scripts/run_tests.sh tests/hermes_cli/test_xai_retirement.py tests/hermes_cli/test_migrate_xai.py— 50/50 passing.HERMES_HOME:hermes migrate xaidry-run lists both violations with the right replacement.hermes migrate xai --applycreatesconfig.yaml.bak-pre-migrate-xai-<ts>, rewrites togrok-4.3, preserves YAML structure.hermes doctorsurfaces the new section and flags retired refs with the migration-guide URL.Closes #23278, closes #23320.