jinzd-ai-cli 0.4.294 → 0.4.297

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 (34) hide show
  1. package/dist/{batch-6YCLYEII.js → batch-YFQ34DHW.js} +2 -2
  2. package/dist/{chunk-FARHJ42Q.js → chunk-3GIKUDYZ.js} +4 -4
  3. package/dist/{chunk-MMP6SIB7.js → chunk-56AX43FT.js} +1 -1
  4. package/dist/{chunk-CUMSLQKQ.js → chunk-6PBWL3XI.js} +1 -1
  5. package/dist/{chunk-HBFES3RR.js → chunk-CF6RC7OB.js} +4 -4
  6. package/dist/{chunk-UPJMIP5S.js → chunk-D7GLDXPQ.js} +1 -1
  7. package/dist/{chunk-AIQMQCVF.js → chunk-DPNKOXJF.js} +48 -11
  8. package/dist/{chunk-SM7VOJ3B.js → chunk-EFHAMIQF.js} +204 -167
  9. package/dist/{chunk-QKZUWT3S.js → chunk-FBOVBL7P.js} +12 -1
  10. package/dist/{chunk-BOG6LVIC.js → chunk-FZUMKY6C.js} +1 -1
  11. package/dist/{chunk-3H7TVTAE.js → chunk-GNJ3XLS3.js} +1 -1
  12. package/dist/{chunk-7KYONZUN.js → chunk-J6CYL6RN.js} +1 -1
  13. package/dist/{chunk-P3BJAJ34.js → chunk-LXORMKZ6.js} +1 -1
  14. package/dist/{chunk-OMA6DEAR.js → chunk-NB2V7H5C.js} +1 -1
  15. package/dist/{chunk-ZBHRTOWC.js → chunk-O33BYKAD.js} +1 -1
  16. package/dist/{chunk-4J6R2VFW.js → chunk-YKJO3SI4.js} +33 -4
  17. package/dist/{ci-SIS77LEG.js → ci-AR2RLLJD.js} +5 -5
  18. package/dist/{ci-format-LRMGY4ND.js → ci-format-S7RRDV4A.js} +2 -2
  19. package/dist/{constants-QRUMNMCK.js → constants-VZBWOKZZ.js} +1 -1
  20. package/dist/{constants-C7LOS6F4.js → constants-W52VYKDV.js} +1 -1
  21. package/dist/{doctor-cli-UB5KUBVI.js → doctor-cli-VX36CZND.js} +5 -5
  22. package/dist/electron-server.js +138 -24
  23. package/dist/{hub-UWBNCMD4.js → hub-LJL3X7KR.js} +1 -1
  24. package/dist/index.js +24 -23
  25. package/dist/{persistent-memory-TUCWY6O3.js → persistent-memory-CMXW4WSP.js} +2 -2
  26. package/dist/{persistent-memory-GQPXSWDK.js → persistent-memory-WEZMJBIV.js} +2 -2
  27. package/dist/{pr-MVUT6IOA.js → pr-GTDFMNKY.js} +5 -5
  28. package/dist/{run-tests-RSIXZR3O.js → run-tests-ILHN2PYU.js} +2 -2
  29. package/dist/{run-tests-BNKQT42K.js → run-tests-MTWA2NNV.js} +2 -2
  30. package/dist/{server-ILSFJUK5.js → server-QXP5NHE7.js} +15 -15
  31. package/dist/{server-YNVHKFGZ.js → server-WFXEEX2E.js} +5 -5
  32. package/dist/{task-orchestrator-7YEWEKS6.js → task-orchestrator-HZPIN4PT.js} +5 -5
  33. package/dist/{usage-DXX4VHOQ.js → usage-UEN6LLOG.js} +3 -3
  34. package/package.json +3 -1
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  computeCost,
4
4
  formatCost
