mslxdff 0.1.231 → 0.1.233

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 (117) hide show
  1. package/bin/mslxdff.js +3 -3
  2. package/package.json +1 -1
  3. package/src/auto.js +264 -254
  4. package/src/bench/cline-bench.js +42 -42
  5. package/src/bench/probe.js +70 -70
  6. package/src/bench/report.js +162 -162
  7. package/src/bench/runner.js +77 -77
  8. package/src/bench/via-probe.js +124 -124
  9. package/src/bench/via-routes.js +87 -87
  10. package/src/bench/workbuddy-bench.js +54 -54
  11. package/src/chat/engine.js +160 -160
  12. package/src/chat/gateway.js +163 -163
  13. package/src/chat/orchestrator.js +234 -234
  14. package/src/chat/prompt.js +70 -70
  15. package/src/chat/repl.js +88 -88
  16. package/src/chat/terminal.js +135 -135
  17. package/src/chat/tools.js +306 -306
  18. package/src/chat-pipeline/index.js +155 -145
  19. package/src/chat-pipeline/policy.js +84 -84
  20. package/src/cli/commands/group.js +266 -266
  21. package/src/cli/commands/model/picks.js +50 -50
  22. package/src/cli/commands/provider/bench-via.js +247 -247
  23. package/src/cli/commands/provider/bench.js +141 -141
  24. package/src/cli/commands/provider/index.js +139 -139
  25. package/src/cli/commands/provider/models.js +149 -149
  26. package/src/cli/commands/provider/qwenwork-login.js +119 -119
  27. package/src/cli/commands/provider/raccoon-quota.js +156 -156
  28. package/src/cli/commands/sync.js +310 -310
  29. package/src/cli/status.js +279 -279
  30. package/src/daemon.js +246 -246
  31. package/src/model-capabilities/enrich.js +86 -86
  32. package/src/model-capabilities/index.js +183 -183
  33. package/src/model-capabilities/parse.js +70 -70
  34. package/src/model-trace.js +10 -2
  35. package/src/models.js +292 -225
  36. package/src/peers.js +345 -345
  37. package/src/providers/agentrouter.js +238 -238
  38. package/src/providers/base.js +164 -164
  39. package/src/providers/cline/auth.js +228 -228
  40. package/src/providers/cline/chat.js +307 -307
  41. package/src/providers/cline.js +2 -2
  42. package/src/providers/codearts/chat.js +207 -207
  43. package/src/providers/dispatcher.js +147 -147
  44. package/src/providers/globalqwenwork/cosy.js +123 -123
  45. package/src/providers/globalqwenwork/crypto.js +218 -218
  46. package/src/providers/globalqwenwork/http.js +20 -20
  47. package/src/providers/globalqwenwork/rsa.js +54 -54
  48. package/src/providers/globalqwenwork/sse.js +268 -268
  49. package/src/providers/globalqwenwork/stream.js +130 -130
  50. package/src/providers/globalqwenwork/upstream.js +122 -122
  51. package/src/providers/keyring.js +60 -60
  52. package/src/providers/qoder/account-store.js +18 -0
  53. package/src/providers/qoder/chat.js +292 -203
  54. package/src/providers/qoder/checkin.js +25 -12
  55. package/src/providers/qoder/index.js +311 -249
  56. package/src/providers/qoder/models.js +64 -2
  57. package/src/providers/qoder/oauth.js +42 -1
  58. package/src/providers/qoder/payload.js +116 -80
  59. package/src/providers/qoder/request.js +7 -2
  60. package/src/providers/qoder/session.js +26 -10
  61. package/src/providers/qoder/sse.js +233 -145
  62. package/src/providers/qoder/sticky.js +5 -2
  63. package/src/providers/qoder/wire-messages.js +242 -0
  64. package/src/providers/qwenwork/account-store.js +133 -133
  65. package/src/providers/qwenwork/constants.js +67 -67
  66. package/src/providers/qwenwork/cosy.js +120 -120
  67. package/src/providers/qwenwork/crypto.js +218 -218
  68. package/src/providers/qwenwork/http.js +20 -20
  69. package/src/providers/qwenwork/index.js +337 -337
  70. package/src/providers/qwenwork/payload.js +144 -144
  71. package/src/providers/qwenwork/rsa.js +54 -54
  72. package/src/providers/qwenwork/sse.js +268 -268
  73. package/src/providers/qwenwork/stream.js +130 -130
  74. package/src/providers/qwenwork/upstream.js +120 -120
  75. package/src/providers/qwenwork.js +1 -1
  76. package/src/providers/raccoon/chat.js +1 -1
  77. package/src/providers/raccoon/const.js +219 -202
  78. package/src/providers/raccoon/credits.js +285 -285
  79. package/src/providers/raccoon/index.js +15 -2
  80. package/src/providers/raccoon/models.js +68 -17
  81. package/src/providers/registry.js +89 -89
  82. package/src/providers/workbuddy/auth.js +16 -0
  83. package/src/providers/workbuddy/chat.js +298 -264
  84. package/src/providers/workbuddy/client-headers.js +148 -0
  85. package/src/providers/workbuddy/desktop-info.js +17 -1
  86. package/src/providers/workbuddy/models.js +8 -20
  87. package/src/providers/workbuddy/reshape.js +152 -152
  88. package/src/providers/workbuddy.js +2 -2
  89. package/src/reasoning.js +32 -32
  90. package/src/routes/chat/broadband-handler.js +80 -80
  91. package/src/routes/chat/gateway.js +46 -46
  92. package/src/routes/chat/relay-pipeline.js +282 -282
  93. package/src/routes/chat/via-route-handler.js +156 -156
  94. package/src/routes/hedge.js +260 -260
  95. package/src/routes/models-route.js +167 -167
  96. package/src/routes/peers.js +373 -373
  97. package/src/routes/stream.js +364 -347
  98. package/src/runtime/bootstrap.js +75 -75
  99. package/src/runtime/keep-warm.js +135 -135
  100. package/src/runtime/provider-gate.js +75 -75
  101. package/src/runtime/providers-setup.js +187 -187
  102. package/src/runtime/raccoon-checkin.js +175 -175
  103. package/src/server.js +85 -85
  104. package/src/state/schemas/allowlist.js +92 -92
  105. package/src/sync-opencode.js +280 -280
  106. package/src/transport/index.js +244 -244
  107. package/src/transport/pool.js +56 -56
  108. package/src/transport/retry.js +24 -24
  109. package/src/transport/sse.js +93 -93
  110. package/src/upstream-probe/display.js +52 -52
  111. package/src/upstream-probe/probe.js +49 -49
  112. package/src/upstream-probe/rotate.js +110 -110
  113. package/src/upstream-probe/start.js +45 -45
  114. package/src/upstream.js +355 -355
  115. package/docs/cli_help_mini.md +0 -148
  116. package/src/providers/AGENTS.md +0 -49
  117. package/src/routes/AGENTS.md +0 -37
