diff --git a/docs/src/content/docs/providers/opencode-go.md b/docs/src/content/docs/providers/opencode-go.md index e047038..6a6fa8b 100644 --- a/docs/src/content/docs/providers/opencode-go.md +++ b/docs/src/content/docs/providers/opencode-go.md @@ -5,8 +5,9 @@ description: Configure an OpenCode Go API key, model routing, streaming, tools, OpenCode Go uses the API at `https://opencode.ai/zen/go/v1`. Its catalog spans OpenAI-compatible chat completions, Anthropic-compatible messages, and OpenAI -Responses; the proxy selects the wire protocol for each registered model. The -registered mapping follows the [official OpenCode Go endpoint table](https://opencode.ai/docs/go/#endpoints). +Responses; the proxy selects the wire protocol for each registered model. Each +mapping comes from the [official OpenCode Go endpoint table](https://opencode.ai/docs/go/#endpoints) +or direct protocol verification against the API. ## Account and authentication @@ -23,10 +24,9 @@ implement an OpenCode login flow. ## Models -Run `claude-code-proxy models` for the statically registered catalog based on -OpenCode's documented endpoint table. Every registered model has a -provider-qualified form. Bare IDs are also accepted when they do not belong to -another provider: +Run `claude-code-proxy models` for the statically registered catalog. Every +registered model has a provider-qualified form. Bare IDs are also accepted when +they do not belong to another provider: ```sh ANTHROPIC_MODEL=opencode-go/glm-5.2 \ @@ -57,6 +57,6 @@ OpenCode Go. - `CCP_OPENCODE_BASE_URL` or `opencode.baseUrl` changes the API base URL. OpenCode Go may expose additional model IDs through `/models`, but the proxy -registers only models whose wire protocol is documented. Unknown IDs are -rejected locally. Access or usage-limit errors for registered models are -surfaced from OpenCode. +registers only models whose wire protocol is documented or has been verified +against the live API. Unknown IDs are rejected locally. Access or usage-limit +errors for registered models are surfaced from OpenCode. diff --git a/src/providers/opencode/model.rs b/src/providers/opencode/model.rs index fa97a4f..7a7307a 100644 --- a/src/providers/opencode/model.rs +++ b/src/providers/opencode/model.rs @@ -30,6 +30,10 @@ pub const MODELS: &[ModelSpec] = &[ id: "glm-5.1", endpoint: EndpointKind::ChatCompletions, }, + ModelSpec { + id: "glm-5", + endpoint: EndpointKind::ChatCompletions, + }, ModelSpec { id: "kimi-k3", endpoint: EndpointKind::ChatCompletions, @@ -42,6 +46,10 @@ pub const MODELS: &[ModelSpec] = &[ id: "kimi-k2.6", endpoint: EndpointKind::ChatCompletions, }, + ModelSpec { + id: "kimi-k2.5", + endpoint: EndpointKind::ChatCompletions, + }, ModelSpec { id: "deepseek-v4-pro", endpoint: EndpointKind::ChatCompletions, @@ -70,6 +78,10 @@ pub const MODELS: &[ModelSpec] = &[ id: "minimax-m2.5", endpoint: EndpointKind::Messages, }, + ModelSpec { + id: "qwen3.8-max", + endpoint: EndpointKind::Messages, + }, ModelSpec { id: "qwen3.7-max", endpoint: EndpointKind::Messages, @@ -82,6 +94,10 @@ pub const MODELS: &[ModelSpec] = &[ id: "qwen3.6-plus", endpoint: EndpointKind::Messages, }, + ModelSpec { + id: "qwen3.5-plus", + endpoint: EndpointKind::Messages, + }, ModelSpec { id: "hy3", endpoint: EndpointKind::ChatCompletions, @@ -126,11 +142,36 @@ mod tests { .iter() .filter(|model| model.endpoint == EndpointKind::Responses) .count(); - assert_eq!(chat, 11); - assert_eq!(messages, 6); + assert_eq!(chat, 13); + assert_eq!(messages, 8); assert_eq!(responses, 1); } + #[test] + fn refreshed_models_resolve_and_are_advertised() { + let advertised = advertised_models(); + for (id, endpoint) in [ + ("glm-5", EndpointKind::ChatCompletions), + ("kimi-k2.5", EndpointKind::ChatCompletions), + ("qwen3.8-max", EndpointKind::Messages), + ("qwen3.5-plus", EndpointKind::Messages), + ] { + let qualified = format!("{MODEL_PREFIX}{id}"); + assert_eq!( + resolve(id).expect("registered bare model").endpoint, + endpoint + ); + assert_eq!( + resolve(&qualified) + .expect("registered provider-qualified model") + .endpoint, + endpoint + ); + assert!(advertised.iter().any(|model| model == id)); + assert!(advertised.contains(&qualified)); + } + } + #[test] fn canonical_prefix_resolves_and_unknown_models_do_not() { let spec = resolve("opencode-go/minimax-m3").expect("known model");