5
- } from "./chunk-4J6R2VFW.js";
5
+ } from "./chunk-YKJO3SI4.js";
6
6
  import {
7
7
  clearRecentlyDeniedAutoActions,
8
8
  estimateTokens,
@@ -16,7 +16,7 @@ import {
16
16
  setPreferredAgentName,
17
17
  truncateForPersist,
18
18
  undoStack
19
- } from "./chunk-AIQMQCVF.js";
19
+ } from "./chunk-DPNKOXJF.js";
20
20
  import {
21
21
  buildReviewPrompt,
22
22
  buildSecurityReviewPrompt
@@ -51,7 +51,7 @@ import {
51
51
  touchMemoryReferences,
52
52
  updateMemoryApproval,
53
53
  updateMemoryEntry
54
- } from "./chunk-7KYONZUN.js";
54
+ } from "./chunk-J6CYL6RN.js";
55
55
  import {
56
56
  theme
57
57
  } from "./chunk-5C76XDDF.js";
@@ -65,7 +65,7 @@ import {
65
65
  import {
66
66
  buildDoctorReport,
67
67
  formatDoctorReport
68
- } from "./chunk-FARHJ42Q.js";
68
+ } from "./chunk-3GIKUDYZ.js";
69
69
  import {
70
70
  describePlugin,
71
71
  getActivePluginAssets,
@@ -80,7 +80,7 @@ import {
80
80
  trustHook,
81
81
  trustPlugin,
82
82
  untrustHook
83
- } from "./chunk-BOG6LVIC.js";
83
+ } from "./chunk-FZUMKY6C.js";
84
84
  import {
85
85
  isCleanDocumentBody,
86
86
  stripOuterCodeFence
@@ -109,7 +109,195 @@ import {
109
109
  MCP_TOOL_PREFIX,
110
110
  REPO_URL,
111
111
  VERSION
112
- } from "./chunk-CUMSLQKQ.js";
112
+ } from "./chunk-6PBWL3XI.js";
113
+
114
+ // src/skills/manager.ts
115
+ import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
116
+ import { join } from "path";
117
+
118
+ // src/skills/types.ts
119
+ import { readFileSync } from "fs";
120
+ import { basename } from "path";
121
+ function parseSimpleYaml(yaml) {
122
+ const result = {};
123
+ for (const line of yaml.split("\n")) {
124
+ const match = line.replace(/\r$/, "").match(/^(\w+)\s*:\s*(.+)$/);
125
+ if (match) {
126
+ result[match[1]] = match[2].trim().replace(/^['"]|['"]$/g, "");
127
+ }
128
+ }
129
+ return result;
130
+ }
131
+ function parseYamlArray(value) {
132
+ const bracketMatch = value.match(/^\[(.+)]$/);
133
+ if (bracketMatch) {
134
+ return bracketMatch[1].split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, ""));
135
+ }
136
+ return [value.trim()];
137
+ }
138
+ function parseSkillFile(filePath) {
139
+ let raw;
140
+ try {
141
+ raw = readFileSync(filePath, "utf-8");
142
+ } catch {
143
+ return null;
144
+ }
145
+ const frontmatterMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
146
+ if (!frontmatterMatch) {
147
+ return {
148
+ meta: {
149
+ name: basename(filePath, ".md"),
150
+ description: ""
151
+ },
152
+ content: raw.trim(),
153
+ filePath
154
+ };
155
+ }
156
+ const [, yaml, content] = frontmatterMatch;
157
+ const parsed = parseSimpleYaml(yaml);
158
+ return {
159
+ meta: {
160
+ name: parsed["name"] ?? basename(filePath, ".md"),
161
+ description: parsed["description"] ?? "",
162
+ tools: parsed["tools"] ? parseYamlArray(parsed["tools"]) : void 0
163
+ },
164
+ content: content.trim(),
165
+ filePath
166
+ };
167
+ }
168
+
169
+ // src/skills/manager.ts
170
+ var SKILL_CONTENT_WARN_CHARS_DEFAULT = 1e4;
171
+ var SkillManager = class {
172
+ skills = /* @__PURE__ */ new Map();
173
+ activeSkill = null;
174
+ skillsDir;
175
+ /** 超大技能文件警告阈值,由调用方从 config 传入;0 = 静默,undefined = 用默认 10000 */
176
+ warnThreshold;
177
+ constructor(skillsDir, warnThreshold) {
178
+ this.skillsDir = skillsDir;
179
+ this.warnThreshold = warnThreshold ?? SKILL_CONTENT_WARN_CHARS_DEFAULT;
180
+ }
181
+ /** 发现并加载 skillsDir 以及额外插件目录下的技能,返回加载数量 */
182
+ loadSkills(extraDirs = []) {
183
+ this.skills.clear();
184
+ this.loadSkillDir(this.skillsDir, true);
185
+ for (const dir of extraDirs) this.loadSkillDir(dir, false);
186
+ return this.skills.size;
187
+ }
188
+ loadSkillDir(dir, createIfMissing) {
189
+ if (!existsSync(dir)) {
190
+ if (createIfMissing) {
191
+ try {
192
+ mkdirSync(dir, { recursive: true });
193
+ } catch {
194
+ }
195
+ }
196
+ return;
197
+ }
198
+ let entries;
199
+ try {
200
+ entries = readdirSync(dir);
201
+ } catch {
202
+ return;
203
+ }
204
+ for (const entry of entries) {
205
+ let filePath;
206
+ const fullPath = join(dir, entry);
207
+ if (entry.endsWith(".md")) {
208
+ filePath = fullPath;
209
+ } else {
210
+ try {
211
+ if (statSync(fullPath).isDirectory()) {
212
+ const skillMd = join(fullPath, "SKILL.md");
213
+ if (existsSync(skillMd)) filePath = skillMd;
214
+ else continue;
215
+ } else {
216
+ continue;
217
+ }
218
+ } catch {
219
+ continue;
220
+ }
221
+ }
222
+ const skill = parseSkillFile(filePath);
223
+ if (skill) {
224
+ if (skill.meta.name === "SKILL" && !entry.endsWith(".md")) skill.meta.name = entry;
225
+ if (!this.skills.has(skill.meta.name)) this.skills.set(skill.meta.name, skill);
226
+ }
227
+ }
228
+ }
229
+ /** 列出所有已加载的技能 */
230
+ listSkills() {
231
+ return [...this.skills.values()];
232
+ }
233
+ /** 按 name 激活技能。返回被激活的 Skill,未找到返回 null。 */
234
+ activate(name) {
235
+ const skill = this.skills.get(name);
236
+ if (!skill) return null;
237
+ this.activeSkill = skill;
238
+ if (this.warnThreshold > 0 && skill.content.length > this.warnThreshold) {
239
+ process.stderr.write(
240
+ `\u26A0 Skill '${skill.meta.name}' is ${skill.content.length} chars (>${this.warnThreshold}) \u2014 this will be injected into the system prompt now. Adjust threshold with: /config set ui.skillSizeWarn <n|0>
241
+ `
242
+ );
243
+ }
244
+ return skill;
245
+ }
246
+ /** 停用当前技能 */
247
+ deactivate() {
248
+ this.activeSkill = null;
249
+ }
250
+ /** 获取当前激活的技能(null 表示无激活技能) */
251
+ getActive() {
252
+ return this.activeSkill;
253
+ }
254
+ /** 获取激活技能的 prompt 内容(null 表示无激活技能) */
255
+ getActivePromptContent() {
256
+ return this.activeSkill?.content ?? null;
257
+ }
258
+ /** 获取激活技能的工具白名单 Set(null 表示无限制) */
259
+ getActiveToolFilter() {
260
+ if (!this.activeSkill?.meta.tools) return null;
261
+ return new Set(this.activeSkill.meta.tools);
262
+ }
263
+ /** 获取技能目录路径 */
264
+ getSkillsDir() {
265
+ return this.skillsDir;
266
+ }
267
+ };
268
+ function levenshtein(a, b) {
269
+ const m = a.length, n = b.length;
270
+ if (m === 0) return n;
271
+ if (n === 0) return m;
272
+ let prev = Array.from({ length: n + 1 }, (_, j) => j);
273
+ for (let i = 1; i <= m; i++) {
274
+ const cur = [i];
275
+ for (let j = 1; j <= n; j++) {
276
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
277
+ cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
278
+ }
279
+ prev = cur;
280
+ }
281
+ return prev[n];
282
+ }
283
+ function suggestSkillName(names, input) {
284
+ const norm = (s) => s.toLowerCase().replace(/[-_\s]/g, "");
285
+ const target = norm(input);
286
+ if (!target) return null;
287
+ const exact = names.find((n) => norm(n) === target);
288
+ if (exact) return exact;
289
+ const limit = Math.min(3, Math.max(1, Math.floor(target.length / 4)));
290
+ let best = null;
291
+ let bestScore = Infinity;
292
+ for (const n of names) {
293
+ const d = levenshtein(norm(n), target);
294
+ if (d <= limit && d < bestScore) {
295
+ best = n;
296
+ bestScore = d;
297
+ }
298
+ }
299
+ return best;
300
+ }
113
301
 
