mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
按发布纪律回流。这四笔原本**误提交在 main** 上(我的操作失误): 纪律要求修复先在 release/v2.0.x 提交、再回流 main。已迁移: ① release 上 cherry-pick 这四笔(干净落地); ② main reset 回 9bec158(那四笔未推送,无远端影响); ③ 内容对齐回 main —— 等价于只捡拾修复、不带版本号。 内容: - channels-qoder 适配器:10605(排队) 与 110(额度耗尽) 分开说,厂商码留在插件域 - channels-cline 适配器:解析英文句子里的等待时长(内核按额度耗尽冷却而非 30s 猛敲) - auto_claim:按 covers_today 记账(Qoder 10:00 刷新前不得算已处理)+ 间隔 2 小时 - isFree:改为按平台声明权威来源(cline 用远端 free[]/命名约定,opencode 用 cost) 校验:git diff release/v2.0.x = 0 行;go build 通过。
68 lines
2.7 KiB
Go
68 lines
2.7 KiB
Go
package core
|
||
|
||
import (
|
||
"testing"
|
||
)
|
||
|
||
// `isFree` 的判定链(照参考 cline-models.ts)。
|
||
//
|
||
// ★ 修的是一个与注释自相矛盾的缺陷:cline 的 3 个模型来自远端 **free 数组**,
|
||
// 却声明在 `models` 里 ⇒ 被标成收费。用户看不到哪个可以不花钱用。
|
||
//
|
||
// 参考的判定链(权威在前):
|
||
//
|
||
// ① 远端 free 数组(`recommended-models` 是**唯一权威**的免费集合;
|
||
// `/api/v1/models` 的 460 个 id 里根本没有 cline-free/*)
|
||
// ② 命名约定前缀 `cline-free/*`(远端未响应时的兜底)
|
||
// ③ 声明的 models_free
|
||
// ④ 能力表的 cost(models.dev)
|
||
//
|
||
// ⚠️ 免费是 **OR** 语义:多个来源任一确认免费就够。写成"后者覆盖前者"会让
|
||
// 「远端说免费、能力表拉不到」退回收费 —— 正是这类静默降级。
|
||
func TestIsFreeUsesAuthorityChain(t *testing.T) {
|
||
_, ps := poolCore(t)
|
||
|
||
// cline 的免费模型必须被标成免费(远端/free_prefix/声明 任一命中即可)
|
||
out, err := ps.Call("channels", "model_list", map[string]interface{}{"platform": "cline"})
|
||
if err != nil {
|
||
t.Fatalf("model_list: %v", err)
|
||
}
|
||
j, _ := out.(map[string]interface{})["json"].(map[string]interface{})
|
||
got := map[string]bool{}
|
||
for _, it := range asArrInterface(j["models"]) {
|
||
if mm, ok := it.(map[string]interface{}); ok {
|
||
if id, ok := mm["id"].(string); ok {
|
||
if f, ok := mm["isFree"].(bool); ok {
|
||
got[id] = f
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// `cline-free/*` 前缀命中 ⇒ 必须免费(命名约定兜底)
|
||
if !got["cline-free/mimo-v2.6-flash"] {
|
||
t.Errorf("cline-free/* 前缀的模型必须免费(命名约定兜底),实得 %v", got)
|
||
}
|
||
// stealth/space-bunny-alpha 来自远端 free 数组,也必须免费
|
||
if !got["stealth/space-bunny-alpha"] {
|
||
t.Errorf("远端 free 数组里的模型必须免费,实得 %v", got)
|
||
}
|
||
|
||
// 命名约定必须生效(远端未响应时唯一的兜底依据)
|
||
probe, _ := ps.Call("channels", "__is_free_probe", map[string]interface{}{
|
||
"platform": "cline", "model_id": "cline-free/some-new-model",
|
||
})
|
||
pj, _ := probe.(map[string]interface{})["json"].(map[string]interface{})
|
||
if pj["is_free"] != true {
|
||
t.Error("远端未响应时,`cline-free/*` 前缀必须能判出免费(这是兜底依据)")
|
||
}
|
||
// 反向:收费通道的同名模型**不得**被判免费
|
||
//(参考点名:免费模型是独立 id,`cline-free/x` 与 `x` 是两个不同模型)
|
||
probe2, _ := ps.Call("channels", "__is_free_probe", map[string]interface{}{
|
||
"platform": "cline", "model_id": "deepseek/deepseek-v4.1-flash",
|
||
})
|
||
pj2, _ := probe2.(map[string]interface{})["json"].(map[string]interface{})
|
||
if pj2["is_free"] == true {
|
||
t.Error("收费通道的模型不得因为前缀规则被判成免费")
|
||
}
|
||
}
|