Skip to content

feat: provider modules — ProviderProfile ABC, 29 providers, fetch_models, transport single-path (salvage #14424)#16326

Open
teknium1 wants to merge 2 commits into
mainfrom
hermes/hermes-8b414b52
Open

feat: provider modules — ProviderProfile ABC, 29 providers, fetch_models, transport single-path (salvage #14424)#16326
teknium1 wants to merge 2 commits into
mainfrom
hermes/hermes-8b414b52

Conversation

@teknium1
Copy link
Copy Markdown
Contributor

Salvage of #14424 onto current main.

Summary

Introduces providers/ as a canonical registry for all inference providers Hermes knows about, behind a ProviderProfile dataclass + 4 overridable hooks. Wires NVIDIA + DeepSeek through a new profile-driven path in ChatCompletionsTransport.build_kwargs, gated by _PROFILE_ACTIVE_PROVIDERS in run_agent.py. Legacy flag-based dispatch untouched for the other 27 providers. Also moves the Copilot ACP client from agent/copilot_acp_client.pyacp_adapter/copilot_client.py (7-line shim left behind for backward compat).

Cycle 2 PR 1 of #14418. Remaining 27 providers get incrementally wired in #14515+.

Changes

  • New: providers/ — 29 provider modules + base.py + README.md
  • New: acp_adapter/copilot_client.py — copied verbatim from main's current agent/copilot_acp_client.py (includes _resolve_home_dir / _build_subprocess_env drift that landed after PR author's base commit)
  • Modified: agent/copilot_acp_client.py → 7-line re-export shim
  • Modified: agent/transports/chat_completions.py_build_kwargs_from_profile() early-return branch; legacy path untouched
  • Modified: run_agent.py — 43 lines (profile allowlist + dispatch block); removes obsolete _is_nvidia / is_nvidia_nim flag threading
  • Modified: pyproject.toml — include providers + providers.* in packages find
  • New tests: tests/providers/ (4 files, 79 tests — profile declarations, transport parity, profile-path E2E)

Conflict resolution notes

Three conflicts resolved against current main (branch was 537 commits behind):

  1. agent/transports/__init__.py — main already shipped a stricter fix for the same "registry partially populated when test imports transport directly" problem the PR was trying to solve (main discovers on every miss; PR regressed to discover-once behind a _discovered flag). Kept main's version, dropped the PR's regression.
  2. agent/copilot_acp_client.py — main had drifted 606 lines in this file (added _resolve_home_dir, _build_subprocess_env, HOME env threading, formatting, a stricter stdin/stdout guard). Used main's current file contents as the source-of-truth for the new acp_adapter/copilot_client.py location to preserve all of that drift. The shim at the old location is unchanged.
  3. uv.lock — trivial regeneration drift; kept main's lockfile since the PR doesn't add new dependencies.

Follow-up fix commit (by us)

fix(tests): update copilot_acp subprocess.Popen patch paths — main added two HOME-handling tests (test_run_prompt_prefers_profile_home_when_available, test_run_prompt_passes_home_when_parent_env_is_clean) after the PR was written. They patch agent.copilot_acp_client.subprocess.Popen, but the shim module no longer has subprocess imported. Updated to acp_adapter.copilot_client.subprocess.Popen.

Validation

Result
scripts/run_tests.sh tests/providers/ 79/79 passed
scripts/run_tests.sh tests/agent/ 1990/1990 passed
scripts/run_tests.sh tests/run_agent/ 1073/1074 passed (1 pre-existing main flake in test_tool_arg_coercion.py::test_inf_stays_string_for_integer_only, unrelated)
E2E: 31 provider profiles resolve via get_provider_profile() all OK
E2E: NVIDIA profile path vs legacy path produce identical build_kwargs output identical
E2E: DeepSeek profile path vs legacy path produce identical output identical
E2E: Nous profile emits extra_body.tags=['product=hermes-agent'] attribution correct
E2E: Kimi profile splits reasoning_effort top-level + extra_body.thinking.type='enabled', temperature=None (fixed-temp) correct
E2E: OpenRouter legacy path still emits extra_body.provider preferences correct
_PROFILE_ACTIVE_PROVIDERS wiring present in run_agent.py, dispatch block early-returns for nvidia/deepseek verified

Credit

Original PR by @kshitijk4poor. Commit 1 (feat: add provider modules + wire transport single-path) authored by kshitijk4poor and preserved via rebase-merge. Commit 2 (test patch follow-up) is ours.

Closes part of #14418. Supersedes #14424.

kshitijk4poor and others added 2 commits April 26, 2026 19:50
Cycle 2 PR 1 (#14418). Introduces providers/ package with ProviderProfile
ABC and auto-discovery registry, then wires ChatCompletionsTransport to
delegate to profiles via a clean single-path method.

Provider profiles (8 providers):
- nvidia: default_max_tokens=16384
- kimi + kimi-cn: OMIT_TEMPERATURE, thinking + top-level reasoning_effort
- openrouter: provider_preferences, full reasoning_config passthrough
- nous: product tags, reasoning with Nous-specific disabled omission
- deepseek: base_url + env_vars
- qwen-oauth: vl_high_resolution extra_body, metadata top-level api_kwargs

Transport integration:
- _build_kwargs_from_profile() replaces the entire legacy flag-based
  assembly when provider_profile param is passed
- Single path: no dual-execution, no overwrites, no legacy fallthrough
- build_api_kwargs_extras() returns (extra_body, top_level) tuple to
  handle Kimi's top-level reasoning_effort vs OpenRouter's extra_body

Auth types: api_key | oauth_device_code | oauth_external | copilot | aws
(expanded from the lossy 'oauth' to match real Hermes auth modes).

64 new tests:
- 30 profile unit tests (registry, all 8 profiles, auth types)
- 19 transport parity tests (pin legacy flag-based behavior)
- 15 profile wiring tests (verify profile path = legacy path)
…apter.copilot_client

Main added two HOME-handling tests (test_run_prompt_prefers_profile_home_when_available,
test_run_prompt_passes_home_when_parent_env_is_clean) after PR #14424 was written.
These patch 'agent.copilot_acp_client.subprocess.Popen', but the shim module no longer
has 'subprocess' imported. Update patch strings to target the real module location.

Follow-up commit on the salvage PR; kshitijk4poor's original commit is preserved above.
@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder labels Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants