feat: add Mistral AI as a first-class provider route - #5295
Conversation
|
Thanks @xavierpestel-ai for taking the time to contribute. This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered. Please read |
9f0595f to
8c83276
Compare
Hmbown
left a comment
There was a problem hiding this comment.
Thanks, Xavier — this is the right overall first-class-provider shape, and I want to preserve your commit/authorship and merge the work through this PR rather than reimplementing it elsewhere. The registry/config/env/docs coverage and the live tool-call smoke are especially useful.
I found three current Mistral-contract mismatches that need correction before we run the full matrix:
-
Several model IDs are documentation-page slugs rather than API IDs. In
crates/agent/src/lib.rs, the current API IDs aremistral-medium-3-5(notmistral-medium-3.5-26-04) andmistral-small-2603(notmistral-small-4-0-26-03). The Nemo dated ID isopen-mistral-nemo-2407, notmistral-nemo-2407; that model is also already past its documented deprecation date, as ispixtral-large-2411, so I would omit both from a new static "shipped" list unless there is a concrete compatibility reason to keep them. Official cards: https://docs.mistral.ai/models/model-cards/mistral-medium-3-5-26-04, https://docs.mistral.ai/models/model-cards/mistral-small-4-0-26-03, https://docs.mistral.ai/models/model-cards/mistral-nemo-12b-24-07, https://docs.mistral.ai/models/model-cards/pixtral-large-24-11. -
The context metadata is reversed. Current Codestral /
codestral-latestis 128k, not 256k, while Mistral Medium 3.5, Mistral Small 4, and Mistral Large 3 are 256k, not 128k. Those values directly affect compaction/output budgeting, so this is runtime correctness rather than cosmetic metadata. Official cards: https://docs.mistral.ai/models/model-cards/codestral-25-08 and https://docs.mistral.ai/models/model-cards/mistral-large-3-25-12 (plus the Medium/Small cards above). -
Reasoning is silently disabled even though the API supports it. The Chat Completions schema accepts
reasoning_effort, and Mistral explicitly documents adjustable reasoning formistral-medium-3-5andmistral-small-latest: https://docs.mistral.ai/studio-api/conversations/reasoning. Right now every Mistral model is markedsupports_reasoning: falseandapply_reasoning_effortno-ops, so a user's selected effort is silently ignored. Please either wire the supported models end-to-end (request plus thinking-chunk streaming/history handling), or narrow the advertised model surface and state the limitation truthfully rather than claiming Mistral Chat Completions does not accept the field.
Please also rebase onto current main; this head is six commits behind, including the final 0.9.5 telemetry/release fixes. The old full-suite caveat in the PR body is no longer current—our exact release/main gates are green—so rerun the current targeted provider checks after the corrections. No need to expose or resend any API key.
Once you push the corrected head, ping me here. I’ll approve the first-contributor Actions run and carry this through review so your authorship stays intact.
0617711 to
012e28c
Compare
|
Thanks @Hmbown — all three points landed. Rebased onto 1. Model IDs — updated against
|
Wire Mistral AI / la Plateforme into the shared provider registry, TUI provider enum, provider-scoped config/env overrides, static model registry, context-window metadata, reasoning wiring, docs, and examples. The route uses Mistral's OpenAI-compatible Chat Completions endpoint at https://api.mistral.ai/v1 with 'mistral-code-latest' as the default model (Codestral coding model, 256K context). Model IDs verified live against https://api.mistral.ai/v1/models: the static registry ships 'mistral-code-latest' (accepts 'codestral-latest' as alias for backward compatibility), 'mistral-medium-latest', 'mistral-small-latest', 'magistral-small-latest', and 'mistral-large-latest'. All models report 262144 (256K) context on /v1/models except mistral-code-latest at 256000; earlier drafts of this PR had those windows reversed. Reasoning is wired end-to-end for the three models that advertise 'reasoning: true' on /v1/models — mistral-medium-latest, mistral-small-latest, and magistral-small-latest. Codewhale sends 'reasoning_effort' (Mistral currently accepts 'none' or 'high' only; intermediate tiers return HTTP 400 code 3051), parses the polymorphic 'content: [{type: thinking, thinking: [{type: text, text: ...}], closed: bool}, {type: text, text: ...}]' shape emitted by reasoning models, and replays the thinking trace back into multi-turn history per docs.mistral.ai/capabilities/reasoning. Non-reasoning models (mistral-code-latest, mistral-large-latest) never receive the field because Mistral would reject it. FIM (/v1/fim/completions) is not wired. Provider aliases: mistral-ai, mistralai, la-plateforme. Env vars: MISTRAL_API_KEY, MISTRAL_BASE_URL, MISTRAL_MODEL. Auth via API key from https://console.mistral.ai/api-keys, config, or 'codewhale auth set'. Test env-poisoning: EnvGuard captures/removes/restores MISTRAL_* so tests stay reproducible when a user has these vars exported in their shell. Validation: - cargo fmt --all -- --check - cargo clippy --workspace --all-targets --all-features --locked (with the documented allow list) -- No issues found - cargo test --workspace --all-features --locked -- 22 pre-existing failures in crates/tui git-shell tests (worktree init failing on 'git commit' in isolated tempdirs), verified identical count on origin/main at 91bca01 and unrelated to this change - python3 scripts/check-provider-registry.py -- passed - codewhale --provider mistral --model mistral-medium-latest exec against api.mistral.ai returned a correct reasoning-mode response - codewhale --provider mistral --model mistral-large-latest exec succeeded without HTTP 400 code 3051 (verifies the model-aware reasoning gate) - TUI smoke previously validated: /status shows mistral + mistral-code-latest, /provider lists Mistral, tool call end-to-end Assisted by Codex CLI for implementation and multiple Oracle review passes (correctness + convention + Hunter's inline review) that surfaced the ProviderArg clap enum gap, the ModelRegistry silent fallthrough to DeepSeek, the Codestral context-window regression, the EnvGuard env-poisoning flake, and the model-ID / context-window / reasoning-support mistakes from the initial docs-slug pass now corrected against the live /v1/models catalog.
012e28c to
f157d34
Compare
Scope Mistral's polymorphic reasoning and replay behavior to exact first-party HTTPS routes, preserve stored thinking across real prompt construction, and keep DeepSeek's sanitizer from injecting a second dialect into tool-call history. Align the current model registry, provider-scoped model override, generated facts, docs, and focused route-isolation tests. Split the large stream decoder test module so the source-structure gate remains below budget. Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Keep the checked source-candidate contract in sync with the generated 41-provider registry so the full web suite validates the new first-class route. Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Hmbown
left a comment
There was a problem hiding this comment.
Approved on exact head 9bac910. Thank you, Xavier, for taking the initial review seriously and for contributing the first-class Mistral route. Your original authored commit remains intact; the maintainer follow-ups route-isolate first-party reasoning shapes, keep custom gateways generic, cover stored-thinking replay and tool-call history, and align generated provider facts. Cargo check, clippy, the full all-features workspace suite, focused provider tests, the complete web suite/build, and exact-head Linux/macOS/Windows CI are green. This supersedes my earlier changes-requested review.
Bump the workspace, every published crate, the npm CLI package and its codewhaleBinaryVersion, the runtime SDK, and the VS Code extension to 0.9.6 — the four version sources the release workflow cross-checks before it will tag. The changelog entry describes v0.9.6 as what it is: a subtractive release. The guards that interrupted live work, the per-mode prompt doctrine, and the deterministic second compaction system are gone; a truncated provider response can no longer be recorded as a finished answer. Most of these were found by running v0.9.5 against Terminal-Bench 2.1 beside Pi 0.8.41 on the same model, effort, endpoint, and task digests, then reading the trials Codewhale lost — so the entry names those trials rather than describing the fixes in the abstract. Mistral AI ships in this release; Xavier Pestel (@xavierpestel-ai) is credited in the contributors section for Hmbown#5295.
Summary
Adds Mistral AI (la Plateforme) as a first-class Codewhale provider route, authored by first-time contributor @xavierpestel-ai and retained as his own commit. The route defaults to
mistral-code-latestand supportsprovider = "mistral",CODEWHALE_PROVIDER=mistral, andcodewhale --provider mistral.What ships
mistral-ai,mistralai,la-plateforme), API-key guidance, config persistence, CLI selection, telemetry, and provider-scopedMISTRAL_API_KEY,MISTRAL_BASE_URL, andMISTRAL_MODELoverrides.mistral-code-latest,mistral-medium-latest,mistral-small-latest, andmistral-large-latest, with provider-owned aliases and catalog-derived context metadata. Deprecated Magistral IDs remain explicit-configuration compatibility routes rather than current picker recommendations./v1hosts. Codewhale sends only the live-verifiednone/higheffort values, parses streaming and non-streaming polymorphic thinking blocks, and replays the complete stored assistant thinking trace on later turns.Maintainer hardening
The second commit keeps Xavier's implementation and authorship intact while closing the review gaps:
MISTRAL_BASE_URLkeeps generic Chat Completions semantics.Message->PromptBuilderhistory preserves and reshapes stored thinking before the request is sent.reasoning_contentdialect from being injected.MISTRAL_MODELprecedence now agree with the wire path.Boundaries
/v1/fim/completions) is not wired in this PR.Verification
cargo fmt --all -- --checkgit diff --checkcargo check --workspace --all-features --lockedcargo clippy --workspace --all-targets --all-features --locked -- -D warningsRUST_MIN_STACK=16777216 cargo test --workspace --all-features --locked— exit 0; TUI library 10,097 passed / 0 failed / 11 ignored, PTY 68 passed / 0 failed / 3 ignored, and all remaining workspace/integration/doc tests green. The first sandboxed attempt could not bind localhost fixtures; the identical command passed when localhost test listeners were allowed.cargo test --locked -p codewhale-tui --lib client::chat -- --nocapture— 100 passed / 0 failed, including prompt replay, tool-call history, non-stream route isolation, and stream-block route isolation.codewhale-config,codewhale-agent, andcodewhale-cliMistral/provider tests.python3 scripts/check-provider-registry.pypython3 scripts/check-source-structure-budget.py— 683,066 owned Rust lines <= 685,165../scripts/sync-changelog.sh --checkweb/npm run check:factsCloses #5304