114
302
  // src/mcp/client.ts
115
303
  import { spawn } from "child_process";
@@ -628,161 +816,6 @@ var McpManager = class {
628
816
  }
629
817
  };
630
818
 
631
- // src/skills/manager.ts
632
- import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
633
- import { join } from "path";
634
-
635
- // src/skills/types.ts
636
- import { readFileSync } from "fs";
637
- import { basename } from "path";
638
- function parseSimpleYaml(yaml) {
639
- const result = {};
640
- for (const line of yaml.split("\n")) {
641
- const match = line.replace(/\r$/, "").match(/^(\w+)\s*:\s*(.+)$/);
642
- if (match) {
643
- result[match[1]] = match[2].trim().replace(/^['"]|['"]$/g, "");
644
- }
645
- }
646
- return result;
647
- }
648
- function parseYamlArray(value) {
649
- const bracketMatch = value.match(/^\[(.+)]$/);
650
- if (bracketMatch) {
651
- return bracketMatch[1].split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, ""));
652
- }
653
- return [value.trim()];
654
- }
655
- function parseSkillFile(filePath) {
656
- let raw;
657
- try {
658
- raw = readFileSync(filePath, "utf-8");
659
- } catch {
660
- return null;
661
- }
662
- const frontmatterMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
663
- if (!frontmatterMatch) {
664
- return {
665
- meta: {
666
- name: basename(filePath, ".md"),
667
- description: ""
668
- },
669
- content: raw.trim(),
670
- filePath
671
- };
672
- }
673
- const [, yaml, content] = frontmatterMatch;
674
- const parsed = parseSimpleYaml(yaml);
675
- return {
676
- meta: {
677
- name: parsed["name"] ?? basename(filePath, ".md"),
678
- description: parsed["description"] ?? "",
679
- tools: parsed["tools"] ? parseYamlArray(parsed["tools"]) : void 0
680
- },
681
- content: content.trim(),
682
- filePath
683
- };
684
- }
685
-
686
- // src/skills/manager.ts
687
- var SKILL_CONTENT_WARN_CHARS_DEFAULT = 1e4;
688
- var SkillManager = class {
689
- skills = /* @__PURE__ */ new Map();
690
- activeSkill = null;
691
- skillsDir;
692
- /** 超大技能文件警告阈值,由调用方从 config 传入;0 = 静默,undefined = 用默认 10000 */
693
- warnThreshold;
694
- constructor(skillsDir, warnThreshold) {
695
- this.skillsDir = skillsDir;
696
- this.warnThreshold = warnThreshold ?? SKILL_CONTENT_WARN_CHARS_DEFAULT;
697
- }
698
- /** 发现并加载 skillsDir 以及额外插件目录下的技能,返回加载数量 */
699
- loadSkills(extraDirs = []) {
700
- this.skills.clear();
701
- this.loadSkillDir(this.skillsDir, true);
702
- for (const dir of extraDirs) this.loadSkillDir(dir, false);
703
- return this.skills.size;
704
- }
705
- loadSkillDir(dir, createIfMissing) {
706
- if (!existsSync(dir)) {
707
- if (createIfMissing) {
708
- try {
709
- mkdirSync(dir, { recursive: true });
710
- } catch {
711
- }
712
- }
713
- return;
714
- }
715
- let entries;
716
- try {
717
- entries = readdirSync(dir);
718
- } catch {
719
- return;
720
- }
721
- for (const entry of entries) {
722
- let filePath;
723
- const fullPath = join(dir, entry);
724
- if (entry.endsWith(".md")) {
725
- filePath = fullPath;
726
- } else {
727
- try {
728
- if (statSync(fullPath).isDirectory()) {
729
- const skillMd = join(fullPath, "SKILL.md");
730
- if (existsSync(skillMd)) filePath = skillMd;
731
- else continue;
732
- } else {
733
- continue;
734
- }
735
- } catch {
736
- continue;
737
- }
738
- }
739
- const skill = parseSkillFile(filePath);
740
- if (skill) {
741
- if (skill.meta.name === "SKILL" && !entry.endsWith(".md")) skill.meta.name = entry;
742
- if (!this.skills.has(skill.meta.name)) this.skills.set(skill.meta.name, skill);
743
- }
744
- }
745
- }
746
- /** 列出所有已加载的技能 */
747
- listSkills() {
748
- return [...this.skills.values()];
749
- }
750
- /** 按 name 激活技能。返回被激活的 Skill,未找到返回 null。 */
751
- activate(name) {
752
- const skill = this.skills.get(name);
753
- if (!skill) return null;
754
- this.activeSkill = skill;
755
- if (this.warnThreshold > 0 && skill.content.length > this.warnThreshold) {
756
- process.stderr.write(
757
- `\u26A0 Skill '${skill.meta.name}' is ${skill.content.length} chars (>${this.warnThreshold}) \u2014 this will be injected into the system prompt now. Adjust threshold with: /config set ui.skillSizeWarn <n|0>
758
- `
759
- );
760
- }
761
- return skill;
762
- }
763
- /** 停用当前技能 */
764
- deactivate() {
765
- this.activeSkill = null;
766
- }
767
- /** 获取当前激活的技能(null 表示无激活技能) */
768
- getActive() {
769
- return this.activeSkill;
770
- }
771
- /** 获取激活技能的 prompt 内容(null 表示无激活技能) */
772
- getActivePromptContent() {
773
- return this.activeSkill?.content ?? null;
774
- }
775
- /** 获取激活技能的工具白名单 Set(null 表示无限制) */
776
- getActiveToolFilter() {
777
- if (!this.activeSkill?.meta.tools) return null;
778
- return new Set(this.activeSkill.meta.tools);
779
- }
780
- /** 获取技能目录路径 */
781
- getSkillsDir() {
782
- return this.skillsDir;
783
- }
784
- };
785
-
786
819
  // src/core/proxy.ts
