hermes-bsd/tests/agent
helix4u ba9964ff0d fix(custom): pass custom provider extra body
Allow custom OpenAI-compatible providers declared under `custom_providers:`
to set provider-specific `extra_body` fields and have Hermes merge them into
chat-completions requests when the matching custom endpoint is active.

This is a manual per-provider override rather than a model-name heuristic.
OpenAI-compatible Gemma thinking support is real, but the on-wire payload
shape is backend-specific: some servers want top-level `enable_thinking`,
while vLLM Gemma and NIM-style endpoints expect `chat_template_kwargs`.
A per-provider override is safer than picking one assumed payload.

Example config:

```yaml
custom_providers:
  - name: gemma-local
    base_url: http://localhost:8080/v1
    model: google/gemma-4-31b-it
    extra_body:
      enable_thinking: true
      reasoning_effort: high
```

For vLLM Gemma or NIM-style endpoints, use the nested shape those servers
expect:

```yaml
extra_body:
  chat_template_kwargs:
    enable_thinking: true
```

Changes:

- `hermes_cli/config.py`: preserve `extra_body` in normalized
  `custom_providers:` entries and allow it in the validated field set.
- `hermes_cli/runtime_provider.py`: propagate custom-provider `extra_body`
  as `request_overrides.extra_body` for named custom runtime resolution,
  including credential-pool paths.
- `agent/agent_init.py`: at agent init, locate the matching custom-provider
  entry by `base_url` (+ optional model) and merge its `extra_body` into
  `AIAgent.request_overrides`, with caller-provided overrides winning on
  conflicting top-level keys.
- `plugins/model-providers/custom/__init__.py`: keep existing CustomProfile
  behavior (Ollama `num_ctx`, `think=False` when reasoning disabled);
  user-configured `extra_body` flows through `request_overrides`.
- `website/docs/integrations/providers.md`: document the explicit
  `extra_body` override and the vLLM/Gemma `chat_template_kwargs` variant.
- Tests cover config normalization, runtime propagation, model matching,
  trailing-slash equivalence, fallback when no `model` field is set, and
  caller-override merging precedence.

Verified end-to-end against `CustomProfile` via `ChatCompletionsTransport`:
configured `extra_body` reaches `kwargs.extra_body` on the wire request,
and coexists with profile-generated entries (Ollama `num_ctx`, `think=False`)
without clobber.

Salvaged from #29022 onto current `main`. Cosmetic typing edit in
`plugins/model-providers/custom/__init__.py` and a stale-base docs revert
in `providers.md` were dropped during cherry-pick.

