Repository navigation
Model drop-in: no model names outside adapters; conformance suite for every kind - #131
Merged
Merged
Conversation
…roster from config - voice.speech_models defaults to empty: the text_to_speech default speaks alone - voice cloning: clone_codebooks and clone_rate tool options instead of Fish's 10 rows at 44.1 kHz - the model-management prompt's roster is rendered from config (ids, roles, needed memory) - transcription tools declare languages: listed, refused outside them, /voice narrows its picker - model-neutral MCP synthesize_speech instructions description; decide.Qwen -> ChatDecider - docs/dev/MODEL-DROPIN.md: the audit, the contract and the ranked gaps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/dropin.zig runs the same checks on two model sets (other ids; testpattern vs the cmd speech worker for speech and transcription; text-only image and video models in set B): MCP tools/list and /v1/capabilities' MCP tools are identical, /v1/models lists exactly the configured models with their kinds and capabilities, every OpenAI endpoint, /v1/systemone and MCP tool works with the model named and picked by defaults, a missing capability is refused naming the model and what it can do, changing only defaults moves unnamed requests, and the voice loop takes either set's speech and transcription models and runs a turn on them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d by config Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…edit pack only for image_edit
MCP decide reads the questions again after the job: a put on a shallow copy of its map could move the
entries out from under it ("state is required" after the decision had run, seen by tests/dropin.zig).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jayleaton
marked this pull request as ready for review
October 28, 2026 16:20
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
A model of a kind LocalRouter already serves is now one adapter plus one config entry. MCP, the OpenAI routes and the voice loop name no model. The audit, the contract each kind follows and the ranked gaps are in
docs/dev/MODEL-DROPIN.md.clone_codebooksandclone_ratetool options; the Jarvis template setsclone_codebooks: 10voice.speech_modelsdefaulted to["fishaudio/drama-3", "kitten-tts-2"]in code: Kitten beat a newly configured TTS defaulttext_to_speechdefault speaks; a box that wants a chain lists it (Jarvis and DGX-02 already do){models}rendered from config: role, id and needed memory of each model/voiceand the companionlanguagesoption: listed in/v1/models/list_models, refused outside it;/voiceand the companion read it (Whisper's list as offline fallback)instructionssaid "Drama 3 hears it…";decide.Qwen; edit-pack hint on every refusalChatDecider; hint only forimage_editThe MCP
tools/liststays a stable, kind-level list. A tool with no capable model is still listed and refused cleanly with the models named. That is the existing contracttests/mcp.zigpins, and a swap leaves the list unchanged. The voice loop already offers its chat model only the tools a model can serve.The new conformance suite also found a latent bug, fixed here. MCP
decidewith nomodelcould fail with "state is required" after the decision had already run.api/decide.zigput the model into a shallow copy of the caller's map, and the put could move the entries out from under the caller.Evidence
tests/dropin.zig, new). For every kind, set A and set B differ in ids and, where a fake exists, in adapter:tools/listand/v1/capabilitiestools are byte-identical across the two sets;/v1/modelslists exactly the configured models;defaultsalone moves an unnamed request to the other model;speech_modelsnames a chain;languagesare listed and enforced before load./root/lrclone, CPU only):fmt exit 0,build exit 0,Build Summary: 22/22 steps succeeded; 297/297 tests passed(227 unit, 70 integration).npm run type-check && npm run lint && npm test, dev box, because the Davit host was below its disk floor): all exit 0,Tests 422 passed | 15 skipped. Mobile code is unchanged (it sends no language); CI checks it.87ea48band this branch, both built in the checks clone, each served the box's ownconfig.jsonwithkeep_loadedoff. Nothing loaded and the service stayed stopped.tools/list,/v1/models,list_models,list_voicesand/v1/capabilitiesare identical except one line:/v1/skills/model-manager(the voice prompt's roster) now comes from config, and its sizes are more accurate (image 42 not 35 GiB, video 52 not 40):Merge Danger
Door: two-way
There is no wire-shape change, no model change and no download. One
tools/listdescription is reworded, and two new optional fields (languages, and the clone options) appear only when configured. Reverting the merge restores the old behaviour.Blast Radius: voice
voice.speech_modelsnow speaks with itstext_to_speechdefault. Jarvis and DGX-02 list it, so nothing changes there.clone_codebooksaccepts any consistent row count. The Jarvis template keeps 10.🤖 Generated with Claude Code