787
820
  async function setupProxy(configProxy) {
788
821
  const proxyUrl = process.env.HTTPS_PROXY ?? process.env.HTTP_PROXY ?? process.env.https_proxy ?? process.env.http_proxy ?? configProxy;
@@ -2393,7 +2426,7 @@ No tools match "${filter}".
2393
2426
  const { join: join6 } = await import("path");
2394
2427
  const { existsSync: existsSync6 } = await import("fs");
2395
2428
  const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
2396
- const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-C7LOS6F4.js");
2429
+ const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-W52VYKDV.js");
2397
2430
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
2398
2431
  const cwd = process.cwd();
2399
2432
  const projectRoot = getGitRoot(cwd) ?? cwd;
@@ -2542,9 +2575,13 @@ No tools match "${filter}".
2542
2575
  ctx.renderer.printSuccess(`Reloaded: ${count} skill(s) found.`);
2543
2576
  return;
2544
2577
  }
2545
- const target = manager.listSkills().find((s) => s.meta.name === sub);
2578
+ const allSkills = manager.listSkills();
2579
+ const target = allSkills.find((s) => s.meta.name === sub);
2546
2580
  if (!target) {
2547
- ctx.renderer.renderError(`Skill '${sub}' not found. Use /skill list to see available skills.`);
2581
+ const guess = suggestSkillName(allSkills.map((s) => s.meta.name), sub);
2582
+ ctx.renderer.renderError(
2583
+ guess ? `Skill '${sub}' not found. Did you mean '${guess}'? (/skill ${guess})` : `Skill '${sub}' not found. Use /skill list to see available skills.`
2584
+ );
2548
2585
  return;
2549
2586
  }
