Skip to content

fix(config): model_list inherits api_key/api_base from providers#1786

Merged
yinwm merged 1 commit intosipeed:mainfrom
sliverp:fix-inherit-provider
Mar 19, 2026
Merged

fix(config): model_list inherits api_key/api_base from providers#1786
yinwm merged 1 commit intosipeed:mainfrom
sliverp:fix-inherit-provider

Conversation

@sliverp
Copy link
Copy Markdown
Contributor

@sliverp sliverp commented Mar 19, 2026

Summary

When users configure credentials in the providers section and define models in model_list, the model entries do not inherit api_key/api_base from the matching provider. Users must duplicate credentials in every model_list entry, violating DRY and causing silent failures when credentials are only set in providers.

Problem

As reported in #1635:

{
  "providers": {
    "deepseek": {
      "api_key": "sk-my-key",
      "api_base": "https://api.deepseek.com/v1"
    }
  },
  "model_list": [
    {
      "model_name": "deepseek-chat",
      "model": "deepseek/deepseek-chat"
    }
  ]
}

The model entry has no api_key — even though providers.deepseek has one. CreateProviderFromConfig sees an empty cfg.APIKey and returns an error. Users expect the protocol prefix (deepseek/) to match the provider automatically.

Solution

Add InheritProviderCredentials() that runs during LoadConfig, after the existing ConvertProvidersToModelList migration. For each model_list entry:

  1. Extract the protocol prefix from the Model field (e.g. deepseek from deepseek/deepseek-chat)
  2. Look up the matching provider in ProvidersConfig via a protocol→provider mapping
  3. Fill in empty api_key, api_base, proxy, and request_timeout from the provider

Explicit model_list values always take precedence — only empty fields are filled.

What changed

  • migration.go: New InheritProviderCredentials() function + protocolProviderMapping covering all 25 supported protocols
  • config.go: LoadConfig() calls InheritProviderCredentials() after provider migration
  • migration_test.go: 6 new tests

What did NOT change

  • ConvertProvidersToModelList logic is unchanged
  • CreateProviderFromConfig factory is unchanged
  • No new dependencies

Tests

6 new tests added:

Test Description
FillsMissingAPIKey Empty model_list entry inherits api_key + api_base from matching provider
ExplicitValuesTakePrecedence Model entry with explicit api_key is NOT overridden
MultipleModels Mixed: some inherit, some keep explicit values
NoMatchingProvider Unknown protocol prefix — no inheritance, no error
EmptyProviders All providers empty — nothing to inherit
InheritsRequestTimeout Ollama model inherits api_base + request_timeout

Breaking Changes

None. This is purely additive. Existing configs that already set api_key on every model_list entry are unaffected (explicit values always win).

Closes #1635

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
@sipeed-bot sipeed-bot Bot added type: bug Something isn't working domain: config domain: provider go Pull requests that update go code labels Mar 19, 2026
Copy link
Copy Markdown
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

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

Review Summary

This PR cleanly solves the credential inheritance problem (#1635) where users had to duplicate / in every entry even when already configured in .

What I checked:

Pass 1 (Critical):

  • ✅ No SQL/data safety concerns (config parsing only)
  • ✅ No race conditions (single-pass config loading)
  • ✅ No LLM output trust boundary issues
  • ✅ Enum completeness: covers all 25 supported protocols

Pass 2 (Informational):

  • ✅ No conditional side effects missing
  • ✅ No magic numbers or string coupling issues
  • ✅ No dead code
  • ✅ Test coverage: 6 new tests covering:
    • Credential inheritance from providers
    • Explicit values taking precedence
    • Multiple models with mixed configs
    • Unknown protocol prefix (no error, no inheritance)
    • Empty providers (no crash)
    • Request timeout inheritance

Design highlights:

  • Backward compatible: Purely additive, existing configs unaffected
  • DRY principle: Explicit values always win
  • Clean implementation: ~80 lines of straightforward logic with good comments

Verdict: LGTM, ready to merge. 🚀

@yinwm yinwm merged commit 38e1fe4 into sipeed:main Mar 19, 2026
4 checks passed
tong3jie pushed a commit to tong3jie/picoclaw that referenced this pull request Mar 20, 2026
…eed#1786)

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
@Orgmar
Copy link
Copy Markdown
Contributor

Orgmar commented Mar 20, 2026

@sliverp Solid work on the credential inheritance. Having model_list entries silently fail because they don't inherit api_key from the matching provider is a frustrating gotcha for users. The protocol-to-provider mapping covering all 25 protocols is thorough, and the 6 test cases cover the edge cases well. Clean fix for #1635.

We're running a PicoClaw Dev Group on Discord for contributors to collaborate more directly. If you'd like to join, send an email to support@sipeed.com with subject [Join PicoClaw Dev Group] sliverp and we'll send you the invite!

j0904 pushed a commit to j0904/picoclaw that referenced this pull request Mar 22, 2026
…eed#1786)

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
renato0307 pushed a commit to renato0307/picoclaw that referenced this pull request Mar 26, 2026
…eed#1786)

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
andressg79 pushed a commit to andressg79/picoclaw that referenced this pull request Mar 30, 2026
…eed#1786)

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
ra1phdd pushed a commit to ra1phdd/picoclaw-pkg that referenced this pull request Apr 12, 2026
…eed#1786)

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
armmer016 pushed a commit to cryptoquantumwave/khunquant that referenced this pull request Apr 14, 2026
…eed#1786)

When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes sipeed#1635
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: config domain: provider go Pull requests that update go code type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] model_list does not inherit api_key/api_base from providers (even with matching protocol prefix)

3 participants