Skip to content

fix: match compatible-provider models owned by public prefix - #13831

Merged
diegosouzapw merged 3 commits into
diegosouzapw:release/v3.8.51from
sahildaswani:fix/13829-compatible-prefix-models
Sep 16, 2026
Merged

diegosouzapw merged 3 commits into
diegosouzapw:release/v3.8.51from
sahildaswani:fix/13829-compatible-prefix-models

Conversation

@sahildaswani

Copy link
Copy Markdown
Contributor

Summary

GET /api/v1/providers/{provider}/models returned an empty data array for compatible provider nodes even though the connection was active, imported/synced models existed, and the same models were routable and listed in the unified catalog with the node's public prefix.

The route resolved compatible IDs enough to pass validation, but then filtered unified-catalog rows only by the internal provider node ID:

const filtered = payload.data.filter((model) => model?.owned_by === providerId);

For compatible provider nodes, the unified catalog emits the node's configured public prefix in owned_by (for example hz) rather than the internal ID (for example openai-compatible-chat-<uuid>), so every valid model was dropped. The toUnprefixedModelId() helper had the same identity gap: it stripped providerAlias/ and providerId/, but not the compatible node's public prefix.

This change resolves the compatible node's prefix and:

  • accepts the internal ID, the alias, and the public prefix when filtering owned_by;
  • strips any of those three from returned model IDs, preserving provider-scoped unprefixed IDs.

Related Issues

Validation

Change type: provider / routing.

  • Added a regression test that seeds a compatible provider node (openai-compatible-chat-<uuid> with prefix hz), an active connection, and one imported synced model, then asserts:
    • the unified catalog exposes the model as hz/<model> with owned_by: "hz";
    • /api/v1/providers/{internal-id}/models returns that model with its unprefixed ID, owned_by: "hz", and parent: null.
  • Focused unit suite passes: node --import tsx/esm --test tests/unit/provider-models-v1-route.test.ts
  • Provider consistency gates pass: npm run check:provider-consistency, npm run check:provider-assets
  • Targeted and full lint pass (including unpruned-suppressions mode): npx eslint ... --pass-on-unpruned-suppressions
  • npm run check:any-budget:t11 passes
  • docs-sync / tracked-artifacts checks pass

The only change to production code is the provider-models route; no migrations or feature flags are involved.

Tests Added Or Updated

  • tests/unit/provider-models-v1-route.test.ts — added the #13829 regression test; the touched lines use { id: string } instead of any in the existing body.data.map callbacks (removing two any suppressions that were already unnecessary).

Coverage Notes

This PR changes src/ (the route). The new test covers the exact regression scenario end to end: node prefix resolution, owned_by matching against the public prefix, and unprefixing of returned IDs. The existing suite already covered the unknown-provider 400 and service-backend paths.

Reviewer Notes

  • Prefix lookups are read-only (getProviderNodeById) and fail soft: if the node is missing or has no prefix, behavior is unchanged from before.
  • If providerAlias already equals the public prefix for some existing provider, the accepted-owners set collapses to the same value — no duplication or double-strip, because unprefixing is checked once per prefix.
  • No new database access beyond the existing route's read path.

Resolves diegosouzapw#13829

The provider-scoped /v1/providers/{provider}/models route filters
unified-catalog rows by internal provider ID. For compatible provider
nodes, the catalog emits the configured public prefix in owned_by, so
all valid models were dropped and the endpoint returned an empty list.

Resolve the compatible node's prefix and accept it alongside the
internal ID when filtering and when stripping the prefix from returned
model ids.
…gosouzapw#13829

Two gate-only touch-ups on top of the fix, no behaviour change:

- prettier --check rejected tests/unit/provider-models-v1-route.test.ts over a
  double blank line before a test block.
- typing the map callback removed the file's only `any`, which left the frozen
  entry in config/quality/eslint-suppressions.json unused; the lint gate fails
  on a stale suppression, so it is pruned.

Both were found by running the gates locally, because this fork PR's workflow
runs are still awaiting maintainer approval and only the semgrep check had run.

Co-authored-by: sahildaswani <sahildaswani@users.noreply.github.com>
@diegosouzapw
diegosouzapw merged commit ff493da into diegosouzapw:release/v3.8.51 Sep 16, 2026
11 of 16 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…uzapw#13831)

* fix: match compatible-provider models owned by public prefix

Resolves diegosouzapw#13829

The provider-scoped /v1/providers/{provider}/models route filters
unified-catalog rows by internal provider ID. For compatible provider
nodes, the catalog emits the configured public prefix in owned_by, so
all valid models were dropped and the endpoint returned an empty list.

Resolve the compatible node's prefix and accept it alongside the
internal ID when filtering and when stripping the prefix from returned
model ids.

* chore(quality): satisfy the format and lint-suppression gates for diegosouzapw#13829

Two gate-only touch-ups on top of the fix, no behaviour change:

- prettier --check rejected tests/unit/provider-models-v1-route.test.ts over a
  double blank line before a test block.
- typing the map callback removed the file's only `any`, which left the frozen
  entry in config/quality/eslint-suppressions.json unused; the lint gate fails
  on a stale suppression, so it is pruned.

Both were found by running the gates locally, because this fork PR's workflow
runs are still awaiting maintainer approval and only the semgrep check had run.

Co-authored-by: sahildaswani <sahildaswani@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: sahildaswani <sahildaswani@users.noreply.github.com>
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.

fix(providers): Provider-scoped models endpoint drops compatible-provider models with custom prefixes

2 participants