@@ -1,70 +1,70 @@
1
- // models.dev 能力目录 → mslxdff 能力形状的纯函数解析层(无 IO,测试接缝 S1)
2
- // 源数据形态(实测 models.opencode.ai/api.json 2026-09-11):
3
- // reasoning_options: [{type:"effort",values:["low","medium","high","max"]} | {type:"toggle"} | {type:"budget_tokens",min}]
4
- // modalities.input 含 "image" 即可读图;limit.context/output;cost.input/output 为 $/M tokens
5
- export function normalizeModelCaps(_id, m) {
6
- const opts = Array.isArray(m?.reasoning_options) ? m.reasoning_options : [];
7
- const effort = opts.find((o) => o?.type === "effort");
8
- const toggle = opts.some((o) => o?.type === "toggle");
9
- const budget = opts.find((o) => o?.type === "budget_tokens");
10
- const input = Array.isArray(m?.modalities?.input) ? m.modalities.input : [];
11
- return {
12
- reasoning: Boolean(m?.reasoning),
13
- effortType: effort ? "effort" : toggle ? "toggle" : budget ? "budget_tokens" : null,
14
- effortValues: effort && Array.isArray(effort.values) ? effort.values.map(String) : null,
15
- imageInput: input.includes("image"),
16
- toolCall: Boolean(m?.tool_call),
17
- context: Number(m?.limit?.context) || null,
18
- maxOutput: Number(m?.limit?.output) || null,
19
- costIn: Number(m?.cost?.input) || null,
20
- costOut: Number(m?.cost?.output) || null,
21
- // opencode Model 形状补充字段(-setto opencode 条目注入用)
22
- attachment: Boolean(m?.attachment),
23
- temperature: Boolean(m?.temperature),
24
- releaseDate: typeof m?.release_date === "string" && m.release_date ? m.release_date : null,
25
- inputModalities: input.length ? input : ["text"],
26
- outputModalities: Array.isArray(m?.modalities?.output) && m.modalities.output.length ? m.modalities.output : ["text"],
27
- // 模型级 SDK 覆盖(models.dev provider.npm):@ai-sdk/openai → responses 端点;null = 继承 provider 默认
28
- npm: typeof m?.provider?.npm === "string" && m.provider.npm ? m.provider.npm : null,
29
- };
30
- }
31
-
32
- // provider.models 对象({ [modelId]: rawModel })→ { [modelId]: caps }
33
- export function normalizeProviderModels(modelsObj) {
34
- const out = {};
35
- if (!modelsObj || typeof modelsObj !== "object") return out;
36
- for (const [id, m] of Object.entries(modelsObj)) {
37
- if (!m || typeof m !== "object") continue;
38
- out[id] = normalizeModelCaps(id, m);
39
- }
40
- return out;
41
- }
42
-
43
- // workbuddy 上游原生字段(/v3/config 产品文档,first-party 最准)→ 统一 caps 形状
44
- // 实测字段(2026-09-11,29 模型全覆盖):maxInputTokens/maxOutputTokens/supportsImages/
45
- // supportsReasoning/reasoning{effort,summary}/supportsToolCall/disabledMultimodal/credits/tags/name/vendor
46
- // reasoning 是"当前档位"非档位列表 → effortType=effort 但 effortValues=null、defaultEffort 记默认档
47
- export function normalizeWorkbuddyCaps(_id, m) {
48
- const imageOk = Boolean(m?.supportsImages) && !m?.disabledMultimodal;
49
- const reasoning = Boolean(m?.supportsReasoning);
50
- const effort = reasoning && m?.reasoning && typeof m.reasoning === "object" ? String(m.reasoning.effort || "").trim() : "";
51
- return {
52
- reasoning,
53
- effortType: reasoning ? "effort" : null,
54
- // 上游只给当前档位不给档位列表;实测 hy3 reasoning_effort low/high 均生效(思考块 99 vs 210),
55
- // 网关层按 OpenAI 兼容标准给通用三档(上游不识别时忽略,无害)
56
- effortValues: reasoning ? ["low", "medium", "high"] : null,
57
- defaultEffort: effort || null,
58
- imageInput: imageOk,
59
- toolCall: Boolean(m?.supportsToolCall),
60
- context: Number(m?.maxInputTokens) || null,
61
- maxOutput: Number(m?.maxOutputTokens) || null,
62
- costIn: null,
63
- costOut: null,
64
- attachment: false,
65
- temperature: m?.temperature != null,
66
- releaseDate: null,
67
- inputModalities: imageOk ? ["text", "image"] : ["text"],
68
- outputModalities: ["text"],
69
- };
70
- }
1
+ // models.dev 能力目录 → mslxdff 能力形状的纯函数解析层(无 IO,测试接缝 S1)
2
+ // 源数据形态(实测 models.opencode.ai/api.json 2026-09-11):
3
+ // reasoning_options: [{type:"effort",values:["low","medium","high","max"]} | {type:"toggle"} | {type:"budget_tokens",min}]
4
+ // modalities.input 含 "image" 即可读图;limit.context/output;cost.input/output 为 $/M tokens
5
+ export function normalizeModelCaps(_id, m) {
6
+ const opts = Array.isArray(m?.reasoning_options) ? m.reasoning_options : [];
7
+ const effort = opts.find((o) => o?.type === "effort");
8
+ const toggle = opts.some((o) => o?.type === "toggle");
9
+ const budget = opts.find((o) => o?.type === "budget_tokens");
10
+ const input = Array.isArray(m?.modalities?.input) ? m.modalities.input : [];
11
+ return {
12
+ reasoning: Boolean(m?.reasoning),
13
+ effortType: effort ? "effort" : toggle ? "toggle" : budget ? "budget_tokens" : null,
14
+ effortValues: effort && Array.isArray(effort.values) ? effort.values.map(String) : null,
15
+ imageInput: input.includes("image"),
16
+ toolCall: Boolean(m?.tool_call),
17
+ context: Number(m?.limit?.context) || null,
18
+ maxOutput: Number(m?.limit?.output) || null,
19
+ costIn: Number(m?.cost?.input) || null,
20
+ costOut: Number(m?.cost?.output) || null,
21
+ // opencode Model 形状补充字段(-setto opencode 条目注入用)
22
+ attachment: Boolean(m?.attachment),
23
+ temperature: Boolean(m?.temperature),
24
+ releaseDate: typeof m?.release_date === "string" && m.release_date ? m.release_date : null,
25
+ inputModalities: input.length ? input : ["text"],
26
+ outputModalities: Array.isArray(m?.modalities?.output) && m.modalities.output.length ? m.modalities.output : ["text"],
27
+ // 模型级 SDK 覆盖(models.dev provider.npm):@ai-sdk/openai → responses 端点;null = 继承 provider 默认
28
+ npm: typeof m?.provider?.npm === "string" && m.provider.npm ? m.provider.npm : null,
29
+ };
30
+ }
31
+
32
+ // provider.models 对象({ [modelId]: rawModel })→ { [modelId]: caps }
33
+ export function normalizeProviderModels(modelsObj) {
34
+ const out = {};
35
+ if (!modelsObj || typeof modelsObj !== "object") return out;
36
+ for (const [id, m] of Object.entries(modelsObj)) {
37
+ if (!m || typeof m !== "object") continue;
38
+ out[id] = normalizeModelCaps(id, m);
39
+ }
40
+ return out;
41
+ }
42
+
43
+ // workbuddy 上游原生字段(/v3/config 产品文档,first-party 最准)→ 统一 caps 形状
44
+ // 实测字段(2026-09-11,29 模型全覆盖):maxInputTokens/maxOutputTokens/supportsImages/
45
+ // supportsReasoning/reasoning{effort,summary}/supportsToolCall/disabledMultimodal/credits/tags/name/vendor
46
+ // reasoning 是"当前档位"非档位列表 → effortType=effort 但 effortValues=null、defaultEffort 记默认档
47
+ export function normalizeWorkbuddyCaps(_id, m) {
48
+ const imageOk = Boolean(m?.supportsImages) && !m?.disabledMultimodal;
49
+ const reasoning = Boolean(m?.supportsReasoning);
50
+ const effort = reasoning && m?.reasoning && typeof m.reasoning === "object" ? String(m.reasoning.effort || "").trim() : "";
51
+ return {
52
+ reasoning,
53
+ effortType: reasoning ? "effort" : null,
54
+ // 上游只给当前档位不给档位列表;实测 hy3 reasoning_effort low/high 均生效(思考块 99 vs 210),
55
+ // 网关层按 OpenAI 兼容标准给通用三档(上游不识别时忽略,无害)
56
+ effortValues: reasoning ? ["low", "medium", "high"] : null,
57
+ defaultEffort: effort || null,
58
+ imageInput: imageOk,
59
+ toolCall: Boolean(m?.supportsToolCall),
60
+ context: Number(m?.maxInputTokens) || null,
61
+ maxOutput: Number(m?.maxOutputTokens) || null,
62
+ costIn: null,
63
+ costOut: null,
64
+ attachment: false,
65
+ temperature: m?.temperature != null,
66
+ releaseDate: null,
67
+ inputModalities: imageOk ? ["text", "image"] : ["text"],
68
+ outputModalities: ["text"],
69
+ };
70
+ }
@@ -84,6 +84,8 @@ const DECISION_FIELDS = [
84
84
  "latencyMs", "ttfMs", "hedged", "hops", "hasShare", "elapsedMs", "threshold",
85
85
  "stallHits", "maxGapMs", "interrupted", "providers", "via",
86
86
  "retry", "step", "max", "delayMs", "upstream", "account", "pick", "cooled", "queued", "nudged", "retries", "waitedMs", "raiseFrom", "raiseTo",
87
+ // qoder 判决定点日志(2026-10-22):login/额度/排队判决各走各的路径,没有这三项,403 盲飞无从分辨
88
+ "login", "nocapacity", "retryAfter",
87
89
  "heldOpen", "terminalForm", "requestWaitedMs", "budgetMs", "budgetOut",
88
90
  // 终局判决(ADR-0058):取证时第一眼要看的三件——判的哪种、命中哪条判据、是否因此没问组员
89
91
  "kind", "marker", "peersSkipped",
@@ -103,8 +105,10 @@ function decisionKv(data = {}) {
103
105
  return out.join(" ");
104
106
  }
105
107
 
106
- // provider 回显头 → 日志字段(谁上的 / 打哪个站 / 为什么选它 / 是否被冷却 / 是否被判排队):
108
+ // provider 回显头 → 日志字段(谁上的 / 打哪个站 / 为什么选它 / 是否被冷却 / 是否被判排队 / 判决命中哪种):
107
109
  // 单一来源,防各处重复写法漂移;取不到时返回空对象(其它供应商零变化)。
110
+ // login/nocapacity/retryAfter(2026-10-22 补):qoder 判决链曾全程盲飞——403 直出日志里只有状态码,
111
+ // 看不出内部是 login 误伤、queue 漏检还是根本没命中,三轮排查全靠猜(用户实证批评:没多打日志)。
108
112
  export function upstreamEcho(res) {
109
113
  const h = res?.headers;
110
114
  if (typeof h?.get !== "function") return {};
@@ -115,6 +119,10 @@ export function upstreamEcho(res) {
115
119
  pick: pick("x-mslxdff-qoder-account"),
116
120
  cooled: pick("x-mslxdff-qoder-cooldown"),
117
121
  queued: pick("x-mslxdff-qoder-queued"),
122
+ login: pick("x-mslxdff-qoder-login"),
123
+ nocapacity: pick("x-mslxdff-qoder-nocapacity"),
124
+ verdict: pick("x-mslxdff-qoder-verdict"),
125
+ qoderRetry: pick("x-mslxdff-qoder-retry-after"),
118
126
  };
119
127
  }
120
128
 
@@ -128,7 +136,7 @@ export function formatModelTrace({ type, reqId, model, data = {}, request = null
128
136
  else if (type === "alias") detail = `rawModel=${data.rawModel || "-"} requested=${data.requested || model || "-"}`;
129
137
  else if (type === "exhausted-local" || type === "exhausted-all") detail = `last=${data.lastModel || model || "-"} status=${data.lastStatus ?? "-"} order=${(data.order || []).join(" | ")}`;
130
138
  else if (type === "upstream-try") detail = `target=${data.model || model || "-"} attempt=${data.attempt ?? "-"} payload=${kv(data.payload || {})}`;
131
- else if (type === "upstream-done" || type === "upstream-error") detail = `upstream status=${data.status ?? "-"} timing=${data.timing?.totalMs ?? "-"}ms${data.upstream ? ` via=${data.upstream}` : ""}${data.account ? ` account=${data.account}` : ""}${data.pick ? ` pick=${data.pick}` : ""}${data.cooled ? ` cooled=${data.cooled}` : ""}${data.queued ? ` queued=1` : ""} ${safeText(data.message || data.error || "")}`;
139
+ else if (type === "upstream-done" || type === "upstream-error") detail = `upstream status=${data.status ?? "-"} timing=${data.timing?.totalMs ?? "-"}ms${data.upstream ? ` via=${data.upstream}` : ""}${data.account ? ` account=${data.account}` : ""}${data.pick ? ` pick=${data.pick}` : ""}${data.cooled ? ` cooled=${data.cooled}` : ""}${data.queued ? ` queued=1` : ""}${data.login ? ` login=1` : ""}${data.nocapacity ? ` nocapacity=1` : ""}${data.verdict ? ` verdict=${data.verdict}` : ""}${data.qoderRetry ? ` retry=${data.qoderRetry}s` : ""} ${safeText(data.message || data.error || "")}`;
132
140
  else if (type === "empty-turn-retry") detail = `空转重试:retry ${data.retry ?? "-"}/${data.max ?? "-"}${data.step != null ? ` step=${data.step}` : ""} delay=${data.delayMs ?? "-"}ms${data.waitedMs ? ` waited=${data.waitedMs}ms` : ""}${data.requestWaitedMs != null ? ` 请求级累计=${data.requestWaitedMs}ms/预算${data.budgetMs ?? "-"}ms` : ""}${data.raiseTo ? ` max_tokens ${data.raiseFrom}→${data.raiseTo}` : ""}${data.upstream ? ` after=${data.upstream}` : ""}${data.account ? ` account=${data.account}` : ""}${data.pick ? ` pick=${data.pick}` : ""}${data.nudged ? ` nudged=1` : ""} reason=empty turn${data.reason ? ` :: ${safeText(data.reason, 120)}` : ""}`;
133
141
  else if (type === "empty-turn-recovered") detail = `空转重试成功:第 ${data.retries ?? "-"}/${data.max ?? "-"} 次重拉拿到真实输出,本轮共白等 ${data.waitedMs ?? "-"}ms${data.upstream ? ` via=${data.upstream}` : ""}${data.account ? ` account=${data.account}` : ""}${data.pick ? ` pick=${data.pick}` : ""}`;
134
142
  else if (type === "empty-turn-exhausted") detail = `空转重试已用尽:重试 ${data.retries ?? 0}/${data.max ?? "-"} 次仍零输出(累计等待 ${data.waitedMs ?? 0}ms${data.budgetOut ? `,请求级等待预算 ${data.budgetMs ?? "-"}ms 用尽` : ""}),交回换候选${data.heldOpen ? "(响应仍开着,换过去的正文还能送达)" : "(响应已封口,重拉只为省额度)"}${data.upstream ? ` after=${data.upstream}` : ""}${data.account ? ` account=${data.account}` : ""}${data.pick ? ` pick=${data.pick}` : ""}${data.reason ? ` :: ${safeText(data.reason, 120)}` : ""}`;