hermes: wire into dotfiles; fix opencode's generated context limits
Two client-side fixes against the covert-gpt LiteLLM gateway, both traced from opencode throwing intermittent ContextWindowExceededError 400s. opencode (mcp-config/sync.sh): spec_for() mapped LiteLLM's /model/info onto opencode's schema 1:1, but the two mean different things by "output". LiteLLM's max_output_tokens is the whole window (vLLM caps TOTAL context, not output separately, which is correct for LiteLLM); opencode's limit.output is a RESERVE it subtracts from context to pick a compaction point. Copying one to the other told opencode to reserve the entire 262144 window, so it targeted an input of context-output and the server counted one token more than opencode did -- landing on context+1 and a hard 400, every time (measured: 196609 in + 65536 out = 262145 vs a 262144 window; the retries shrinking max_tokens by 65 never helped because the input grew to compensate). Capping the reserve alone would NOT have fixed it -- opencode would still sit exactly on the boundary, just at a different input size. So: cap the reserve (OUTPUT_RESERVE_CAP) and hold a margin back from context (CONTEXT_SAFETY_MARGIN). Generated at sync time, so it fixes every gateway model at once, including third-party ones. hermes (hermes/gateway.yaml, hermes/install.sh): Hermes reached the gateway by pretending it WAS OpenRouter -- the LiteLLM key in OPENROUTER_API_KEY, the gateway in OPENROUTER_BASE_URL. Requests routed fine, but fetch_openrouter_models hardcodes openrouter.ai/api/v1/models and ignores OPENROUTER_BASE_URL, so the picker listed OpenRouter's ~342-model catalog -- models this gateway cannot serve -- while the gateway's own models, including cg-1's, never appeared at all. Replaced with a named custom provider. install.sh now merges gateway.yaml into ~/.hermes/config.yaml, so a fresh box gets a Hermes that can actually talk to the gateway instead of one pointed at nothing. The merge is idempotent and narrow: only the covert-gpt entry is touched, model.default/provider are seeded only when unset, and a box still on the masquerade is migrated off it (fingerprint: provider openrouter + base_url pointing at this gateway; a genuine OpenRouter user never has that, and is left alone). No secrets: gateway.yaml names the key via key_env, and mcp-config/sync.sh is what exports it. Hermes needs no context safety margin -- it omits max_tokens entirely, so vLLM bounds output by whatever context is left. Also folds in the in-flight hermes bootstrap wiring. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# hermes/gateway.yaml — the covert-gpt LiteLLM gateway, as a Hermes custom
|
||||
# provider. Merged into ~/.hermes/config.yaml by hermes/install.sh.
|
||||
#
|
||||
# NO SECRETS, EVER: the key is referenced by NAME via `key_env: LITELLM_KEY`,
|
||||
# never by value. mcp-config/sync.sh exports LITELLM_KEY into every interactive
|
||||
# shell from ~/.config/mcp-sync/key (0600), and Hermes — launched from such a
|
||||
# shell — resolves it at runtime. So this file is safe in a PUBLIC repo, and
|
||||
# `hermes/install.sh` has no key to prompt for. Run mcp-config/install.sh first;
|
||||
# without it LITELLM_KEY is unset and Hermes falls back to "no-key-required",
|
||||
# which the gateway rejects with a 401.
|
||||
#
|
||||
# WHY a custom provider instead of `model.provider: openrouter` + a base_url:
|
||||
# that older shape pointed Hermes at the gateway by pretending it WAS OpenRouter
|
||||
# (OPENROUTER_API_KEY held the LiteLLM key, OPENROUTER_BASE_URL held the gateway
|
||||
# URL). Requests reached the gateway, but the MODEL PICKER did not: Hermes'
|
||||
# fetch_openrouter_models hardcodes openrouter.ai/api/v1/models and ignores
|
||||
# OPENROUTER_BASE_URL, so the picker listed OpenRouter's ~342-model catalog —
|
||||
# models this gateway cannot serve — while the gateway's own models never
|
||||
# appeared. A named custom provider probes THIS base_url instead.
|
||||
#
|
||||
# NOTE ON COMMENTS: Hermes rewrites ~/.hermes/config.yaml itself (save_config)
|
||||
# and does not preserve comments, so none of this survives into the deployed
|
||||
# file. That is exactly why the reasoning lives HERE, in the repo, rather than
|
||||
# inline in the generated config.
|
||||
custom_providers:
|
||||
- name: covert-gpt
|
||||
base_url: https://llm.covert-gpt.com/v1
|
||||
key_env: LITELLM_KEY
|
||||
api_mode: chat_completions
|
||||
# `discover_models` is deliberately left at its default (true): with a key
|
||||
# present Hermes probes the gateway's /v1/models and REPLACES the picker's
|
||||
# list with the live catalog, so new gateway models show up with no edit
|
||||
# here. The `models:` map below is NOT the picker list — it exists purely to
|
||||
# carry per-model context_length overrides, which are read from config
|
||||
# independently of discovery.
|
||||
models:
|
||||
# These MUST track each node's --max-model-len in ai-k8s-iac
|
||||
# (charts/inference/values.yaml > vllm.nodes[].extraArgs). They are a
|
||||
# separate copy of that number; there is no single source across repos.
|
||||
#
|
||||
# Unlike opencode, Hermes needs NO safety margin here. opencode reserves
|
||||
# `limit.output` and targets an input of exactly context - output, landing
|
||||
# one token over the window (a hard 400); Hermes omits max_tokens entirely
|
||||
# unless model.max_tokens is set, so vLLM just bounds output by whatever
|
||||
# context remains. Do NOT add model.max_tokens to work around anything: it
|
||||
# is GLOBAL, would apply to every provider (including Anthropic), and only
|
||||
# shrinks the effective input budget Hermes compacts against.
|
||||
qwen3-vl-30b-a3b: # cg-1 — multimodal, tool calling
|
||||
context_length: 262144
|
||||
supports_vision: true
|
||||
qwen3-coder-next: # cg-2 — agentic coder
|
||||
context_length: 262144
|
||||
# Models the gateway proxies to third parties (kimi, glm, …) are
|
||||
# intentionally absent: discovery still lists them, and inventing a
|
||||
# context_length we have not verified is worse than letting Hermes probe.
|
||||
Reference in New Issue
Block a user