Skip to content

fix: handle keyless providers in initial list models requests - #833

Merged
Pratham-Mishra04 merged 1 commit into
mainfrom
11-14-fix_custom_keyless_providers_first_list_models_request_fixes
Nov 14, 2025
Merged

fix: handle keyless providers in initial list models requests#833
Pratham-Mishra04 merged 1 commit into
mainfrom
11-14-fix_custom_keyless_providers_first_list_models_request_fixes

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Fixed issues with custom keyless providers during initial list models requests, ensuring proper initialization and handling of providers that don't require API keys.

Changes

  • Added a check to skip key retrieval for providers that don't require keys
  • Implemented auto-initialization of providers when they're not yet initialized but have a valid config
  • Added support for keyless model listing in Anthropic, Cohere, Gemini, and OpenAI providers
  • Updated provider implementations to handle keyless configurations properly

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

Test listing models with custom keyless providers:

# Core/Transports
go version
go test ./...

# Test with a custom keyless provider configuration
curl -X GET "http://localhost:8000/v1/models" -H "Authorization: Bearer your_token"

Breaking changes

  • Yes
  • No

Related issues

Fixes issues with custom keyless providers failing to initialize or list models properly.

Security considerations

This change maintains the security model by properly handling keyless provider configurations without exposing sensitive information.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Suite Available

This PR can be tested by a repository admin.

Run tests for PR #833

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Nov 14, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Fixed model listing for custom providers that do not require API keys. These providers now correctly handle initial model discovery requests through an optimized keyless pathway.

Walkthrough

List models flows updated to support key-less custom providers: bifrost skips key retrieval when providerRequiresKey is false; getProviderByKey now loads provider config from account, uses a per-provider mutex, double-checks providers, and prepares the provider under the lock. Multiple providers route key-less ListModels to single-key handlers.

Changes

Cohort / File(s) Summary
Core bifrost logic
core/bifrost.go
Skip key fetching in ListModelsRequest when providerRequiresKey(...) is false (keys remain nil). getProviderByKey now: fetches provider config from account when missing, locks a per-provider mutex, double-checks the provider list after locking, calls prepareProvider to initialize, and returns the prepared provider (removes prior recursion-based path).
Provider single-key handlers
core/providers/anthropic/anthropic.go, core/providers/cohere/cohere.go, core/providers/gemini/gemini.go, core/providers/openai/openai.go
Each provider's ListModels gains an early-return guard: if customProviderConfig != nil && customProviderConfig.IsKeyLess then delegate to the provider-specific single-key handler (listModelsByKey / listModelsByKeyOpenAI) with an empty key instead of the multi-key aggregation flow. Anthropic adds a new private listModelsByKey implementation.
Changelogs
core/changelog.md, transports/changelog.md
Updated changelog entries: re-adds the openrouter response chore line and adds a fix entry for custom keyless providers initial list models request fixes.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Bifrost as Bifrost.ListModels
    participant Account as Account.GetConfigForProvider
    participant ProviderReg as providers registry
    participant Provider as Provider.ListModels
    participant KeyHandler as Provider.listModelsByKey

    Client->>Bifrost: ListModelsRequest
    Bifrost->>Bifrost: providerRequiresKey(provider, cfg)?
    
    alt providerRequiresKey == false (key-less)
        Bifrost->>Bifrost: keys = nil (skip getAllSupportedKeys)
    else providerRequiresKey == true
        Bifrost->>Bifrost: getAllSupportedKeys(...)
    end

    Bifrost->>ProviderReg: getProviderByKey(providerName)
    ProviderReg->>ProviderReg: provider found?
    alt not found
        ProviderReg->>Account: GetConfigForProvider(providerName)
        Account-->>ProviderReg: providerConfig
        ProviderReg->>ProviderReg: lock per-provider mutex
        ProviderReg->>ProviderReg: double-check providers slice
        ProviderReg->>ProviderReg: prepareProvider(providerConfig)
        ProviderReg-->>Bifrost: prepared provider
    else found
        ProviderReg-->>Bifrost: provider
    end

    Bifrost->>Provider: ListModels(request, keys)
    alt customProviderConfig && IsKeyLess
        Provider->>KeyHandler: listModelsByKey(empty_key, request)
        KeyHandler-->>Provider: models response
    else
        Provider->>Provider: standard multi-key aggregation
    end

    Provider-->>Client: BifrostListModelsResponse
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Areas to inspect closely:
    • Correctness of the conditional that skips key retrieval (providerRequiresKey usage).
    • Concurrency and locking around per-provider mutex in getProviderByKey (double-check for races and deadlocks).
    • That prepareProvider fully initializes provider state used later (no missed fields).
    • Provider single-key handlers: ensure empty key handling and error paths match previous semantics.
    • Any error propagation/metrics changes when keys are skipped.

Poem

🐰 A hop for keys now left behind,
The list flows tidy, swift, and kind,
Under mutex watch I stitch the seam,
Providers wake and join the dream.
Models found with no keys to bind. ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: handling keyless providers in initial list models requests, which is the core focus of the changeset.
Description check ✅ Passed The description covers all major template sections including Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, and Security considerations with appropriate detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 11-14-fix_custom_keyless_providers_first_list_models_request_fixes

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7eeb4f6 and 165b8e6.

📒 Files selected for processing (7)
  • core/bifrost.go (2 hunks)
  • core/changelog.md (1 hunks)
  • core/providers/anthropic/anthropic.go (1 hunks)
  • core/providers/cohere/cohere.go (1 hunks)
  • core/providers/gemini/gemini.go (1 hunks)
  • core/providers/openai/openai.go (1 hunks)
  • transports/changelog.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • core/providers/cohere/cohere.go
  • transports/changelog.md
  • core/providers/openai/openai.go
🧰 Additional context used
🧬 Code graph analysis (3)
core/bifrost.go (2)
core/schemas/account.go (1)
  • Key (8-17)
core/schemas/provider.go (2)
  • CustomProviderConfig (142-148)
  • Provider (207-234)
core/providers/gemini/gemini.go (1)
core/schemas/account.go (1)
  • Key (8-17)
core/providers/anthropic/anthropic.go (1)
core/schemas/account.go (1)
  • Key (8-17)
🔇 Additional comments (4)
core/providers/gemini/gemini.go (1)

182-184: LGTM! Keyless provider support correctly implemented.

The early return routes keyless providers through the single-key listing path with an empty key, which is handled correctly by listModelsByKey (lines 142-144 check for non-empty key.Value before setting the header). This pattern is consistent with other providers in the PR.

core/bifrost.go (2)

278-284: LGTM! Conditional key retrieval properly implemented.

The conditional check correctly skips key retrieval for keyless providers, and the provider implementations handle empty keys appropriately (checking key.Value != "" before setting auth headers).


1422-1457: Lazy initialization with mutex correctly addresses the race condition.

The implementation properly uses a per-provider mutex with double-checking to avoid race conditions during lazy initialization, addressing the concern from the previous review. The initial config fetch (line 1423) technically happens outside the lock, but this is acceptable since config changes are rare and the account interface is expected to be thread-safe.

core/providers/anthropic/anthropic.go (1)

238-240: LGTM! Keyless provider support correctly implemented.

The early return routes keyless providers through the single-key listing path, consistent with the pattern in other providers (Gemini, Cohere, OpenAI). The pagination concern from the previous review was dismissed by the author as being handled externally.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
core/providers/cohere/cohere.go (1)

260-262: Keyless ListModels path looks good; use request.PageSize when provided.

The guard/early-return is correct. In listModelsByKey we still send DefaultPageSize—prefer request.PageSize (bounded) when set to reduce work and align with client intent.

core/providers/gemini/gemini.go (1)

182-184: Keyless routing correct; implement pagination parameter handling.

