hermes-agent/tests/plugins/model_providers
Changhyun Min 20502b407c feat(agent): add Upstage Solar as a model provider
Adds Upstage Solar as a bundled model-provider plugin. Solar exposes an
OpenAI-compatible chat-completions endpoint at https://api.upstage.ai/v1, so
the generic chat_completions transport handles request/response/streaming/tool
calls — the profile is the core integration.

Provider registration (Upstage isn't in models.dev, so each registry that does
not auto-wire from the plugin layer needs an explicit entry — same pattern as
nvidia/gmi):
- plugins/model-providers/upstage/: UpstageProfile + plugin.yaml. Picker default
  and offline catalog list only the agentic Solar Pro models, led by `solar-pro`
  (rolling alias for the latest Pro). default_aux_model empty so aux tasks use
  the main model. `solar` alias. UPSTAGE_BASE_URL overrides the host.
- hermes_cli/providers.py: HERMES_OVERLAYS + label + `solar` alias, so
  resolve_provider_full('upstage') resolves (without this, an explicit
  `provider: upstage` in config was dropped and fell through to auto-detect).
- hermes_cli/auth.py: PROVIDER_REGISTRY entry + `solar` alias, so `hermes
  doctor` / resolve_provider recognise upstage (the static-registry path the
  lazy profile-extension doesn't reliably cover at validation time).
- hermes_cli/models.py: CANONICAL_PROVIDERS entry places Upstage Solar in the
  curated picker order (above the auto-appended `custom`).
- agent/model_metadata.py: context-window fallbacks (/v1/models omits
  context_length); `solar-pro` carries the 128K Pro context as the catch-all.

Reasoning: UpstageProfile.build_api_kwargs_extras wires Solar's top-level
`reasoning_effort` (low|medium|high; xhigh/max→high). Reasoning-capable families
are solar-pro* and solar-open*; solar-mini/syn-pro never receive it. Defaults ON
at medium when unset (matches the /reasoning "medium (default)" label);
`/reasoning none` disables; explicit/saved settings are honored. No
reasoning_content echo handling needed (unlike DeepSeek/Kimi).

Web dashboard:
- web/src/pages/EnvPage.tsx: add an "Upstage Solar" provider group so
  UPSTAGE_API_KEY / UPSTAGE_BASE_URL appear under LLM Providers (not "Other").

Docs/tests:
- .env.example: documents UPSTAGE_API_KEY / UPSTAGE_BASE_URL.
- tests: profile wiring, reasoning_effort mapping (pro/open/mini, efforts,
  disabled, default-on), provider-resolver regression (resolve_provider_full /
  get_provider / solar alias / overlay), `solar-pro` default.

Testing: pytest tests/providers tests/plugins/model_providers
tests/hermes_cli/test_upstage_provider.py tests/run_agent/test_provider_parity.py
tests/hermes_cli/test_api_key_providers.py; ruff clean. Verified end-to-end:
`hermes doctor` shows "Upstage Solar", and live chat works via both
`--provider upstage` and `--provider solar`. Reasoning wire format per
https://console.upstage.ai/api/docs/for-agents/raw. Platforms tested: macOS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 00:09:24 +05:30
..
test_custom_profile.py fix(custom-provider): emit reasoning_effort at the live profile path 2026-07-04 14:19:44 +05:30
test_deepseek_profile.py fix(deepseek): set default_aux_model on profile so aux warning stops firing 2026-05-16 22:54:22 -07:00
test_fireworks_profile.py fix(providers): align Fireworks integration with project policy 2026-07-11 05:43:35 -07:00
test_kimi_profile.py fix(kimi): send thinking xor reasoning_effort, never both 2026-06-07 01:24:29 -07:00
test_minimax_profile.py fix: route minimax m3 reasoning controls through profile 2026-06-15 07:08:43 -07:00
test_ollama_cloud_profile.py feat(reasoning): add max and ultra effort levels (#62650) 2026-07-12 00:26:49 -07:00
test_opencode_go_profile.py feat(providers): GLM-5.2 native reasoning_effort controls (#58884) 2026-07-05 13:48:01 -07:00
test_upstage_profile.py feat(agent): add Upstage Solar as a model provider 2026-07-15 00:09:24 +05:30
test_zai_profile.py feat(providers): GLM-5.2 native reasoning_effort controls (#58884) 2026-07-05 13:48:01 -07:00