feat(cli): widen list_models to expose model family (#128, Slice B-i)#172
Merged
Conversation
Foundation for the interactive model picker: OllamaClient.list_models()
now returns list[InstalledModel] (tag + family) parsed from the /api/tags
`details.family` field, instead of a bare list of tags. This lets a
follow-up slice filter embedding models out of the chat-model picker.
- Add the InstalledModel frozen dataclass and is_embedding_model(), which
classifies the families {bert, nomic-bert} (case-insensitive) as
embeddings; a missing or unknown family is treated as non-embedding so
ambiguity never hides a legitimate chat model.
- Parse family defensively: a missing, null, or non-dict `details`, or a
missing/non-str `family`, yields family=None without dropping the entry
or raising; malformed top-level shapes still surface as OllamaError.
- Adapt every list_models() consumer behavior-preservingly (doctor checks
3/4/5, the init post-write preflight, the model spike): model_tag_matches
keeps its list[str] signature; call sites pass [m.tag for m in installed].
Advances #128 (Slice B-i); the picker itself lands in Slice B-ii.
This was referenced Jul 25, 2026
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
Slice B-i of #128 — the foundation for the interactive model picker. Widens
OllamaClient.list_models()so a follow-up slice can filter embedding models out of the chat-model list.list_models()now returnslist[InstalledModel](tag+family), parsed from the/api/tagsdetails.familyfield, instead of a barelist[str].is_embedding_model()classifies the families{bert, nomic-bert}(case-insensitive) as embeddings. A missing or unknown family is treated as non-embedding — ambiguity never hides a legitimate chat model.details, or a missing / non-strfamily, yieldsfamily=Nonewithout dropping the entry or raising; malformed top-level shapes still surface asOllamaError.list_models()consumer adapted behavior-preservingly (doctor checks 3/4/5, the init post-write preflight, the model spike).model_tag_matcheskeeps itslist[str]signature; call sites pass[m.tag for m in installed].Scope
src/openkos/llm/ollama.py(contract),src/openkos/cli/main.py(call-site adaptation),evals/model_spike/run_spike.py(one caller), plus test updates. ~215 lines.Verification
uv run pytest: 2099 passed, exit 0uv run ruff check . && uv run ruff format --check .: cleanuv run mypy .: clean/api/tagsshapes; all consumers adapted; behavior-preserving)Strict TDD throughout (RED confirmed before each GREEN).
Issue
Advances #128 (Slice B-i). The picker itself lands in Slice B-ii (a follow-up PR), which will close #128.