jinzd-ai-cli 0.4.276 → 0.4.277

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 (36) hide show
  1. package/dist/{batch-F7SKIBI3.js → batch-2I5TPZA2.js} +2 -2
  2. package/dist/{chunk-OMBKLWLJ.js → chunk-3VFOXEIL.js} +1 -1
  3. package/dist/{chunk-GLSR2NR3.js → chunk-4DEMGCK4.js} +4 -3
  4. package/dist/{chunk-KWSGSSWN.js → chunk-7BO5H2QI.js} +1 -1
  5. package/dist/{chunk-WYDP2WEQ.js → chunk-7IPMONKZ.js} +4 -4
  6. package/dist/{chunk-4NH4Q7QK.js → chunk-7YYUITED.js} +1 -1
  7. package/dist/{chunk-ATD2Y3PB.js → chunk-BYNNKJUC.js} +1 -1
  8. package/dist/{chunk-NXAHXWPF.js → chunk-HCF442WL.js} +1 -1
  9. package/dist/{chunk-MCKUGWOY.js → chunk-HJVKCOAG.js} +3 -3
  10. package/dist/{chunk-MXPUOF5K.js → chunk-I3PYD2YN.js} +4 -4
  11. package/dist/{chunk-NXNXWM6H.js → chunk-KIGKL3PZ.js} +16 -7
  12. package/dist/{chunk-VF7DMSKF.js → chunk-OCOGYIRY.js} +1 -1
  13. package/dist/{chunk-QCG6UU2S.js → chunk-PPIISCFN.js} +4 -3
  14. package/dist/{chunk-4KTK2OYU.js → chunk-UGY5SVNX.js} +46 -20
  15. package/dist/{chunk-AOISQVXS.js → chunk-UWQCTTP4.js} +1 -1
  16. package/dist/{chunk-UNL7NR55.js → chunk-Z752LDYF.js} +1 -1
  17. package/dist/{chunk-FLDYAXJR.js → chunk-ZP3RCZKM.js} +1 -1
  18. package/dist/{ci-VURFRMWQ.js → ci-JFC45LIS.js} +5 -5
  19. package/dist/{ci-format-AFJJIURF.js → ci-format-P3LIZHUR.js} +2 -2
  20. package/dist/{constants-WO7ERENL.js → constants-N3CHKZJY.js} +1 -1
  21. package/dist/{doctor-cli-BGGILTHE.js → doctor-cli-Z3TGHTSX.js} +5 -5
  22. package/dist/electron-server.js +77 -35
  23. package/dist/{hub-Z73RLNJI.js → hub-NEWIFMQ3.js} +1 -1
  24. package/dist/index.js +44 -45
  25. package/dist/{indexer-M2LJGTY2.js → indexer-RBEKMFT4.js} +1 -1
  26. package/dist/{indexer-VZETNE4H.js → indexer-TNDWGFRI.js} +1 -1
  27. package/dist/{persistent-memory-5QMARQJF.js → persistent-memory-6Q5FDFJ7.js} +2 -2
  28. package/dist/{persistent-memory-CI544RLT.js → persistent-memory-ZFR5GI7D.js} +2 -2
  29. package/dist/{pr-24REDMGV.js → pr-ZUGSWQ5R.js} +5 -5
  30. package/dist/{run-tests-JJ3KOY5E.js → run-tests-76M6AC3G.js} +2 -2
  31. package/dist/{run-tests-72VNZXNT.js → run-tests-USV7IJ7X.js} +2 -2
  32. package/dist/{server-JMXC2N3F.js → server-C523CIGN.js} +30 -19
  33. package/dist/{server-QJHCJDA7.js → server-R7D5RR36.js} +6 -6
  34. package/dist/{task-orchestrator-DJN36HP5.js → task-orchestrator-G2MQDNGQ.js} +8 -8
  35. package/dist/{usage-HXJVDETY.js → usage-EFHXXMYX.js} +2 -2
  36. package/package.json +1 -1
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-SKET65WZ.js";
14
14
  import {
15
15
  indexProject
16
- } from "./chunk-QCG6UU2S.js";
16
+ } from "./chunk-PPIISCFN.js";
17
17
  import {
18
18
  addMemoryEntry,
19
19
  backupMemoryStore,
@@ -40,14 +40,14 @@ import {
40
40
  touchMemoryReferences,
41
41
  updateMemoryApproval,
42
42
  updateMemoryEntry
43
- } from "./chunk-4NH4Q7QK.js";
43
+ } from "./chunk-7YYUITED.js";
44
44
  import {
45
45
  redactJson,
46
46
  scanString
47
47
  } from "./chunk-FSC6KEWU.js";
48
48
  import {
49
49
  runTestsTool
50
- } from "./chunk-ATD2Y3PB.js";
50
+ } from "./chunk-BYNNKJUC.js";
51
51
  import {
52
52
  AGENTIC_BEHAVIOR_GUIDELINE,
53
53
  APP_NAME,
@@ -80,7 +80,7 @@ import {
80
80
  SUBAGENT_MAX_ROUNDS_LIMIT,
81
81
  VERSION,
82
82
  buildUserIdentityPrompt
83
- } from "./chunk-UNL7NR55.js";
83
+ } from "./chunk-Z752LDYF.js";
84
84
  import {
85
85
  hasSemanticIndex,
86
86
  semanticSearch
@@ -1155,7 +1155,8 @@ var BaseProvider = class {
1155
1155
  return this.reliableContentOnlyTee;
1156
1156
  }
1157
1157
  /**
1158
- * 该 provider 是否支持 `reasoning_effort` 档位(low/high/max)。目前只有 DeepSeek V4。
1158
+ * 该 provider 是否支持 `reasoning_effort` 档位(low/high/max)。目前是 DeepSeek V4
1159
+ * 与智谱 GLM-5 系列(v0.4.276 接入 GLM-5.3 时补上——它关不掉思考,档位是唯一的成本闸门)。
1159
1160
  *
1160
1161
  * 2026-08-14 审计 P2-03:提示符标签此前无条件渲染成 `[THINK:high]`,于是 Claude
1161
1162
  * (用 thinkingBudget 计 token 预算)和 GLM(根本没有 effort 概念)也显示一个
@@ -2136,6 +2137,16 @@ Node.js does not automatically use system proxies. Try one of the following:
2136
2137
  // src/providers/openai-compatible.ts
2137
2138
  import OpenAI from "openai";
2138
2139
 
2140
+ // src/providers/openai-extensions.ts
2141
+ function toSdkParams(params) {
2142
+ return params;
2143
+ }
2144
+ function readReasoningContent(message) {
2145
+ if (!message || typeof message !== "object") return void 0;
2146
+ const value = message.reasoning_content;
2147
+ return typeof value === "string" ? value : void 0;
2148
+ }
2149
+
2139
2150
  // src/tools/hallucination.ts
2140
2151
  var HALLUCINATION_PATTERNS = [
2141
2152
  /文件路径[::]\s*`?[^\s`]+\.\w{1,5}/,
@@ -3377,7 +3388,7 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3377
3388
  continue;
3378
3389
  }
3379
3390
  if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
3380
- const assistantMsg = {
3391
+ msgs.push({
3381
3392
  role: "assistant",
3382
3393
  content: typeof m.content === "string" && m.content ? m.content : null,
3383
3394
  tool_calls: m.toolCalls.map((tc) => ({
@@ -3386,15 +3397,22 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3386
3397
  function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
3387
3398
  })),
3388
3399
  reasoning_content: m.reasoningContent ?? ""
3389
- };
3390
- msgs.push(assistantMsg);
3400
+ });
3391
3401
  continue;
3392
3402
  }
3393
- const base = { role: m.role, content: m.content };
3394
3403
  if (m.role === "assistant") {
3395
- base.reasoning_content = m.reasoningContent ?? "";
3404
+ msgs.push({
3405
+ role: "assistant",
3406
+ content: typeof m.content === "string" ? m.content : "",
3407
+ reasoning_content: m.reasoningContent ?? ""
3408
+ });
3409
+ continue;
3396
3410
  }
3397
- msgs.push(base);
3411
+ if (m.role === "system") {
3412
+ msgs.push({ role: "system", content: typeof m.content === "string" ? m.content : "" });
3413
+ continue;
3414
+ }
3415
+ msgs.push({ role: "user", content: m.content });
3398
3416
  }
3399
3417
  const systemContent = [request.systemPrompt, request.systemPromptVolatile].filter(Boolean).join("\n\n---\n\n");
3400
3418
  if (systemContent) {
@@ -3423,12 +3441,13 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3423
3441
  */
3424
3442
  async chat(request) {
3425
3443
  try {
3426
- const response = await this.client.chat.completions.create({
3444
+ const params = {
3427
3445
  model: request.model,
3428
3446
  messages: this.buildMessages(request),
3429
3447
  ...this.buildChatRequestParams(request),
3430
3448
  stream: false
3431
- }, {
3449
+ };
3450
+ const response = await this.client.chat.completions.create(toSdkParams(params), {
3432
3451
  timeout: request.timeout ?? this.defaultTimeout,
3433
3452
  signal: request.signal
3434
3453
  });
@@ -3436,7 +3455,7 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3436
3455
  if (!firstChoice) {
3437
3456
  return { content: "", model: response.model, usage: void 0 };
3438
3457
  }
3439
- const reasoningContent = firstChoice.message.reasoning_content;
3458
+ const reasoningContent = readReasoningContent(firstChoice.message);
3440
3459
  return {
3441
3460
  content: firstChoice.message.content ?? "",
3442
3461
  model: response.model,
@@ -3449,14 +3468,15 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3449
3468
  }
3450
3469
  async *chatStream(request) {
3451
3470
  try {
3452
- const stream = await this.client.chat.completions.create({
3471
+ const params = {
3453
3472
  model: request.model,
3454
3473
  messages: this.buildMessages(request),
3455
3474
  ...this.buildChatRequestParams(request),
3456
3475
  stream: true,
3457
3476
  // 请求末尾 usage chunk,供 token 统计使用
3458
3477
  stream_options: { include_usage: true }
3459
- }, {
3478
+ };
3479
+ const stream = await this.client.chat.completions.create(toSdkParams(params), {
3460
3480
  timeout: request.timeout ?? this.defaultTimeout,
3461
3481
  signal: request.signal
3462
3482
  });
@@ -3526,14 +3546,15 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3526
3546
  const baseMessages = this.buildMessages(request);
3527
3547
  const extraMessages = request._extraMessages ?? [];
3528
3548
  const allMessages = [...baseMessages, ...extraMessages];
3529
- const response = await this.client.chat.completions.create({
3549
+ const params = {
3530
3550
  model: request.model,
3531
3551
  messages: allMessages,
3532
3552
  tools: openaiTools,
3533
3553
  tool_choice: "auto",
3534
3554
  ...this.buildChatRequestParams(request),
3535
3555
  stream: false
3536
- }, {
3556
+ };
3557
+ const response = await this.client.chat.completions.create(toSdkParams(params), {
3537
3558
  timeout: request.timeout ?? this.defaultTimeout,
3538
3559
  // 非流式路径同样必须收 signal,否则 Ctrl+C 期间整个请求不可中断(见 chat() 上方注释)
3539
3560
  signal: request.signal
@@ -3546,7 +3567,7 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3546
3567
  const finishReason = firstChoice.finish_reason;
3547
3568
  const usage = toUsage(response.usage);
3548
3569
  const hasToolCalls = !!(message.tool_calls && message.tool_calls.length > 0);
3549
- const reasoningContent = message.reasoning_content;
3570
+ const reasoningContent = readReasoningContent(message);
3550
3571
  if (message.tool_calls && message.tool_calls.length > 0) {
3551
3572
  const toolCalls = message.tool_calls.map((tc) => {
3552
3573
  const parsed = parseToolCallArguments(
@@ -3625,7 +3646,7 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3625
3646
  const extraMessages = request._extraMessages ?? [];
3626
3647
  const allMessages = [...baseMessages, ...extraMessages];
3627
3648
  try {
3628
- const stream = await this.client.chat.completions.create({
3649
+ const params = {
3629
3650
  model: request.model,
3630
3651
  messages: allMessages,
3631
3652
  tools: openaiTools,
@@ -3633,7 +3654,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3633
3654
  ...this.buildChatRequestParams(request),
3634
3655
  stream: true,
3635
3656
  stream_options: { include_usage: true }
3636
- }, {
3657
+ };
3658
+ const stream = await this.client.chat.completions.create(toSdkParams(params), {
3637
3659
  timeout: request.timeout ?? this.defaultTimeout,
3638
3660
  signal: request.signal
3639
3661
  });
@@ -3751,9 +3773,11 @@ var OpenAICompatibleProvider = class extends BaseProvider {
3751
3773
  name: tc.name,
3752
3774
  arguments: JSON.stringify(tc.arguments)
3753
3775
  }
3754
- }))
3776
+ })),
3777
+ // DeepSeek V4 thinking 模式严格校验:assistant 消息必须包含 reasoning_content
3778
+ // 字段(即使为空字符串也必须存在,否则 API 返回 400)
3779
+ reasoning_content: reasoningContent ?? ""
3755
3780
  };
3756
- assistantMsg.reasoning_content = reasoningContent ?? "";
3757
3781
  const resultMsgs = results.map((r) => ({
3758
3782
  role: "tool",
3759
3783
  tool_call_id: r.callId,
@@ -3966,7 +3990,7 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
3966
3990
  buildChatRequestParams(request) {
3967
3991
  const params = super.buildChatRequestParams(request);
3968
3992
  if (request.thinkingEffort && REASONING_EFFORT_MODELS.test(request.model)) {
3969
- params["reasoning_effort"] = request.thinkingEffort;
3993
+ params.reasoning_effort = request.thinkingEffort;
3970
3994
  }
3971
3995
  return params;
3972
3996
  }
@@ -8525,7 +8549,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
8525
8549
  const mode = appendMode ? "appended" : "written";
8526
8550
  void (async () => {
8527
8551
  try {
8528
- const { updateFile } = await import("./indexer-M2LJGTY2.js");
8552
+ const { updateFile } = await import("./indexer-RBEKMFT4.js");
8529
8553
  await updateFile(process.cwd(), filePath);
8530
8554
  } catch {
8531
8555
  }
@@ -10733,6 +10757,13 @@ function formatResults2(query, data, _requested) {
10733
10757
  return header + "\n" + results.join("\n\n");
10734
10758
  }
10735
10759
 
10760
+ // src/core/tool-capable-provider.ts
10761
+ function isToolCapableProvider(provider) {
10762
+ if (!provider) return false;
10763
+ const candidate = provider;
10764
+ return typeof candidate.chatWithTools === "function" && typeof candidate.buildToolResultMessages === "function";
10765
+ }
10766
+
10736
10767
  // src/agents/agent-config.ts
10737
10768
  import { existsSync as existsSync18, readdirSync as readdirSync8, readFileSync as readFileSync15 } from "fs";
10738
10769
  import { join as join13 } from "path";
@@ -11544,7 +11575,8 @@ async function runSubAgent(task, maxRounds, agentIndex, ctx, agent) {
11544
11575
  if (!ctx.provider) {
11545
11576
  throw new ToolError("spawn_agent", "provider not initialized (context not injected)");
11546
11577
  }
11547
- const providerFromConfig = agent.provider && ctx.providers?.has(agent.provider) ? ctx.providers.get(agent.provider) : void 0;
11578
+ const configured = agent.provider && ctx.providers?.has(agent.provider) ? ctx.providers.get(agent.provider) : void 0;
11579
+ const providerFromConfig = isToolCapableProvider(configured) ? configured : void 0;
11548
11580
  const provider = providerFromConfig ?? ctx.provider;
11549
11581
  const model = agent.model ?? (providerFromConfig?.info?.defaultModel ?? ctx.model);
11550
11582
  const run = startAgentRun({
@@ -16143,7 +16175,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
16143
16175
  Cost: ${formatCost(cost)}` : "";
16144
16176
  let memoryLine = "";
16145
16177
  try {
16146
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-CI544RLT.js");
16178
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-ZFR5GI7D.js");
16147
16179
  const pending = countPendingMemories2(ctx.config.getConfigDir());
16148
16180
  if (pending > 0) memoryLine = `
16149
16181
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -16956,7 +16988,7 @@ async function handleTest(args, ctx) {
16956
16988
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
16957
16989
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
16958
16990
  }
16959
- const runTests = ctx.runTests ?? (await import("./run-tests-72VNZXNT.js")).executeTests;
16991
+ const runTests = ctx.runTests ?? (await import("./run-tests-USV7IJ7X.js")).executeTests;
16960
16992
  const report = await runTests(testArgs);
16961
16993
  ctx.send({ type: "info", message: report });
16962
16994
  } catch (err) {
@@ -17134,7 +17166,7 @@ async function handleIndex(args, ctx) {
17134
17166
  const sub = (args[0] ?? "status").toLowerCase();
17135
17167
  const root = process.cwd();
17136
17168
  const { loadIndex: loadIndex2, clearIndex } = await import("./store-VO37H6LS.js");
17137
- const { indexProject: indexProject2 } = await import("./indexer-M2LJGTY2.js");
17169
+ const { indexProject: indexProject2 } = await import("./indexer-RBEKMFT4.js");
17138
17170
  const { loadVectorStore, clearVectorStore } = await import("./vector-store-JBAE6PS4.js");
17139
17171
  if (sub === "status") {
17140
17172
  const idx = loadIndex2(root);
@@ -17292,7 +17324,7 @@ async function handleMemory(args, ctx) {
17292
17324
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
17293
17325
  } else if (sub === "export") {
17294
17326
  if (args[1] === "md") {
17295
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-CI544RLT.js");
17327
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-ZFR5GI7D.js");
17296
17328
  ctx.send({
17297
17329
  type: "export_data",
17298
17330
  format: "md",
@@ -18052,9 +18084,19 @@ var SessionHandler = class {
18052
18084
  }
18053
18085
  runLifecycleHooks(hooks, "SessionStart", { source: "web" }, { configDir: this.config.getConfigDir() });
18054
18086
  this.sendStatus();
18055
- askUserContext.rl = null;
18087
+ askUserContext.rl = void 0;
18056
18088
  askUserContext.prompting = false;
18057
18089
  }
18090
+ /**
18091
+ * P3-03:本方法与 `WebCommandContext` 列出的其余 36 个成员一并由 private 放开为
18092
+ * public——它们本就经由 ctx 门面暴露给每一个 web 命令 handler,`private` 只是名义上的。
18093
+ *
18094
+ * `web-command-context.ts` 的文件注释明明白白写着「`ctx: WebCommandContext = this`
18095
+ * 这个赋值保证 handler 只能碰到这些成员」,而 `handleCommand` 实际写的是
18096
+ * `this as unknown as WebCommandContext`——那道保证被这一次 cast 整个绕过了,
18097
+ * 唯一拦着真赋值的就是这些名义上的 private。去掉 cast 之后,SessionHandler 与门面
18098
+ * 接口之间的任何漂移(少一个成员、签名改了)都会当场编译失败,而不是等到运行时。
18099
+ */
18058
18100
  send(msg) {
18059
18101
  if (this.ws.readyState === this.ws.OPEN) {
18060
18102
  this.ws.send(JSON.stringify(msg));
@@ -18423,10 +18465,10 @@ var SessionHandler = class {
18423
18465
  this.processing = false;
18424
18466
  return;
18425
18467
  }
18426
- const hasToolSupport = typeof provider.chatWithTools === "function";
18427
- const { toolDefs, mcpBudgetNote } = hasToolSupport ? this.getFilteredToolDefs() : { toolDefs: [], mcpBudgetNote: null };
18428
- if (hasToolSupport && toolDefs.length > 0) {
18429
- await this.handleChatWithTools(provider, session.messages, toolDefs, mcpBudgetNote, routingDecision.model);
18468
+ const toolCapable = isToolCapableProvider(provider) ? provider : null;
18469
+ const { toolDefs, mcpBudgetNote } = toolCapable ? this.getFilteredToolDefs() : { toolDefs: [], mcpBudgetNote: null };
18470
+ if (toolCapable && toolDefs.length > 0) {
18471
+ await this.handleChatWithTools(toolCapable, session.messages, toolDefs, mcpBudgetNote, routingDecision.model);
18430
18472
  } else {
18431
18473
  await this.handleChatSimple(provider, session.messages, routingDecision.model);
18432
18474
  }
@@ -158,7 +158,7 @@ ${content}`);
158
158
  }
159
159
  }
160
160
  async function runTaskMode(config, providers, configManager, topic) {
161
- const { TaskOrchestrator } = await import("./task-orchestrator-DJN36HP5.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-G2MQDNGQ.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ import {
28
28
  setupProxy,
29
29
  snapshotFile,
30
30
  stripRoutingTags
31
- } from "./chunk-MCKUGWOY.js";
31
+ } from "./chunk-HJVKCOAG.js";
32
32
  import {
33
33
  CostTracker,
34
34
  computeCost,
@@ -48,6 +48,7 @@ import {
48
48
  getRecentlyDeniedAutoActions,
49
49
  googleSearchContext,
50
50
  isInterrupted,
51
+ isToolCapableProvider,
51
52
  lastResponseStore,
52
53
  renderDiff,
53
54
  requestInterrupt,
@@ -57,7 +58,7 @@ import {
57
58
  setMaxOutputCap,
58
59
  spawnAgentContext,
59
60
  undoStack
60
- } from "./chunk-NXNXWM6H.js";
61
+ } from "./chunk-KIGKL3PZ.js";
61
62
  import {
62
63
  buildReviewPrompt,
63
64
  buildSecurityReviewPrompt
@@ -98,8 +99,8 @@ import {
98
99
  touchMemoryReferences,
99
100
  updateMemoryApproval,
100
101
  updateMemoryEntry
101
- } from "./chunk-KWSGSSWN.js";
102
- import "./chunk-GLSR2NR3.js";
102
+ } from "./chunk-7BO5H2QI.js";
103
+ import "./chunk-4DEMGCK4.js";
103
104
  import "./chunk-UUSRWSSX.js";
104
105
  import "./chunk-CKH4KQ4E.js";
105
106
  import "./chunk-BXP6YZ2P.js";
@@ -122,7 +123,7 @@ import {
122
123
  formatDoctorReport,
123
124
  loadContextFiles,
124
125
  writeCrashLog
125
- } from "./chunk-WYDP2WEQ.js";
126
+ } from "./chunk-7IPMONKZ.js";
126
127
  import {
127
128
  describePlugin,
128
129
  getActivePluginAssets,
@@ -139,14 +140,14 @@ import {
139
140
  trustHook,
140
141
  trustPlugin,
141
142
  untrustHook
142
- } from "./chunk-AOISQVXS.js";
143
+ } from "./chunk-UWQCTTP4.js";
143
144
  import {
144
145
  ProviderRegistry,
145
146
  listBuiltInProviderMetadata
146
- } from "./chunk-4KTK2OYU.js";
147
+ } from "./chunk-UGY5SVNX.js";
147
148
  import {
148
149
  ConfigManager
149
- } from "./chunk-VF7DMSKF.js";
150
+ } from "./chunk-OCOGYIRY.js";
150
151
  import {
151
152
  CONTENT_ONLY_STREAM_REMINDER,
152
153
  TEE_FINAL_USER_NUDGE,
@@ -184,7 +185,7 @@ import {
184
185
  import {
185
186
  fileCheckpoints
186
187
  } from "./chunk-4BKXL7SM.js";
187
- import "./chunk-OMBKLWLJ.js";
188
+ import "./chunk-3VFOXEIL.js";
188
189
  import {
189
190
  AGENTIC_BEHAVIOR_GUIDELINE,
190
191
  AUTHOR,
@@ -202,7 +203,7 @@ import {
202
203
  SKILLS_DIR_NAME,
203
204
  VERSION,
204
205
  buildUserIdentityPrompt
205
- } from "./chunk-FLDYAXJR.js";
206
+ } from "./chunk-ZP3RCZKM.js";
206
207
 
207
208
  // src/index.ts
208
209
  import { program } from "commander";
@@ -1408,7 +1409,7 @@ No tools match "${filter}".
1408
1409
  const { join: join6 } = await import("path");
1409
1410
  const { existsSync: existsSync6 } = await import("fs");
1410
1411
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1411
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-WO7ERENL.js");
1412
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-N3CHKZJY.js");
1412
1413
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1413
1414
  const cwd = process.cwd();
1414
1415
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2328,7 +2329,7 @@ function createReviewCommands() {
2328
2329
  usage: "/test [command|filter]",
2329
2330
  async execute(args, ctx) {
2330
2331
  try {
2331
- const { executeTests } = await import("./run-tests-JJ3KOY5E.js");
2332
+ const { executeTests } = await import("./run-tests-76M6AC3G.js");
2332
2333
  const argStr = args.join(" ").trim();
2333
2334
  let testArgs = {};
2334
2335
  if (argStr) {
@@ -2590,7 +2591,7 @@ function createMemoryCommands() {
2590
2591
  const sub = (args[0] ?? "status").toLowerCase();
2591
2592
  const root = process.cwd();
2592
2593
  const { loadIndex, clearIndex } = await import("./store-MWNHVGJT.js");
2593
- const { indexProject } = await import("./indexer-VZETNE4H.js");
2594
+ const { indexProject } = await import("./indexer-TNDWGFRI.js");
2594
2595
  const { loadVectorStore, clearVectorStore } = await import("./vector-store-BBDXB5IQ.js");
2595
2596
  if (sub === "status") {
2596
2597
  const idx = loadIndex(root);
@@ -4765,7 +4766,7 @@ function removePreviousGrapheme(line, cursor) {
4765
4766
  };
4766
4767
  }
4767
4768
  function installUnicodeBackspaceRepair(input, rl, shouldHandle = () => true) {
4768
- const editable = rl;
4769
+ const editable = rlInternal(rl);
4769
4770
  let previous = { line: editable.line, cursor: editable.cursor };
4770
4771
  const onKeypress = (_character, key) => {
4771
4772
  const current = { line: editable.line, cursor: editable.cursor };
@@ -5543,8 +5544,7 @@ ${ctxLine}` : "")
5543
5544
  showPrompt() {
5544
5545
  this.firstPromptShown = true;
5545
5546
  this.refreshPrompt();
5546
- const rlInternal2 = this.rl;
5547
- rlInternal2.prevRows = 0;
5547
+ rlInternal(this.rl).prevRows = 0;
5548
5548
  this.rl.prompt();
5549
5549
  }
5550
5550
  async start() {
@@ -5690,7 +5690,7 @@ Session '${this.resumeSessionId}' not found.
5690
5690
  }
5691
5691
  void (async () => {
5692
5692
  try {
5693
- const { indexProject } = await import("./indexer-VZETNE4H.js");
5693
+ const { indexProject } = await import("./indexer-TNDWGFRI.js");
5694
5694
  const { loadIndex } = await import("./store-MWNHVGJT.js");
5695
5695
  const root = process.cwd();
5696
5696
  const existed = loadIndex(root);
@@ -5884,10 +5884,10 @@ Session '${this.resumeSessionId}' not found.
5884
5884
  processing = false;
5885
5885
  if (this.running) {
5886
5886
  rlAny.output = savedOutput;
5887
- const rlInternal2 = this.rl;
5888
- rlInternal2.line = "";
5889
- rlInternal2.cursor = 0;
5890
- rlInternal2.paused = false;
5887
+ const internal = rlInternal(this.rl);
5888
+ internal.line = "";
5889
+ internal.cursor = 0;
5890
+ internal.paused = false;
5891
5891
  process.stdin.resume();
5892
5892
  this.showPrompt();
5893
5893
  } else {
@@ -6012,8 +6012,7 @@ Session '${this.resumeSessionId}' not found.
6012
6012
  const t0 = Date.now();
6013
6013
  try {
6014
6014
  const provider = this.providers.get(this.currentProvider);
6015
- const supportsTools = "chatWithTools" in provider;
6016
- if (supportsTools) {
6015
+ if (isToolCapableProvider(provider)) {
6017
6016
  await this.handleChatWithTools(
6018
6017
  provider,
6019
6018
  session.messages,
@@ -6675,11 +6674,10 @@ ${mcpBudgetNote}` : "");
6675
6674
  this.providers,
6676
6675
  fallbackOpts,
6677
6676
  (p, m) => {
6678
- const tc = p;
6679
- if (typeof tc.chatWithToolsStream !== "function") {
6677
+ if (typeof p.chatWithToolsStream !== "function") {
6680
6678
  throw new Error(`provider ${p.info.id} does not support streaming tool calls`);
6681
6679
  }
6682
- return tc.chatWithToolsStream({ ...chatRequest, model: m, signal: streamAc.signal }, toolDefs);
6680
+ return p.chatWithToolsStream({ ...chatRequest, model: m, signal: streamAc.signal }, toolDefs);
6683
6681
  }
6684
6682
  );
6685
6683
  const streamResult = await this.consumeToolStream(streamGen, spinner);
@@ -6707,10 +6705,12 @@ ${mcpBudgetNote}` : "");
6707
6705
  effectiveModel,
6708
6706
  this.providers,
6709
6707
  fallbackOpts,
6710
- (p, m) => p.chatWithTools(
6711
- { ...chatRequest, model: m, signal },
6712
- toolDefs
6713
- )
6708
+ (p, m) => {
6709
+ if (!isToolCapableProvider(p)) {
6710
+ throw new Error(`provider ${p.info.id} does not support tool calls`);
6711
+ }
6712
+ return p.chatWithTools({ ...chatRequest, model: m, signal }, toolDefs);
6713
+ }
6714
6714
  ),
6715
6715
  // 中断:以 host-stop 正常收尾,不为一次主动取消喷 provider 报错
6716
6716
  () => ({ toolCalls: [], content: "", stopLoop: true })
@@ -7278,9 +7278,9 @@ Tip: You can continue the conversation by asking the AI to proceed.`
7278
7278
  select: (prompt, items, initialIndex) => {
7279
7279
  this.selecting = true;
7280
7280
  return selectFromList(prompt, items, initialIndex).finally(() => {
7281
- const rlInternal2 = this.rl;
7282
- rlInternal2.line = "";
7283
- rlInternal2.cursor = 0;
7281
+ const internal = rlInternal(this.rl);
7282
+ internal.line = "";
7283
+ internal.cursor = 0;
7284
7284
  process.stdin.pause();
7285
7285
  setImmediate(() => {
7286
7286
  this.selecting = false;
@@ -7400,9 +7400,8 @@ Tip: You can continue the conversation by asking the AI to proceed.`
7400
7400
  if (!session) return;
7401
7401
  session.addMessage({ role: "user", content: message, timestamp: /* @__PURE__ */ new Date() });
7402
7402
  const provider = this.providers.get(this.currentProvider);
7403
- const toolCapable = provider;
7404
- if (typeof toolCapable.chatWithTools === "function") {
7405
- await this.handleChatWithTools(toolCapable, session.messages);
7403
+ if (isToolCapableProvider(provider)) {
7404
+ await this.handleChatWithTools(provider, session.messages);
7406
7405
  } else {
7407
7406
  await this.handleChatSimple(provider, session.messages);
7408
7407
  }
@@ -7560,7 +7559,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7560
7559
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7561
7560
  process.exit(1);
7562
7561
  }
7563
- const { startWebServer } = await import("./server-JMXC2N3F.js");
7562
+ const { startWebServer } = await import("./server-C523CIGN.js");
7564
7563
  await startWebServer({ port, host: options.host });
7565
7564
  });
7566
7565
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
@@ -7727,11 +7726,11 @@ program.command("sessions").description("List recent conversation sessions").opt
7727
7726
  console.log(footer + "\n");
7728
7727
  });
7729
7728
  program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
7730
- const { runUsageCli } = await import("./usage-HXJVDETY.js");
7729
+ const { runUsageCli } = await import("./usage-EFHXXMYX.js");
7731
7730
  await runUsageCli(options);
7732
7731
  });
7733
7732
  program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
7734
- const { runDoctorCli } = await import("./doctor-cli-BGGILTHE.js");
7733
+ const { runDoctorCli } = await import("./doctor-cli-Z3TGHTSX.js");
7735
7734
  const argv = process.argv.slice(2);
7736
7735
  await runDoctorCli({
7737
7736
  json: !!options.json || argv.includes("--json"),
@@ -7740,7 +7739,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
7740
7739
  });
7741
7740
  program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
7742
7741
  try {
7743
- const batch = await import("./batch-F7SKIBI3.js");
7742
+ const batch = await import("./batch-2I5TPZA2.js");
7744
7743
  switch (action) {
7745
7744
  case "submit":
7746
7745
  if (!arg) {
@@ -7783,7 +7782,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7783
7782
  }
7784
7783
  });
7785
7784
  program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
7786
- const { startMcpServer } = await import("./server-QJHCJDA7.js");
7785
+ const { startMcpServer } = await import("./server-R7D5RR36.js");
7787
7786
  await startMcpServer({
7788
7787
  allowDestructive: !!options.allowDestructive,
7789
7788
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7796,7 +7795,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
7796
7795
  console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
7797
7796
  process.exit(1);
7798
7797
  }
7799
- const { runPrCli } = await import("./pr-24REDMGV.js");
7798
+ const { runPrCli } = await import("./pr-ZUGSWQ5R.js");
7800
7799
  const result = await runPrCli({
7801
7800
  action,
7802
7801
  target,
@@ -7816,8 +7815,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
7816
7815
  process.exit(result.exitCode);
7817
7816
  });
7818
7817
  program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number or URL; diff fetched via gh pr diff <value>", (v) => /^#?\d+$/.test(v) ? parseInt(v.replace(/^#/, ""), 10) : v).option("--base <ref>", "Base ref for git diff <ref>...HEAD (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").option("--json", "Output a structured JSON report").option("--markdown", "Output Markdown report (default)").option("--sarif", "Output SARIF 2.1.0 for code scanning artifacts").option("--fail-on-security-high", "Fail when the security review contains HIGH/CRITICAL findings (default)").option("--no-fail-on-security-high", "Do not fail on security HIGH/CRITICAL findings").option("--fail-on-test-failure", "Fail when the report mentions test failures (default)").option("--no-fail-on-test-failure", "Do not fail on test failure findings").option("--fail-on-lint-failure", "Fail when the report mentions lint/typecheck failures (default)").option("--no-fail-on-lint-failure", "Do not fail on lint/typecheck failure findings").action(async (options) => {
7819
- const { runCi } = await import("./ci-VURFRMWQ.js");
7820
- const { formatCiResult } = await import("./ci-format-AFJJIURF.js");
7818
+ const { runCi } = await import("./ci-JFC45LIS.js");
7819
+ const { formatCiResult } = await import("./ci-format-P3LIZHUR.js");
7821
7820
  const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
7822
7821
  if (formats > 1) {
7823
7822
  console.error("Choose only one output format: --json, --markdown, or --sarif.");
@@ -7975,7 +7974,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7975
7974
  config.get("customProviders"),
7976
7975
  config.getConfigDir()
7977
7976
  );
7978
- const { startHub } = await import("./hub-Z73RLNJI.js");
7977
+ const { startHub } = await import("./hub-NEWIFMQ3.js");
7979
7978
  await startHub(
7980
7979
  {
7981
7980
  topic: topic ?? "",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  indexProject,
3
3
  updateFile
4
- } from "./chunk-QCG6UU2S.js";
4
+ } from "./chunk-PPIISCFN.js";
5
5
  import "./chunk-RWM2GFRC.js";
6
6
  import "./chunk-6BUTA5VW.js";
7
7
  export {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  indexProject,
4
4
  updateFile
5
- } from "./chunk-GLSR2NR3.js";
5
+ } from "./chunk-4DEMGCK4.js";
6
6
  import "./chunk-CKH4KQ4E.js";
7
7
  import "./chunk-IW3Q7AE5.js";
8
8
  export {
@@ -28,11 +28,11 @@ import {
28
28
  touchMemoryReferences,
29
29
  updateMemoryApproval,
30
30
  updateMemoryEntry
31
- } from "./chunk-KWSGSSWN.js";
31
+ } from "./chunk-7BO5H2QI.js";
32
32
  import "./chunk-3FEZSLGI.js";
33
33
  import "./chunk-HOSJZMQS.js";
34
34
  import "./chunk-IW3Q7AE5.js";
35
- import "./chunk-FLDYAXJR.js";
35
+ import "./chunk-ZP3RCZKM.js";
36
36
  export {
37
37
  addMemoryEntry,
38
38
  backupMemoryStore,
@@ -27,9 +27,9 @@ import {
27
27
  touchMemoryReferences,
28
28
  updateMemoryApproval,
29
29
  updateMemoryEntry
30
- } from "./chunk-4NH4Q7QK.js";
30
+ } from "./chunk-7YYUITED.js";
31
31
  import "./chunk-FSC6KEWU.js";
32
- import "./chunk-UNL7NR55.js";
32
+ import "./chunk-Z752LDYF.js";
33
33
  import "./chunk-6BUTA5VW.js";
34
34
  export {
35
35
  addMemoryEntry,