package core import ( "regexp" "strings" "testing" ) // ★ 源的 chat URL = `base_url + endpoint`(内核 provider.go ChatURL)。 // // 真实缺陷(生产实测):多个渠道平台的 `base_url` 里塞了**完整路径**, // 而适配器默认 endpoint 又是 "/chat/completions" ⇒ 实际请求变成 // // https://copilot.tencent.com/v2/chat/completions/chat/completions // // ⇒ 上游回 `{"error_msg":"404 Route Not Found"}`(APISIX 的措辞,不是模型错误)。 // // 受影响平台 8 个:buddy / cline / lobsterai / opencode / qoder / loomy / // raccoon(zcode 当时已用 endpoint 覆盖,形态正确)。 // // ★ 为什么这个缺陷能活很久:**模型名被多个源服务**。 // // `deepseek-v4.1-flash` 同时由 4 个源提供(alittokenplan/vela/oin/channels-buddy…) // ⇒ 网关在 buddy 源失败后会**继续尝试下一个源**并成功 ⇒ 用户看到"能回话", // 于是"buddy 通道是好的"这个结论**完全没有证据**。 // 而 `hy3` 只由 buddy 一个源提供 ⇒ 一调就暴露真因。 // ⇒ 判据必须断言**源的 URL 形态**(结构不变量),不能靠"某个模型能调通"。 // // 判据:base_url 不得自带任何 chat 路径段(它只应是 host[+协议公共前缀]), // 路径必须在 `endpoint` 里。 func TestChannelSourceBaseURLHasNoChatPath(t *testing.T) { src, err := readBundledChannels(t) if err != nil { t.Fatal(err) } s := string(src) // 只在平台定义区里找 base_url(避免误判注释/文档里的示例) declRe := regexp.MustCompile(`(?m)^\s*base_url = "([^"]+)"\s*,?$`) // 已知适配器会把这些路径各追加一次;出现即说明 base_url 侵占了 endpoint 的地盘 banned := []string{"/chat/completions", "/v1/messages", "/generateContent", "/api/chat"} found := 0 for _, m := range declRe.FindAllStringSubmatch(s, -1) { url := m[1] found++ for _, b := range banned { if strings.Contains(url, b) { t.Errorf("base_url 侵占了 endpoint 的路径:%s\n"+ " 内核的 URL 是 `base_url + endpoint`(provider.go ChatURL),"+ "适配器默认 endpoint=\"/chat/completions\" ⇒ 实际会请求 %s%s\n"+ " 修法:base_url 只留 host,把 `%s` 移到该平台的 `endpoint = \"...\"`", url, url, b, b) } } } if found == 0 { t.Fatal("没扫到任何 base_url 声明(判据失效)") } t.Logf("✓ %d 个 base_url 均不含 chat 路径段", found) } // ★ 反过来也要咬:说明该缺陷**确实已被修好**、而不是判据太松。 // 用一段**故意的坏数据**验证判据的判别力(变异测试的静态等价物)。 func TestChannelBaseURLJudgeBitesOnBadInput(t *testing.T) { bad := ` base_url = "https://copilot.tencent.com/v2/chat/completions",` declRe := regexp.MustCompile(`(?m)^\s*base_url = "([^"]+)"\s*,?$`) m := declRe.FindStringSubmatch(bad) if m == nil { t.Fatal("判据的正则匹配不到坏数据 ⇒ 判据无判别力(形同虚设)") } if !strings.Contains(m[1], "/chat/completions") { t.Fatal("坏数据未被识别 ⇒ 判据无判别力") } t.Log("✓ 判据对坏数据有判别力") }