Closes #29022
2026-05-21 07:48:53 -07:00
..
lsp fix(lint): skip per-file shell linter when LSP will handle the file (#29054) 2026-05-20 01:46:40 -05:00
transports fix(xai): restore encrypted reasoning replay across turns 2026-05-20 23:12:45 -07:00
__init__.py
test_anthropic_adapter.py feat(azure-foundry): add Microsoft Entra ID auth 2026-05-18 10:14:38 -07:00
test_anthropic_keychain.py
test_anthropic_oauth_pkce.py test(security): regression guard for OAuth PKCE state/verifier separation 2026-05-16 02:38:02 -07:00
test_arcee_trinity_overrides.py test(arcee): cover Trinity Large Thinking temperature + compression overrides 2026-05-05 17:23:45 -07:00
test_async_utils.py fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
test_auxiliary_client.py test: use subprocesses for each test file (#29016) 2026-05-21 16:40:04 +05:30
test_auxiliary_client_anthropic_custom.py
test_auxiliary_client_azure_foundry.py feat(azure-foundry): add Microsoft Entra ID auth 2026-05-18 10:14:38 -07:00
test_auxiliary_config_bridge.py fix(tests): pin UTF-8 encoding when reading source files on Windows 2026-05-09 02:47:28 -07:00
test_auxiliary_main_first.py chore: ruff auto-fix PLR6201 resweep — tuple → set in membership tests (#27355) 2026-05-17 02:29:41 -07:00
test_auxiliary_named_custom_providers.py
test_auxiliary_transport_autodetect.py
test_azure_identity_adapter.py feat(azure-foundry): add Microsoft Entra ID auth 2026-05-18 10:14:38 -07:00
test_bedrock_1m_context.py feat(azure-foundry): add Microsoft Entra ID auth 2026-05-18 10:14:38 -07:00
test_bedrock_adapter.py test(ci): stabilize shared optional dependency baselines 2026-05-13 17:32:22 -07:00
test_bedrock_integration.py test(ci): stabilize shared optional dependency baselines 2026-05-13 17:32:22 -07:00
test_codex_cloudflare_headers.py
test_compress_focus.py
test_compressor_historical_media.py Port from Kilo-Org/kilocode#9434: strip historical media after compression (#27189) 2026-05-16 17:18:25 -07:00
test_compressor_image_tokens.py
test_context_compressor.py fix(compress): make abort-on-summary-failure opt-in via config flag (#28117) 2026-05-18 10:28:20 -07:00
test_context_compressor_summary_continuity.py fix(ci): stabilize shared test state after 21012 2026-05-14 14:28:14 -07:00
test_context_engine.py
test_context_references.py
test_copilot_acp_client.py
test_copilot_acp_deprecation.py fix(copilot-acp): tighten deprecation detection + sharpen GitHub Models 413 hint 2026-05-16 02:24:48 -07:00
test_credential_pool.py fix(codex-oauth): quarantine terminal refresh errors so dead tokens are not replayed across sessions 2026-05-18 10:31:40 -07:00
test_credential_pool_routing.py
test_crossloop_client_cache.py
test_curator.py
test_curator_activity.py
test_curator_backup.py
test_curator_classification.py feat(curator): hint at hermes curator pin in the rename block (#23212) 2026-05-10 06:44:53 -07:00
test_curator_reports.py
test_custom_provider_extra_body.py fix(custom): pass custom provider extra body 2026-05-21 07:48:53 -07:00
test_deepseek_anthropic_thinking.py chore: ruff auto-fix PLR6201 resweep — tuple → set in membership tests (#27355) 2026-05-17 02:29:41 -07:00
test_direct_provider_url_detection.py
test_display.py fix: classify landed file mutations with diagnostics 2026-05-13 06:46:23 -07:00
test_display_emoji.py
test_error_classifier.py fix(error_classifier): classify generic-typed timeout messages as transient (carve-out of #22664) 2026-05-09 17:54:07 -07:00
test_external_skills.py
test_external_skills_dirs_cache.py perf(cli): cut ~19s from 'hermes' cold start (skills cache + lazy Feishu + no Nous HTTP) (#22138) 2026-05-08 16:39:32 -07:00
test_gemini_cloudcode.py fix(agent/gemini-cloudcode): seed delta defaults for reasoning-only stream chunks 2026-05-14 08:03:56 -07:00
test_gemini_fast_fallback.py fix: wrap _pool_may_recover_from_rate_limit call through run_agent namespace 2026-05-18 20:04:57 -07:00
test_gemini_free_tier_gate.py
test_gemini_native_adapter.py
test_gemini_schema.py
test_i18n.py feat(i18n): localize all gateway commands + web dashboard, add 8 new locales (16 total) (#22914) 2026-05-10 07:14:14 -07:00
test_image_gen_registry.py
test_image_routing.py fix(agent): consult supports_vision override in auto-mode routing 2026-05-20 23:27:10 -07:00
test_insights.py
test_kimi_coding_anthropic_thinking.py
test_local_stream_timeout.py
test_markdown_tables.py fix(cli): vertical fallback for markdown tables wider than terminal (#23948) 2026-05-11 16:49:13 -07:00
test_memory_provider.py
test_memory_session_switch.py feat(hindsight): probe API for update_mode='append' support, dedupe across processes 2026-05-05 15:09:59 -07:00
test_memory_user_id.py
test_minimax_auxiliary_url.py
test_minimax_provider.py feat: provider modules — ProviderProfile ABC, 33 providers, fetch_models, transport single-path 2026-05-05 13:40:01 -07:00
test_model_metadata.py fix(metadata): qwen3.6-plus has a 1M context window (#27008) 2026-05-17 02:31:18 -07:00
test_model_metadata_local_ctx.py
test_model_metadata_ssl.py
test_models_dev.py perf(models_dev): cache-first lookup, skip network when disk cache is fresh (#22808) 2026-05-09 13:32:38 -07:00
test_moonshot_schema.py fix(moonshot): strip $ref siblings and collapse tuple items in tool schemas (#27104) 2026-05-16 13:02:19 -07:00
test_nous_rate_guard.py
test_onboarding.py
test_openrouter_response_cache.py fix(openrouter): use canonical X-Title attribution header 2026-05-05 10:13:34 -07:00
test_plugin_llm.py feat(plugins): run any LLM call from inside a plugin via ctx.llm (#23194) 2026-05-10 07:09:28 -07:00
test_portal_tags.py feat(nous): unified client=hermes-client-v<version> tag on every Portal request (#24779) 2026-05-12 20:49:20 -07:00
test_prompt_builder.py fix(agent): add qwen and deepseek to TOOL_USE_ENFORCEMENT_MODELS 2026-05-18 20:06:49 -07:00
test_prompt_caching.py fix(cache): kill long-lived prefix layout — system prompt is now byte-static within a session (#24778) 2026-05-12 20:46:04 -07:00
test_proxy_and_url_validation.py
test_rate_limit_tracker.py
test_redact.py fix(security): redact xAI (Grok) API keys in logs 2026-05-18 10:21:22 -07:00
test_shell_hooks.py fix(security): restore type safety and extract constant in shell hook block handler 2026-05-17 02:31:18 -07:00
test_shell_hooks_consent.py
test_skill_bundles.py feat(skills): add skill bundles — alias /<name> loads multiple skills (#28373) 2026-05-18 21:38:05 -07:00
test_skill_commands.py test: use subprocesses for each test file (#29016) 2026-05-21 16:40:04 +05:30
test_skill_commands_reload.py
test_skill_utils.py
test_streaming_context_scrubber.py 🐛 fix(memory): require newline after context tag 2026-05-18 10:53:08 -07:00
test_subagent_progress.py
test_subagent_stop_hook.py
test_subdirectory_hints.py
test_system_prompt_restore.py perf(prompt-cache): date-only timestamp + loud gateway-DB roundtrip logging 2026-05-17 23:20:37 -07:00
test_think_scrubber.py fix(agent): stateful streaming scrubber for reasoning-block leaks (#17924) (#20184) 2026-05-05 04:33:38 -07:00
test_title_generator.py fix: improve telegram topic mode setup 2026-05-04 12:07:17 -07:00
test_tool_guardrails.py fix: add recovery hints to loop guard warnings 2026-05-19 00:12:12 -07:00
test_tool_result_classification.py fix: classify landed file mutations with diagnostics 2026-05-13 06:46:23 -07:00
test_unsupported_parameter_retry.py test: remove 50 stale/broken tests to unblock CI (#22098) 2026-05-08 14:55:40 -07:00
test_unsupported_temperature_retry.py
test_usage_pricing.py fix(pricing): add deepseek-v4-pro to official docs pricing table 2026-05-12 16:32:57 -07:00
test_video_gen_registry.py feat(video_gen): unified video_generate tool with pluggable provider backends (#25126) 2026-05-13 16:39:41 -07:00
test_vision_resolved_args.py