2550
2587
  const prev = manager.getActive();
@@ -3497,7 +3534,7 @@ function createReviewCommands() {
3497
3534
  usage: "/test [command|filter]",
3498
3535
  async execute(args, ctx) {
3499
3536
  try {
3500
- const { executeTests } = await import("./run-tests-BNKQT42K.js");
3537
+ const { executeTests } = await import("./run-tests-MTWA2NNV.js");
3501
3538
  const argStr = args.join(" ").trim();
3502
3539
  let testArgs = {};
3503
3540
  if (argStr) {
@@ -5633,6 +5670,8 @@ export {
5633
5670
  agentUnknownMessage,
5634
5671
  parseSkillCommand,
5635
5672
  skillHistoryNote,
5673
+ parseSimpleYaml,
5674
+ SkillManager,
5636
5675
  applyProfileCommand,
5637
5676
  readGitDiff,
5638
5677
  parseRewindArgs,
@@ -5663,7 +5702,6 @@ export {
5663
5702
  getClipboardHint,
5664
5703
  CommandRegistry,
5665
5704
  createDefaultCommands,
5666
- parseSimpleYaml,
5667
5705
  persistToolRound,
5668
5706
  autoTrimSessionIfNeeded,
5669
5707
  estimateConversationTokens,
@@ -5677,7 +5715,6 @@ export {
5677
5715
  loadDevState,
5678
5716
  clearDevState,
5679
5717
  McpManager,
5680
- SkillManager,
5681
5718
  snapshotFile,
5682
5719
  armDeferredSave,
5683
5720
  decideDeferredSave,
@@ -2061,7 +2061,18 @@ var OPENROUTER_CONFIG = {
2061
2061
  { id: "meta-llama/llama-4-maverick", displayName: "Llama 4 Maverick", contextWindow: 1048576, supportsStreaming: true },
2062
2062
  { id: "meta-llama/llama-4-scout", displayName: "Llama 4 Scout", contextWindow: 512e3, supportsStreaming: true },
2063
2063
  { id: "qwen/qwen3-coder", displayName: "Qwen3 Coder", contextWindow: 262144, supportsStreaming: true },
2064
- { id: "mistralai/mistral-large", displayName: "Mistral Large", contextWindow: 131072, supportsStreaming: true }
2064
+ { id: "mistralai/mistral-large", displayName: "Mistral Large", contextWindow: 131072, supportsStreaming: true },
2065
+ // ── 国产旗舰(2026-08-29 对 /api/v1/models 实测取回的真实 id、上下文与价格)──
2066
+ // 走 OpenRouter 的理由不只是"多一个入口":DeepSeek V4 Flash 在这里比直连国内**便宜一个
2067
+ // 数量级**(详见 pricing.ts 的对照注释)。id 一律 `vendor/model` 形式,与直连 provider
2068
+ // 的裸 id 不冲突。
2069
+ { id: "deepseek/deepseek-v4-flash-0731", displayName: "DeepSeek V4 Flash (0731) \u2014 \u6781\u5EC9\u4EF7, 1.31M", contextWindow: 1310720, supportsStreaming: true, supportsThinking: true },
2070
+ { id: "deepseek/deepseek-v4-pro-0813", displayName: "DeepSeek V4 Pro (0813), 1M", contextWindow: 1048576, supportsStreaming: true, supportsThinking: true },
2071
+ { id: "z-ai/glm-5.3-flash", displayName: "GLM-5.3 Flash (\u591A\u6A21\u6001, 1.31M)", contextWindow: 1310720, supportsStreaming: true, supportsThinking: true },
2072
+ { id: "z-ai/glm-5.3", displayName: "GLM-5.3 (\u65D7\u8230, 1.31M)", contextWindow: 1310720, supportsStreaming: true, supportsThinking: true },
2073
+ { id: "z-ai/glm-4.6", displayName: "GLM-4.6 (\u4E2D\u6587\u5199\u4F5C, 200K)", contextWindow: 204800, supportsStreaming: true },
2074
+ { id: "moonshotai/kimi-k3", displayName: "Kimi K3 (1M)", contextWindow: 1048576, supportsStreaming: true, supportsThinking: true },
2075
+ { id: "minimax/minimax-m3", displayName: "MiniMax M3 (1M)", contextWindow: 1048576, supportsStreaming: true }
2065
2076
  ]
2066
2077
  };
2067
2078
  var OpenRouterProvider = createStaticProviderClass(OPENROUTER_CONFIG);
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  CONFIG_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-CUMSLQKQ.js";
11
+ } from "./chunk-6PBWL3XI.js";
12
12
 
13
13
  // src/diagnostics/tool-stats.ts
14
14
  import { mkdirSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-CUMSLQKQ.js";
4
+ } from "./chunk-6PBWL3XI.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -13,7 +13,7 @@ import {
13
13
  MEMORY_FILE_NAME,
14
14
  MEMORY_MAX_CHARS,
15
15
  MEMORY_STORE_FILE_NAME
16
- } from "./chunk-CUMSLQKQ.js";
16
+ } from "./chunk-6PBWL3XI.js";
17
17
 
18
18
  // src/memory/persistent-memory.ts
19
19
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -12,7 +12,7 @@ import {
12
12
  MEMORY_FILE_NAME,
13
13
  MEMORY_MAX_CHARS,
14
14
  MEMORY_STORE_FILE_NAME
15
- } from "./chunk-UPJMIP5S.js";
15
+ } from "./chunk-D7GLDXPQ.js";
16
16
 
17
17
  // src/memory/persistent-memory.ts
18
18
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TEST_TIMEOUT
3
- } from "./chunk-UPJMIP5S.js";
3
+ } from "./chunk-D7GLDXPQ.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -11,7 +11,7 @@ import {
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-CUMSLQKQ.js";
14
+ } from "./chunk-6PBWL3XI.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -113,14 +113,42 @@ var PRICING_TABLE = {
113
113
  "glm-5.1-air": { input: 0.4, output: 1.2 },
