| Files | Last commit | Last update |
|---|---|---|
chore(main): 回流 release/v2.0.x(v2.0.12)—— 内容对齐,main 无独有内容 按发布纪律回流。**注意这是内容对齐而非 merge**,理由与依据: 1. 纪律禁止 merge 回主干,因为 merge 会把发布分支的**版本号变更**带进 main。 本项目版本号**只由 git describe --tags 推导**(Makefile VERSION), 仓库里没有任何文件存放版本号 ⇒ 回流不存在版本污染风险。 2. 逐项核对确认 **main 是 release 的内容严格子集**: - main 独有的**文件**:0 个; - internal/lua/plugins.go / internal/core/kernel_actions.go 等内核文件 main 独有行数:0; - deploy.sh 那 14 行只是 emoji 清理(release 刻意去掉了 emoji); - channels.lua 那 333 行是**旧版内容**(旧 exports 表、旧模型名单)。 - main 独有的 9 个提交按 patch-id **全部已在 release 中等效存在** (git cherry 逐条列出均为 -,即已合入)。 3. 故回流 = 把 release 的内容带到 main,等价于"只捡拾修复、不带版本号", 且不会丢任何 main 独有的修复。 本次带回 v2.0.12 的全部内容(37 个提交): - 源串行 + 按模型节流(照 model-gate) - 已失效模型存储 + 远端目录闸门 - 余额分档选号 - 模型能力元数据(models.dev,isFree 权威判定) - **凭据续期修复**(此前恒报 ok:true 却一个请求都不发) - 通用件 TTL 缓存 + 串行锁;account_test/account_adopt/account_delete 修正 - 内核级:出站授权持久化重启后不生效、__llmsproxy_plugin_dir ground truth 校验:git diff release/v2.0.x = 0 行;go build -tags luajit ./... 通过。 | 25 days ago | |
test(retry): 钉住声明式重试判据与流式握手重试语义 - config:ShouldRetry/DelayDuration 表驱动(nil/次数=1/状态不匹配/body 不匹配/ 空子串/多信号/非法间隔) - provider:命中策略就重试直到 200、body 不匹配**不许**重试(400 也常用于真错误)、 流式只重试握手(首帧之后不重试,避免重复输出) (cherry picked from commit 0ae7d2c8be4e15c134d67594f127d39577916813) | 19 days ago | |
fix(channels): trae 目录用错头族——IDE 端点必须发 IDE 头(此前恒回 2001) ## 真因:两套头混用 用户报「trae 还是无法从上游拉取,示例插件都可以」。用探针把**原始响应**打出来 才看清:目录端点 HTTP **200**,但 22 个 function 全部 error_code 2001 "Config detail for function: X not found" —— 于是远端目录恒空, 插件只能退回兜底表,用户侧表现成「模型不正确 / 渠道不可用」。 根因不是网络、不是账号、不是 body:是**头族用错了**。 - traeCheckinHeaders 面向 api.trae.cn 的签到/积分:VSCode UA + X-Market-* + X-Lscbd-* + Vscode-Sessionid + **派生**的 market device id; - traeIdeHeaders 面向 trae-api-cn.mchost.guru 的目录/对话:Trae/0.1.52 UA + X-App-Id + X-Ide-Version(-Code) + Request-Traffic-Type + **凭据里登录时的** device_id/machine_id。 目录刷新当时复用的是签到头(注释还写着"复用更安全"),发到 IDE 端点就被逐 function 判 2001。用 IDE 头直发同一端点:**HTTP 200 + 2.6 MB**、每个 function 都带 config_info_list。 修法(全部在插件内,内核零改动): 1. 新增 traeIdeHeaders(),与签到头**明确分开**,注释写清两套头的适用面; 2. 目录刷新(sign="trae_solo")改用它,Accept: application/json; 3. 加判据 __trae_headers_probe + TestTraeHeadersKeptSeparate:钉死两套头的 键集合互不越界(IDE 头必须有 X-App-Id/X-Machine-Id、不得有 X-Market-*; 签到头反之)。这类"都能跑、但跑错了"的错只能靠契约钉死。 ## 目录拉通后暴露的第二个问题:目录≠可调用 拿到真实目录(22 function / 93 条去重模型)后逐个实测,发现**同一个 config_name 在不同 function 里可用性不同**,而本插件适配器恒发 solo_work_lite: - kimi-k2.8-preview / deepseek-V3 / glm-4.7 / code-review-judge / multimodal_image_kimi-k2.5 → HTTP 200 但 **content 为空**; - sagitta → 自称 Claude、aquila → 自称 ChatGPT、custom_model_gpt-5 → 自称 GPT-4 系列 ⇒ 这些是**未知 config 时上游悄悄回落默认模型** —— 这正是"模型不正确"的真实来源。 于是补两道准入(都是**声明式**平台数据,不写死逻辑): - models_remote.admit_functions = { "solo_work_lite" }:只收本适配器**会发** 的那条通道里的模型(白名单只说"该通道在本端点可调用",不等于"适配器会发"); - models_fallback_no_supplement = true:远端目录可用时**不再补兜底表** (兜底表里 sagitta/aquila/glm-5/DeepSeek-V4-Flash 等在上游已无对应配置)。 结果:trae 可选模型 = **20 个**(glm-5.3 / glm-5.3-flash / glm-5.3-flashx / glm-5.2 / kimi-k3 / kimi-k2.7-code / kimi-k2.6 / minimax-m3 / minimax-m3.1-flash / qwen3.8-max / qwen-3.7-plus / step-5-preview / mimo-v2.6-{flash,pro} / deepseek-v4.1-flash / DeepSeek-V4-{Flash,Pro}-Official / Doubao-Seed-2.1-{Pro,Turbo,Evolving}), **20/20 逐个实测返回非空内容**。 ## 回归测试 - TestTraeHeadersKeptSeparate(新):两套头键集合互斥(不联网即可复现该类回归) - TestTraeCustomModelSlotsAreNotOffered / TestTraeSourceOmitsCustomModelSlots (上一版):custom_model_* 槽位不进 UI 也不进上游源 - 死模型判据:opencode 的 has been deprecated 文案阳/阴性(上一版) (cherry picked from commit 7f193a997d500970f8f280810b7a4d7373ac0994) | 19 days ago | |
fix: 收口渠道源迁移与测试页合并 (cherry picked from commit 12bfd53f162b3f806ccda8abea80758946c50216) | 19 days ago | |
fix(codearts): 上游限流改为可声明重试(内核通用能力)+ 会话/连接两处真因 用户连续报「codeart 还是不可用 / empty stream」。把上游原始响应打出来逐条对齐, 三个症状同源,且都不是"模型坏了": | 场景 | 上游实际返回 | |---|---| | 流式、短时间连续请求 | HTTP **200** + 只带 error 的帧 ⇒ 内核判 empty stream | | 非流式、同一条件 | HTTP 400 TM.00001041: 并发会话数已达上限(3个) | | 突发请求 | HTTP 429 TPM limit … 500000 tokens per minute | 实测:最后一个请求结束后约 **44~60 秒**释放;同一账号连续请求 3~4 次即占满。 参考实现(示例插件 llm-adapter.ts)的做法是**每 10s 轮询后重试 chat**(最多 30 分钟),所以用户那边"看起来没事"。 ## 我们的改法(内核只做通用机制,厂商知识留在插件) 1. **内核新增声明式重试策略** source.retry(纯数据:状态码列表 + 响应体子串 + 间隔 + 次数)。内核不认识任何厂商;命中即在同一网关请求内每 10s 重试一次。 流式只在**握手阶段**重试(首帧尚未下发,不会重复输出),非流式整体重试。 2. **插件为 codearts 声明**:400/429 + 命中 TM.00001041 / TPM limit / 并发会话数已达上限 → 10s × 最多 18 次(≈3 分钟)。 3. **适配器补两个会话细节**:Connection: close(keep-alive 空闲连接会被上游 计入并发会话)与稳定 Session-Id(同一账号恒定,避免每次请求新建会话)。 4. 错误文案补可行动提示(并发会话上限 / TPM 限流,约 1 分钟释放)。 ## 验证(生产) - 连续 6 次**流式**:6/6 成功(撞上限时自动等 10s 再试,客户端只感觉慢): +0s / +12s / +34s / +86s / +100s / +144s - 连续 5 次**非流式**:5/5 成功(+0 / +11 / +20 / +28 / +38s) - 修复前:第 4 个请求起必然 TM.00001041 / empty stream。 > 注:TM.00001005 无正常可用套餐 属于账号权益问题(不重试、如实报出), > 与限流要分开处理。 (cherry picked from commit 6454b094bc5cfa0ff2a07597785da3ab898aec7f) | 19 days ago | |
test(retry): 钉住声明式重试判据与流式握手重试语义 - config:ShouldRetry/DelayDuration 表驱动(nil/次数=1/状态不匹配/body 不匹配/ 空子串/多信号/非法间隔) - provider:命中策略就重试直到 200、body 不匹配**不许**重试(400 也常用于真错误)、 流式只重试握手(首帧之后不重试,避免重复输出) (cherry picked from commit 0ae7d2c8be4e15c134d67594f127d39577916813) | 19 days ago | |
chore(main): 回流 release/v2.0.x(v2.0.12)—— 内容对齐,main 无独有内容 按发布纪律回流。**注意这是内容对齐而非 merge**,理由与依据: 1. 纪律禁止 merge 回主干,因为 merge 会把发布分支的**版本号变更**带进 main。 本项目版本号**只由 git describe --tags 推导**(Makefile VERSION), 仓库里没有任何文件存放版本号 ⇒ 回流不存在版本污染风险。 2. 逐项核对确认 **main 是 release 的内容严格子集**: - main 独有的**文件**:0 个; - internal/lua/plugins.go / internal/core/kernel_actions.go 等内核文件 main 独有行数:0; - deploy.sh 那 14 行只是 emoji 清理(release 刻意去掉了 emoji); - channels.lua 那 333 行是**旧版内容**(旧 exports 表、旧模型名单)。 - main 独有的 9 个提交按 patch-id **全部已在 release 中等效存在** (git cherry 逐条列出均为 -,即已合入)。 3. 故回流 = 把 release 的内容带到 main,等价于"只捡拾修复、不带版本号", 且不会丢任何 main 独有的修复。 本次带回 v2.0.12 的全部内容(37 个提交): - 源串行 + 按模型节流(照 model-gate) - 已失效模型存储 + 远端目录闸门 - 余额分档选号 - 模型能力元数据(models.dev,isFree 权威判定) - **凭据续期修复**(此前恒报 ok:true 却一个请求都不发) - 通用件 TTL 缓存 + 串行锁;account_test/account_adopt/account_delete 修正 - 内核级:出站授权持久化重启后不生效、__llmsproxy_plugin_dir ground truth 校验:git diff release/v2.0.x = 0 行;go build -tags luajit ./... 通过。 | 25 days ago | |
feat(types): 统一格式落地为内核实际使用的类型 —— 私有字段泄漏归零 Phase 2 收尾(入向)。ChatRequest 从"客户端发什么就是什么"改为 UnifiedRequest(最大集合)的别名,内核真正用上了那个超集类型。 改掉的具体缺陷: 1. 私有字段泄漏归零(v1 的核心问题) v1 的 disable_thinking 是内核私有开关,却被序列化进交给适配器的 body, 迫使 10 个适配器各自写 req.disable_thinking = nil 来清理。 现在它是中立的 thinking 字段({enabled, budget_tokens}),客户端与 适配器都认这个词: - gateway/chat.go:thinkingFromClient() 把 disable_thinking 翻译成 thinking.enabled=false;冲突时中立字段优先(它能带预算,布尔不能) - deepseek.lua:thinking.enabled=false → extra_body.thinking.type=disabled - anthropic.lua:thinking.enabled=true + budget → 原生 {type,budget_tokens} (enabled=false 时不传该字段——Anthropic 没有 type=disabled 这个写法) - 其余 7 个适配器:把"清理内核私有字段"改成"清理中立字段" 2. Tools/ToolChoice 改 json.RawMessage 原为 []interface{}(OpenAI 原始形状 = 内核在假设某个协议)。 内核从不解释工具 schema——它原样交给适配器,所以原始形状不损失任何 内核侧统一性。ToolDef 结构化类型保留在包内供新适配器选用。 3. 删除 MarshalJSON 后门 v1 手工 splice ExtraBody 进 OpenAI 形状的 body;现在 ExtraBody 是 UnifiedRequest 上一个正正经经声明的字段。 渐进迁移:ChatRequest 保留为别名(不是新类型),49 处引用零改动编译, 语义变更不被机械改名淹没。 测试:新增 thinking_test.go(翻译链 4 例 + 泄漏回归 + tools 透传); vm_test.go 两处迁移到中立语义。golden 字节级未漂移。 | 28 days ago |