feat: add options.onlyLoaded to offer only loaded models - #49
Open
dgnsrekt wants to merge 2 commits into
Open
Conversation
`capabilities.reasoning` pinned `allowed_options` and `default` to `off|on|low|medium|high`. LM Studio now publishes an `xhigh` level, and because the enum sits inside the response schema a single model carrying it fails `LMStudioModelsResponseSchema.safeParse` for the entire payload. `discoverModels` then throws `unsupported response`, so discovery yields no models at all and the provider falls back to models.dev entries the user has not downloaded. The reasoning block is parsed but never mapped: the v1 contract leaves OpenCode's `reasoning` flag unset until both projects publish an interoperable mapping. Validating these values strictly gains nothing and costs total discovery whenever LM Studio adds a level. Accept any string and keep the known levels as an exported constant for documentation, so a future level cannot break discovery the same way. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S7Wjrr4wy4Eiig1PqtHfpD
Discovery offers every generative record so LM Studio can load a model on demand when it is selected. With a large library most entries are idle, and the picker fills with models that are merely downloaded (agustif#17). On shared or remote servers, on-demand loading may not be wanted at all. `provider.lmstudio.options.onlyLoaded` restricts the generated models and whitelist to records with a non-empty `loaded_instances`, so the list matches `lms ps`. Default behavior is unchanged: the option is opt-in and only the boolean `true` enables it, so an unusable value cannot silently empty the model list. When nothing is loaded the plugin generates an empty model list rather than falling back to idle entries, and the discovery log reports `onlyLoaded` and `skippedUnloaded` so the filter is visible. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S7Wjrr4wy4Eiig1PqtHfpD
Author
|
Filed the duplicate-key observation from the PR description as #50, with a reproduction and the sanitized record shapes. It reproduces on One thing that fell out of writing it up: |
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.
Closes #17.
Motivation
Discovery offers every generative record so LM Studio can load a model on demand when it is selected. That is the right default, but it has costs:
Change
provider.lmstudio.options.onlyLoadedrestricts generated models and the generated whitelist to records with a non-emptyloaded_instances:{ "provider": { "lmstudio": { "options": { "onlyLoaded": true } } } }Follows the
options.*convention used for provider-scoped plugin settings (same shape asoptions.badgein #43).Default behavior is unchanged — the option is opt-in, and only the boolean
trueenables it, so a malformed value can't silently empty the model list. When nothing is loaded the plugin generates an empty model list rather than falling back to idle entries; the discovery log gainsonlyLoadedandskippedUnloadedso the filter is visible.One incidental benefit: when a key has both a loaded and an unloaded record, the filter keeps the loaded one, so
limit.contextreflects the live allocation rather than whichever record landed last.Verification
9 tests added (28 → 37): opt-in filtering, whitelist narrowing, default-unchanged, empty-when-nothing-loaded, explicit-override precedence, and a fail-open matrix over
undefined | false | "true" | 1 | null.npm run validateclean (lint, typecheck, 37 tests, build).End-to-end against LM Studio 0.4.x, 37 records / 4 loaded instances, via
opencode models lmstudio:onlyLoadedabsentonlyLoaded: trueThe 2 match the
MODELcolumn oflms psexactly (google/gemma-4-26b-a4b-qat,qwen/qwen3.8-27b).Observation, not addressed here
That run also surfaced something pre-existing: my server reports the same
keyfrom more than one host, soloaded_instancesfor one key spans several machines and three native records collapse into two model entries viaObject.fromEntries. It's whydiscoveredcounts records while the map holds fewer. I left the semantics exactly as they are onmainrather than widen this PR — it looks related to #42, and I'm happy to open a separate issue with the payload if useful.🤖 Generated with Claude Code
https://claude.ai/code/session_01S7Wjrr4wy4Eiig1PqtHfpD