Skip to content

feat(agent): add Upstage Solar as a model provider (internal review)#1

Open
minchang wants to merge 1 commit into
mainfrom
feat/upstage-solar-provider
Open

feat(agent): add Upstage Solar as a model provider (internal review)#1
minchang wants to merge 1 commit into
mainfrom
feat/upstage-solar-provider

Conversation

@minchang

@minchang minchang commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Internal review before upstream

Internal review PR within UpstageAI/hermes-agent before we submit to nousresearch/hermes-agent. (Upstream PR NousResearch#41697 was opened then closed to revise here first.)

What

Adds Upstage Solar as a model provider so it appears in the hermes model / hermes setup provider picker. Solar exposes an OpenAI-compatible chat-completions endpoint (https://api.upstage.ai/v1), so this uses Hermes' documented fast path — a self-registering ProviderProfile plugin. No transport changes.

  • Setup default: solar-pro (rolling alias for the latest Solar Pro).
  • Offline catalog (fallback_models): only the agentic Solar Pro models (solar-pro, solar-pro3). When a key is set, the live /v1/models catalog lists everything available.
  • Descriptions are intentionally model-agnostic so the list isn't pinned to today's lineup as new models ship.

Changes

  • plugins/model-providers/upstage/ProviderProfile + plugin.yaml. Name upstage, alias solar, UPSTAGE_API_KEY (+ optional UPSTAGE_BASE_URL). default_aux_model left empty so auxiliary side tasks (compression, vision, memory) fall back to the user's main model. Every downstream layer auto-wires from the registry.
  • agent/model_metadata.py — context-window fallbacks (/v1/models omits context_length). Versioned ids resolve exactly; solar-pro carries the 128K Pro context as the rolling-alias catch-all for future solar-pro* releases.
  • .env.example — documents UPSTAGE_API_KEY / UPSTAGE_BASE_URL.
  • tests — profile registration, wiring contract, and solar-pro default.

Review feedback applied

  • ✅ Default model is now solar-pro (= latest Solar Pro), led in fallback_models[0].
  • solar-mini removed from the default/fallback model list. It's also not pinned as the aux model — default_aux_model is left empty so background tasks use the main model, avoiding a silent 404 when Mini is deprecated (no committed replacement).
  • solar-pro2 dropped from promotion; descriptions no longer enumerate a fixed model list, so better models surface automatically via the live catalog.
  • ✅ Context-length catch-all keys on solar-pro (128K) instead of a bare solar (32K) entry — future solar-pro4 inherits the Pro context.

Still to confirm before upstreaming

  1. solar-pro / solar-pro3 are the exact native slugs returned by https://api.upstage.ai/v1/models (vs OpenRouter's dashed solar-pro-3). fallback_models only matters offline — the live catalog overrides it when a key is set.
  2. Context windows — Solar Pro = 128K, Pro 2 = 64K, Mini = 32K.
  3. solar-mini as aux model — resolved: aux model left empty (falls back to main solar-pro), so no dependency on Mini.
  4. Reasoning — left as the generic chat-completions shape (no reasoning_effort wiring). Confirm Solar Pro doesn't require echoing reasoning_content back on later turns (the DeepSeek/Kimi trap); if it does, we'll add a build_api_kwargs_extras override.
  5. Signup URLhttps://console.upstage.ai/api-keys.
  6. Commit scopefeat(agent).

Testing

594+ passed across provider/plugin/runtime/CLI/parity/api-key suites; ruff clean. Verified the picker shows "Upstage Solar", the default resolves to solar-pro, and a future solar-pro4 inherits the Pro context window.

Platforms tested: macOS.

🤖 Generated with Claude Code

@minchang minchang force-pushed the feat/upstage-solar-provider branch 19 times, most recently from 118a925 to cf599d5 Compare June 8, 2026 15:59
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>
@minchang minchang force-pushed the feat/upstage-solar-provider branch from cf599d5 to 4317c2d Compare June 8, 2026 16:03
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.

1 participant