mslxdff 0.1.200 → 0.1.203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/README.md +3 -3
  2. package/bin/mslxdff.js +1 -1
  3. package/package.json +38 -38
  4. package/plugins/README.md +14 -14
  5. package/plugins/prefer-model.mjs.example +14 -14
  6. package/src/anthropic/count-tokens.js +61 -61
  7. package/src/anthropic/request-body.js +126 -126
  8. package/src/anthropic/shared.js +18 -18
  9. package/src/anthropic/sse-aggregate.js +56 -56
  10. package/src/anthropic/translate.js +287 -287
  11. package/src/anthropic/web-search.js +361 -361
  12. package/src/api-kind.js +31 -31
  13. package/src/autostart.js +288 -288
  14. package/src/bench/probe.js +1 -1
  15. package/src/bench/runner.js +1 -1
  16. package/src/bench/via-probe.js +1 -1
  17. package/src/bench/via.js +144 -144
  18. package/src/bench/workbuddy-bench.js +1 -1
  19. package/src/chat/config.js +11 -11
  20. package/src/chat/cooling.js +81 -81
  21. package/src/chat/direct.js +58 -58
  22. package/src/chat/index.js +6 -6
  23. package/src/chat/spinner.js +38 -38
  24. package/src/chat/sse.js +69 -69
  25. package/src/chat/stats.js +247 -247
  26. package/src/chat/store.js +48 -48
  27. package/src/chat/tool-handlers.js +67 -67
  28. package/src/chat/tools.js +1 -1
  29. package/src/chat/upstream.js +59 -59
  30. package/src/chat-pipeline/auto-race.js +158 -158
  31. package/src/chat-pipeline/empty-turn.js +147 -147
  32. package/src/chat-pipeline/engine.js +17 -17
  33. package/src/chat-pipeline/serial-trial.js +283 -283
  34. package/src/chat-pipeline/terminal-verdict.js +147 -147
  35. package/src/chooser.js +54 -54
  36. package/src/claude-desktop/apply.js +101 -101
  37. package/src/claude-desktop/context1m.js +38 -38
  38. package/src/claude-desktop/doctor.js +146 -146
  39. package/src/claude-desktop/slots.js +152 -152
  40. package/src/cli/bootstrap.js +1 -1
  41. package/src/cli/commands/claude-desktop.js +284 -284
  42. package/src/cli/commands/daemon.js +231 -231
  43. package/src/cli/commands/model/list-live.js +22 -22
  44. package/src/cli/commands/model/list-providers.js +76 -76
  45. package/src/cli/commands/model/list-render.js +77 -77
  46. package/src/cli/commands/model/list-sort.js +52 -52
  47. package/src/cli/commands/model/list-tty.js +76 -76
  48. package/src/cli/commands/model/list.js +166 -166
  49. package/src/cli/commands/model/live-models.js +24 -24
  50. package/src/cli/commands/model/stats.js +43 -43
  51. package/src/cli/commands/model/status.js +47 -47
  52. package/src/cli/commands/model.js +51 -51
  53. package/src/cli/commands/provider/add.js +108 -108
  54. package/src/cli/commands/provider/allowlist.js +99 -99
  55. package/src/cli/commands/provider/cline-free.js +99 -99
  56. package/src/cli/commands/provider/cline-login.js +218 -218
  57. package/src/cli/commands/provider/cline-quota.js +65 -65
  58. package/src/cli/commands/provider/codearts-login.js +45 -45
  59. package/src/cli/commands/provider/config.js +119 -119
  60. package/src/cli/commands/provider/globalqwenwork-login.js +126 -126
  61. package/src/cli/commands/provider/keys-guard.js +50 -50
  62. package/src/cli/commands/provider/keys.js +161 -161
  63. package/src/cli/commands/provider/qoder-checkin.js +81 -81
  64. package/src/cli/commands/provider/qoder-login.js +102 -102
  65. package/src/cli/commands/provider/raccoon-login.js +180 -180
  66. package/src/cli/commands/provider/raccoon-password.js +162 -162
  67. package/src/cli/commands/provider/raccoon-quota.js +109 -109
  68. package/src/cli/commands/provider/traework-checkin.js +144 -144
  69. package/src/cli/commands/provider/traework-login.js +164 -164
  70. package/src/cli/commands/provider/workbuddy-login.js +153 -153
  71. package/src/cli/commands/provider/zcode-login.js +77 -77
  72. package/src/cli/commands/provider/zcode-quota.js +55 -55
  73. package/src/cli/commands/provider.js +1 -1
  74. package/src/cli/commands/stats.js +149 -149
  75. package/src/cli/commands/system.js +261 -261
  76. package/src/cli/commands/timezone.js +47 -47
  77. package/src/cli/commands/use-group.js +60 -60
  78. package/src/cli/commands/workbuddy.js +189 -189
  79. package/src/cli/format.js +141 -141
  80. package/src/cli/group-helpers.js +70 -70
  81. package/src/cli/help.js +80 -80
  82. package/src/cli/index.js +70 -70
  83. package/src/cli/interactive.js +121 -121
  84. package/src/cli/join-core.js +99 -99
  85. package/src/cli/join-wizard.js +175 -175
  86. package/src/cli/policy.js +136 -136
  87. package/src/cli/provider-row.js +126 -126
  88. package/src/cli/util.js +24 -24
  89. package/src/compat.js +53 -53
  90. package/src/events.js +38 -38
  91. package/src/free-lane.js +131 -131
  92. package/src/free-watcher.js +63 -63
  93. package/src/groups.js +262 -262
  94. package/src/logs.js +195 -195
  95. package/src/metrics.js +62 -62
  96. package/src/model-capabilities/context-lookup.js +65 -65
  97. package/src/model-capabilities/merge.js +142 -142
  98. package/src/model-trace.js +187 -187
  99. package/src/models.js +1 -1
  100. package/src/opencode-identity.js +72 -72
  101. package/src/peers.js +254 -251
  102. package/src/plugins.js +107 -107
  103. package/src/providers/base.js +164 -164
  104. package/src/providers/classify.js +22 -22
  105. package/src/providers/cline/allowlist-sync.js +93 -93
  106. package/src/providers/cline/free-catalog.js +71 -71
  107. package/src/providers/cline/headers.js +37 -37
  108. package/src/providers/cline/index.js +130 -130
  109. package/src/providers/cline/models.js +150 -150
  110. package/src/providers/cline/usage.js +274 -274
  111. package/src/providers/codearts/auth-pool.js +148 -148
  112. package/src/providers/codearts/concurrency.js +34 -34
  113. package/src/providers/codearts/const.js +65 -65
  114. package/src/providers/codearts/dpop.js +95 -95
  115. package/src/providers/codearts/index.js +175 -175
  116. package/src/providers/codearts/login.js +214 -214
  117. package/src/providers/codearts/models.js +182 -182
  118. package/src/providers/codearts/sign.js +96 -96
  119. package/src/providers/codearts/sse.js +204 -204
  120. package/src/providers/codearts/stream.js +209 -209
  121. package/src/providers/codearts/sts.js +124 -124
  122. package/src/providers/codearts.js +1 -1
  123. package/src/providers/dispatcher.js +146 -146
  124. package/src/providers/generic.js +156 -156
  125. package/src/providers/globalqwenwork/account-store.js +141 -141
  126. package/src/providers/globalqwenwork/constants.js +73 -73
  127. package/src/providers/globalqwenwork/crypto.js +2 -2
  128. package/src/providers/globalqwenwork/http.js +2 -2
  129. package/src/providers/globalqwenwork/index.js +331 -331
  130. package/src/providers/globalqwenwork/payload.js +147 -147
  131. package/src/providers/globalqwenwork/rsa.js +2 -2
  132. package/src/providers/globalqwenwork/sse.js +2 -2
  133. package/src/providers/globalqwenwork/stream.js +2 -2
  134. package/src/providers/globalqwenwork.js +1 -1
  135. package/src/providers/globalworkbuddy/account-store.js +198 -198
  136. package/src/providers/globalworkbuddy/auth.js +97 -97
  137. package/src/providers/globalworkbuddy/catalog.js +138 -138
  138. package/src/providers/globalworkbuddy/constants.js +73 -73
  139. package/src/providers/globalworkbuddy/device-auth.js +120 -120
  140. package/src/providers/globalworkbuddy/errors.js +98 -98
  141. package/src/providers/globalworkbuddy/headers.js +89 -89
  142. package/src/providers/globalworkbuddy/models.js +96 -96
  143. package/src/providers/globalworkbuddy/payload.js +80 -80
  144. package/src/providers/index.js +5 -5
  145. package/src/providers/model-id.js +172 -172
  146. package/src/providers/opencode.js +19 -19
  147. package/src/providers/openrouter.js +31 -31
  148. package/src/providers/qoder/account-store.js +106 -106
  149. package/src/providers/qoder/aggregate.js +60 -60
  150. package/src/providers/qoder/baseprompt.json +591 -591
  151. package/src/providers/qoder/checkin.js +160 -160
  152. package/src/providers/qoder/constants.js +44 -44
  153. package/src/providers/qoder/encode.js +41 -41
  154. package/src/providers/qoder/fingerprint.js +38 -38
  155. package/src/providers/qoder/models.js +77 -77
  156. package/src/providers/qoder/oauth.js +84 -84
  157. package/src/providers/qoder/payload.js +162 -162
  158. package/src/providers/qoder/request.js +27 -27
  159. package/src/providers/qoder/session.js +134 -134
  160. package/src/providers/qoder/sticky.js +38 -38
  161. package/src/providers/qoder/stream.js +116 -116
  162. package/src/providers/qoder.js +1 -1
  163. package/src/providers/raccoon/account-store.js +216 -216
  164. package/src/providers/raccoon/auth.js +67 -67
  165. package/src/providers/raccoon/chat.js +228 -228
  166. package/src/providers/raccoon/const.js +180 -165
  167. package/src/providers/raccoon/credits.js +185 -175
  168. package/src/providers/raccoon/crypto.js +43 -0
  169. package/src/providers/raccoon/envelope.js +31 -31
  170. package/src/providers/raccoon/headers.js +45 -45
  171. package/src/providers/raccoon/index.js +216 -216
  172. package/src/providers/raccoon/login.js +279 -279
  173. package/src/providers/raccoon/models.js +160 -160
  174. package/src/providers/raccoon/password-login.js +102 -87
  175. package/src/providers/raccoon/qr-codewords.js +115 -115
  176. package/src/providers/raccoon/qr.js +236 -236
  177. package/src/providers/raccoon/sse.js +135 -135
  178. package/src/providers/responses-channel.js +120 -120
  179. package/src/providers/share-keys.js +53 -53
  180. package/src/providers/traework/account-store.js +234 -234
  181. package/src/providers/traework/chat.js +217 -217
  182. package/src/providers/traework/checkin.js +77 -77
  183. package/src/providers/traework/constants.js +41 -41
  184. package/src/providers/traework/errors.js +52 -52
  185. package/src/providers/traework/headers.js +79 -79
  186. package/src/providers/traework/index.js +132 -132
  187. package/src/providers/traework/market-identity.js +116 -116
  188. package/src/providers/traework/models.js +98 -98
  189. package/src/providers/traework/payload.js +86 -86
  190. package/src/providers/traework/sse.js +184 -184
  191. package/src/providers/traework/token.js +52 -52
  192. package/src/providers/traework.js +2 -2
  193. package/src/providers/workbuddy/account-store.js +186 -186
  194. package/src/providers/workbuddy/auth.js +158 -158
  195. package/src/providers/workbuddy/balance.js +86 -86
  196. package/src/providers/workbuddy/cat-travel.js +125 -125
  197. package/src/providers/workbuddy/checkin.js +75 -75
  198. package/src/providers/workbuddy/desktop-info.js +78 -78
  199. package/src/providers/workbuddy/growth-api.js +67 -67
  200. package/src/providers/workbuddy/growth-plans.js +63 -63
  201. package/src/providers/workbuddy/growth.js +181 -181
  202. package/src/providers/workbuddy/index.js +217 -217
  203. package/src/providers/workbuddy/models.js +126 -126
  204. package/src/providers/workbuddy/payload.js +141 -141
  205. package/src/providers/workbuddy/rotation-log.js +83 -83
  206. package/src/providers/workbuddy/sanitize-tools.js +61 -61
  207. package/src/providers/workbuddy/sdk-chat.js +26 -26
  208. package/src/providers/workbuddy-balance.js +78 -78
  209. package/src/providers/zcode/account-store.js +129 -129
  210. package/src/providers/zcode/auth.js +28 -28
  211. package/src/providers/zcode/chat.js +179 -179
  212. package/src/providers/zcode/const.js +54 -54
  213. package/src/providers/zcode/context-shape.js +162 -162
  214. package/src/providers/zcode/headers.js +93 -93
  215. package/src/providers/zcode/index.js +124 -124
  216. package/src/providers/zcode/models.js +65 -65
  217. package/src/providers/zcode/oauth.js +120 -120
  218. package/src/providers/zcode/quota.js +176 -176
  219. package/src/providers/zcode/sse.js +196 -196
  220. package/src/readline-compat.js +25 -25
  221. package/src/responses/translate.js +311 -311
  222. package/src/routes/chat/broadband-handler.js +72 -72
  223. package/src/routes/chat/empty-turn-report.js +31 -31
  224. package/src/routes/chat/exhausted-handler.js +87 -87
  225. package/src/routes/chat/hedge-handler.js +130 -130
  226. package/src/routes/chat/index.js +1 -1
  227. package/src/routes/chat/local-handler.js +63 -63
  228. package/src/routes/chat/peer-handler.js +81 -81
  229. package/src/routes/chat.js +3 -3
  230. package/src/routes/fallback.js +88 -88
  231. package/src/routes/groups-relay.js +214 -214
  232. package/src/routes/groups.js +122 -122
  233. package/src/routes/helpers.js +83 -83
  234. package/src/routes/index.js +147 -147
  235. package/src/routes/messages-route.js +365 -365
  236. package/src/routes/peers.js +23 -1
  237. package/src/routes/relay-queue.js +181 -181
  238. package/src/routes/relay.js +60 -60
  239. package/src/routes/responses-route.js +213 -213
  240. package/src/routes/stream-body.js +84 -84
  241. package/src/routes/stream-hold.js +337 -337
  242. package/src/routes/stream-scan.js +366 -366
  243. package/src/routes.js +3 -3
  244. package/src/runtime/auto-update.js +113 -113
  245. package/src/runtime/bootstrap.js +8 -0
  246. package/src/runtime/broadband-stream.js +79 -79
  247. package/src/runtime/broadband.js +103 -103
  248. package/src/runtime/group-sync.js +81 -81
  249. package/src/runtime/keep-warm.js +120 -0
  250. package/src/runtime/lifecycle-forensics.js +116 -116
  251. package/src/runtime/lifecycle-log.js +87 -87
  252. package/src/runtime/log-stamp.js +73 -73
  253. package/src/runtime/proc-info.js +137 -137
  254. package/src/runtime/qoder-checkin.js +93 -93
  255. package/src/runtime/raccoon-checkin.js +126 -126
  256. package/src/runtime/server-lifecycle.js +189 -189
  257. package/src/runtime/traework-checkin.js +118 -118
  258. package/src/runtime/workbuddy-checkin.js +120 -120
  259. package/src/runtime/workbuddy-growth.js +133 -133
  260. package/src/server.js +7 -0
  261. package/src/state/facade.js +58 -58
  262. package/src/state/memory.js +162 -162
  263. package/src/state/merge.js +25 -25
  264. package/src/state/migrations/cline-unify.js +94 -94
  265. package/src/state/migrations.js +33 -33
  266. package/src/state/persist.js +42 -42
  267. package/src/state/provider-config.js +142 -142
  268. package/src/state/schemas/group.js +31 -31
  269. package/src/state/schemas/model.js +94 -94
  270. package/src/state/schemas/peer.js +31 -31
  271. package/src/state/schemas/port.js +10 -10
  272. package/src/state/schemas/provider.js +202 -202
  273. package/src/state/schemas/timezone.js +70 -70
  274. package/src/state/schemas/token.js +48 -48
  275. package/src/state/schemas/use-group.js +102 -102
  276. package/src/state/store.js +176 -176
  277. package/src/state.js +1 -1
  278. package/src/sync-claude-desktop.js +234 -234
  279. package/src/sync-claude.js +152 -152
  280. package/src/sync-codex.js +116 -116
  281. package/src/sync-workbuddy.js +158 -158
  282. package/src/talk-full-redact.js +129 -129
  283. package/src/talk-full.js +131 -131
  284. package/src/talk-log.js +257 -257
  285. package/src/text-tokens.js +52 -52
  286. package/src/thinking-effort.js +67 -67
  287. package/src/time.js +106 -106
  288. package/src/timeline.js +26 -26
  289. package/src/transport/index.js +1 -1
  290. package/src/upstream-engine/index.js +74 -74
  291. package/src/upstream-engine/mode.js +15 -15
  292. package/src/upstream-engine/sdk/attempt.js +221 -221
  293. package/src/upstream-engine/sdk/chat.js +28 -28
  294. package/src/upstream-engine/sdk/convert.js +192 -192
  295. package/src/upstream-engine/sdk/diagnose.js +62 -62
  296. package/src/upstream-engine/sdk/dispatch.js +55 -55
  297. package/src/upstream-engine/sdk/responses.js +176 -176
  298. package/src/upstream-engine/sdk/sse.js +166 -166
  299. package/src/upstream-responses.js +305 -305
  300. package/src/usage/record.js +106 -106
  301. package/src/usage/report.js +195 -195
  302. package/src/v6pool/claim.js +157 -157
  303. package/src/v6pool/config.js +65 -65
  304. package/src/v6pool/detect.js +130 -130
  305. package/src/v6pool/index.js +152 -152
  306. package/src/v6pool/prefix.js +140 -140
  307. package/src/v6pool/probe.js +40 -40
  308. package/src/v6pool/report.js +104 -104
  309. package/src/v6pool/rotate.js +263 -263
  310. package/src/warp-pool/config.js +74 -74
  311. package/src/warp-pool/health.js +106 -106
  312. package/src/warp-pool/identity.js +141 -141
  313. package/src/warp-pool/index.js +358 -358
  314. package/src/warp-pool/keys.js +29 -29
  315. package/src/warp-pool/nodes.js +95 -95
  316. package/src/warp-pool/ports.js +160 -160
  317. package/src/warp-pool/register.js +113 -113
  318. package/src/warp-pool/report.js +232 -232
  319. package/src/warp-pool/revive.js +168 -168
  320. package/src/warp-pool/rotate.js +214 -214
  321. package/src/warp-pool/strategy.js +43 -43
  322. package/src/warp-pool/verdict.js +69 -69
  323. package/src/warp-pool/wireproxy.js +162 -162
  324. package/docs/cli_help_mini.md +0 -146
  325. package/src/providers/AGENTS.md +0 -49
  326. package/src/routes/AGENTS.md +0 -37
