Skip to content

feat(stt): honor stt.mistral.base_url, completing endpoint parity - #97188

Open
meltforce wants to merge 2 commits into
NousResearch:mainfrom
meltforce:feat/stt-mistral-base-url
Open

meltforce wants to merge 2 commits into
NousResearch:mainfrom
meltforce:feat/stt-mistral-base-url

Conversation

@meltforce

Copy link
Copy Markdown

What does this PR do?

stt.provider: mistral can only ever address api.mistral.ai. _transcribe_mistral builds its client as Mistral(api_key=api_key) with no server_url, so no configuration reaches the endpoint.

Every other STT provider already honors a base URL from its own config block — openai (_resolve_openai_stt_client_config), xai, elevenlabs and deepinfra. Mistral is the exception.

The TTS half is not: #73512 introduced what its description calls class-level base_url parity for TTS providers, and _generate_mistral_tts has read tts.mistral.base_url into the SDK's server_url since. This is the same change for the transcription side, in the shape _transcribe_elevenlabs uses — config block, then env, then module constant.

Unset, no server_url is passed at all and the SDK keeps its own endpoint, so an install that does not configure this behaves exactly as before.

Why it matters. A self-hosted gateway or authenticating reverse proxy in front of Mistral is reachable for synthesis and unreachable for transcription, which makes the provider pair unusable in that deployment — with nothing in the configuration to indicate why. Concretely, this came up routing both directions through Tailscale Aperture, whose HTTP connector answers /v1/audio/speech and /v1/audio/transcriptions identically; TTS could be pointed at it, STT could not.

Related Issue

None open that I could find — searched stt base_url, voxtral, and voxtral endpoint across issues and PRs per CONTRIBUTING § Search First. The closest prior art is #73512 (merged), which this continues.

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)

Changes Made

  • tools/transcription_tools.py_transcribe_mistral resolves stt.mistral.base_urlSTT_MISTRAL_BASE_URLMISTRAL_STT_BASE_URL (new module constant, empty by default) and passes it to the SDK as server_url only when set.
  • tests/tools/test_transcription_tools.py — three cases in TestTranscribeMistral: config base_url becomes server_url (with trailing-slash normalization), an unconfigured provider passes no server_url at all, and the env variable applies when the config block is silent.
  • website/docs/user-guide/features/tts.md — the key in the STT config block, and a sentence in the Mistral provider detail.
  • website/docs/reference/environment-variables.mdSTT_MISTRAL_BASE_URL.

How to Test

  1. python -m pytest tests/tools/test_transcription_tools.py -k "Mistral or mistral" — 9 passed.

  2. Regression across the transcription suite: python -m pytest tests/tools/test_transcription_tools.py tests/tools/test_pre_transcription_hook.py tests/tools/test_transcription.py tests/tools/test_stt_language_resolution.py — 101 passed.

  3. End to end against a real proxy: set

    stt:
      provider: mistral
      mistral:
        model: voxtral-mini-latest
        base_url: "https://<your-gateway>/v1/connectors/Mistral"

    and send a voice message. Verified this way on agent v0.20.6 against a Tailscale Aperture HTTP connector, which returned the correct transcript; without the change the same configuration reaches api.mistral.ai and the base_url value is ignored.

Every other STT provider reads a base URL from its own config block —
openai (`_resolve_openai_stt_client_config`), xai, elevenlabs and
deepinfra all do. `_transcribe_mistral` was the exception: it built
`Mistral(api_key=api_key)` with no `server_url`, so `stt.provider:
mistral` could only ever address api.mistral.ai.

The TTS half already has this. NousResearch#73512 introduced what its description
calls "class-level base_url parity" for TTS providers, and
`_generate_mistral_tts` has read `tts.mistral.base_url` into the SDK's
`server_url` since. This is the same change for the transcription side,
in the shape `_transcribe_elevenlabs` uses: config block, then env, then
the module constant.

Unset, no `server_url` is passed at all and the SDK keeps its own
endpoint, so an install that does not configure this behaves exactly as
before.

Why it matters: a self-hosted gateway or authenticating reverse proxy in
front of Mistral is reachable for TTS and unreachable for STT, which
makes the provider pair unusable in that deployment for no reason
visible from the configuration.
@alt-glitch alt-glitch added type/feature New feature or request tool/tts Text-to-speech and transcription area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades P3 Low — cosmetic, nice to have labels Aug 28, 2026
@Enough1122

Copy link
Copy Markdown
Contributor

AI code review — automated review for reference; please use your judgment.

Overall: Completes endpoint parity for Mistral STT — stt.mistral.base_url → SDK server_url.

What it does

  • tools/transcription_tools.py adds MISTRAL_STT_BASE_URL = os.getenv("STT_MISTRAL_BASE_URL", "") (empty default keeps SDK default) and maps config stt.mistral.base_url to SDK server_url (mirrors tts.mistral.base_url pattern).
  • tests/tools/test_transcription_tools.py adds test_config_base_url_becomes_server_url and docs website/docs/... updated with env var + config comment.

Non-blocking notes

  • Env var is STT_MISTRAL_BASE_URL but config key is stt.mistral.base_url — mapping precedence is config > env > SDK default; verify code checks config.get("base_url") first then fallback to MISTRAL_STT_BASE_URL, not the reverse, so user config overrides env as documented for TTS.
  • Test mocks mistralai module — ensure it asserts server_url kwarg name exactly as SDK expects (server_url vs base_url); current test checks server_url, correct.

Small parity completion; no breaking change when unset.

Non-blocking — please use your judgment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles P3 Low — cosmetic, nice to have sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/tts Text-to-speech and transcription type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants