jinzd-ai-cli 0.4.287 → 0.4.289

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 (32) hide show
  1. package/dist/{batch-6OH7D5YU.js → batch-GVD4CZZQ.js} +2 -2
  2. package/dist/{chunk-UDFK5Q52.js → chunk-25VQORAZ.js} +1 -1
  3. package/dist/{chunk-5F7BGV72.js → chunk-2SQCGJ6H.js} +1 -1
  4. package/dist/{chunk-AXSWLNCU.js → chunk-AA6PZRJO.js} +104 -127
  5. package/dist/{chunk-L7RAEUUN.js → chunk-BDN6ZCPQ.js} +1 -1
  6. package/dist/{chunk-HNUT4STJ.js → chunk-BW4H53KI.js} +7 -7
  7. package/dist/{chunk-L625B2XV.js → chunk-GXB5EOFI.js} +1 -1
  8. package/dist/{chunk-3BHJKMPQ.js → chunk-I73JWHNT.js} +1 -1
  9. package/dist/{chunk-RZVGR3KD.js → chunk-NP446QJS.js} +3 -3
  10. package/dist/{chunk-CYUAHF6X.js → chunk-NWM7CTQQ.js} +1 -1
  11. package/dist/{chunk-HEUB5PV6.js → chunk-QL2QACHI.js} +1 -1
  12. package/dist/{chunk-3Y5BCGD2.js → chunk-TKG6BI6G.js} +1 -1
  13. package/dist/{chunk-ERDFOXYK.js → chunk-TOH67ARY.js} +1 -1
  14. package/dist/{chunk-EU6NMK7G.js → chunk-VIDUFFHT.js} +3 -3
  15. package/dist/{ci-WXCMI4ND.js → ci-U7X5OWOA.js} +4 -4
  16. package/dist/{ci-format-JXD2BQM6.js → ci-format-PDP5K5LR.js} +2 -2
  17. package/dist/{constants-2B7CN2ER.js → constants-GBIMYBKD.js} +1 -1
  18. package/dist/{constants-SRRV3K5Y.js → constants-MYTDRODA.js} +1 -1
  19. package/dist/{doctor-cli-LQYTDJ74.js → doctor-cli-64WRAKH3.js} +4 -4
  20. package/dist/electron-server.js +143 -238
  21. package/dist/{hub-Y62P5MIA.js → hub-FSITPTD5.js} +1 -1
  22. package/dist/index.js +18 -17
  23. package/dist/{persistent-memory-46JSUEYV.js → persistent-memory-7GPL7NSO.js} +2 -2
  24. package/dist/{persistent-memory-3N2XQKJK.js → persistent-memory-7PPH6QES.js} +2 -2
  25. package/dist/{pr-L7Y3XHGL.js → pr-T7VURNFJ.js} +4 -4
  26. package/dist/{run-tests-WC644BHH.js → run-tests-CSAB2M4A.js} +2 -2
  27. package/dist/{run-tests-3ZOMRFIX.js → run-tests-PPTDYVS7.js} +2 -2
  28. package/dist/{server-XWURZCAF.js → server-6B2JFKRN.js} +53 -117
  29. package/dist/{server-L4QHJT2I.js → server-O54U4OOB.js} +5 -5
  30. package/dist/{task-orchestrator-6TVKJYKC.js → task-orchestrator-HA4JE4TF.js} +5 -5
  31. package/dist/{usage-L2PSI2KH.js → usage-HX6MPQT2.js} +2 -2
  32. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  setupProxy,
25
25
  snapshotFile,
26
26
  stripRoutingTags
27
- } from "./chunk-HNUT4STJ.js";
27
+ } from "./chunk-BW4H53KI.js";
28
28
  import {
29
29
  CostTracker,
30
30
  getPricing,
@@ -49,7 +49,7 @@ import {
49
49
  setMaxOutputCap,
50
50
  spawnAgentContext,
51
51
  undoStack
52
- } from "./chunk-AXSWLNCU.js";
52
+ } from "./chunk-AA6PZRJO.js";
53
53
  import "./chunk-HLWUDRBO.js";
54
54
  import {
55
55
  NO_THINKING,
@@ -62,7 +62,7 @@ import {
62
62
  countPendingMemories,
63
63
  detectStaleLegacyMarkdownEdit,
64
64
  formatMemoryForPrompt
65
- } from "./chunk-ERDFOXYK.js";
65
+ } from "./chunk-TOH67ARY.js";
66
66
  import "./chunk-4DEMGCK4.js";
67
67
  import "./chunk-UUSRWSSX.js";
68
68
  import "./chunk-CKH4KQ4E.js";
@@ -83,14 +83,14 @@ import {
83
83
  import {
84
84
  loadContextFiles,
85
85
  writeCrashLog
86
- } from "./chunk-EU6NMK7G.js";
86
+ } from "./chunk-VIDUFFHT.js";
87
87
  import {
88
88
  getActivePluginAssets,
89
89
  getPendingHookTrust,
90
90
  installFlushOnExit,
91
91
  mergePluginHooks,
92
92
  runLifecycleHooks
93
- } from "./chunk-HEUB5PV6.js";
93
+ } from "./chunk-QL2QACHI.js";
94
94
  import "./chunk-RS7SKYTS.js";
95
95
  import {
96
96
  ProviderRegistry,
@@ -98,7 +98,7 @@ import {
98
98
  } from "./chunk-ALSSNFNK.js";
99
99
  import {
100
100
  ConfigManager
101
- } from "./chunk-5F7BGV72.js";
101
+ } from "./chunk-2SQCGJ6H.js";
102
102
  import {
103
103
  CONTENT_ONLY_STREAM_REMINDER,
104
104
  TEE_FINAL_USER_NUDGE,
@@ -132,7 +132,7 @@ import {
132
132
  } from "./chunk-IW3Q7AE5.js";
133
133
  import "./chunk-XNFIYS7G.js";
134
134
  import "./chunk-4BKXL7SM.js";
135
- import "./chunk-L7RAEUUN.js";
135
+ import "./chunk-BDN6ZCPQ.js";
136
136
  import {
137
137
  AGENTIC_BEHAVIOR_GUIDELINE,
138
138
  AUTHOR,
@@ -149,7 +149,7 @@ import {
149
149
  SKILLS_DIR_NAME,
150
150
  VERSION,
151
151
  buildUserIdentityPrompt
152
- } from "./chunk-UDFK5Q52.js";
152
+ } from "./chunk-25VQORAZ.js";
153
153
 
154
154
  // src/index.ts
155
155
  import { program } from "commander";
@@ -3028,6 +3028,7 @@ Session '${this.resumeSessionId}' not found.
3028
3028
  let toolDefs;
3029
3029
  let mcpBudgetNote = null;
3030
3030
  const usedMcpToolNames = /* @__PURE__ */ new Set();
3031
+ this.toolExecutor.planMode = this.planMode;
3031
3032
  if (this.planMode) {
3032
3033
  toolDefs = this.toolRegistry.getDefinitions().filter((t) => PLAN_MODE_READONLY_TOOLS.has(t.name));
3033
3034
  } else {
@@ -3990,7 +3991,7 @@ program.command("web").description("Start Web UI server with browser-based chat
3990
3991
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
3991
3992
  process.exit(1);
3992
3993
  }
3993
- const { startWebServer } = await import("./server-XWURZCAF.js");
3994
+ const { startWebServer } = await import("./server-6B2JFKRN.js");
3994
3995
  await startWebServer({ port, host: options.host });
3995
3996
  });
3996
3997
  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) => {
@@ -4157,11 +4158,11 @@ program.command("sessions").description("List recent conversation sessions").opt
4157
4158
  console.log(footer + "\n");
4158
4159
  });
4159
4160
  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) => {
4160
- const { runUsageCli } = await import("./usage-L2PSI2KH.js");
4161
+ const { runUsageCli } = await import("./usage-HX6MPQT2.js");
4161
4162
  await runUsageCli(options);
4162
4163
  });
4163
4164
  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) => {
4164
- const { runDoctorCli } = await import("./doctor-cli-LQYTDJ74.js");
4165
+ const { runDoctorCli } = await import("./doctor-cli-64WRAKH3.js");
4165
4166
  const argv = process.argv.slice(2);
4166
4167
  await runDoctorCli({
4167
4168
  json: !!options.json || argv.includes("--json"),
@@ -4170,7 +4171,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
4170
4171
  });
4171
4172
  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) => {
4172
4173
  try {
4173
- const batch = await import("./batch-6OH7D5YU.js");
4174
+ const batch = await import("./batch-GVD4CZZQ.js");
4174
4175
  switch (action) {
4175
4176
  case "submit":
4176
4177
  if (!arg) {
@@ -4213,7 +4214,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
4213
4214
  }
4214
4215
  });
4215
4216
  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) => {
4216
- const { startMcpServer } = await import("./server-L4QHJT2I.js");
4217
+ const { startMcpServer } = await import("./server-O54U4OOB.js");
4217
4218
  await startMcpServer({
4218
4219
  allowDestructive: !!options.allowDestructive,
4219
4220
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -4226,7 +4227,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
4226
4227
  console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
4227
4228
  process.exit(1);
4228
4229
  }
4229
- const { runPrCli } = await import("./pr-L7Y3XHGL.js");
4230
+ const { runPrCli } = await import("./pr-T7VURNFJ.js");
4230
4231
  const result = await runPrCli({
4231
4232
  action,
4232
4233
  target,
@@ -4246,8 +4247,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
4246
4247
  process.exit(result.exitCode);
4247
4248
  });
4248
4249
  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) => {
4249
- const { runCi } = await import("./ci-WXCMI4ND.js");
4250
- const { formatCiResult } = await import("./ci-format-JXD2BQM6.js");
4250
+ const { runCi } = await import("./ci-U7X5OWOA.js");
4251
+ const { formatCiResult } = await import("./ci-format-PDP5K5LR.js");
4251
4252
  const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
4252
4253
  if (formats > 1) {
4253
4254
  console.error("Choose only one output format: --json, --markdown, or --sarif.");
@@ -4405,7 +4406,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
4405
4406
  config.get("customProviders"),
4406
4407
  config.getConfigDir()
4407
4408
  );
4408
- const { startHub } = await import("./hub-Y62P5MIA.js");
4409
+ const { startHub } = await import("./hub-FSITPTD5.js");
4409
4410
  await startHub(
4410
4411
  {
4411
4412
  topic: topic ?? "",
@@ -28,11 +28,11 @@ import {
28
28
  touchMemoryReferences,
29
29
  updateMemoryApproval,
30
30
  updateMemoryEntry
31
- } from "./chunk-ERDFOXYK.js";
31
+ } from "./chunk-TOH67ARY.js";
32
32
  import "./chunk-3FEZSLGI.js";
33
33
  import "./chunk-HOSJZMQS.js";
34
34
  import "./chunk-IW3Q7AE5.js";
35
- import "./chunk-UDFK5Q52.js";
35
+ import "./chunk-25VQORAZ.js";
36
36
  export {
37
37
  addMemoryEntry,
38
38
  backupMemoryStore,
@@ -27,11 +27,11 @@ import {
27
27
  touchMemoryReferences,
28
28
  updateMemoryApproval,
29
29
  updateMemoryEntry
30
- } from "./chunk-L625B2XV.js";
30
+ } from "./chunk-GXB5EOFI.js";
31
31
  import "./chunk-FSC6KEWU.js";
32
32
  import "./chunk-6BUTA5VW.js";
33
33
  import "./chunk-CGLYJRFA.js";
34
- import "./chunk-CYUAHF6X.js";
34
+ import "./chunk-NWM7CTQQ.js";
35
35
  export {
36
36
  addMemoryEntry,
37
37
  backupMemoryStore,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  countSeverity,
4
4
  runCi
5
- } from "./chunk-RZVGR3KD.js";
6
- import "./chunk-3Y5BCGD2.js";
5
+ } from "./chunk-NP446QJS.js";
6
+ import "./chunk-TKG6BI6G.js";
7
7
  import {
8
8
  buildReviewPrompt,
9
9
  buildSecurityReviewPrompt,
@@ -17,13 +17,13 @@ import {
17
17
  } from "./chunk-ALSSNFNK.js";
18
18
  import {
19
19
  ConfigManager
20
- } from "./chunk-5F7BGV72.js";
20
+ } from "./chunk-2SQCGJ6H.js";
21
21
  import "./chunk-TEXT4DAT.js";
22
22
  import "./chunk-TU3L3PW7.js";
23
23
  import "./chunk-IW3Q7AE5.js";
24
24
  import {
25
25
  VERSION
26
- } from "./chunk-UDFK5Q52.js";
26
+ } from "./chunk-25VQORAZ.js";
27
27
 
28
28
  // src/cli/pr.ts
29
29
  import { execFileSync } from "child_process";
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-L7RAEUUN.js";
6
- import "./chunk-UDFK5Q52.js";
5
+ } from "./chunk-BDN6ZCPQ.js";
6
+ import "./chunk-25VQORAZ.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-3BHJKMPQ.js";
5
- import "./chunk-CYUAHF6X.js";
4
+ } from "./chunk-I73JWHNT.js";
5
+ import "./chunk-NWM7CTQQ.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -81,7 +81,7 @@ import {
81
81
  skillHistoryNote,
82
82
  snapshotFile,
83
83
  stripRoutingTags
84
- } from "./chunk-HNUT4STJ.js";
84
+ } from "./chunk-BW4H53KI.js";
85
85
  import {
86
86
  CNY_PER_USD,
87
87
  CostTracker,
@@ -100,9 +100,11 @@ import {
100
100
  cleanupRejectedTeeFile,
101
101
  clearBashSession,
102
102
  clearRecentlyDeniedAutoActions,
103
+ decideToolGate,
103
104
  defaultActionClassifier,
104
105
  estimateTokens,
105
106
  formatPermissionProfileWarning,
107
+ gateMessages,
106
108
  getPreferredAgentName,
107
109
  getRecentlyDeniedAutoActions,
108
110
  googleSearchContext,
@@ -110,6 +112,7 @@ import {
110
112
  isToolCapableProvider,
111
113
  listAgentConfigs,
112
114
  listAgentRuns,
115
+ needsPermissionRequestHook,
113
116
  recordRecentlyDeniedAutoAction,
114
117
  renderDiff,
115
118
  requestAgentStop,
@@ -123,7 +126,7 @@ import {
123
126
  spawnAgentContext,
124
127
  truncateOutput,
125
128
  undoStack
126
- } from "./chunk-AXSWLNCU.js";
129
+ } from "./chunk-AA6PZRJO.js";
127
130
  import {
128
131
  buildReviewPrompt,
129
132
  buildSecurityReviewPrompt
@@ -150,7 +153,7 @@ import {
150
153
  restoreMemoryEntries,
151
154
  updateMemoryApproval,
152
155
  updateMemoryEntry
153
- } from "./chunk-ERDFOXYK.js";
156
+ } from "./chunk-TOH67ARY.js";
154
157
  import "./chunk-4DEMGCK4.js";
155
158
  import "./chunk-UUSRWSSX.js";
156
159
  import "./chunk-CKH4KQ4E.js";
@@ -169,7 +172,7 @@ import {
169
172
  buildDoctorReport,
170
173
  formatDoctorReport,
171
174
  loadContextFiles
172
- } from "./chunk-EU6NMK7G.js";
175
+ } from "./chunk-VIDUFFHT.js";
173
176
  import {
174
177
  describePlugin,
175
178
  getActivePluginAssets,
@@ -184,14 +187,14 @@ import {
184
187
  runTool,
185
188
  setPluginEnabled,
186
189
  trustPlugin
187
- } from "./chunk-HEUB5PV6.js";
190
+ } from "./chunk-QL2QACHI.js";
188
191
  import "./chunk-RS7SKYTS.js";
189
192
  import {
190
193
  ProviderRegistry
191
194
  } from "./chunk-ALSSNFNK.js";
192
195
  import {
193
196
  ConfigManager
194
- } from "./chunk-5F7BGV72.js";
197
+ } from "./chunk-2SQCGJ6H.js";
195
198
  import {
196
199
  CONTENT_ONLY_STREAM_REMINDER,
197
200
  TEE_FINAL_USER_NUDGE,
@@ -203,6 +206,7 @@ import {
203
206
  evaluateTeeContent,
204
207
  freshPriorContent,
205
208
  getDangerLevel,
209
+ isAbortError,
206
210
  runAgentLoop,
207
211
  stripToolCallReminder,
208
212
  teeStreamErrorSummary
@@ -221,7 +225,7 @@ import {
221
225
  maskConfigSecrets
222
226
  } from "./chunk-XNFIYS7G.js";
223
227
  import "./chunk-4BKXL7SM.js";
224
- import "./chunk-L7RAEUUN.js";
228
+ import "./chunk-BDN6ZCPQ.js";
225
229
  import {
226
230
  AGENTIC_BEHAVIOR_GUIDELINE,
227
231
  AUTHOR,
@@ -237,7 +241,7 @@ import {
237
241
  SKILLS_DIR_NAME,
238
242
  VERSION,
239
243
  buildUserIdentityPrompt
240
- } from "./chunk-UDFK5Q52.js";
244
+ } from "./chunk-25VQORAZ.js";
241
245
 
242
246
  // src/web/server.ts
243
247
  import express from "express";
@@ -283,6 +287,14 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
283
287
  sessionAutoApprove = false;
284
288
  /** Session-level Auto Mode: rule-based low-risk auto approval. */
285
289
  sessionAutoMode = false;
290
+ /**
291
+ * Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
292
+ *
293
+ * 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
294
+ * 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
295
+ * 放行——只读保护形同虚设(审计 P2-01)。
296
+ */
297
+ planMode = false;
286
298
  /** Track tool start times for duration calculation */
287
299
  toolStartTimes = /* @__PURE__ */ new Map();
288
300
  /**
@@ -488,15 +500,6 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
488
500
  { configDir: this.hookConfigDir, onSummary: (message) => this.send({ type: "info", message: `[hook] ${message}` }) }
489
501
  );
490
502
  const preDeny = preToolDecisions.find((d) => d.action === "deny");
491
- if (preDeny) {
492
- const result = {
493
- callId: call.id,
494
- content: `[Hook denied] ${preDeny.reason ?? `PreToolUse blocked ${call.name}`}. Do not retry without asking.`,
495
- isError: true
496
- };
497
- this.sendToolCallResult(call, result.content, true);
498
- return result;
499
- }
500
503
  for (const d of preToolDecisions) {
501
504
  const warnings = [d.warning, ...d.warnings ?? []].filter(Boolean);
502
505
  for (const warning of warnings) this.send({ type: "info", message: `[hook] ${warning}` });
@@ -516,7 +519,20 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
516
519
  }
517
520
  );
518
521
  const networkPermission = checkNetworkPolicy(call.name, call.arguments, this.networkPolicy);
519
- if (networkPermission?.action === "confirm" || permission.action === "confirm") {
522
+ const gate = decideToolGate(call, {
523
+ dangerLevel,
524
+ permission,
525
+ networkPermission,
526
+ hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
527
+ planMode: this.planMode,
528
+ sessionAutoMode: this.sessionAutoMode,
529
+ sessionAutoApprove: this.sessionAutoApprove,
530
+ classify: () => defaultActionClassifier.classify(call, dangerLevel, {
531
+ workspaceRoot: this.workspaceRoot,
532
+ tempDirs: [tmpdir()]
533
+ })
534
+ });
535
+ if (needsPermissionRequestHook({ permission, networkPermission })) {
520
536
  runLifecycleHooks(
521
537
  this.hookConfig,
522
538
  "PermissionRequest",
@@ -524,105 +540,24 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
524
540
  { configDir: this.hookConfigDir, onSummary: (message) => this.send({ type: "info", message: "[hook] " + message }) }
525
541
  );
526
542
  }
527
- if (networkPermission?.action === "deny") {
528
- const reason = networkPermission.reason ? ` (${networkPermission.reason})` : "";
529
- return {
530
- callId: call.id,
531
- content: `[Permission denied] Tool ${call.name} is blocked by networkPolicy${reason}. Do not retry.`,
532
- isError: true
533
- };
534
- }
535
- if (permission.action === "deny") {
536
- const reason = permission.reason ? ` (${permission.reason})` : "";
537
- return {
538
- callId: call.id,
539
- content: `[Permission denied] Tool ${call.name} is blocked by permission profile "${permission.profileName}"${reason}. Do not retry.`,
540
- isError: true
541
- };
543
+ if (gate.kind === "denied") {
544
+ if (gate.source === "auto-mode") recordRecentlyDeniedAutoAction(call, gate.classification);
545
+ this.sendToolCallResult(call, gate.message, true);
546
+ return { callId: call.id, content: gate.message, isError: true };
542
547
  }
543
- if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
544
- this.sendToolCallStart(call);
545
- try {
546
- const rawContent = await runTool(tool, call.arguments, call.name);
547
- const content = truncateOutput(rawContent, call.name);
548
- this.sendToolCallResult(call, rawContent, false);
549
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
550
- runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
551
- return { callId: call.id, content, isError: false };
552
- } catch (err) {
553
- const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
554
- this.sendToolCallResult(call, message, true);
555
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
556
- runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
557
- return { callId: call.id, content: message, isError: true };
548
+ if (gate.kind === "confirm") {
549
+ if (!toolCallStarted) {
550
+ this.sendToolCallStart(call);
551
+ toolCallStarted = true;
558
552
  }
559
- }
560
- const requiresHardConfirmation = permission.action === "confirm" && permission.hardBoundary === true;
561
- if ((networkPermission?.action === "confirm" || requiresHardConfirmation) && dangerLevel === "safe") {
562
- this.sendToolCallStart(call);
563
- toolCallStarted = true;
564
- const confirmed = await this.confirm(call, "write");
553
+ const confirmed = await this.confirm(call, gate.level);
565
554
  if (!confirmed) {
566
- const rejectionMsg = `[User cancelled] The user declined permission for ${call.name}. Do not retry without asking.`;
555
+ const rejectionMsg = gate.source === "permission" ? gateMessages.permissionCancelled(call.name) : gateMessages.operationCancelled(call.name, gate.level);
567
556
  this.sendToolCallResult(call, rejectionMsg, true);
568
557
  return { callId: call.id, content: rejectionMsg, isError: true };
569
558
  }
570
559
  }
571
560
  if (!toolCallStarted) this.sendToolCallStart(call);
572
- if (this.sessionAutoMode && networkPermission?.action !== "confirm") {
573
- const classification = defaultActionClassifier.classify(call, dangerLevel, {
574
- workspaceRoot: this.workspaceRoot,
575
- tempDirs: [tmpdir()]
576
- });
577
- if (classification.decision === "deny") {
578
- recordRecentlyDeniedAutoAction(call, classification);
579
- const rejectionMsg = `[Auto denied] ${classification.reason}. Do not retry without asking.`;
580
- this.sendToolCallResult(call, rejectionMsg, true);
581
- return { callId: call.id, content: rejectionMsg, isError: true };
582
- }
583
- if (classification.decision === "auto-approve" && !requiresHardConfirmation) {
584
- this.send({ type: "info", message: `\u26A1 Auto-approved (/auto: ${classification.ruleId})` });
585
- try {
586
- const rawContent = await runTool(tool, call.arguments, call.name);
587
- const content = truncateOutput(rawContent, call.name);
588
- this.sendToolCallResult(call, rawContent, false);
589
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
590
- runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
591
- return { callId: call.id, content, isError: false };
592
- } catch (err) {
593
- const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
594
- this.sendToolCallResult(call, message, true);
595
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
596
- runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
597
- return { callId: call.id, content: message, isError: true };
598
- }
599
- }
600
- }
601
- if (this.sessionAutoApprove && dangerLevel === "write" && !requiresHardConfirmation) {
602
- try {
603
- const rawContent = await runTool(tool, call.arguments, call.name);
604
- const content = truncateOutput(rawContent, call.name);
605
- this.sendToolCallResult(call, rawContent, false);
606
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
607
- runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
608
- return { callId: call.id, content, isError: false };
609
- } catch (err) {
610
- const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
611
- this.sendToolCallResult(call, message, true);
612
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
613
- runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
614
- return { callId: call.id, content: message, isError: true };
615
- }
616
- }
617
- if (dangerLevel === "write" || dangerLevel === "destructive") {
618
- const confirmed = await this.confirm(call, dangerLevel);
619
- if (!confirmed) {
620
- const label = dangerLevel === "destructive" ? "destructive " : "";
621
- const rejectionMsg = `[User cancelled] The user declined the ${label}${call.name} operation. Do not retry without asking.`;
622
- this.sendToolCallResult(call, rejectionMsg, true);
623
- return { callId: call.id, content: rejectionMsg, isError: true };
624
- }
625
- }
626
561
  try {
627
562
  const rawContent = await runTool(tool, call.arguments, call.name);
628
563
  const content = truncateOutput(rawContent, call.name);
@@ -995,7 +930,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
995
930
  Cost: ${formatCost(cost)}` : "";
996
931
  let memoryLine = "";
997
932
  try {
998
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-46JSUEYV.js");
933
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-7GPL7NSO.js");
999
934
  const pending = countPendingMemories2(ctx.config.getConfigDir());
1000
935
  if (pending > 0) memoryLine = `
1001
936
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -1919,7 +1854,7 @@ async function handleTest(args, ctx) {
1919
1854
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
1920
1855
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
1921
1856
  }
1922
- const runTests = ctx.runTests ?? (await import("./run-tests-WC644BHH.js")).executeTests;
1857
+ const runTests = ctx.runTests ?? (await import("./run-tests-CSAB2M4A.js")).executeTests;
1923
1858
  const report = await runTests(testArgs);
1924
1859
  ctx.send({ type: "info", message: report });
1925
1860
  } catch (err) {
@@ -2194,7 +2129,7 @@ async function handleMemory(args, ctx) {
2194
2129
  }
2195
2130
  if (intent.kind === "status") {
2196
2131
  const { getChatIndexStatus } = await import("./chat-index-2D5GK2DB.js");
2197
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-46JSUEYV.js");
2132
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-7GPL7NSO.js");
2198
2133
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
2199
2134
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
2200
2135
  const view = buildMemoryStatusView({
@@ -2217,7 +2152,7 @@ async function handleMemory(args, ctx) {
2217
2152
  return;
2218
2153
  }
2219
2154
  if (intent.kind === "recall") {
2220
- const { searchPersistentMemories, touchMemoryReferences } = await import("./persistent-memory-46JSUEYV.js");
2155
+ const { searchPersistentMemories, touchMemoryReferences } = await import("./persistent-memory-7GPL7NSO.js");
2221
2156
  const { searchChatMemory } = await import("./chat-index-2D5GK2DB.js");
2222
2157
  const persistentHits = searchPersistentMemories(configDir, intent.query, process.cwd(), 3);
2223
2158
  if (persistentHits.length > 0) {
@@ -2338,7 +2273,7 @@ async function handleMemory(args, ctx) {
2338
2273
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
2339
2274
  } else if (intent.kind === "export") {
2340
2275
  if (args[1] === "md") {
2341
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-46JSUEYV.js");
2276
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-7GPL7NSO.js");
2342
2277
  ctx.send({
2343
2278
  type: "export_data",
2344
2279
  format: "md",
@@ -3344,7 +3279,7 @@ var SessionHandler = class {
3344
3279
  ...simpleReasoning ? { reasoningContent: simpleReasoning } : {}
3345
3280
  });
3346
3281
  } catch (err) {
3347
- if (err.name === "AbortError") {
3282
+ if (isAbortError(err)) {
3348
3283
  this.send({ type: "info", message: "[interrupted]" });
3349
3284
  } else {
3350
3285
  throw err;
@@ -3361,7 +3296,7 @@ var SessionHandler = class {
3361
3296
  const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
3362
3297
  const autoPauseInterval = typeof autoPauseIntervalRaw === "number" ? autoPauseIntervalRaw : 50;
3363
3298
  const { stable: toolStable, volatile: toolVolatile } = this.buildSystemPrompt();
3364
- const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval });
3299
+ const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval, planMode: this.planMode });
3365
3300
  const systemPrompt = toolStable + TOOL_CALL_REMINDER + roundBudgetHint + (mcpBudgetNote ? `
3366
3301
 
3367
3302
  ${mcpBudgetNote}` : "");
@@ -3664,7 +3599,7 @@ ${summaryContent}`,
3664
3599
  this.send({ type: "info", message: "[interrupted]" });
3665
3600
  }
3666
3601
  } catch (err) {
3667
- if (err.name === "AbortError") {
3602
+ if (isAbortError(err)) {
3668
3603
  this.send({ type: "info", message: "[interrupted]" });
3669
3604
  } else {
3670
3605
  throw err;
@@ -4277,6 +4212,7 @@ Backup saved: ${result.backupPath}` : "";
4277
4212
  };
4278
4213
  }
4279
4214
  getFilteredToolDefs() {
4215
+ this.toolExecutor.planMode = this.planMode;
4280
4216
  if (this.planMode) {
4281
4217
  return {
4282
4218
  toolDefs: this.toolRegistry.getDefinitions().filter((t) => PLAN_MODE_READONLY_TOOLS.has(t.name)),
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-AXSWLNCU.js";
4
+ } from "./chunk-AA6PZRJO.js";
5
5
  import "./chunk-GHWZVPUV.js";
6
- import "./chunk-ERDFOXYK.js";
6
+ import "./chunk-TOH67ARY.js";
7
7
  import "./chunk-4DEMGCK4.js";
8
8
  import "./chunk-UUSRWSSX.js";
9
9
  import "./chunk-CKH4KQ4E.js";
@@ -14,7 +14,7 @@ import "./chunk-NYNSYLFY.js";
14
14
  import "./chunk-3FEZSLGI.js";
15
15
  import {
16
16
  runTool
17
- } from "./chunk-HEUB5PV6.js";
17
+ } from "./chunk-QL2QACHI.js";
18
18
  import "./chunk-RS7SKYTS.js";
19
19
  import {
20
20
  getDangerLevel,
@@ -24,10 +24,10 @@ import "./chunk-TU3L3PW7.js";
24
24
  import "./chunk-HOSJZMQS.js";
25
25
  import "./chunk-IW3Q7AE5.js";
26
26
  import "./chunk-4BKXL7SM.js";
27
- import "./chunk-L7RAEUUN.js";
27
+ import "./chunk-BDN6ZCPQ.js";
28
28
  import {
29
29
  VERSION
30
- } from "./chunk-UDFK5Q52.js";
30
+ } from "./chunk-25VQORAZ.js";
31
31
 
32
32
  // src/mcp/server.ts
33
33
  import { createInterface } from "readline";
@@ -4,9 +4,9 @@ import {
4
4
  googleSearchContext,
5
5
  isToolCapableProvider,
6
6
  truncateOutput
7
- } from "./chunk-AXSWLNCU.js";
7
+ } from "./chunk-AA6PZRJO.js";
8
8
  import "./chunk-GHWZVPUV.js";
9
- import "./chunk-ERDFOXYK.js";
9
+ import "./chunk-TOH67ARY.js";
10
10
  import "./chunk-4DEMGCK4.js";
11
11
  import "./chunk-UUSRWSSX.js";
12
12
  import "./chunk-CKH4KQ4E.js";
@@ -17,7 +17,7 @@ import "./chunk-NYNSYLFY.js";
17
17
  import "./chunk-3FEZSLGI.js";
18
18
  import {
19
19
  runTool
20
- } from "./chunk-HEUB5PV6.js";
20
+ } from "./chunk-QL2QACHI.js";
21
21
  import "./chunk-RS7SKYTS.js";
22
22
  import {
23
23
  getDangerLevel,
@@ -29,10 +29,10 @@ import {
29
29
  atomicWriteFileSync
30
30
  } from "./chunk-IW3Q7AE5.js";
31
31
  import "./chunk-4BKXL7SM.js";
32
- import "./chunk-L7RAEUUN.js";
32
+ import "./chunk-BDN6ZCPQ.js";
33
33
  import {
34
34
  SUBAGENT_ALLOWED_TOOLS
35
- } from "./chunk-UDFK5Q52.js";
35
+ } from "./chunk-25VQORAZ.js";
36
36
 
37
37
  // src/hub/task-orchestrator.ts
38
38
  import { createInterface } from "readline";
@@ -9,10 +9,10 @@ import {
9
9
  import "./chunk-RS7SKYTS.js";
10
10
  import {
11
11
  ConfigManager
12
- } from "./chunk-5F7BGV72.js";
12
+ } from "./chunk-2SQCGJ6H.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
- import "./chunk-UDFK5Q52.js";
15
+ import "./chunk-25VQORAZ.js";
16
16
 
17
17
  // src/cli/usage.ts
18
18
  function classifyRowCost(row) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.287",
3
+ "version": "0.4.289",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",