114
114
  "glm-z1": { input: 0.5, output: 1.5 },
115
115
  "glm-z1-air": { input: 0.2, output: 0.6 },
116
- "glm-z1-flash": { input: 0, output: 0 }
116
+ "glm-z1-flash": { input: 0, output: 0 },
117
117
  // ── MiniMax (海螺) ────────────────────────────────────────────
118
118
  // GAP (v0.4.184): MiniMax-M3 / M2.x are unpriced — no verified rate anchor yet.
119
119
  // Unpriced → `aicli usage` shows "—" (unknown), not a false $0.00. Add when confirmed.
120
120
  // ── OpenRouter (pass-through — actual cost depends on underlying model) ──
121
- // Left empty by design: model IDs are "vendor/model" (e.g. anthropic/claude-sonnet-4)
122
- // and the real price is set by the underlying model + OpenRouter markup, not statically
123
- // resolvable here. Shows "—" (unknown) in `aicli usage`.
121
+ // 绝大多数 id 仍**刻意留空**:真实价由底层模型 + OpenRouter 加价决定,静态表覆盖不了
122
+ // 396 个模型,未收录的照旧显示 "—"(未知)而不是假的 $0.00。
123
+ //
124
+ // 下面这批是 curated 列表里的国产旗舰,**2026-08-29 对 `/api/v1/models` 实测取回的一手
125
+ // 价格**(该端点直接返回每 token 单价,这里换算成每百万 token 的美元数)。收录它们是因为
126
+ // 东叔真的会用,而 `aicli usage` 记不到价就等于这条路的花费不进预算告警。
127
+ //
128
+ // ⚠ 这是**快照**,不是实时价:OpenRouter 的价格随底层供应商变动,且它自己就有多家供应商
129
+ // 轮转。偏差方向未知(不像智谱那次能靠"记恢复价"保证高估),故注明取数日期,发现明显不符
130
+ // 时以 `/api/v1/models` 为准重取。
131
+ //
132
+ // 与直连国内的对照(同一模型、同一天):
133
+ // deepseek-v4-flash-0731 直连闲时 $0.217/$0.652、峰时 $0.435/$1.304
134
+ // OpenRouter $0.045/$0.090 → **便宜约 5–14 倍**
135
+ // deepseek-v4-pro-0813 直连闲时 $0.652/$1.957 ≈ OpenRouter $0.660/$1.980(基本持平)
136
+ // 直连峰时 $1.304/$3.913 → OpenRouter 便宜约一半
137
+ // glm-5.3-flash 直连恢复价 $0.116/$0.406、5 折促销价 $0.058/$0.203
138
+ // OpenRouter $0.075/$0.250 → 比恢复价便宜、比促销价略贵
139
+ // kimi-k3 两边同价($3.00/$15.00)
140
+ "deepseek/deepseek-v4-flash-0731": { input: 0.045, output: 0.09 },
141
+ "deepseek/deepseek-v4-flash-0731:batch": { input: 0.14, output: 0.28 },
142
+ "deepseek/deepseek-v4-flash": { input: 0.086, output: 0.171 },
143
+ "deepseek/deepseek-v4-pro-0813": { input: 0.66, output: 1.98 },
144
+ "deepseek/deepseek-v4-pro-0813:batch": { input: 1.32, output: 3.96 },
145
+ "deepseek/deepseek-v4-pro": { input: 0.701, output: 1.402 },
146
+ "z-ai/glm-5.3-flash": { input: 0.075, output: 0.25 },
147
+ "z-ai/glm-5.3-flash:batch": { input: 0.15, output: 0.5 },
148
+ "z-ai/glm-5.3": { input: 1.4, output: 4.4 },
149
+ "z-ai/glm-4.6": { input: 0.43, output: 1.75 },
150
+ "moonshotai/kimi-k3": { input: 3, output: 15 },
151
+ "minimax/minimax-m3": { input: 0.3, output: 1.2 }
124
152
  // ── Ollama (local, zero cost) ─────────────────────────────────
