feat(models): define capability schema and readers#2739
Conversation
3dc6b8d to
2fb83e4
Compare
…arity, tests Follow-up to review on odysseus-dev#3031 (RaresKeY): - resolve the per-model preference by endpoint identity (model membership) when several endpoint rows share a base_url, instead of first-URL-match; full stable-identity resolution remains the odysseus-dev#2739-aligned step - document scope explicitly as default-off /think enablement; name /no_think as the future off-direction increment - clarify auto/on/off is user preference (intent), not capability/adaptive metadata (a odysseus-dev#2739 concept) - TODO(odysseus-dev#2739): swap the name-substring dispatch for odysseus-dev#2739 control evidence once that evidence is wired at runtime - test: same-base-url disambiguation by model + no-leak for an unserved model Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
671ff76 to
8f53e3f
Compare
…arity, tests Follow-up to review on odysseus-dev#3031 (RaresKeY): - resolve the per-model preference by endpoint identity (model membership) when several endpoint rows share a base_url, instead of first-URL-match; full stable-identity resolution remains the odysseus-dev#2739-aligned step - document scope explicitly as default-off /think enablement; name /no_think as the future off-direction increment - clarify auto/on/off is user preference (intent), not capability/adaptive metadata (a odysseus-dev#2739 concept) - TODO(odysseus-dev#2739): swap the name-substring dispatch for odysseus-dev#2739 control evidence once that evidence is wired at runtime - test: same-base-url disambiguation by model + no-leak for an unserved model Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
I did a read-only freshness/rebase scan against current Quick reconciliation map:
Conflict shape in
Suggested rebase shape:
I’m happy to do a deeper pass or help with the rebase if useful, but I won’t push to the branch unless you want me to. |
8f53e3f to
fd97fa2
Compare
|
Pushed an updated branch for this PR. I rebased the model capability schema/readers work onto the current Local validation on the rebased branch:
|
Restrict native catalog probing to the Gemini host, keep provider keys out of request URLs, filter non-chat model resources, and preserve the manual refresh default in the built-in Google add flow.
…arity, tests Follow-up to review on odysseus-dev#3031 (RaresKeY): - resolve the per-model preference by endpoint identity (model membership) when several endpoint rows share a base_url, instead of first-URL-match; full stable-identity resolution remains the odysseus-dev#2739-aligned step - document scope explicitly as default-off /think enablement; name /no_think as the future off-direction increment - clarify auto/on/off is user preference (intent), not capability/adaptive metadata (a odysseus-dev#2739 concept) - TODO(odysseus-dev#2739): swap the name-substring dispatch for odysseus-dev#2739 control evidence once that evidence is wired at runtime - test: same-base-url disambiguation by model + no-leak for an unserved model Co-Authored-By: Claude <noreply@anthropic.com>
alteixeira20
left a comment
There was a problem hiding this comment.
Approved.
I reviewed this as the parent model-capability contract for the follow-up provider-catalog work.
What I validated:
- The PR is correctly scoped as a bootstrap schema and reader layer, not runtime capability enforcement.
- The schema establishes canonical families, modalities, capabilities, deterministic controls, reasoning controls, evidence/confidence fields, probe-result shape, stable model identity, and display-surface helpers.
- Provider readers follow the stated rule of using provider-reported/native shape fields rather than inferring authoritative capability from model names.
- Generic OpenAI-compatible catalogs remain inventory-only.
- Unknown configured providers remain inventory-only.
- Google native catalog probing is conservative: it can retain provider-reported IDs and token limits without claiming unreported modalities or display surfaces.
- The frontend refresh-mode change is in scope because it allows the backend Google default to remain manual when the frontend would otherwise force
auto. - The follow-up #5576 confirms this PR is the intended parent contract and will be rebased after this lands.
Validation on the exact reviewed head:
- Exact head:
d8627fcdf26d9ba76567157c7614651d0d422a34 - Merge into current
devwas clean. git diff --checkpassed.- Python compilation passed.
node --check static/js/admin.jspassed.- Focused merge-result suite passed:
252 passed, 1 warning. - Additional hard-contract probes passed with zero hard failures.
I do not consider the remaining observations blockers for this slice. Mixed-task modeling, runtime capability persistence, probe semantics, model-picker exposure, and runtime execution policy belong in the follow-up capability/runtime work rather than blocking this schema/readers foundation.
Summary
Adds a bootstrap model capability schema and shape-driven provider reader layer so Odysseus can represent model families, modalities, capabilities, evidence level, deterministic controls, and endpoint-scoped model identity without inferring behavior from model names. The complete/tested vendor coverage in this first slice is limited to LM Studio, llama.cpp, Google AI Studio, OpenRouter, OpenAI, and Ollama; this is not intended to claim complete coverage for every provider. Versioned local backend APIs are handled as compatibility layers: prefer latest vendor-native shape, parse tested common legacy shapes, and keep OpenAI-compatible fallbacks inventory-only. This also updates Google model catalog probing to use the native paginated Gemini Models API for configured Google endpoints instead of relying on OpenAI-compatible
/modelsor curated fallback lists.Target branch
dev, notmain. All PRs land indev;mainis curated by the maintainer at each release. If your PR is onmainby accident, click "Edit" on this PR and change the base.Linked Issue
Closes #4145
Parent tracker: #2737
Related
#4145, #2737, #315, #2905, #968, #735, #2541, #2562, discussion #2972, #451, #185, #1430, #1704, #2519, #2522, #664, #1122, #1126, #1130, #1478, #1274, #2785, #2603, #753, #909, #1170, #2627, #2361, #385, #837, #862, #2163, #2758, #2770, #2876, #2995, #2955, #2923, #2751, #2949, #2757, #3015, #3031, #3117, #3110
Coordinating PRs
feat(reasoning): per-model reasoning toggle — /think soft-switch (Category #1) #3031
Runtime reasoning-control follow-up. It currently adds the per-model preference store and the first
/thinkrequest mutation path. This PR stays focused on capability/control evidence and schema.Type of Change
Checklist
devdocker compose uporuvicorn app:app) and verified the change works end-to-end. Type-checks and unit tests are not enough.How to Test
Run the focused Python test suite:
Run compile checks for the changed Python modules:
./venv/bin/python -m py_compile src/model_capabilities.py src/model_capability_readers/*.py routes/model_routes.py tests/test_model_capabilities.py tests/test_model_capability_readers.py tests/test_model_routes.py tests/test_endpoint_probing.pyCheck for whitespace errors:
Optional manual review: inspect
src/model_capability_readers/and confirm vendor readers map explicit payload fields and provider-reported shape only, not model ID/name patterns.Build and start the app with Docker Compose. Verify the app starts on the default loopback ports and the root/login page and health endpoint return
200 OK.Visual / UI changes - REQUIRED if you touched anything that renders
No UI or rendering files were changed.
Screenshots / clips
N/A - no visual changes.
Notes For Review
src/model_capabilities.pydefines canonical families, modalities, capabilities, source/confidence tags, capability assertions, probe result shape, deterministic controls, endpoint-type mapping, and display-surface queries.src/model_capability_readers/adds a small reader registry plus shape-driven readers/scaffolding. Complete/tested vendor coverage in this PR is limited to LM Studio, llama.cpp, Google AI Studio, OpenRouter, OpenAI, and Ollama./v1/modelsremains identity-only and therefore normalizes to unknown capability.architecture,supported_parameters,default_parameters, and limits./api/show.capabilities;/api/tagsremains inventory/identity only./v1/modelsremains inventory/identity only./props/slots/model metadata when present and avoids treatingowned_byas capability evidence./v1beta/models, follows pagination, defaults Google refresh mode to manual when unspecified, and avoids curated fallback on keyed Google catalog failures.Verification Run Locally
./venv/bin/python -m pytest tests/test_model_capabilities.py tests/test_model_capability_readers.py tests/test_model_routes.py tests/test_endpoint_probing.py -q->168 passed, 1 warning./venv/bin/python -m py_compile src/model_capabilities.py src/model_capability_readers/*.py routes/model_routes.py tests/test_model_capabilities.py tests/test_model_capability_readers.py tests/test_model_routes.py tests/test_endpoint_probing.py-> passedgit diff --check-> passeddocker compose up -d --build-> image built and stack started on default loopback ports; root/login page and/api/healthreturned200 OK.Follow-Ups
/api/modelsonly after the schema and reader layer settles.