From dc9216512dc26d1f740cb49a9d449ffb22b4581b Mon Sep 17 00:00:00 2001 From: alfadb Date: Fri, 18 Sep 2026 09:16:42 +0800 Subject: [PATCH] fix(opencode): normalize the quota endpoint for the /zen/go base variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenCode Go 有两个都合法的 base_url:https://opencode.ai/zen/go/v1(OpenAI 协议档,DefaultOpenCodeGoBaseURL)与 https://opencode.ai/zen/go(Anthropic 协议档,前端 defaultCNBaseUrl 会写入)。旧拼接只做 strings.TrimRight(base, "/") + "/usage",Anthropic 档账号的额度探测必然打到 /zen/go/usage。 实测证据(curl 无鉴权,401=端点存在,404=不存在): 401 https://opencode.ai/zen/go/v1/usage 404 https://opencode.ai/zen/go/usage 修法沿用同包 kimiQuotaURL(coding/v1 与 coding 两种 base)的既有惯例: TrimSuffix(base, "/v1") 后统一拼回 /v1/usage,两个变体与尾斜杠写法都归一到 https://opencode.ai/zen/go/v1/usage;自定义 base 保持同一语义。 --- backend/internal/service/opencode_go.go | 8 ++++++- backend/internal/service/opencode_go_test.go | 23 +++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/backend/internal/service/opencode_go.go b/backend/internal/service/opencode_go.go index 5e2dcc78a9..1364179b01 100644 --- a/backend/internal/service/opencode_go.go +++ b/backend/internal/service/opencode_go.go @@ -322,10 +322,16 @@ func (a *Account) ResolveOpenCodeGoUpstreamProtocol(model string) string { } } +// openCodeGoQuotaURL 根据 base_url 解析 OpenCode Go 额度端点。 +// /zen/go/v1(Chat 协议默认,DefaultOpenCodeGoBaseURL)与 /zen/go +// (Anthropic 协议默认,DefaultOpenCodeGoAnthropicBaseURL)两种 base 统一 +// 剥掉尾部 /v1 后拼回 /v1/usage(实测 /zen/go/usage → 404),协议切换不 +// 影响额度探测端点。与 kimiQuotaURL 同一惯例。 func openCodeGoQuotaURL(baseURL string) string { base := strings.TrimRight(strings.TrimSpace(baseURL), "/") if base == "" { base = DefaultOpenCodeGoBaseURL } - return base + openCodeGoUsagePath + base = strings.TrimSuffix(base, "/v1") + return base + "/v1" + openCodeGoUsagePath } diff --git a/backend/internal/service/opencode_go_test.go b/backend/internal/service/opencode_go_test.go index 47e8db85ce..796487c952 100644 --- a/backend/internal/service/opencode_go_test.go +++ b/backend/internal/service/opencode_go_test.go @@ -205,9 +205,26 @@ func TestNormalizeOpenCodeGoProtocolRulesCredentials(t *testing.T) { func TestOpenCodeGoQuotaURL(t *testing.T) { t.Parallel() - require.Equal(t, "https://opencode.ai/zen/go/v1/usage", openCodeGoQuotaURL("")) - require.Equal(t, "https://opencode.ai/zen/go/v1/usage", openCodeGoQuotaURL(DefaultOpenCodeGoBaseURL+"/")) - require.Equal(t, "https://custom.example/v1/usage", openCodeGoQuotaURL("https://custom.example/v1")) + const want = "https://opencode.ai/zen/go/v1/usage" + cases := []struct { + name string + baseURL string + want string + }{ + {"empty falls back to default", "", want}, + {"chat base (/v1)", DefaultOpenCodeGoBaseURL, want}, + {"chat base trailing slash", DefaultOpenCodeGoBaseURL + "/", want}, + {"anthropic base (no /v1)", DefaultOpenCodeGoAnthropicBaseURL, want}, + {"anthropic base trailing slash", DefaultOpenCodeGoAnthropicBaseURL + "/", want}, + {"zen base stays idempotent", DefaultOpenCodeZenBaseURL, "https://opencode.ai/zen/v1/usage"}, + {"custom base with /v1", "https://custom.example/v1", "https://custom.example/v1/usage"}, + {"custom base with /v1 trailing slash", "https://custom.example/v1/", "https://custom.example/v1/usage"}, + // 与 kimiQuotaURL 同语义:无条件补 /v1,非官方域名同样归一。 + {"custom base without /v1", "https://custom.example", "https://custom.example/v1/usage"}, + } + for _, tc := range cases { + require.Equal(t, tc.want, openCodeGoQuotaURL(tc.baseURL), "case=%s", tc.name) + } } func TestDefaultOpenCodeGoModelIDsCoverDocumentedCatalog(t *testing.T) {