125
153
  // Handled via provider check below (FREE_PROVIDERS → genuine $0.00, not "unknown").
126
154
  };
@@ -130,6 +158,7 @@ function getPricing(provider, model, at = /* @__PURE__ */ new Date()) {
130
158
  return { input: 0, output: 0 };
131
159
  }
132
160
  const key = model.toLowerCase();
161
+ if (key.endsWith(":free")) return { input: 0, output: 0 };
133
162
  if (provider.toLowerCase() === "deepseek") {
134
163
  const dynamicPricing = getDeepSeekV4Pricing(key, at);
135
164
  if (dynamicPricing) return dynamicPricing;
@@ -3,16 +3,16 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-HBFES3RR.js";
7
- import "./chunk-3H7TVTAE.js";
6
+ } from "./chunk-CF6RC7OB.js";
7
+ import "./chunk-GNJ3XLS3.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
9
  import "./chunk-6YZEZFX5.js";
10
- import "./chunk-QKZUWT3S.js";
11
- import "./chunk-ZBHRTOWC.js";
10
+ import "./chunk-FBOVBL7P.js";
11
+ import "./chunk-O33BYKAD.js";
12
12
  import "./chunk-Y56UGZPX.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
- import "./chunk-CUMSLQKQ.js";
15
+ import "./chunk-6PBWL3XI.js";
16
16
  export {
17
17
  CI_COMMENT_MARKER,
18
18
  countSeverity,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-3H7TVTAE.js";
10
- import "./chunk-CUMSLQKQ.js";
9
+ } from "./chunk-GNJ3XLS3.js";
10
+ import "./chunk-6PBWL3XI.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -37,7 +37,7 @@ import {
37
37
  TEST_TIMEOUT,