@@ -1,179 +1,179 @@
1
- // zcode 模型转发:OpenAI 请求 → Anthropic messages(网关出站恒流式;非流式本地聚合回 OpenAI JSON)。
2
- // 失败响应带 x-mslxdff-zcode-kind 标记,供 provider 工厂决定冷却策略。
3
- import { timeoutSignal } from "../../compat.js";
4
- import { effortLevelFromBody } from "../../thinking-effort.js";
5
- import { ZCODE_MESSAGES_URL, canonicalZcodeModel, zcodeErrorKind } from "./const.js";
6
- import { shapeZcodeWireRequest } from "./context-shape.js";
7
- import { buildZcodeModelHeaders } from "./headers.js";
8
- import { aggregateAnthropicToOpenAi, anthropicToOpenAiStream } from "./sse.js";
9
-
10
- const DEFAULT_MAX_TOKENS = 4096;
11
-
12
- function textOf(content) {
13
- if (typeof content === "string") return content;
14
- if (Array.isArray(content)) return content.filter((p) => p?.type === "text").map((p) => p.text || "").join("");
15
- return "";
16
- }
17
-
18
- function mapToolChoice(tc) {
19
- if (!tc) return undefined;
20
- if (tc === "auto") return { type: "auto" };
21
- if (tc === "required") return { type: "any" };
22
- if (tc === "none") return { type: "none" };
23
- const name = tc?.function?.name;
24
- return name ? { type: "tool", name: String(name) } : undefined;
25
- }
26
-
27
- export function toAnthropicRequest(body = {}) {
28
- const messages = [];
29
- let system = "";
30
- for (const m of Array.isArray(body.messages) ? body.messages : []) {
31
- const role = String(m?.role || "");
32
- if (role === "system") {
33
- const part = textOf(m.content);
34
- if (part) system += (system ? "\n\n" : "") + part;
35
- continue;
36
- }
37
- if (role === "tool") {
38
- messages.push({
39
- role: "user",
40
- content: [{ type: "tool_result", tool_use_id: String(m.tool_call_id || ""), content: typeof m.content === "string" ? m.content : textOf(m.content) }],
41
- });
42
- continue;
43
- }
44
- if (role === "assistant") {
45
- const blocks = [];
46
- const text = textOf(m.content);
47
- if (text) blocks.push({ type: "text", text });
48
- for (const tc of Array.isArray(m.tool_calls) ? m.tool_calls : []) {
49
- let input = {};
50
- try {
51
- input = JSON.parse(tc?.function?.arguments || "{}");
52
- } catch {}
53
- blocks.push({ type: "tool_use", id: String(tc?.id || ""), name: String(tc?.function?.name || ""), input });
54
- }
55
- if (blocks.length) messages.push({ role: "assistant", content: blocks });
56
- continue;
57
- }
58
- messages.push({ role: "user", content: textOf(m.content) });
59
- }
60
-
61
- const req = {
62
- model: canonicalZcodeModel(body.model),
63
- max_tokens: Number(body.max_tokens ?? body.max_completion_tokens) || DEFAULT_MAX_TOKENS,
64
- messages,
65
- stream: true, // 上游恒流式;非流式在本地聚合
66
- };
67
- if (system) req.system = system;
68
- if (Number.isFinite(Number(body.temperature))) req.temperature = Number(body.temperature);
69
- if (Array.isArray(body.tools) && body.tools.length) {
70
- req.tools = body.tools
71
- .map((t) => ({
72
- name: String(t?.function?.name || t?.name || ""),
73
- description: String(t?.function?.description || t?.description || ""),
74
- input_schema: t?.function?.parameters || t?.parameters || { type: "object", properties: {} },
75
- }))
76
- .filter((t) => t.name);
77
- }
78
- // tool_choice 独立映射(不依赖 tools 是否在场,客户端显式给定即按 Anthropic 形状透出)
79
- const choice = mapToolChoice(body.tool_choice);
80
- if (choice) req.tool_choice = choice;
81
- if (body.stop !== undefined && body.stop !== null) {
82
- req.stop_sequences = Array.isArray(body.stop) ? body.stop : [String(body.stop)];
83
- }
84
- // 思考档位透传(change fix-thinking-effort-passthrough):Anthropic 形状的 thinking 对象原样带上;
85
- // effort 有则原样、无则由 reasoning_effort 回退。上游不认就如实透出 400,不替上游静默吞掉。
86
- if (body.thinking && typeof body.thinking === "object") req.thinking = body.thinking;
87
- // 档位载体统一走共享词表(只取真档位,不含 thinking.type 开关):reasoning_effort > reasoningEffort > effort。
88
- const effort = effortLevelFromBody(body);
89
- if (effort) req.effort = effort;
90
- return req;
91
- }
92
-
93
- export function classifyZcodeFailure(status, payload) {
94
- const code = Number(payload?.code) || 0;
95
- let kind = zcodeErrorKind(code);
96
- if (kind === "unknown") {
97
- if (status === 401) kind = "auth";
98
- else if (status === 429) kind = "rate_limit";
99
- else if (status >= 500) kind = "server";
100
- }
101
- return { kind, code, status, message: String(payload?.msg || payload?.message || "").trim() };
102
- }
103
-
104
- const ERROR_MAP = {
105
- auth: { status: 401, type: "auth_error", text: (f) => `zcode: 登录已失效(code ${f.code || 1006})。请运行 mslxdff -provider zcode login 重新登录` },
106
- quota: { status: 429, type: "quota_exhausted", text: () => "zcode: 免费额度已用完(按日重置),请明日再试或添加账号" },
107
- rate_limit: { status: 429, type: "all_cooling", text: () => "zcode: 上游限流(账号冷却中),请稍后重试" },
108
- security: { status: 403, type: "security_reject", text: (f) => `zcode: 安全校验拒绝(code ${f.code || 3007})${f.message ? `:${f.message}` : ""} · v3.14.4 起模型请求已免验证码(仅 claim 通道仍需要),偶发请重试,见 docs/adr/0038` },
109
- param: { status: 400, type: "invalid_request", text: (f) => `zcode: 请求参数被上游拒绝(code ${f.code})${f.message ? `:${f.message}` : ""}` },
110
- server: { status: 502, type: "upstream_error", text: (f) => `zcode: 上游服务异常${f.code ? `(code ${f.code})` : ""}${f.message ? `:${f.message}` : ""}` },
111
- network: { status: 502, type: "upstream_error", text: (f) => `zcode: 网络错误 ${f.message || ""}`.trim() },
112
- unknown: { status: 502, type: "upstream_error", text: (f) => `zcode: 上游错误(HTTP ${f.status || "?"}${f.code ? ` code ${f.code}` : ""})${f.message ? `:${f.message}` : ""}` },
113
- };
114
-
115
- export function zcodeErrorResponse(fail = {}) {
116
- const kind = ERROR_MAP[fail.kind] ? fail.kind : "unknown";
117
- const entry = ERROR_MAP[kind];
118
- const headers = { "Content-Type": "application/json" };
119
- if (fail.kind) headers["x-mslxdff-zcode-kind"] = fail.kind;
120
- return new Response(JSON.stringify({ error: { message: entry.text(fail), type: entry.type, code: fail.code || 0 } }), {
121
- status: entry.status,
122
- headers,
123
- });
124
- }
125
-
126
- export async function forwardZcodeChat({ body, token, deviceMid, fetchImpl, version, timeoutMs = 120_000, provider = "zai" } = {}) {
127
- const anthropicBody = toAnthropicRequest(body);
128
- const modelId = anthropicBody.model; // 响应回显用 canonical id;出站另行归一
129
- // 官方线形:小写模型 + system 身份块 + currentDate 前缀(缺任一 → 上游 3012)。
130
- // deviceMid 入参保留签名兼容,但模型请求出站不带(官方 CLI 模型请求不带该头,实测)。
131
- const wireBody = shapeZcodeWireRequest(anthropicBody, { provider });
132
- const headers = { "content-type": "application/json", ...buildZcodeModelHeaders({ token, version }) };
133
- void deviceMid;
134
-
135
- let res;
136
- try {
137
- res = await fetchImpl(ZCODE_MESSAGES_URL, {
138
- method: "POST",
139
- headers,
140
- body: JSON.stringify(wireBody),
141
- signal: timeoutSignal(timeoutMs),
142
- });
143
- } catch (e) {
144
- return zcodeErrorResponse({ kind: "network", message: String(e?.message || e).slice(0, 160) });
145
- }
146
-
147
- if (!res.ok) {
148
- const payload = await res.json().catch(() => null);
149
- return zcodeErrorResponse({ ...classifyZcodeFailure(res.status, payload), model: modelId });
150
- }
151
-
152
- // 上游业务错误惯例:HTTP 200 + JSON body(code 非 0/200)→ 同样按错误分类
153
- if (!String(res.headers.get("content-type") || "").includes("text/event-stream")) {
154
- const payload = await res.json().catch(() => null);
155
- const code = Number(payload?.code);
156
- const bizOk = payload?.success !== false && (!Number.isFinite(code) || code === 0 || code === 200);
157
- if (payload && !bizOk) {
158
- return zcodeErrorResponse({ ...classifyZcodeFailure(res.status, payload), model: modelId });
159
- }
160
- if (payload && body?.stream === false) {
161
- return new Response(JSON.stringify(payload), { status: 200, headers: { "Content-Type": "application/json" } });
162
- }
163
- }
164
-
165
- if (body?.stream !== false) {
166
- const stream = anthropicToOpenAiStream(res.body, { model: modelId });
167
- return new Response(stream, {
168
- status: 200,
169
- headers: { "Content-Type": "text/event-stream; charset=utf-8", "Cache-Control": "no-cache" },
170
- });
171
- }
172
-
173
- const text = await res.text();
174
- const out = await aggregateAnthropicToOpenAi(text, { model: modelId });
175
- if (out.error) {
176
- return zcodeErrorResponse({ kind: out.error.kind || "server", code: out.error.code || 0, status: 200, message: out.error.message });
177
- }
178
- return new Response(JSON.stringify(out.openAi), { status: 200, headers: { "Content-Type": "application/json" } });
179
- }
1
+ // zcode 模型转发:OpenAI 请求 → Anthropic messages(网关出站恒流式;非流式本地聚合回 OpenAI JSON)。
2
+ // 失败响应带 x-mslxdff-zcode-kind 标记,供 provider 工厂决定冷却策略。
3
+ import { timeoutSignal } from "../../compat.js";
4
+ import { effortLevelFromBody } from "../../thinking-effort.js";
5
+ import { ZCODE_MESSAGES_URL, canonicalZcodeModel, zcodeErrorKind } from "./const.js";
6
+ import { shapeZcodeWireRequest } from "./context-shape.js";
7
+ import { buildZcodeModelHeaders } from "./headers.js";
8
+ import { aggregateAnthropicToOpenAi, anthropicToOpenAiStream } from "./sse.js";
9
+
10
+ const DEFAULT_MAX_TOKENS = 4096;
11
+
12
+ function textOf(content) {
13
+ if (typeof content === "string") return content;
14
+ if (Array.isArray(content)) return content.filter((p) => p?.type === "text").map((p) => p.text || "").join("");
15
+ return "";
16
+ }
17
+
18
+ function mapToolChoice(tc) {
19
+ if (!tc) return undefined;
20
+ if (tc === "auto") return { type: "auto" };
21
+ if (tc === "required") return { type: "any" };
22
+ if (tc === "none") return { type: "none" };
23
+ const name = tc?.function?.name;
24
+ return name ? { type: "tool", name: String(name) } : undefined;
25
+ }
26
+
27
+ export function toAnthropicRequest(body = {}) {
28
+ const messages = [];
29
+ let system = "";
30
+ for (const m of Array.isArray(body.messages) ? body.messages : []) {
31
+ const role = String(m?.role || "");
32
+ if (role === "system") {
33
+ const part = textOf(m.content);
34
+ if (part) system += (system ? "\n\n" : "") + part;
35
+ continue;
36
+ }
37
+ if (role === "tool") {
38
+ messages.push({
39
+ role: "user",
40
+ content: [{ type: "tool_result", tool_use_id: String(m.tool_call_id || ""), content: typeof m.content === "string" ? m.content : textOf(m.content) }],
41
+ });
42
+ continue;
43
+ }
44
+ if (role === "assistant") {
45
+ const blocks = [];
46
+ const text = textOf(m.content);
47
+ if (text) blocks.push({ type: "text", text });
48
+ for (const tc of Array.isArray(m.tool_calls) ? m.tool_calls : []) {
49
+ let input = {};
50
+ try {
51
+ input = JSON.parse(tc?.function?.arguments || "{}");
52
+ } catch {}
53
+ blocks.push({ type: "tool_use", id: String(tc?.id || ""), name: String(tc?.function?.name || ""), input });
54
+ }
55
+ if (blocks.length) messages.push({ role: "assistant", content: blocks });
56
+ continue;
57
+ }
58
+ messages.push({ role: "user", content: textOf(m.content) });
59
+ }
60
+
61
+ const req = {
62
+ model: canonicalZcodeModel(body.model),
63
+ max_tokens: Number(body.max_tokens ?? body.max_completion_tokens) || DEFAULT_MAX_TOKENS,
64
+ messages,
65
+ stream: true, // 上游恒流式;非流式在本地聚合
66
+ };
67
+ if (system) req.system = system;
68
+ if (Number.isFinite(Number(body.temperature))) req.temperature = Number(body.temperature);
69
+ if (Array.isArray(body.tools) && body.tools.length) {
70
+ req.tools = body.tools
71
+ .map((t) => ({
72
+ name: String(t?.function?.name || t?.name || ""),
73
+ description: String(t?.function?.description || t?.description || ""),
74
+ input_schema: t?.function?.parameters || t?.parameters || { type: "object", properties: {} },
75
+ }))
76
+ .filter((t) => t.name);
77
+ }
78
+ // tool_choice 独立映射(不依赖 tools 是否在场,客户端显式给定即按 Anthropic 形状透出)
79
+ const choice = mapToolChoice(body.tool_choice);
80
+ if (choice) req.tool_choice = choice;
81
+ if (body.stop !== undefined && body.stop !== null) {
82
+ req.stop_sequences = Array.isArray(body.stop) ? body.stop : [String(body.stop)];
83
+ }
84
+ // 思考档位透传(change fix-thinking-effort-passthrough):Anthropic 形状的 thinking 对象原样带上;
85
+ // effort 有则原样、无则由 reasoning_effort 回退。上游不认就如实透出 400,不替上游静默吞掉。
86
+ if (body.thinking && typeof body.thinking === "object") req.thinking = body.thinking;
87
+ // 档位载体统一走共享词表(只取真档位,不含 thinking.type 开关):reasoning_effort > reasoningEffort > effort。
88
+ const effort = effortLevelFromBody(body);
89
+ if (effort) req.effort = effort;
90
+ return req;
91
+ }
92
+
93
+ export function classifyZcodeFailure(status, payload) {
94
+ const code = Number(payload?.code) || 0;
95
+ let kind = zcodeErrorKind(code);
96
+ if (kind === "unknown") {
97
+ if (status === 401) kind = "auth";
98
+ else if (status === 429) kind = "rate_limit";
99
+ else if (status >= 500) kind = "server";
100
+ }
101
+ return { kind, code, status, message: String(payload?.msg || payload?.message || "").trim() };
102
+ }
103
+
104
+ const ERROR_MAP = {
105
+ auth: { status: 401, type: "auth_error", text: (f) => `zcode: 登录已失效(code ${f.code || 1006})。请运行 mslxdff -provider zcode login 重新登录` },
106
+ quota: { status: 429, type: "quota_exhausted", text: () => "zcode: 免费额度已用完(按日重置),请明日再试或添加账号" },
107
+ rate_limit: { status: 429, type: "all_cooling", text: () => "zcode: 上游限流(账号冷却中),请稍后重试" },
108
+ security: { status: 403, type: "security_reject", text: (f) => `zcode: 安全校验拒绝(code ${f.code || 3007})${f.message ? `:${f.message}` : ""} · v3.14.4 起模型请求已免验证码(仅 claim 通道仍需要),偶发请重试,见 docs/adr/0038` },
109
+ param: { status: 400, type: "invalid_request", text: (f) => `zcode: 请求参数被上游拒绝(code ${f.code})${f.message ? `:${f.message}` : ""}` },
110
+ server: { status: 502, type: "upstream_error", text: (f) => `zcode: 上游服务异常${f.code ? `(code ${f.code})` : ""}${f.message ? `:${f.message}` : ""}` },
111
+ network: { status: 502, type: "upstream_error", text: (f) => `zcode: 网络错误 ${f.message || ""}`.trim() },
112
+ unknown: { status: 502, type: "upstream_error", text: (f) => `zcode: 上游错误(HTTP ${f.status || "?"}${f.code ? ` code ${f.code}` : ""})${f.message ? `:${f.message}` : ""}` },
113
+ };
114
+
115
+ export function zcodeErrorResponse(fail = {}) {
116
+ const kind = ERROR_MAP[fail.kind] ? fail.kind : "unknown";
117
+ const entry = ERROR_MAP[kind];
118
+ const headers = { "Content-Type": "application/json" };
119
+ if (fail.kind) headers["x-mslxdff-zcode-kind"] = fail.kind;
120
+ return new Response(JSON.stringify({ error: { message: entry.text(fail), type: entry.type, code: fail.code || 0 } }), {
121
+ status: entry.status,
122
+ headers,
123
+ });
124
+ }
125
+
126
+ export async function forwardZcodeChat({ body, token, deviceMid, fetchImpl, version, timeoutMs = 120_000, provider = "zai" } = {}) {
127
+ const anthropicBody = toAnthropicRequest(body);
128
+ const modelId = anthropicBody.model; // 响应回显用 canonical id;出站另行归一
129
+ // 官方线形:小写模型 + system 身份块 + currentDate 前缀(缺任一 → 上游 3012)。
130
+ // deviceMid 入参保留签名兼容,但模型请求出站不带(官方 CLI 模型请求不带该头,实测)。
131
+ const wireBody = shapeZcodeWireRequest(anthropicBody, { provider });
132
+ const headers = { "content-type": "application/json", ...buildZcodeModelHeaders({ token, version }) };
133
+ void deviceMid;
134
+
135
+ let res;
136
+ try {
137
+ res = await fetchImpl(ZCODE_MESSAGES_URL, {
138
+ method: "POST",
139
+ headers,
140
+ body: JSON.stringify(wireBody),
141
+ signal: timeoutSignal(timeoutMs),
142
+ });
143
+ } catch (e) {
144
+ return zcodeErrorResponse({ kind: "network", message: String(e?.message || e).slice(0, 160) });
145
+ }
146
+
147
+ if (!res.ok) {
148
+ const payload = await res.json().catch(() => null);
149
+ return zcodeErrorResponse({ ...classifyZcodeFailure(res.status, payload), model: modelId });
150
+ }
151
+
152
+ // 上游业务错误惯例:HTTP 200 + JSON body(code 非 0/200)→ 同样按错误分类
153
+ if (!String(res.headers.get("content-type") || "").includes("text/event-stream")) {
154
+ const payload = await res.json().catch(() => null);
155
+ const code = Number(payload?.code);
156
+ const bizOk = payload?.success !== false && (!Number.isFinite(code) || code === 0 || code === 200);
157
+ if (payload && !bizOk) {
158
+ return zcodeErrorResponse({ ...classifyZcodeFailure(res.status, payload), model: modelId });
159
+ }
160
+ if (payload && body?.stream === false) {
161
+ return new Response(JSON.stringify(payload), { status: 200, headers: { "Content-Type": "application/json" } });
162
+ }
163
+ }
164
+
165
+ if (body?.stream !== false) {
166
+ const stream = anthropicToOpenAiStream(res.body, { model: modelId });
167
+ return new Response(stream, {
168
+ status: 200,
169
+ headers: { "Content-Type": "text/event-stream; charset=utf-8", "Cache-Control": "no-cache" },
170
+ });
171
+ }
172
+
173
+ const text = await res.text();
174
+ const out = await aggregateAnthropicToOpenAi(text, { model: modelId });
175
+ if (out.error) {
176
+ return zcodeErrorResponse({ kind: out.error.kind || "server", code: out.error.code || 0, status: 200, message: out.error.message });
177
+ }
178
+ return new Response(JSON.stringify(out.openAi), { status: 200, headers: { "Content-Type": "application/json" } });
179
+ }
@@ -1,54 +1,54 @@
1
- // zcode 供应商常量单一源:网关地址、客户端版本、业务码表、Start/Coding Plan 模型目录。
2
- // 端点契约调研自 zai-org/ZCode 源码(official-coding-plan-gateway.ts / zcodeEndpoint.ts)与 zcode-switch 实测。
3
- export const ZCODE_ORIGIN = "https://zcode.z.ai";
4
- export const ZCODE_CLI_INIT_URL = `${ZCODE_ORIGIN}/api/v1/oauth/cli/init`;
5
- export const zcodeCliPollUrl = (flowId) =>
6
- `${ZCODE_ORIGIN}/api/v1/oauth/cli/poll/${encodeURIComponent(String(flowId || ""))}`;
7
- export const ZCODE_MESSAGES_URL = `${ZCODE_ORIGIN}/api/v1/zcode-plan/anthropic/v1/messages`;
8
- export const zcodeBalanceUrl = (appVersion) =>
9
- `${ZCODE_ORIGIN}/api/v1/zcode-plan/billing/balance?app_version=${encodeURIComponent(String(appVersion || ""))}`;
10
-
11
- export const ZCODE_DEFAULT_APP_VERSION = "3.14.4";
12
- export const ZCODE_RELEASE_CHANNEL = "stable";
13
-
14
- export function zcodeAppVersion(env = process.env) {
15
- const v = typeof env?.MSLXDFF_ZCODE_APP_VERSION === "string" ? env.MSLXDFF_ZCODE_APP_VERSION.trim() : "";
16
- return v || ZCODE_DEFAULT_APP_VERSION;
17
- }
18
-
19
- // 业务码表(zcode-switch quota.rs classify + ZCode 客户端 model-execution.ts 实测):
20
- // 401/1006 鉴权失效,1005 额度耗尽(data/plan/ends_at 为下次时间),限流组,3007 安全校验拒绝。
21
- export const ZCODE_ERROR_KINDS = {
22
- 401: "auth",
23
- 1006: "auth",
24
- 1005: "quota",
25
- 3002: "rate_limit",
26
- 3008: "rate_limit",
27
- 3009: "rate_limit",
28
- 3010: "rate_limit",
29
- 3007: "security",
30
- 2007: "server",
31
- 3001: "param",
32
- 3006: "param",
33
- 3102: "param",
34
- };
35
-
36
- export function zcodeErrorKind(code) {
37
- const n = Number(code);
38
- return ZCODE_ERROR_KINDS[n] || "unknown";
39
- }
40
-
41
- // 官方 canonical id(quota.rs BUILTIN_*_MODELS);入站大小写不敏感,出站规范化为该表内的写法。
42
- export const ZCODE_CODING_PLAN_MODELS = ["GLM-5.3", "GLM-5.3-Flash"];
43
- export const ZCODE_START_PLAN_MODELS = ["GLM-5.3-Flash", "GLM-5.2", "GLM-5-Turbo"];
44
- export const ZCODE_MODEL_CATALOG = [...new Set([...ZCODE_CODING_PLAN_MODELS, ...ZCODE_START_PLAN_MODELS])];
45
-
46
- export function canonicalZcodeModel(id) {
47
- let raw = String(id || "").trim();
48
- if (raw.startsWith("zcode/")) raw = raw.slice(6);
49
- const low = raw.toLowerCase();
50
- for (const m of ZCODE_MODEL_CATALOG) {
51
- if (m.toLowerCase() === low) return m;
52
- }
53
- return raw;
54
- }
1
+ // zcode 供应商常量单一源:网关地址、客户端版本、业务码表、Start/Coding Plan 模型目录。
2
+ // 端点契约调研自 zai-org/ZCode 源码(official-coding-plan-gateway.ts / zcodeEndpoint.ts)与 zcode-switch 实测。
3
+ export const ZCODE_ORIGIN = "https://zcode.z.ai";
4
+ export const ZCODE_CLI_INIT_URL = `${ZCODE_ORIGIN}/api/v1/oauth/cli/init`;
5
+ export const zcodeCliPollUrl = (flowId) =>
6
+ `${ZCODE_ORIGIN}/api/v1/oauth/cli/poll/${encodeURIComponent(String(flowId || ""))}`;
7
+ export const ZCODE_MESSAGES_URL = `${ZCODE_ORIGIN}/api/v1/zcode-plan/anthropic/v1/messages`;
8
+ export const zcodeBalanceUrl = (appVersion) =>
9
+ `${ZCODE_ORIGIN}/api/v1/zcode-plan/billing/balance?app_version=${encodeURIComponent(String(appVersion || ""))}`;
10
+
11
+ export const ZCODE_DEFAULT_APP_VERSION = "3.14.4";
12
+ export const ZCODE_RELEASE_CHANNEL = "stable";
13
+
14
+ export function zcodeAppVersion(env = process.env) {
15
+ const v = typeof env?.MSLXDFF_ZCODE_APP_VERSION === "string" ? env.MSLXDFF_ZCODE_APP_VERSION.trim() : "";
16
+ return v || ZCODE_DEFAULT_APP_VERSION;
17
+ }
18
+
19
+ // 业务码表(zcode-switch quota.rs classify + ZCode 客户端 model-execution.ts 实测):
20
+ // 401/1006 鉴权失效,1005 额度耗尽(data/plan/ends_at 为下次时间),限流组,3007 安全校验拒绝。
21
+ export const ZCODE_ERROR_KINDS = {
22
+ 401: "auth",
23
+ 1006: "auth",
24
+ 1005: "quota",
25
+ 3002: "rate_limit",
26
+ 3008: "rate_limit",
27
+ 3009: "rate_limit",
28
+ 3010: "rate_limit",
29
+ 3007: "security",
30
+ 2007: "server",
31
+ 3001: "param",
32
+ 3006: "param",
33
+ 3102: "param",
34
+ };
35
+
36
+ export function zcodeErrorKind(code) {
37
+ const n = Number(code);
38
+ return ZCODE_ERROR_KINDS[n] || "unknown";
39
+ }
40
+
41
+ // 官方 canonical id(quota.rs BUILTIN_*_MODELS);入站大小写不敏感,出站规范化为该表内的写法。
42
+ export const ZCODE_CODING_PLAN_MODELS = ["GLM-5.3", "GLM-5.3-Flash"];
43
+ export const ZCODE_START_PLAN_MODELS = ["GLM-5.3-Flash", "GLM-5.2", "GLM-5-Turbo"];
44
+ export const ZCODE_MODEL_CATALOG = [...new Set([...ZCODE_CODING_PLAN_MODELS, ...ZCODE_START_PLAN_MODELS])];
45
+
46
+ export function canonicalZcodeModel(id) {
47
+ let raw = String(id || "").trim();
48
+ if (raw.startsWith("zcode/")) raw = raw.slice(6);
49
+ const low = raw.toLowerCase();
50
+ for (const m of ZCODE_MODEL_CATALOG) {
51
+ if (m.toLowerCase() === low) return m;
52
+ }
53
+ return raw;
54
+ }