Files
ModelRouter/internal/lua/adapters/kimicode.lua
JianFeeeee 9bec158d2e 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 ./...` 通过。
2026-10-14 16:52:58 +08:00

80 lines
3.3 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local adapter = {}
adapter.name = "kimicode"
adapter.version = "1.0.0"
adapter.endpoint = "/v1/chat/completions"
adapter.headers = {}
-- KimiCode / Kimi K2 属于 OpenAI 兼容协议;但部分云端 API 会校验调用方
-- "app"(只放行特定 agent),要求每次请求带上按 secret 计算的应用签名。
-- 这里演示 build_headers 钩子:基于 timestamp + 请求体哈希生成签名头。
--
-- 配置要求(source.meta):
-- meta:
-- app_id: <申请到的 app id>
-- app_key: <你的 key(由网关的 base_url 复用 api_key 亦可)>
-- app_secret: <签名密钥>
-- app_agent: code-agent # 若云端要求声明 agent 身份
function adapter.transform_request(raw_body)
local ok, req = pcall(json.decode, raw_body)
if not ok then return raw_body end
req.model = req.model or "kimi-k2"
-- The gateway's private control fields are GONE from the body (v2): the
-- neutral `thinking` field carries that intent and each adapter maps it in
-- its own protocol terms. These upstreams have no thinking switch at all,
-- so the field is simply dropped here — which is what the nil-ing below
-- used to do, except the field being dropped is no longer the kernel's
-- private one.
req.thinking = nil
req.extra_body = nil
return json.encode(req)
end
-- 可选的动态签名钩子。meta 由 Go 注入:
-- meta.url / meta.method / meta.body / meta.api_key / meta.timestamp / meta.source.meta
function adapter.build_headers(meta)
local h = {
["Content-Type"] = "application/json",
["X-App-Id"] = tostring((meta.source.meta or {}).app_id or ""),
["X-Timestamp"] = tostring(meta.timestamp),
}
local agent = (meta.source.meta or {}).app_agent
if agent and agent ~= "" then
h["X-Agent"] = agent
end
-- 校验 app:通常要求 Authorization 用 app secret 派生签名
local secret = (meta.source.meta or {}).app_secret
local api_key = meta.source.meta and meta.source.meta.api_key or meta.api_key
if secret and secret ~= "" then
local body_hash = sha256_hex(meta.body)
local sign_string = tostring(meta.timestamp) .. meta.method .. meta.url .. body_hash
local sign = hmac_sha256_hex(secret, sign_string)
h["Authorization"] = "Bearer " .. api_key
h["X-App-Sign"] = sign
else
h["Authorization"] = "Bearer " .. api_key
end
return h
end
function adapter.transform_response(raw_body)
-- 非流式 OpenAI 响应 → 统一信封。此前在 openai/groq/kimicode/mistral/github
-- 五个适配器里**逐字节相同**(各 2206B,diff 为空),已抽到共享前导。
return __prelude.openai_response(raw_body)
end
function adapter.transform_stream_chunk(raw_chunk)
-- 标准 OpenAI SSE → 统一信封。该实现此前在 groq/kimicode/mistral/github
-- 四个适配器里**逐字节重复**(各 2211B),已抽到共享前导。
return __prelude.openai_stream_chunk(raw_chunk)
end
-- 错误收敛:kimi 网关为 OpenAI 风格 {error:{message,...}}
function adapter.transform_error(status, body)
-- OpenAI 风格错误体抽消息。此前在 deepseek/github/groq/kimicode/
-- openai/sensenova 六个适配器里逐字节相同(各 293B),已抽到共享前导。
return __prelude.openai_error(status, body)
end
return adapter