From 36aace34aa6d391d06c57815ac9388c69933c007 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:47:51 -0700 Subject: [PATCH] fix(opencode-go): strip trailing /v1 from base URL for Anthropic models (#4918) The Anthropic SDK appends /v1/messages to the base_url, so OpenCode's base URL https://opencode.ai/zen/go/v1 produced a double /v1 path (https://opencode.ai/zen/go/v1/v1/messages), causing 404s for MiniMax models. Strip trailing /v1 when api_mode is anthropic_messages. Also adds MiMo-V2-Pro, MiMo-V2-Omni, and MiniMax-M2.5 to the OpenCode Go model lists per their updated docs. Fixes #4890 --- agent/model_metadata.py | 2 ++ hermes_cli/models.py | 3 +++ hermes_cli/runtime_provider.py | 11 +++++++++++ hermes_cli/setup.py | 2 +- tests/test_runtime_provider_resolution.py | 7 +++++-- 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/agent/model_metadata.py b/agent/model_metadata.py index 66e97c0f..6f23b96c 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -123,6 +123,8 @@ DEFAULT_CONTEXT_LENGTHS = { "moonshotai/Kimi-K2-Thinking": 262144, "MiniMaxAI/MiniMax-M2.5": 204800, "XiaomiMiMo/MiMo-V2-Flash": 32768, + "mimo-v2-pro": 1048576, + "mimo-v2-omni": 1048576, "zai-org/GLM-5": 202752, } diff --git a/hermes_cli/models.py b/hermes_cli/models.py index 1243d160..74db2f3a 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -201,7 +201,10 @@ _PROVIDER_MODELS: dict[str, list[str]] = { "opencode-go": [ "glm-5", "kimi-k2.5", + "mimo-v2-pro", + "mimo-v2-omni", "minimax-m2.7", + "minimax-m2.5", ], "ai-gateway": [ "anthropic/claude-opus-4.6", diff --git a/hermes_cli/runtime_provider.py b/hermes_cli/runtime_provider.py index 6c942352..0ed4c826 100644 --- a/hermes_cli/runtime_provider.py +++ b/hermes_cli/runtime_provider.py @@ -3,6 +3,7 @@ from __future__ import annotations import os +import re from typing import Any, Dict, Optional from hermes_cli import auth as auth_mod @@ -168,6 +169,13 @@ def _resolve_runtime_from_pool_entry( elif base_url.rstrip("/").endswith("/anthropic"): api_mode = "anthropic_messages" + # OpenCode base URLs end with /v1 for OpenAI-compatible models, but the + # Anthropic SDK prepends its own /v1/messages to the base_url. Strip the + # trailing /v1 so the SDK constructs the correct path (e.g. + # https://opencode.ai/zen/go/v1/messages instead of .../v1/v1/messages). + if api_mode == "anthropic_messages" and provider in ("opencode-zen", "opencode-go"): + base_url = re.sub(r"/v1/?$", "", base_url) + return { "provider": provider, "api_mode": api_mode, @@ -700,6 +708,9 @@ def resolve_runtime_provider( # (e.g. https://api.minimax.io/anthropic, https://dashscope.../anthropic) elif base_url.rstrip("/").endswith("/anthropic"): api_mode = "anthropic_messages" + # Strip trailing /v1 for OpenCode Anthropic models (see comment above). + if api_mode == "anthropic_messages" and provider in ("opencode-zen", "opencode-go"): + base_url = re.sub(r"/v1/?$", "", base_url) return { "provider": provider, "api_mode": api_mode, diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index 0668acb5..a72fd4e2 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -115,7 +115,7 @@ _DEFAULT_PROVIDER_MODELS = { "ai-gateway": ["anthropic/claude-opus-4.6", "anthropic/claude-sonnet-4.6", "openai/gpt-5", "google/gemini-3-flash"], "kilocode": ["anthropic/claude-opus-4.6", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4", "google/gemini-3-pro-preview", "google/gemini-3-flash-preview"], "opencode-zen": ["gpt-5.4", "gpt-5.3-codex", "claude-sonnet-4-6", "gemini-3-flash", "glm-5", "kimi-k2.5", "minimax-m2.7"], - "opencode-go": ["glm-5", "kimi-k2.5", "minimax-m2.5", "minimax-m2.7"], + "opencode-go": ["glm-5", "kimi-k2.5", "mimo-v2-pro", "mimo-v2-omni", "minimax-m2.5", "minimax-m2.7"], "huggingface": [ "Qwen/Qwen3.5-397B-A17B", "Qwen/Qwen3-235B-A22B-Thinking-2507", "Qwen/Qwen3-Coder-480B-A35B-Instruct", "deepseek-ai/DeepSeek-R1-0528", diff --git a/tests/test_runtime_provider_resolution.py b/tests/test_runtime_provider_resolution.py index 0234c69e..11604704 100644 --- a/tests/test_runtime_provider_resolution.py +++ b/tests/test_runtime_provider_resolution.py @@ -859,7 +859,9 @@ def test_opencode_zen_claude_defaults_to_messages(monkeypatch): assert resolved["provider"] == "opencode-zen" assert resolved["api_mode"] == "anthropic_messages" - assert resolved["base_url"] == "https://opencode.ai/zen/v1" + # Trailing /v1 stripped for anthropic_messages mode — the Anthropic SDK + # appends its own /v1/messages to the base_url. + assert resolved["base_url"] == "https://opencode.ai/zen" def test_opencode_go_minimax_defaults_to_messages(monkeypatch): @@ -872,7 +874,8 @@ def test_opencode_go_minimax_defaults_to_messages(monkeypatch): assert resolved["provider"] == "opencode-go" assert resolved["api_mode"] == "anthropic_messages" - assert resolved["base_url"] == "https://opencode.ai/zen/go/v1" + # Trailing /v1 stripped — Anthropic SDK appends /v1/messages itself. + assert resolved["base_url"] == "https://opencode.ai/zen/go" def test_opencode_go_glm_defaults_to_chat_completions(monkeypatch):