mslxdff 0.1.155 → 0.1.158

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 (151) hide show
  1. package/bin/mslxdff.js +4 -4
  2. package/docs/ARCHITECTURE.md +426 -0
  3. package/docs/FEATURE_TREE.md +164 -0
  4. package/docs/MOBILE.md +82 -0
  5. package/docs/adr/0001-reasoning-content-injection.md +14 -0
  6. package/docs/adr/0002-models-free-filter.md +12 -0
  7. package/docs/adr/0003-zero-state-no-auth.md +10 -0
  8. package/docs/adr/0004-bearer-token.md +18 -0
  9. package/docs/adr/0005-peer-mesh.md +53 -0
  10. package/docs/adr/0006-broadband-member.md +103 -0
  11. package/docs/adr/0007-multi-provider-prefix.md +25 -0
  12. package/docs/adr/0008-share-keys-to-peers.md +52 -0
  13. package/docs/adr/0009-chat-repl.md +37 -0
  14. package/docs/adr/0010-allowlist.md +36 -0
  15. package/docs/adr/0011-broadband-stream.md +30 -0
  16. package/docs/adr/0012-responses-endpoint-codex-sync.md +48 -0
  17. package/docs/adr/0013-node16-compat.md +41 -0
  18. package/docs/adr/0014-deepseek-provider.md +52 -0
  19. package/docs/adr/0015-upstream-probe-routing.md +50 -0
  20. package/docs/adr/0016-model-capabilities.md +27 -0
  21. package/docs/adr/0017-ai-sdk-upstream-engine.md +59 -0
  22. package/docs/adr/0018-zen-client-identity.md +52 -0
  23. package/docs/adr/0019-share-keys-always-lend.md +59 -0
  24. package/docs/adr/0020-zen-free-lane-agent-shape.md +52 -0
  25. package/docs/adr/0021-usage-report-jsonl.md +47 -0
  26. package/docs/adr/0022-models-capability-merge.md +61 -0
  27. package/docs/adr/0023-key-provider-default-direct.md +58 -0
  28. package/docs/adr/0024-node18-baseline.md +63 -0
  29. package/docs/adr/0025-workbuddy-authdir-follows-state.md +71 -0
  30. package/docs/adr/0026-cline-provider-id-unify.md +67 -0
  31. package/docs/adr/0027-codearts-provider.md +48 -0
  32. package/docs/adr/0028-traework-provider.md +34 -0
  33. package/docs/adr/0029-qoder-native-provider.md +60 -0
  34. package/docs/adr/0030-models-list-scoped-by-picks.md +53 -0
  35. package/docs/adr/0031-qoder-true-streaming.md +50 -0
  36. package/docs/adr/0032-generic-responses-channel.md +72 -0
  37. package/docs/adr/0033-cline-allowlist-auto-sync.md +75 -0
  38. package/docs/adr/0034-request-level-human-readable-observability.md +60 -0
  39. package/docs/adr/0035-sdk-channel-headers-timeout.md +49 -0
  40. package/docs/adr/0036-qoder-per-request-sticky-account.md +82 -0
  41. package/docs/adr/0037-qwenwork-independent-provider.md +82 -0
  42. package/docs/adr/0038-zcode-provider.md +140 -0
  43. package/docs/agents/domain.md +51 -0
  44. package/docs/agents/issue-tracker.md +30 -0
  45. package/docs/agents/triage-labels.md +15 -0
  46. package/docs/cli_help.md +1391 -0
  47. package/docs/cli_help_mini.md +133 -0
  48. package/docs/plans/bench-via-latency-2026-09-01.md +215 -0
  49. package/docs/plugins.md +187 -0
  50. package/package.json +1 -1
  51. package/src/auto.js +254 -254
  52. package/src/bench/cline-bench.js +42 -42
  53. package/src/bench/probe.js +70 -70
  54. package/src/bench/report.js +162 -162
  55. package/src/bench/runner.js +77 -77
  56. package/src/bench/via-probe.js +124 -124
  57. package/src/bench/via-routes.js +87 -87
  58. package/src/bench/workbuddy-bench.js +54 -54
  59. package/src/chat/engine.js +160 -160
  60. package/src/chat/gateway.js +163 -163
  61. package/src/chat/orchestrator.js +234 -234
  62. package/src/chat/prompt.js +70 -70
  63. package/src/chat/repl.js +88 -88
  64. package/src/chat/terminal.js +135 -135
  65. package/src/chat/tools.js +306 -306
  66. package/src/chat-pipeline/index.js +123 -123
  67. package/src/chat-pipeline/policy.js +76 -76
  68. package/src/chat-pipeline/serial-trial.js +210 -210
  69. package/src/cli/commands/group.js +249 -249
  70. package/src/cli/commands/model/list-providers.js +4 -3
  71. package/src/cli/commands/model/list-render.js +7 -9
  72. package/src/cli/commands/model/list-sort.js +52 -0
  73. package/src/cli/commands/model/list-tty.js +76 -0
  74. package/src/cli/commands/model/list.js +5 -62
  75. package/src/cli/commands/model/picks.js +50 -50
  76. package/src/cli/commands/provider/bench-via.js +247 -247
  77. package/src/cli/commands/provider/bench.js +141 -141
  78. package/src/cli/commands/provider/index.js +124 -116
  79. package/src/cli/commands/provider/models.js +139 -128
  80. package/src/cli/commands/provider/qwenwork-login.js +119 -0
  81. package/src/cli/commands/provider/zcode-login.js +77 -0
  82. package/src/cli/commands/provider/zcode-quota.js +55 -0
  83. package/src/cli/commands/sync.js +232 -232
  84. package/src/cli/provider-row.js +2 -2
  85. package/src/cli/status.js +279 -279
  86. package/src/daemon.js +96 -96
  87. package/src/model-capabilities/enrich.js +86 -86
  88. package/src/model-capabilities/index.js +183 -183
  89. package/src/model-capabilities/parse.js +70 -70
  90. package/src/model-trace.js +1 -0
  91. package/src/models.js +225 -225
  92. package/src/providers/classify.js +1 -1
  93. package/src/providers/cline/auth.js +228 -228
  94. package/src/providers/cline/chat.js +307 -307
  95. package/src/providers/cline.js +2 -2
  96. package/src/providers/keyring.js +60 -56
  97. package/src/providers/qoder/chat.js +183 -100
  98. package/src/providers/qoder/index.js +230 -184
  99. package/src/providers/qoder/sse.js +103 -46
  100. package/src/providers/qoder/sticky.js +1 -0
  101. package/src/providers/qoder/stream.js +32 -9
  102. package/src/providers/qwenwork/account-store.js +133 -0
  103. package/src/providers/qwenwork/constants.js +67 -0
  104. package/src/providers/qwenwork/cosy.js +120 -0
  105. package/src/providers/qwenwork/crypto.js +218 -0
  106. package/src/providers/qwenwork/http.js +20 -0
  107. package/src/providers/qwenwork/index.js +327 -0
  108. package/src/providers/qwenwork/payload.js +142 -0
  109. package/src/providers/qwenwork/rsa.js +54 -0
  110. package/src/providers/qwenwork/sse.js +268 -0
  111. package/src/providers/qwenwork/stream.js +130 -0
  112. package/src/providers/qwenwork/upstream.js +120 -0
  113. package/src/providers/qwenwork.js +1 -0
  114. package/src/providers/registry.js +66 -56
  115. package/src/providers/share-keys.js +2 -2
  116. package/src/providers/workbuddy/chat.js +248 -248
  117. package/src/providers/workbuddy/reshape.js +152 -152
  118. package/src/providers/workbuddy.js +2 -2
  119. package/src/providers/zcode/account-store.js +129 -0
  120. package/src/providers/zcode/auth.js +28 -0
  121. package/src/providers/zcode/chat.js +171 -0
  122. package/src/providers/zcode/const.js +54 -0
  123. package/src/providers/zcode/headers.js +55 -0
  124. package/src/providers/zcode/index.js +124 -0
  125. package/src/providers/zcode/models.js +65 -0
  126. package/src/providers/zcode/oauth.js +120 -0
  127. package/src/providers/zcode/quota.js +176 -0
  128. package/src/providers/zcode/sse.js +179 -0
  129. package/src/reasoning.js +32 -32
  130. package/src/routes/chat/gateway.js +46 -46
  131. package/src/routes/chat/relay-pipeline.js +250 -246
  132. package/src/routes/chat/via-route-handler.js +144 -144
  133. package/src/routes/hedge.js +255 -255
  134. package/src/routes/models-route.js +167 -167
  135. package/src/routes/peers.js +273 -273
  136. package/src/routes/stream.js +438 -399
  137. package/src/runtime/bootstrap.js +45 -45
  138. package/src/runtime/provider-gate.js +33 -30
  139. package/src/runtime/providers-setup.js +165 -165
  140. package/src/server.js +64 -64
  141. package/src/state/schemas/allowlist.js +92 -92
  142. package/src/sync-opencode.js +280 -280
  143. package/src/transport/index.js +244 -244
  144. package/src/transport/pool.js +56 -56
  145. package/src/transport/retry.js +24 -24
  146. package/src/transport/sse.js +93 -93
  147. package/src/upstream-probe/display.js +52 -52
  148. package/src/upstream-probe/probe.js +49 -49
  149. package/src/upstream-probe/rotate.js +110 -110
  150. package/src/upstream-probe/start.js +45 -45
  151. package/src/upstream.js +289 -289
