Skip to content

Fix stale WebUI provider model options#203

Merged
EterUltimate merged 1 commit into
NickCharlie:mainfrom
EterUltimate:codex/webui-live-provider-models
Jun 11, 2026
Merged

Fix stale WebUI provider model options#203
EterUltimate merged 1 commit into
NickCharlie:mainfrom
EterUltimate:codex/webui-live-provider-models

Conversation

@EterUltimate

@EterUltimate EterUltimate commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • fetch provider models live via provider get_models() or OpenAI-compatible /v1/models when building WebUI config schema
  • keep provider option values as provider IDs while replacing stale model labels with live model previews and available_models metadata
  • cache live model lookups within a single schema request and fall back to configured model labels if live fetching is unavailable

Tests

  • python -m py_compile webui\services\config_service.py
  • python -m pytest tests\unit\test_config_service.py tests\integration\test_config_blueprint.py --basetemp .tmp\pytest-basetemp -p no:cacheprovider
  • git diff --check -- webui\services\config_service.py tests\unit\test_config_service.py

Notes

  • AstrBot pre-review still reports existing repository findings and local .tmp artifacts unrelated to this change; no new blocking I/O warning was introduced by the WebUI model fetch path.

Summary by Sourcery

Fetch and surface live provider model lists in the WebUI config schema so provider options stay in sync with currently available models, falling back to configured models when live discovery is unavailable.

New Features:

  • Add asynchronous fetching of provider models via provider instances or OpenAI-compatible /v1/models endpoints when building WebUI provider options.
  • Expose live model metadata in provider options, including model counts, availability flags, and concise model previews used in option labels and field schemas.

Enhancements:

  • Cache provider model lookups per schema request and deduplicate provider options while preferring live model-backed entries.
  • Normalize provider and configuration metadata (IDs, model names, API bases, and API keys) to robustly derive models endpoints from diverse provider configurations.

Tests:

  • Add unit tests ensuring stale configured model labels are replaced with live model lists and that configuration labels are used when live models cannot be fetched.

@sourcery-ai

sourcery-ai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds live model discovery for WebUI provider options by querying provider get_models() or OpenAI-compatible /v1/models endpoints, wiring the results into the config schema and provider option labels while caching lookups per schema request and falling back to configured models if live data is unavailable.

Sequence diagram for live provider model discovery in get_config_schema

sequenceDiagram
    participant WebUI as WebUI
    participant ConfigService as ConfigService
    participant Provider as Provider
    participant HTTP as OpenAI_Models_Endpoint

    WebUI->>ConfigService: get_config_schema()
    ConfigService->>ConfigService: _provider_options_async("chat_completion", model_cache)
    loop for each provider
        ConfigService->>ConfigService: _provider_option_async(provider, "chat_completion", model_cache)
        ConfigService->>ConfigService: _provider_identity(provider, "chat_completion")
        ConfigService->>ConfigService: _models_from_provider_instance(provider, provider_id, provider_type, model_cache)
        alt provider has get_models
            ConfigService->>Provider: get_models()
            Provider-->>ConfigService: models_payload
            ConfigService->>ConfigService: _normalize_model_list(models_payload)
        else no get_models or empty result
            ConfigService->>ConfigService: _models_from_provider_config(provider.provider_config, provider_type, model_cache)
            ConfigService->>ConfigService: _provider_api_base(provider_config, provider_type)
            ConfigService->>ConfigService: _models_url_from_api_base(api_base)
            ConfigService->>ConfigService: _provider_api_key(provider_config, provider_type)
            ConfigService->>HTTP: _fetch_models_from_endpoint(models_url, api_key, custom_headers)
            HTTP-->>ConfigService: JSON models payload
            ConfigService->>ConfigService: _models_payload_to_list(payload)
        end
        ConfigService->>ConfigService: _build_provider_option(provider_id, model_name, provider_type, models)
    end
    ConfigService->>ConfigService: _dedupe_options(provider_options)
    ConfigService-->>WebUI: schema with groups, provider_options, provider_options_by_type
Loading

File-Level Changes

Change Details Files
Refactor provider identity and option construction to support live model metadata and richer option payloads.
  • Introduce helpers to extract provider identity and configured model from provider instances and configs.
  • Extend _build_provider_option to accept live model lists, compute model labels via a new model preview helper, and attach metadata such as model_source, available_models, model_count, and configured_model_available.
  • Update _provider_option, _provider_option_from_config, and _dedupe_options to work with the richer option structure and prefer live-model-backed options when deduplicating.