Early-return to listModelsByKey for keyless configs is correct and consistent. However, verification confirms the pagination concern: listModelsByKey accepts a request with PageSize and PageToken fields but ignores both, hardcoding DefaultPageSize in the URL (line 139) and not passing pageToken. The Gemini API supports both parameters—update line 139 to use request.PageSize if provided (fallback to DefaultPageSize), and append request.PageToken to the URL when present to support cursor-based pagination and reduce over-fetching.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c2f450 and 7eeb4f6.

📒 Files selected for processing (7)
  • core/bifrost.go (2 hunks)
  • core/changelog.md (1 hunks)
  • core/providers/anthropic/anthropic.go (1 hunks)
  • core/providers/cohere/cohere.go (1 hunks)
  • core/providers/gemini/gemini.go (1 hunks)
  • core/providers/openai/openai.go (1 hunks)
  • transports/changelog.md (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
core/providers/cohere/cohere.go (1)
core/schemas/account.go (1)
  • Key (8-17)
core/bifrost.go (2)
core/schemas/account.go (1)
  • Key (8-17)
core/schemas/provider.go (2)
  • CustomProviderConfig (142-148)
  • Provider (207-234)
core/providers/gemini/gemini.go (1)
core/schemas/account.go (1)
  • Key (8-17)
core/providers/anthropic/anthropic.go (1)
core/schemas/account.go (1)
  • Key (8-17)
core/providers/openai/openai.go (3)
core/schemas/bifrost.go (1)
  • ListModelsRequest (84-84)
core/schemas/account.go (1)
  • Key (8-17)
core/providers/utils/utils.go (1)
  • ShouldSendBackRawResponse (480-485)
🔇 Additional comments (4)
core/changelog.md (1)

2-3: Changelog entries read well.

No issues from my side.

core/providers/openai/openai.go (1)

86-96: Keyless ListModels routing is correct.

Early-return to listModelsByKeyOpenAI for IsKeyLess is clean and leverages existing URL/path override logic. LGTM.

transports/changelog.md (1)

4-5: Changelog updates match the code changes.

Looks good.

core/bifrost.go (1)

278-284: Verification confirmed: guard is correctly implemented.

The providerRequiresKey function at core/utils.go:54-59 properly handles the IsKeyLess flag. It returns false when customConfig.IsKeyLess is true (except intentionally for Bedrock per the "not allowed" comment), and also handles native keyless providers (Ollama, SGL). All custom provider implementations (OpenAI, Cohere, Gemini, Anthropic) respect this flag, confirming the keyless flow is properly supported across intended providers.

Comment thread core/bifrost.go
Comment thread core/providers/anthropic/anthropic.go
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 11-14-fix_custom_keyless_providers_first_list_models_request_fixes branch from 7eeb4f6 to 165b8e6 Compare November 14, 2025 11:57

Pratham-Mishra04 commented Nov 14, 2025

Copy link
Copy Markdown
Collaborator Author

Merge activity

  • Nov 14, 12:33 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Nov 14, 12:33 PM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 merged commit a4da467 into main Nov 14, 2025
4 of 5 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 11-14-fix_custom_keyless_providers_first_list_models_request_fixes branch November 14, 2025 12:33
akshaydeo pushed a commit that referenced this pull request Nov 17, 2025
## Summary

Fixed issues with custom keyless providers during initial list models requests, ensuring proper initialization and handling of providers that don't require API keys.

## Changes

- Added a check to skip key retrieval for providers that don't require keys
- Implemented auto-initialization of providers when they're not yet initialized but have a valid config
- Added support for keyless model listing in Anthropic, Cohere, Gemini, and OpenAI providers
- Updated provider implementations to handle keyless configurations properly

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [x] Providers/Integrations
- [ ] Plugins
- [ ] UI (Next.js)
- [ ] Docs

## How to test

Test listing models with custom keyless providers:

```sh
# Core/Transports
go version
go test ./...

# Test with a custom keyless provider configuration
curl -X GET "http://localhost:8000/v1/models" -H "Authorization: Bearer your_token"
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Fixes issues with custom keyless providers failing to initialize or list models properly.

## Security considerations

This change maintains the security model by properly handling keyless provider configurations without exposing sensitive information.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
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