@@ -0,0 +1,76 @@
1
+ // 交互式 `-models`(TTY 多选)主流程:从 list.js 拆出以守住 ≤10KB 体积门。
2
+ // 候选合并(allowlist + live + picks 孤儿)→ 展示排序 → 勾选落盘。
3
+ // Note: 排序规则单一来源在 list-sort.js;候选集合语义不变(只改展示顺序)。
4
+ import { loadModelErrors, loadModelPicks, saveModelPicks } from "../../../state.js";
5
+ import { getPreferredModel } from "../../../auto.js";
6
+ import { pickInteractiveMulti } from "../../interactive.js";
7
+ import { filterStalePicks } from "../../../providers/model-id.js";
8
+ import { mergeLiveIds } from "./list-live.js";
9
+ import { sortModelIds } from "./list-sort.js";
10
+
11
+ /**
12
+ * 拼交互候选:opencode live ids + 已启用 provider 的 allowlist + live 补齐 + 可见 picks。
13
+ * 返回 { items, pickedIds };items 已按 sortModelIds 排序。
14
+ */
15
+ export async function buildPickerItems(liveIds, pickedIds) {
16
+ const statuses = loadModelErrors();
17
+ const current = getPreferredModel();
18
+ const combinedIds = [...liveIds];
19
+ const seen = new Set(combinedIds);
20
+ let staleFilter = null;
21
+ try {
22
+ const { loadProviderConfigs, loadProviderAllowedModels } = await import("../../../state.js");
23
+ const { buildProviderRows } = await import("../../provider-row.js");
24
+ // 已知 = 已启用(与 -provider list 同一 enabled 口径:有 baseUrl 且有 key;
25
+ // openrouter 有 key 即算,opencode 内置恒启用)。未启用 provider 的 picks
26
+ // 不进列表,启用后自动回来(数据未动)。
27
+ const knownProviders = buildProviderRows({}).filter((r) => r.enabled).map((r) => r.id);
28
+ loadProviderConfigs();
29
+ const allowedIds = [];
30
+ for (const pid of knownProviders.filter((k) => String(k).toLowerCase() !== "opencode")) {
31
+ for (const raw of loadProviderAllowedModels(pid)) {
32
+ const canonical = `${pid}/${raw}`;
33
+ allowedIds.push(canonical);
34
+ if (!seen.has(canonical)) {
35
+ seen.add(canonical);
36
+ combinedIds.push(canonical);
37
+ }
38
+ }
39
+ }
40
+ await mergeLiveIds({ combinedIds, seen, knownProviders, liveIds });
41
+ staleFilter = { knownProviders, liveIds, allowedIds };
42
+ } catch {}
43
+ // provider 已不存在的 picks 孤儿不进交互列表(数据不动,status --all 仍可审计)。
44
+ // configs 读失败时 staleFilter 为空 → 不过滤(默认放行)。
45
+ const visiblePicks = staleFilter ? filterStalePicks(pickedIds, staleFilter) : pickedIds;
46
+ for (const pid of visiblePicks) {
47
+ if (!seen.has(pid)) {
48
+ seen.add(pid);
49
+ combinedIds.push(pid);
50
+ }
51
+ }
52
+ // 展示排序:opencode free 最前 → opencode 其他 → 各供应商分组,组内字母序。
53
+ const items = sortModelIds(combinedIds).map((id) => {
54
+ const e = statuses[id];
55
+ return {
56
+ id,
57
+ status: typeof e === "number" ? "error" : e?.status || "normal",
58
+ current: id === current,
59
+ picked: pickedIds.includes(id),
60
+ };
61
+ });
62
+ return { items, pickedIds };
63
+ }
64
+
65
+ /** 跑一轮 TTY 勾选并落盘 picks(取消则不写)。调用方负责 exit。 */
66
+ export async function runInteractivePick(liveIds) {
67
+ const pickedIds = loadModelPicks();
68
+ const { items } = await buildPickerItems(liveIds, pickedIds);
69
+ const result = await pickInteractiveMulti(items, new Set(pickedIds), Math.max(0, items.findIndex((x) => x.current)));
70
+ if (!result) {
71
+ console.log("cancelled — picks unchanged");
72
+ return;
73
+ }
74
+ saveModelPicks([...result]);
75
+ console.log(`saved ${result.size} picked model(s): ${[...result].join(", ") || "(none — auto uses full list)"}`);
76
+ }
@@ -2,16 +2,12 @@ import { join } from "node:path";
2
2
  import { createModelsService } from "../../../models.js";
