fix voice auto-install chain — use canonical lmstudio-community GGUF ids and respect non-lmstudio providers#519
Merged
Conversation
…ids and skip non-lmstudio voice providers The previous chain referenced model ids that `lms get` can't fetch: qwen/qwen3.5-9b was never released (Qwen line is 2.5 → 3 → 3.6); meta-llama/Llama-3.1-8B-Instruct is a gated HF repo; qwen/qwen3-4b-2507 is the MLX-only slug. Each attempt failed in ~100 ms with empty stderr, which the regex-filtered warning rendered as "unavailable ()". Replace with the un-gated lmstudio-community/...-GGUF ids that already appear in the curated localLlmCatalog so the "recommended installs" UI and the voice auto-installer agree on the same model set. Also gate ensureToolCapableModel / preloadModel on the voice provider so Ollama users don't see the install chain run for a CLI they're not using, and rewrite the per-attempt warning to surface the last non-empty line of stderr (or stdout) instead of the trailing newline.
…ing LM Studio provisioning resolveLlmEndpoint in llm.js falls back to LM Studio whenever voice.llm.provider points to a deleted, CLI-type, or endpoint-less provider — meaning the chat path still uses LM Studio. The previous gate short-circuited on the raw provider id string and would skip provisioning in those fallback cases, leaving voice without a tool-capable model. Mirror the resolution logic: only skip when the configured provider id actually resolves to a usable non-lmstudio api-type backend.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes the voice agent's auto-install chain so it (a) targets canonical lmstudio-community/...-GGUF ids that lms get can actually fetch, (b) only runs when the effective voice provider resolves to LM Studio, and (c) surfaces actionable failure reasons instead of empty () warnings.
Changes:
- Replace the default tool-model chain with un-gated
lmstudio-community/*-GGUFids that matchlocalLlmCatalog.js. - Add
isEffectiveLmStudioVoiceProviderand gate bothensureToolCapableModelandpreloadModelon it, mirroringresolveLlmEndpoint's fallback rules. - Improve the per-attempt failure warning to print the last non-empty line of stderr/stdout instead of a trailing newline.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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
The voice agent's auto-install chain in
server/services/voice/bootstrap.jswas firing on startup with model idslms getcan't fetch, producing:Two root causes:
qwen/qwen3.5-9bwas never released (Qwen line went 2.5 → 3 → 3.6);meta-llama/Llama-3.1-8B-Instructis a gated HF repo thatlms getcan't pull without auth;qwen/qwen3-4b-2507is the MLX-only slug. Each attempt failed in ~100 ms with empty stderr, which the regex-filtered warning rendered as the literal().ensureToolCapableModel/preloadModelalways invokedlms get/lms loadregardless of the configured voice provider, so an Ollama user sawlmsfailures for a CLI they never asked for.Changes
lmstudio-community/...-GGUFids thatlms getactually accepts — and that match the curatedlocalLlmCatalog.jsentries, so the "recommended installs" UI and the voice auto-installer agree on the same model set:lmstudio-community/Qwen3-4B-Instruct-2507-GGUF(~2.6 GB, current non-thinking Qwen3, fast TTFT)lmstudio-community/Llama-3.2-3B-Instruct-GGUF(~2 GB, smaller fallback)lmstudio-community/Qwen2.5-7B-Instruct-GGUF(~4.7 GB, classic workhorse)lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF(~4.7 GB, Llama fallback)ensureToolCapableModel/preloadModelon the effective voice provider — mirrorsresolveLlmEndpoint's fallback (deleted / CLI-type / endpoint-less providers still resolve to LM Studio, so we still provision in those cases). Only skip when the configured provider resolves to a usable non-lmstudio api-type backend (e.g. a working Ollama).().isEffectiveLmStudioVoiceProviderhelper nearLMS_BASE.Test plan
cd server && npm test -- --run services/voice/→ 387 voice tests passvoice.llm.provider='lmstudio',voice.llm.tools.enabled=true,voice.llm.model='auto'— verify the install chain attempts a real id and either succeeds or logs an actionable failure reasonvoice.llm.provider='ollama'— verify nolms getlog lines appear