Skip to content

feat(models): define capability schema and readers#2739

Merged
alteixeira20 merged 2 commits into
odysseus-dev:devfrom
RaresKeY:feature/model-capability-schema
Jul 18, 2026
Merged

feat(models): define capability schema and readers#2739
alteixeira20 merged 2 commits into
odysseus-dev:devfrom
RaresKeY:feature/model-capability-schema

Conversation

@RaresKeY

@RaresKeY RaresKeY commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

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 /models or curated fallback lists.

Target branch

  • This PR targets dev, not main. All PRs land in dev; main is curated by the maintainer at each release. If your PR is on main by 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

Type of Change

  • Bug fix (non-breaking - fixes a confirmed issue)
  • New feature (non-breaking - adds new behaviour)
  • Breaking change (changes or removes existing behaviour)
  • Refactor / cleanup (behaviour unchanged)
  • Documentation only
  • CI / tooling / configuration

Checklist

  • I searched open issues and open PRs - this is not a duplicate.
  • This PR targets dev
  • My changes are limited to the scope described above - no unrelated refactors or whitespace changes mixed in.
  • I actually ran the app (docker compose up or uvicorn app:app) and verified the change works end-to-end. Type-checks and unit tests are not enough.

How to Test

  1. Run the focused Python test suite:

    ./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
  2. 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.py
  3. Check for whitespace errors:

    git diff --check
  4. 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.

  5. 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.

  • Screenshot or short clip of the change in the running app, attached below. Mobile screenshot too if the change affects mobile.
  • Style match: not applicable; no visual surface changed.
  • No new component patterns. Not applicable; no frontend components changed.
  • I am not an LLM agent submitting a bulk PR. If you are, please open an issue describing the problem first - bulk auto-generated PRs that don't match the project's visual style are closed on sight, even when the underlying fix is correct.

Screenshots / clips

N/A - no visual changes.

Notes For Review

  • src/model_capabilities.py defines 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.
  • Other provider reader scaffolding should be treated as the start of the normalization layer, not as a claim of complete provider support.
  • Versioned local backend support belongs in vendor readers as tested shape compatibility, not model-name inference; latest native shapes are preferred, with common legacy native shapes parsed where stable.
  • OpenAI official /v1/models remains identity-only and therefore normalizes to unknown capability.
  • OpenRouter maps explicit architecture, supported_parameters, default_parameters, and limits.
  • Google AI Studio maps native Models API method/token fields without inferring image/video/audio from names.
  • Ollama maps /api/show.capabilities; /api/tags remains inventory/identity only.
  • LM Studio maps native/current and common legacy model metadata shape; OpenAI-compatible /v1/models remains inventory/identity only.
  • llama.cpp uses native /props/slots/model metadata when present and avoids treating owned_by as capability evidence.
  • Google endpoint probing now uses native /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 -> passed
  • git diff --check -> passed
  • docker compose up -d --build -> image built and stack started on default loopback ports; root/login page and /api/health returned 200 OK.

Follow-Ups

  • Add durable capability/probe storage and admin-run smoke probes in a separate PR.
  • Expose normalized capabilities through /api/models only after the schema and reader layer settles.
  • Add model-picker capability icons after the API has normalized capability records and evidence levels.
  • Add standalone metadata probe tooling in a separate PR if it is still useful after the schema layer lands.

@github-actions github-actions Bot added the ready for review Description complete — ready for maintainer review label Jun 5, 2026
@RaresKeY
RaresKeY force-pushed the feature/model-capability-schema branch from 3dc6b8d to 2fb83e4 Compare June 5, 2026 02:44
@RaresKeY
RaresKeY marked this pull request as ready for review June 5, 2026 02:46
nsgds added a commit to nsgds/odysseus that referenced this pull request Jun 6, 2026
…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>
@RaresKeY
RaresKeY force-pushed the feature/model-capability-schema branch 2 times, most recently from 671ff76 to 8f53e3f Compare June 11, 2026 14:56
@RaresKeY RaresKeY changed the title Define model capability schema and shape readers feat(models): define capability schema and readers Jun 11, 2026
nsgds added a commit to nsgds/odysseus that referenced this pull request Jun 13, 2026
…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>
@undergroundrap

Copy link
Copy Markdown
Collaborator

I did a read-only freshness/rebase scan against current dev (1f6dc80).

Quick reconciliation map:

  • #2739 is currently stale against dev and appears to be 716 commits behind / 1 commit ahead.
  • The PR is still conceptually scoped: one schema/readers commit plus route/test integration.
  • Merge conflict surface is narrow: routes/model_routes.py has the only content conflict.
  • tests/test_model_routes.py auto-merges, but should still be rerun because both sides changed endpoint/model probing behavior.

Conflict shape in routes/model_routes.py:

  • Current dev added/keeps endpoint-probe hardening helpers:

    • _is_loading_model_response
    • tolerant _openai_model_ids
    • _ollama_model_names
    • loading-model handling in endpoint test/probe flows
  • #2739 adds Google/native capability-reader support in the same helper area:

    • _is_google_api_base
    • _normalize_endpoint_refresh_mode(..., base_url=...)
    • _google_native_root
    • _google_native_models_url
    • _google_model_id_from_item
    • _probe_google_models
    • early Google native catalog branch inside _probe_endpoint

Suggested rebase shape:

  1. Keep the current dev probe-hardening helpers.
  2. Insert the Google native helpers from #2739 before _probe_endpoint.
  3. Keep the #2739 Google branch early in _probe_endpoint, after chatgpt-subscription handling and before Anthropic/OpenAI-compatible probing.
  4. Preserve current dev behavior for tolerant model-id parsing, Ollama parsing, and loading-model responses.
  5. Rerun the focused model/capability tests after resolving:
    • tests/test_model_routes.py
    • tests/test_model_capabilities.py
    • tests/test_model_capability_readers.py

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.

@RaresKeY
RaresKeY force-pushed the feature/model-capability-schema branch from 8f53e3f to fd97fa2 Compare July 4, 2026 17:04
@RaresKeY

RaresKeY commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed an updated branch for this PR.

I rebased the model capability schema/readers work onto the current dev head and resolved the routes/model_routes.py conflict by keeping the current dev probe hardening while preserving the Google/native model probing changes.

Local validation on the rebased branch:

  • python3 -m pytest tests/test_model_capabilities.py tests/test_model_capability_readers.py tests/test_model_routes.py tests/test_endpoint_probing.py -q
    • 244 passed, 1 warning
  • python3 -m py_compile ...
    • passed
  • git diff --check origin/dev...HEAD
    • passed

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.
nsgds added a commit to nsgds/odysseus that referenced this pull request Jul 13, 2026
…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 alteixeira20 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 dev was clean.
  • git diff --check passed.
  • Python compilation passed.
  • node --check static/js/admin.js passed.
  • 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.

@alteixeira20
alteixeira20 merged commit 4f04c34 into odysseus-dev:dev Jul 18, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready for review Description complete — ready for maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

models: bootstrap capability schema and shape readers

3 participants