3
3
  import { createUpstreamClient } from "../../../upstream.js";
4
4
  import { logDir } from "../../../logs.js";
5
- import { loadModelErrors, loadModelPicks, saveModelPicks } from "../../../state.js";
6
- import { getPreferredModel } from "../../../auto.js";
5
+ import { loadModelPicks } from "../../../state.js";
7
6
  import { fmtShanghaiYMDHM } from "../../../time.js";
8
7
  import { readModelsCache } from "../../util.js";
9
- import { pickInteractiveMulti } from "../../interactive.js";
10
8
  import { buildAliasMap, readFullAliases, renderProviderList, renderFreeList, groupByProvider } from "./list-render.js";
11
9
  import { renderOtherProviders } from "./list-providers.js";
12
- import { filterStalePicks } from "../../../providers/model-id.js";
13
- import { mergeLiveIds } from "./list-live.js";
14
-
10
+ import { compareModelIds } from "./list-sort.js";
15
11
  /**
16
12
  * `-model list` 全流程:参数解析 → 刷新/回退 → provider 分支 → TTY 交互 → 分组渲染。
17
13
  * 渲染下沉 list-render / list-providers,本文件只留流程编排。
@@ -104,8 +100,7 @@ export async function handleModelList(args, idx, sub) {
104
100
  const at2 = cachedAt ? ` (cached ${fmtShanghaiYMDHM(cachedAt)})` : "";
105
101
  console.log(`${allowed.length} model(s) for ${prov}${at2} (allowlist,原名 + 别名):`);
106
102
  const pickedIds2 = loadModelPicks();
107
- for (const raw of allowed) {
108
- const canonical = `${prov}/${raw}`;
103
+ for (const canonical of allowed.map((raw) => `${prov}/${raw}`).sort(compareModelIds)) {
109
104
  let alias = null;
110
105
  try { alias = getAliasForModel(canonical); } catch {}
111
106
  if (!alias && String(canonical).includes("/")) alias = String(canonical).replace(/\//g, "-");
@@ -134,60 +129,8 @@ export async function handleModelList(args, idx, sub) {
134
129
  process.exit(0);
135
130
  }
136
131
  if (sub === undefined && process.stdin.isTTY && process.stdout.isTTY) {
137
- const statuses = loadModelErrors();
138
- const current = getPreferredModel();
139
- const pickedIds = loadModelPicks();
140
- const combinedIds = [...ids];
141
- const seen = new Set(combinedIds);
142
- let staleFilter = null;
143
- try {
144
- const { loadProviderConfigs, loadProviderAllowedModels } = await import("../../../state.js");
145
- const { buildProviderRows } = await import("../../provider-row.js");
146
- // 已知 = 已启用(与 -provider list 同一 enabled 口径:有 baseUrl 且有 key;
147
- // openrouter 有 key 即算,opencode 内置恒启用)。未启用 provider 的 picks
148
- // 不进列表,启用后自动回来(数据未动)。
149
- const knownProviders = buildProviderRows({}).filter((r) => r.enabled).map((r) => r.id);
150
- const configs = loadProviderConfigs();
151
- const allowedIds = [];
152
- for (const pid of knownProviders.filter((k) => String(k).toLowerCase() !== "opencode")) {
153
- const allowed = loadProviderAllowedModels(pid);
154
- for (const raw of allowed) {
155
- const canonical = `${pid}/${raw}`;
156
- allowedIds.push(canonical);
157
- if (!seen.has(canonical)) {
158
- seen.add(canonical);
159
- combinedIds.push(canonical);
160
- }
161
- }
162
- }
163
- await mergeLiveIds({ combinedIds, seen, knownProviders, liveIds: ids });
164
- staleFilter = { knownProviders, liveIds: ids, allowedIds };
165
- } catch {}
166
- // provider 已不存在的 picks 孤儿不进交互列表(数据不动,status --all 仍可审计)。
167
- // configs 读失败时 staleFilter 为空 → 不过滤(默认放行)。
168
- const visiblePicks = staleFilter ? filterStalePicks(pickedIds, staleFilter) : pickedIds;
169
- for (const pid of visiblePicks) {
170
- if (!seen.has(pid)) {
171
- seen.add(pid);
172
- combinedIds.push(pid);
173
- }
174
- }
175
- const items = combinedIds.map((id) => {
176
- const e = statuses[id];
177
- return {
178
- id,
179
- status: typeof e === "number" ? "error" : e?.status || "normal",
180
- current: id === current,
181
- picked: pickedIds.includes(id),
182
- };
183
- });
184
- const result = await pickInteractiveMulti(items, new Set(pickedIds), Math.max(0, items.findIndex((x) => x.current)));
185
- if (!result) {
186
- console.log("cancelled — picks unchanged");
187
- process.exit(0);
188
- }
189
- saveModelPicks([...result]);
190
- console.log(`saved ${result.size} picked model(s): ${[...result].join(", ") || "(none — auto uses full list)"}`);
132
+ const { runInteractivePick } = await import("./list-tty.js");
133
+ await runInteractivePick(ids);
191
134
  process.exit(0);
192
135
  }
193
136
  const at = cachedAt ? ` (cached ${fmtShanghaiYMDHM(cachedAt)})` : "";
@@ -1,50 +1,50 @@
1
- import { savePreferredModel, loadModelPicks, saveModelPicks } from "../../../state.js";
2
-
3
- /**
4
- * 勾选集分支:set / pick / unpick / picks / pick clear。
5
- * 命中返回 true(分支内 process.exit,不会实际返回);未命中返回 false。
6
- */
7
- export async function handlePicksCommand(args, idx, sub) {
8
- if (sub === "set" && args[idx + 2]) {
9
- const id = args[idx + 2];
10
- savePreferredModel(id);
11
- const picks = [...new Set([...loadModelPicks(), id])];
12
- saveModelPicks(picks);
13
- console.log(`default model set to: ${id} (daemon hot-reloads on next request)`);
14
- console.log(`picked: ${picks.join(", ") || "(none)"} (auto will pick within these)`);
15
- process.exit(0);
16
- }
17
- if (sub === "pick" && args[idx + 2] && args[idx + 2] !== "clear") {
18
- // 多 id 勾选:`-model pick a b c`(空格分隔)与 `-model pick a,b`(逗号)均支持
19
- const ids = args.slice(idx + 2).flatMap((x) => String(x).split(",")).map((x) => x.trim()).filter(Boolean);
20
- const picks = [...new Set([...loadModelPicks(), ...ids])];
21
- saveModelPicks(picks);
22
- console.log(`picked ${ids.length} model(s): ${ids.join(", ")}`);
23
- console.log(`picked: ${picks.join(", ") || "(none)"} (auto will pick within these)`);
24
- process.exit(0);
25
- }
26
- if (sub === "pick" && args[idx + 2] === "clear") {
27
- saveModelPicks([]);
28
- console.log("picks cleared — auto uses the full model list again");
29
- process.exit(0);
30
- }
31
- if (sub === "unpick" && args[idx + 2]) {
32
- const removeSet = new Set(args.slice(idx + 2).flatMap((x) => String(x).split(",")).map((x) => x.trim()).filter(Boolean));
33
- const picks = loadModelPicks().filter((x) => !removeSet.has(x));
34
- saveModelPicks(picks);
35
- console.log(`unpicked ${removeSet.size}: ${[...removeSet].join(", ")}`);
36
- console.log(`picked: ${picks.join(", ") || "(none)"}${picks.length === 0 ? " (auto uses full list)" : ""}`);
37
- process.exit(0);
38
- }
39
- if (sub === "picks") {
40
- const picks = loadModelPicks();
41
- if (!picks.length) {
42
- console.log("no picks — auto uses the full model list");
43
- } else {
44
- console.log(`${picks.length} picked model(s), auto only selects within these:`);
45
- }
46
- for (const id of picks) console.log(` ${id}`);
47
- process.exit(0);
48
- }
49
- return false;
50
- }
1
+ import { savePreferredModel, loadModelPicks, saveModelPicks } from "../../../state.js";
2
+
3
+ /**
4
+ * 勾选集分支:set / pick / unpick / picks / pick clear。
5
+ * 命中返回 true(分支内 process.exit,不会实际返回);未命中返回 false。
6
+ */
7
+ export async function handlePicksCommand(args, idx, sub) {
8
+ if (sub === "set" && args[idx + 2]) {
9
+ const id = args[idx + 2];
10
+ savePreferredModel(id);
11
+ const picks = [...new Set([...loadModelPicks(), id])];
12
+ saveModelPicks(picks);
13
+ console.log(`default model set to: ${id} (daemon hot-reloads on next request)`);
14
+ console.log(`picked: ${picks.join(", ") || "(none)"} (auto will pick within these)`);
15
+ process.exit(0);
16
+ }
17
+ if (sub === "pick" && args[idx + 2] && args[idx + 2] !== "clear") {
18
+ // 多 id 勾选:`-model pick a b c`(空格分隔)与 `-model pick a,b`(逗号)均支持
19
+ const ids = args.slice(idx + 2).flatMap((x) => String(x).split(",")).map((x) => x.trim()).filter(Boolean);
20
+ const picks = [...new Set([...loadModelPicks(), ...ids])];
21
+ saveModelPicks(picks);
22
+ console.log(`picked ${ids.length} model(s): ${ids.join(", ")}`);
23
+ console.log(`picked: ${picks.join(", ") || "(none)"} (auto will pick within these)`);
24
+ process.exit(0);
25
+ }
26
+ if (sub === "pick" && args[idx + 2] === "clear") {
27
+ saveModelPicks([]);
28
+ console.log("picks cleared — auto uses the full model list again");
29
+ process.exit(0);
30
+ }
31
+ if (sub === "unpick" && args[idx + 2]) {
32
+ const removeSet = new Set(args.slice(idx + 2).flatMap((x) => String(x).split(",")).map((x) => x.trim()).filter(Boolean));
33
+ const picks = loadModelPicks().filter((x) => !removeSet.has(x));
34
+ saveModelPicks(picks);
35
+ console.log(`unpicked ${removeSet.size}: ${[...removeSet].join(", ")}`);
36
+ console.log(`picked: ${picks.join(", ") || "(none)"}${picks.length === 0 ? " (auto uses full list)" : ""}`);
37
+ process.exit(0);
38
+ }
39
+ if (sub === "picks") {
40
+ const picks = loadModelPicks();
41
+ if (!picks.length) {
42
+ console.log("no picks — auto uses the full model list");
43
+ } else {
44
+ console.log(`${picks.length} picked model(s), auto only selects within these:`);
45
+ }
46
+ for (const id of picks) console.log(` ${id}`);
47
+ process.exit(0);
48
+ }
49
+ return false;
50
+ }