Skip to content

fix(config): restore custom providers after v11→v12 migration#8814

Closed
BlackishGreen33 wants to merge 2 commits into
NousResearch:mainfrom
BlackishGreen33:bg/fix-8776-custom-provider-migration
Closed

fix(config): restore custom providers after v11→v12 migration#8814
BlackishGreen33 wants to merge 2 commits into
NousResearch:mainfrom
BlackishGreen33:bg/fix-8776-custom-provider-migration

Conversation

@BlackishGreen33

Copy link
Copy Markdown
Contributor

What does this PR do?

The v11 -> v12 config migration rewrites custom_providers into providers, but runtime resolution still reads custom_providers. After migration, named custom providers and fallback providers can stop resolving at runtime.

This PR restores compatibility in two places:

  • the migration keeps or rebuilds custom_providers so already-migrated configs keep working
  • runtime resolution falls back to providers when custom_providers is missing

This keeps the fix small and compatibility-focused. It does not try to fully cut runtime over to a new config model.

Related Issue

Fixes #8776

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • added providers_dict_to_custom_providers() in hermes_cli/config.py to keep the field mapping in one place
  • updated the v11 -> v12 migration to stop deleting custom_providers
  • added a v16 -> v17 compatibility migration that rebuilds custom_providers from providers when needed
  • updated hermes_cli/runtime_provider.py so named custom provider lookup falls back to providers
  • added regression tests for config migration, runtime provider resolution, and auxiliary client fallback paths
  • updated the browser config version assertion to match the current schema version

How to Test

  1. source venv/bin/activate
  2. python -m pytest tests/hermes_cli/test_config.py -q
  3. python -m pytest tests/hermes_cli/test_runtime_provider_resolution.py -q
  4. python -m pytest tests/agent/test_auxiliary_named_custom_providers.py -q
  5. Optional: python -m pytest tests/ -q

Example migrated config that now resolves correctly again:

model:
  default: openai/gpt-5.4
  provider: openrouter
providers:
  openai-direct:
    api: https://api.openai.com/v1
    api_key: dir-key
    default_model: gpt-5-mini
    name: OpenAI Direct
    transport: codex_responses
fallback_providers:
- provider: openai-direct
  model: gpt-5-mini

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS arm64, Python 3.11

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

Targeted regression tests passed locally.

I also ran python -m pytest tests/ -q locally. The current tree still has unrelated failures outside this diff, including missing acp imports and existing failures in gateway, voice, reasoning, and auxiliary-client tests.

Copilot AI review requested due to automatic review settings April 13, 2026 05:49

Copilot AI 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.

Pull request overview

Restores runtime compatibility for named custom providers after the v11→v12 config migration introduced a providers: dict while runtime resolution still relied on custom_providers:.

Changes:

  • Keep/rebuild custom_providers during/after migrations so previously migrated configs continue to resolve named custom providers.
  • Add runtime fallback to resolve named custom providers from providers when custom_providers is absent.
  • Add regression tests for migration + runtime resolution paths and bump schema version assertions to v17.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
hermes_cli/config.py Bumps schema to v17, adds providers_dict_to_custom_providers(), stops deleting custom_providers in v11→v12 migration, and adds v16→v17 restoration migration.
hermes_cli/runtime_provider.py Falls back to providers-derived entries when custom_providers is missing/invalid, restoring named custom provider lookup post-migration.
tests/hermes_cli/test_config.py Adds migration regression tests ensuring custom_providers survives/restores and updates version assertion to 17.
tests/hermes_cli/test_runtime_provider_resolution.py Adds runtime regression coverage for resolving named custom providers from providers and adds missing monkeypatching for pool behavior.
tests/agent/test_auxiliary_named_custom_providers.py Ensures auxiliary client resolution works with named providers defined in providers dict.
tests/tools/test_browser_camofox_state.py Updates schema version assertion to 17.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hermes_cli/config.py Outdated
teknium1 pushed a commit that referenced this pull request Apr 13, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes #8776, salvaged from PR #8814
teknium1 pushed a commit that referenced this pull request Apr 13, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes #8776, salvaged from PR #8814
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #9016 with extended coverage to all consumers (cli.py, gateway/run.py, run_agent.py, model_switch, credential_pool). Your commit was cherry-picked with your authorship preserved in git log. Thanks for the fix and the thorough issue report (#8776)!

WingedDragon pushed a commit to WingedDragon/hermes-agent that referenced this pull request Apr 16, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes NousResearch#8776, salvaged from PR NousResearch#8814
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes NousResearch#8776, salvaged from PR NousResearch#8814
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes NousResearch#8776, salvaged from PR NousResearch#8814
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes NousResearch#8776, salvaged from PR NousResearch#8814
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes NousResearch#8776, salvaged from PR NousResearch#8814
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
The v11→v12 migration converts custom_providers (list) into providers
(dict), then deletes the list. But all runtime resolvers read from
custom_providers — after migration, named custom endpoints silently stop
resolving and fallback chains fail with AuthError.

Add get_compatible_custom_providers() that reads from both config schemas
(legacy custom_providers list + v12+ providers dict), normalizes entries,
deduplicates, and returns a unified list. Update ALL consumers:

- hermes_cli/runtime_provider.py: _get_named_custom_provider() + key_env
- hermes_cli/auth_commands.py: credential pool provider names
- hermes_cli/main.py: model picker + _model_flow_named_custom()
- agent/auxiliary_client.py: key_env + custom_entry model fallback
- agent/credential_pool.py: _iter_custom_providers()
- cli.py + gateway/run.py: /model switch custom_providers passthrough
- run_agent.py + gateway/run.py: per-model context_length lookup

Also: use config.pop() instead of del for safer migration, fix stale
_config_version assertions in tests, add pool mock to codex test.

Co-authored-by: 墨綠BG <s5460703@gmail.com>
Closes NousResearch#8776, salvaged from PR NousResearch#8814
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.

v11→v12 config migration converts custom_providers → providers: dict, but no runtime code reads providers:

3 participants