38
38
  VERSION,
39
39
  buildUserIdentityPrompt
40
- } from "./chunk-UPJMIP5S.js";
40
+ } from "./chunk-D7GLDXPQ.js";
41
41
  export {
42
42
  AGENTIC_BEHAVIOR_GUIDELINE,
43
43
  APP_NAME,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-CUMSLQKQ.js";
41
+ } from "./chunk-6PBWL3XI.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -2,16 +2,16 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-FARHJ42Q.js";
6
- import "./chunk-BOG6LVIC.js";
5
+ } from "./chunk-3GIKUDYZ.js";
6
+ import "./chunk-FZUMKY6C.js";
7
7
  import "./chunk-RS7SKYTS.js";
8
- import "./chunk-QKZUWT3S.js";
9
- import "./chunk-ZBHRTOWC.js";
8
+ import "./chunk-FBOVBL7P.js";
9
+ import "./chunk-O33BYKAD.js";
10
10
  import "./chunk-Y56UGZPX.js";
11
11
  import "./chunk-TU3L3PW7.js";
12
12
  import "./chunk-HOSJZMQS.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
- import "./chunk-CUMSLQKQ.js";
14
+ import "./chunk-6PBWL3XI.js";
15
15
  export {
16
16
  formatDoctorReport,
17
17
  runDoctorCli