webui/services/config_service.py
Add infrastructure to resolve provider API configuration and fetch model lists from providers or OpenAI-compatible /v1/models endpoints with caching and timeouts.
  • Implement helpers to normalize model lists from various payload shapes and to derive model IDs and preview strings.
  • Add logic to resolve API keys (including env-var references) and API bases from provider configs, and to build a /v1/models URL from generic or per-endpoint API bases.
  • Introduce asynchronous helpers that call provider.get_models() when available or fallback to HTTP GET on the models endpoint using aiohttp, applying a short timeout and caching results per (source, type, provider) key.
webui/services/config_service.py
Wire live model fetching into provider option generation and config schema building so WebUI options show current models and reuse fetched data across fields.
  • Introduce async variants of provider option builders that populate live model data and cache results for provider instances and configs.
  • Refactor _provider_options and add _provider_options_async plus a model_cache to produce provider_options and provider_options_by_type from live data, then pass these into _build_group_schema and _build_field_spec so provider-select fields reuse the same options.
  • Update get_config_schema to orchestrate live provider options retrieval, deduplicate combined options, and include them in the returned schema payload.
webui/services/config_service.py
Add tests to verify replacement of stale configured models with live models and fallback behavior when live fetching fails.
  • Add async tests that monkeypatch _fetch_models_from_endpoint to return live models or an empty list and validate the resulting schema provider_options and field options.
  • Assert that labels prefer live models over deleted configured models when available, and that configured models remain in labels when live data is absent, along with correct model_source and available_models metadata.
tests/unit/test_config_service.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@EterUltimate EterUltimate force-pushed the codex/webui-live-provider-models branch from 5087b2d to d66383d Compare June 11, 2026 16:07

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The new asynchronous provider option flow duplicates much of the logic that still exists in the synchronous _provider_options path; consider consolidating common pieces (e.g., iteration over provider_manager/context) to a single implementation to reduce maintenance overhead and the risk of divergence.
  • In _provider_options_async, model discovery for each provider is performed sequentially with awaited calls; if you expect many providers, consider batching these with asyncio.gather (while still honoring the per-call timeout) to avoid slow schema generation under higher provider counts.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new asynchronous provider option flow duplicates much of the logic that still exists in the synchronous `_provider_options` path; consider consolidating common pieces (e.g., iteration over provider_manager/context) to a single implementation to reduce maintenance overhead and the risk of divergence.
- In `_provider_options_async`, model discovery for each provider is performed sequentially with awaited calls; if you expect many providers, consider batching these with `asyncio.gather` (while still honoring the per-call timeout) to avoid slow schema generation under higher provider counts.

## Individual Comments

### Comment 1
<location path="webui/services/config_service.py" line_range="1466-1467" />
<code_context>
                 field_spec["provider_type"] or "Provider",
             )
-            field_spec["options"] = self._provider_options(field_spec["provider_type"])
+            if provider_options_by_type is not None:
+                field_spec["options"] = provider_options_by_type.get(
+                    field_spec["provider_type"],
+                    [],
</code_context>
<issue_to_address>
**issue (bug_risk):** Fields with no explicit provider_type now get no options when provider_options_by_type is used.

With this change, when `field_spec["provider_type"]` is empty or not in `provider_options_by_type`, `field_spec["options"]` becomes an empty list, whereas previously `_provider_options(...)` returned a broad/default set so generic provider fields still had choices.

This affects fields where `_provider_expected_type_for_field` returns `None`, and any future field whose type isn’t in `{"chat_completion", "embedding", "rerank"}`. To avoid regressing those fields, you could:
- Fall back to a combined options list when `provider_type` is empty (e.g. the flattened `provider_options` from `get_config_schema`), or
- Use a default like `provider_options_by_type.get(provider_type) or provider_options_by_type.get("chat_completion", [])` when `provider_type` is falsey.

This preserves the async prefetching while ensuring generic provider fields still show options.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread webui/services/config_service.py Outdated
@EterUltimate EterUltimate force-pushed the codex/webui-live-provider-models branch from d66383d to 5b69b55 Compare June 11, 2026 16:12
@EterUltimate

Copy link
Copy Markdown
Collaborator Author

Addressed the Sourcery bug-risk note in 5b69b55: generic provider fields with no explicit provider_type now use the combined prefetched provider options, with a unit test covering the fallback.

@EterUltimate EterUltimate merged commit 3c17f07 into NickCharlie:main Jun 11, 2026
4 checks passed
@EterUltimate EterUltimate deleted the codex/webui-live-provider-models branch June 18, 2026 05:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant