Skip to content

Route Mistral API key autodetection through this.fetch#13003

Open
devYRPauli wants to merge 2 commits into
continuedev:mainfrom
devYRPauli:fix/mistral-autodetect-request-options
Open

Route Mistral API key autodetection through this.fetch#13003
devYRPauli wants to merge 2 commits into
continuedev:mainfrom
devYRPauli:fix/mistral-autodetect-request-options

Conversation

@devYRPauli

Copy link
Copy Markdown

Description

Mistral.autodetectApiKeyType() calls the global fetch directly:

const mistralResp = await fetch("https://api.mistral.ai/v1/models", {

That bypasses fetchwithRequestOptions, so this one request ignores the user's configured proxy, caBundlePath, verifySsl and custom headers. Every other request in this provider goes through this.fetch, which BaseLLM wires to fetchwithRequestOptions with this.requestOptions (core/llm/index.ts). The inherited call sites in OpenAI.ts all use this.fetch(...) already.

The call is reachable in the common case: the constructor invokes it whenever apiBase is not set explicitly, in order to decide between the codestral and mistral endpoints. Its rejection is swallowed by an empty .catch((err: any) => {}), so behind an intercepting corporate proxy or with a custom CA the request fails silently, no error surfaces, and the provider is left with an incorrectly autodetected apiBase.

This is a one line change to use this.fetch, which is already available on the class and has the same (url, init) => Promise<Response> signature. Only .status is read from the response, so there is no typing change.

This is a sibling of #12993 and #12999, which fixed the same class of bypass elsewhere in the codebase.

Checklist

  • I've read the contributing guide
  • The relevant docs, if any, have been updated or created
  • The relevant tests, if any, have been updated or created

Tests

No new tests. The change swaps one call onto the same fetch wrapper every sibling method already uses, and the behaviour it restores (honouring requestOptions) needs a proxy or custom CA to observe, which the existing suite does not set up.

I ran a typecheck over core before and after the change: 115 pre-existing errors both times, none in Mistral.ts. The pre-existing errors are unrelated module resolution failures for unbuilt @continuedev/* workspace packages.

autodetectApiKeyType used the global fetch, so it bypassed
fetchwithRequestOptions and ignored the user's configured proxy,
custom CA bundle, verifySsl setting, and custom headers. Every other
request in this provider goes through this.fetch.

The call runs from the constructor whenever apiBase is not set
explicitly, and its rejection is swallowed by an empty catch, so behind
an intercepting proxy the request failed silently and the provider was
left with an incorrectly autodetected apiBase and no error surfaced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@devYRPauli
devYRPauli requested a review from a team as a code owner July 20, 2026 15:09
@devYRPauli
devYRPauli requested review from sestinj and removed request for a team July 20, 2026 15:09
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jul 20, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

on("models/fetch", async (msg) => {

P1 Badge Restore enterprise license key handler

This new registration replaced the removed on("mdm/setLicenseKey", ...) handler, but the extension entry points still call that message (extensions/vscode/src/commands.ts:708 and extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/license/AddLicenseKey.kt:30). In those IDEs, entering an enterprise license key now has no core handler, so VS Code treats the result as invalid and IntelliJ gets a failed/no-content response instead of validating and saving the key.


case "slug":
throw new Error("Slug-based package resolution is not supported");

P1 Badge Keep slug package resolution working

Rejecting every uriType: "slug" breaks the existing local unroll paths that still pass slug packages here, including --config owner/package when unauthenticated (extensions/cli/src/configLoader.ts:467-470) and local configs with uses: blocks. Those documented configurations now fail with Slug-based package resolution is not supported instead of fetching/unrolling the referenced package.


const mistralResp = await this.fetch("https://api.mistral.ai/v1/models", {

P1 Badge Let Mistral autodetection rebuild the Codestral adapter

Using this.fetch here makes the 401 probe for a Codestral-only key throw before mistralResp.status can be inspected (BaseLLM.fetch throws on non-OK responses). The constructor then swallows the rejection, so the .then block at Mistral.ts:45-56 never rebuilds openaiAdapter after switching apiBase to the Codestral endpoint; default Codestral users with no explicit apiBase keep the adapter created by super() for api.mistral.ai and their requests fail with the wrong endpoint.


const target = redirectTo.startsWith("http")
? redirectTo
: `/docs${redirectTo}`;

P2 Badge Do not prefix internal docs redirects with /docs

For an internal redirect like /cli/overview -> /cli/quickstart, this sends the browser to /docs/cli/quickstart, but the new docs app serves pages at the root and even resolveHref strips /docs for internal links (docs-site/lib/resolveHref.ts:7-10). On the standalone docs site this lands on a non-generated route, and on GitHub Pages it also drops the /continue base path.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

this.fetch routes through customFetch, which calls parseError and throws
on any non-ok response. autodetectApiKeyType detects a Codestral key by
inspecting a 401, so routing it through this.fetch made that throw, get
swallowed by the empty catch, and autodetection stop working.

Call fetchwithRequestOptions directly instead. It is the same helper
customFetch wraps, so requestOptions are still honoured, but it returns
the response rather than throwing on a non-ok status.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant