jinzd-ai-cli 0.4.288 → 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-YAEXKK2C.js → batch-GVD4CZZQ.js} +2 -2
  2. package/dist/{chunk-O4CZPTPU.js → chunk-25VQORAZ.js} +1 -1
  3. package/dist/{chunk-7RC7AN6V.js → chunk-2SQCGJ6H.js} +1 -1
  4. package/dist/{chunk-37WBQV3E.js → chunk-AA6PZRJO.js} +18 -4
  5. package/dist/{chunk-6NEEFOVF.js → chunk-BDN6ZCPQ.js} +1 -1
  6. package/dist/{chunk-NJDQCQ7P.js → chunk-BW4H53KI.js} +7 -7
  7. package/dist/{chunk-EYA4IXQJ.js → chunk-GXB5EOFI.js} +1 -1
  8. package/dist/{chunk-E66SCDTD.js → chunk-I73JWHNT.js} +1 -1
  9. package/dist/{chunk-WQ2YQ5YC.js → chunk-NP446QJS.js} +3 -3
  10. package/dist/{chunk-U4NQ2IRE.js → chunk-NWM7CTQQ.js} +1 -1
  11. package/dist/{chunk-5G6HX57U.js → chunk-QL2QACHI.js} +1 -1
  12. package/dist/{chunk-G5QZS5TN.js → chunk-TKG6BI6G.js} +1 -1
  13. package/dist/{chunk-JBNNJ32H.js → chunk-TOH67ARY.js} +1 -1
  14. package/dist/{chunk-C5UAM4X7.js → chunk-VIDUFFHT.js} +3 -3
  15. package/dist/{ci-RO2NLIRH.js → ci-U7X5OWOA.js} +4 -4
  16. package/dist/{ci-format-GBSRK2J4.js → ci-format-PDP5K5LR.js} +2 -2
  17. package/dist/{constants-T2B3SBMR.js → constants-GBIMYBKD.js} +1 -1
  18. package/dist/{constants-JQP6BENR.js → constants-MYTDRODA.js} +1 -1
  19. package/dist/{doctor-cli-CVOE7FAE.js → doctor-cli-64WRAKH3.js} +4 -4
  20. package/dist/electron-server.js +36 -13
  21. package/dist/{hub-LFWL5PGH.js → hub-FSITPTD5.js} +1 -1
  22. package/dist/index.js +18 -17
  23. package/dist/{persistent-memory-4UR27ACM.js → persistent-memory-7GPL7NSO.js} +2 -2
  24. package/dist/{persistent-memory-LFE3YHZO.js → persistent-memory-7PPH6QES.js} +2 -2
  25. package/dist/{pr-3QAG7XO7.js → pr-T7VURNFJ.js} +4 -4
  26. package/dist/{run-tests-GGNFI7CL.js → run-tests-CSAB2M4A.js} +2 -2
  27. package/dist/{run-tests-R3JB4UEI.js → run-tests-PPTDYVS7.js} +2 -2
  28. package/dist/{server-I6DXVJRO.js → server-6B2JFKRN.js} +27 -16
  29. package/dist/{server-THHSJRNI.js → server-O54U4OOB.js} +5 -5
  30. package/dist/{task-orchestrator-6HH3KQUQ.js → task-orchestrator-HA4JE4TF.js} +5 -5
  31. package/dist/{usage-UB4ZT5PE.js → usage-HX6MPQT2.js} +2 -2
  32. package/package.json +1 -1
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-RS7SKYTS.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-7RC7AN6V.js";
7
+ } from "./chunk-2SQCGJ6H.js";
8
8
  import "./chunk-TU3L3PW7.js";
9
9
  import {
10
10
  atomicWriteFileSync
11
11
  } from "./chunk-IW3Q7AE5.js";
12
- import "./chunk-O4CZPTPU.js";
12
+ import "./chunk-25VQORAZ.js";
13
13
 
14
14
  // src/cli/batch.ts
15
15
  import Anthropic from "@anthropic-ai/sdk";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.288";
4
+ var VERSION = "0.4.289";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -11,7 +11,7 @@ import {
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-O4CZPTPU.js";
14
+ } from "./chunk-25VQORAZ.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -11,7 +11,7 @@ import {
11
11
  searchPersistentMemories,
12
12
  touchMemoryReferences,
13
13
  updateMemoryEntry
14
- } from "./chunk-JBNNJ32H.js";
14
+ } from "./chunk-TOH67ARY.js";
15
15
  import {
16
16
  indexProject
17
17
  } from "./chunk-4DEMGCK4.js";
@@ -30,7 +30,7 @@ import {
30
30
  runHook,
31
31
  runLifecycleHooks,
32
32
  runTool
33
- } from "./chunk-5G6HX57U.js";
33
+ } from "./chunk-QL2QACHI.js";
34
34
  import {
35
35
  buildTruncatedArgumentsError,
36
36
  getDangerLevel,
@@ -50,14 +50,15 @@ import {
50
50
  } from "./chunk-4BKXL7SM.js";
51
51
  import {
52
52
  runTestsTool
53
- } from "./chunk-6NEEFOVF.js";
53
+ } from "./chunk-BDN6ZCPQ.js";
54
54
  import {
55
55
  CONFIG_DIR_NAME,
56
56
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
57
+ PLAN_MODE_READONLY_TOOLS,
57
58
  SUBAGENT_ALLOWED_TOOLS,
58
59
  SUBAGENT_DEFAULT_MAX_ROUNDS,
59
60
  SUBAGENT_MAX_ROUNDS_LIMIT
60
- } from "./chunk-O4CZPTPU.js";
61
+ } from "./chunk-25VQORAZ.js";
61
62
 
62
63
  // src/tools/shell-pool.ts
63
64
  import { spawn as spawn2 } from "child_process";
@@ -1633,6 +1634,7 @@ var gateMessages = {
1633
1634
  hookDenied: (toolName, reason) => `[Hook denied] ${reason ?? `PreToolUse blocked ${toolName}`}. Do not retry without asking.`,
1634
1635
  networkDenied: (toolName, reason) => `[Permission denied] Tool ${toolName} is blocked by networkPolicy${reason ? ` (${reason})` : ""}. Do not retry.`,
1635
1636
  profileDenied: (toolName, profileName, reason) => `[Permission denied] Tool ${toolName} is blocked by permission profile "${profileName}"${reason ? ` (${reason})` : ""}. Do not retry.`,
1637
+ planModeDenied: (toolName) => `[Plan Mode] ${toolName} is disabled in read-only Plan Mode. Do not retry it. Use read_file / list_dir / grep_files / glob_files to investigate, and write_todos to present your plan. If the user wants this executed, tell them to type /plan execute first.`,
1636
1638
  autoDenied: (reason) => `[Auto denied] ${reason}. Do not retry without asking.`,
1637
1639
  permissionCancelled: (toolName) => `[User cancelled] The user declined permission for ${toolName}. Do not retry without asking.`,
1638
1640
  operationCancelled: (toolName, level) => `[User cancelled] The user declined the ${level === "destructive" ? "destructive " : ""}${toolName} operation. Do not retry without asking.`
@@ -1645,6 +1647,9 @@ function decideToolGate(call, input) {
1645
1647
  if (input.hookDeny) {
1646
1648
  return { kind: "denied", source: "hook", message: gateMessages.hookDenied(call.name, input.hookDeny.reason) };
1647
1649
  }
1650
+ if (input.planMode && !PLAN_MODE_READONLY_TOOLS.has(call.name)) {
1651
+ return { kind: "denied", source: "plan-mode", message: gateMessages.planModeDenied(call.name) };
1652
+ }
1648
1653
  if (networkPermission?.action === "deny") {
1649
1654
  return { kind: "denied", source: "network", message: gateMessages.networkDenied(call.name, networkPermission.reason) };
1650
1655
  }
@@ -2259,6 +2264,14 @@ var ToolExecutor = class {
2259
2264
  sessionAutoApprove = false;
2260
2265
  /** Session-level Auto Mode: rule-based low-risk auto approval. */
2261
2266
  sessionAutoMode = false;
2267
+ /**
2268
+ * Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
2269
+ *
2270
+ * 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
2271
+ * 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
2272
+ * 放行——只读保护形同虚设(审计 P2-01)。
2273
+ */
2274
+ planMode = false;
2262
2275
  /**
2263
2276
  * Logical session key used to scope per-session state in stateful tools
2264
2277
  * (currently only `bash`'s persistent cwd). Web mode sets this per-tab so
@@ -2371,6 +2384,7 @@ var ToolExecutor = class {
2371
2384
  permission,
2372
2385
  networkPermission,
2373
2386
  hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
2387
+ planMode: this.planMode,
2374
2388
  sessionAutoMode: this.sessionAutoMode,
2375
2389
  sessionAutoApprove: this.sessionAutoApprove,
2376
2390
  classify: () => defaultActionClassifier.classify(call, dangerLevel, {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-O4CZPTPU.js";
4
+ } from "./chunk-25VQORAZ.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -16,7 +16,7 @@ import {
16
16
  setPreferredAgentName,
17
17
  truncateForPersist,
18
18
  undoStack
19
- } from "./chunk-37WBQV3E.js";
19
+ } from "./chunk-AA6PZRJO.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-JBNNJ32H.js";
54
+ } from "./chunk-TOH67ARY.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-C5UAM4X7.js";
68
+ } from "./chunk-VIDUFFHT.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-5G6HX57U.js";
83
+ } from "./chunk-QL2QACHI.js";
84
84
  import {
85
85
  isCleanDocumentBody,
86
86
  stripOuterCodeFence
@@ -109,7 +109,7 @@ import {
109
109
  MCP_TOOL_PREFIX,
110
110
  REPO_URL,
111
111
  VERSION
112
- } from "./chunk-O4CZPTPU.js";
112
+ } from "./chunk-25VQORAZ.js";
113
113
 
114
114
  // src/mcp/client.ts
115
115
  import { spawn } from "child_process";
@@ -2393,7 +2393,7 @@ No tools match "${filter}".
2393
2393
  const { join: join6 } = await import("path");
2394
2394
  const { existsSync: existsSync6 } = await import("fs");
2395
2395
  const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
2396
- const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-T2B3SBMR.js");
2396
+ const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-GBIMYBKD.js");
2397
2397
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
2398
2398
  const cwd = process.cwd();
2399
2399
  const projectRoot = getGitRoot(cwd) ?? cwd;
@@ -3497,7 +3497,7 @@ function createReviewCommands() {
3497
3497
  usage: "/test [command|filter]",
3498
3498
  async execute(args, ctx) {
3499
3499
  try {
3500
- const { executeTests } = await import("./run-tests-GGNFI7CL.js");
3500
+ const { executeTests } = await import("./run-tests-CSAB2M4A.js");
3501
3501
  const argStr = args.join(" ").trim();
3502
3502
  let testArgs = {};
3503
3503
  if (argStr) {
@@ -12,7 +12,7 @@ import {
12
12
  MEMORY_FILE_NAME,
13
13
  MEMORY_MAX_CHARS,
14
14
  MEMORY_STORE_FILE_NAME
15
- } from "./chunk-U4NQ2IRE.js";
15
+ } from "./chunk-NWM7CTQQ.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-U4NQ2IRE.js";
3
+ } from "./chunk-NWM7CTQQ.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-G5QZS5TN.js";
5
+ } from "./chunk-TKG6BI6G.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -16,10 +16,10 @@ import {
16
16
  } from "./chunk-ALSSNFNK.js";
17
17
  import {
18
18
  ConfigManager
19
- } from "./chunk-7RC7AN6V.js";
19
+ } from "./chunk-2SQCGJ6H.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-O4CZPTPU.js";
22
+ } from "./chunk-25VQORAZ.js";
23
23
 
24
24
  // src/cli/ci.ts
25
25
  import { execFileSync } from "child_process";
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.288";
2
+ var VERSION = "0.4.289";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  CONFIG_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-O4CZPTPU.js";
11
+ } from "./chunk-25VQORAZ.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-O4CZPTPU.js";
4
+ } from "./chunk-25VQORAZ.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-O4CZPTPU.js";
16
+ } from "./chunk-25VQORAZ.js";
17
17
 
18
18
  // src/memory/persistent-memory.ts
19
19
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -8,13 +8,13 @@ import {
8
8
  listHooks,
9
9
  listInstalledPlugins,
10
10
  resetStats
11
- } from "./chunk-5G6HX57U.js";
11
+ } from "./chunk-QL2QACHI.js";
12
12
  import {
13
13
  ProviderRegistry
14
14
  } from "./chunk-ALSSNFNK.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-7RC7AN6V.js";
17
+ } from "./chunk-2SQCGJ6H.js";
18
18
  import {
19
19
  getGitRoot
20
20
  } from "./chunk-HOSJZMQS.js";
@@ -26,7 +26,7 @@ import {
26
26
  MCP_PROJECT_CONFIG_NAME,
27
27
  MEMORY_FILE_NAME,
28
28
  VERSION
29
- } from "./chunk-O4CZPTPU.js";
29
+ } from "./chunk-25VQORAZ.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -3,16 +3,16 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-WQ2YQ5YC.js";
7
- import "./chunk-G5QZS5TN.js";
6
+ } from "./chunk-NP446QJS.js";
7
+ import "./chunk-TKG6BI6G.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
9
  import "./chunk-6YZEZFX5.js";
10
10
  import "./chunk-ALSSNFNK.js";
11
- import "./chunk-7RC7AN6V.js";
11
+ import "./chunk-2SQCGJ6H.js";
12
12
  import "./chunk-TEXT4DAT.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
- import "./chunk-O4CZPTPU.js";
15
+ import "./chunk-25VQORAZ.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-G5QZS5TN.js";
10
- import "./chunk-O4CZPTPU.js";
9
+ } from "./chunk-TKG6BI6G.js";
10
+ import "./chunk-25VQORAZ.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-O4CZPTPU.js";
41
+ } from "./chunk-25VQORAZ.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -37,7 +37,7 @@ import {
37
37
  TEST_TIMEOUT,
38
38
  VERSION,
39
39
  buildUserIdentityPrompt
40
- } from "./chunk-U4NQ2IRE.js";
40
+ } from "./chunk-NWM7CTQQ.js";
41
41
  export {
42
42
  AGENTIC_BEHAVIOR_GUIDELINE,
43
43
  APP_NAME,
@@ -2,16 +2,16 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-C5UAM4X7.js";
6
- import "./chunk-5G6HX57U.js";
5
+ } from "./chunk-VIDUFFHT.js";
6
+ import "./chunk-QL2QACHI.js";
7
7
  import "./chunk-RS7SKYTS.js";
8
8
  import "./chunk-ALSSNFNK.js";
9
- import "./chunk-7RC7AN6V.js";
9
+ import "./chunk-2SQCGJ6H.js";
10
10
  import "./chunk-TEXT4DAT.js";
11
11
  import "./chunk-TU3L3PW7.js";
12
12
  import "./chunk-HOSJZMQS.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
- import "./chunk-O4CZPTPU.js";
14
+ import "./chunk-25VQORAZ.js";
15
15
  export {
16
16
  formatDoctorReport,
17
17
  runDoctorCli
@@ -50,7 +50,7 @@ import {
50
50
  touchMemoryReferences,
51
51
  updateMemoryApproval,
52
52
  updateMemoryEntry
53
- } from "./chunk-EYA4IXQJ.js";
53
+ } from "./chunk-GXB5EOFI.js";
54
54
  import {
55
55
  DEFAULT_PATTERNS,
56
56
  redactJson,
@@ -66,7 +66,7 @@ import {
66
66
  } from "./chunk-CGLYJRFA.js";
67
67
  import {
68
68
  runTestsTool
69
- } from "./chunk-E66SCDTD.js";
69
+ } from "./chunk-I73JWHNT.js";
70
70
  import {
71
71
  AGENTIC_BEHAVIOR_GUIDELINE,
72
72
  APP_NAME,
@@ -100,7 +100,7 @@ import {
100
100
  SUBAGENT_MAX_ROUNDS_LIMIT,
101
101
  VERSION,
102
102
  buildUserIdentityPrompt
103
- } from "./chunk-U4NQ2IRE.js";
103
+ } from "./chunk-NWM7CTQQ.js";
104
104
 
105
105
  // src/web/server.ts
106
106
  import express from "express";
@@ -7267,6 +7267,7 @@ var gateMessages = {
7267
7267
  hookDenied: (toolName, reason) => `[Hook denied] ${reason ?? `PreToolUse blocked ${toolName}`}. Do not retry without asking.`,
7268
7268
  networkDenied: (toolName, reason) => `[Permission denied] Tool ${toolName} is blocked by networkPolicy${reason ? ` (${reason})` : ""}. Do not retry.`,
7269
7269
  profileDenied: (toolName, profileName, reason) => `[Permission denied] Tool ${toolName} is blocked by permission profile "${profileName}"${reason ? ` (${reason})` : ""}. Do not retry.`,
7270
+ planModeDenied: (toolName) => `[Plan Mode] ${toolName} is disabled in read-only Plan Mode. Do not retry it. Use read_file / list_dir / grep_files / glob_files to investigate, and write_todos to present your plan. If the user wants this executed, tell them to type /plan execute first.`,
7270
7271
  autoDenied: (reason) => `[Auto denied] ${reason}. Do not retry without asking.`,
7271
7272
  permissionCancelled: (toolName) => `[User cancelled] The user declined permission for ${toolName}. Do not retry without asking.`,
7272
7273
  operationCancelled: (toolName, level) => `[User cancelled] The user declined the ${level === "destructive" ? "destructive " : ""}${toolName} operation. Do not retry without asking.`
@@ -7279,6 +7280,9 @@ function decideToolGate(call, input) {
7279
7280
  if (input.hookDeny) {
7280
7281
  return { kind: "denied", source: "hook", message: gateMessages.hookDenied(call.name, input.hookDeny.reason) };
7281
7282
  }
7283
+ if (input.planMode && !PLAN_MODE_READONLY_TOOLS.has(call.name)) {
7284
+ return { kind: "denied", source: "plan-mode", message: gateMessages.planModeDenied(call.name) };
7285
+ }
7282
7286
  if (networkPermission?.action === "deny") {
7283
7287
  return { kind: "denied", source: "network", message: gateMessages.networkDenied(call.name, networkPermission.reason) };
7284
7288
  }
@@ -8025,6 +8029,14 @@ var ToolExecutor = class {
8025
8029
  sessionAutoApprove = false;
8026
8030
  /** Session-level Auto Mode: rule-based low-risk auto approval. */
8027
8031
  sessionAutoMode = false;
8032
+ /**
8033
+ * Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
8034
+ *
8035
+ * 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
8036
+ * 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
8037
+ * 放行——只读保护形同虚设(审计 P2-01)。
8038
+ */
8039
+ planMode = false;
8028
8040
  /**
8029
8041
  * Logical session key used to scope per-session state in stateful tools
8030
8042
  * (currently only `bash`'s persistent cwd). Web mode sets this per-tab so
@@ -8137,6 +8149,7 @@ var ToolExecutor = class {
8137
8149
  permission,
8138
8150
  networkPermission,
8139
8151
  hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
8152
+ planMode: this.planMode,
8140
8153
  sessionAutoMode: this.sessionAutoMode,
8141
8154
  sessionAutoApprove: this.sessionAutoApprove,
8142
8155
  classify: () => defaultActionClassifier.classify(call, dangerLevel, {
@@ -13803,6 +13816,14 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13803
13816
  sessionAutoApprove = false;
13804
13817
  /** Session-level Auto Mode: rule-based low-risk auto approval. */
13805
13818
  sessionAutoMode = false;
13819
+ /**
13820
+ * Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
13821
+ *
13822
+ * 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
13823
+ * 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
13824
+ * 放行——只读保护形同虚设(审计 P2-01)。
13825
+ */
13826
+ planMode = false;
13806
13827
  /** Track tool start times for duration calculation */
13807
13828
  toolStartTimes = /* @__PURE__ */ new Map();
13808
13829
  /**
@@ -14032,6 +14053,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
14032
14053
  permission,
14033
14054
  networkPermission,
14034
14055
  hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
14056
+ planMode: this.planMode,
14035
14057
  sessionAutoMode: this.sessionAutoMode,
14036
14058
  sessionAutoApprove: this.sessionAutoApprove,
14037
14059
  classify: () => defaultActionClassifier.classify(call, dangerLevel, {
@@ -16879,7 +16901,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
16879
16901
  Cost: ${formatCost(cost)}` : "";
16880
16902
  let memoryLine = "";
16881
16903
  try {
16882
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-LFE3YHZO.js");
16904
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-7PPH6QES.js");
16883
16905
  const pending = countPendingMemories2(ctx.config.getConfigDir());
16884
16906
  if (pending > 0) memoryLine = `
16885
16907
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -17862,7 +17884,7 @@ async function handleTest(args, ctx) {
17862
17884
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
17863
17885
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
17864
17886
  }
17865
- const runTests = ctx.runTests ?? (await import("./run-tests-R3JB4UEI.js")).executeTests;
17887
+ const runTests = ctx.runTests ?? (await import("./run-tests-PPTDYVS7.js")).executeTests;
17866
17888
  const report = await runTests(testArgs);
17867
17889
  ctx.send({ type: "info", message: report });
17868
17890
  } catch (err) {
@@ -18252,7 +18274,7 @@ async function handleMemory(args, ctx) {
18252
18274
  }
18253
18275
  if (intent.kind === "status") {
18254
18276
  const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-DGUOUUQW.js");
18255
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-LFE3YHZO.js");
18277
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-7PPH6QES.js");
18256
18278
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
18257
18279
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
18258
18280
  const view = buildMemoryStatusView({
@@ -18275,7 +18297,7 @@ async function handleMemory(args, ctx) {
18275
18297
  return;
18276
18298
  }
18277
18299
  if (intent.kind === "recall") {
18278
- const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-LFE3YHZO.js");
18300
+ const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-7PPH6QES.js");
18279
18301
  const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-DGUOUUQW.js");
18280
18302
  const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
18281
18303
  if (persistentHits.length > 0) {
@@ -18396,7 +18418,7 @@ async function handleMemory(args, ctx) {
18396
18418
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
18397
18419
  } else if (intent.kind === "export") {
18398
18420
  if (args[1] === "md") {
18399
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-LFE3YHZO.js");
18421
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-7PPH6QES.js");
18400
18422
  ctx.send({
18401
18423
  type: "export_data",
18402
18424
  format: "md",
@@ -19401,7 +19423,7 @@ No tools match "${filter}".
19401
19423
  const { join: join29 } = await import("path");
19402
19424
  const { existsSync: existsSync33 } = await import("fs");
19403
19425
  const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
19404
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-JQP6BENR.js");
19426
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-MYTDRODA.js");
19405
19427
  const { approveProject, hashMcpFile } = await import("./project-trust-MUG325AW.js");
19406
19428
  const cwd = process.cwd();
19407
19429
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -20316,7 +20338,7 @@ function createReviewCommands() {
20316
20338
  usage: "/test [command|filter]",
20317
20339
  async execute(args, ctx) {
20318
20340
  try {
20319
- const { executeTests } = await import("./run-tests-R3JB4UEI.js");
20341
+ const { executeTests } = await import("./run-tests-PPTDYVS7.js");
20320
20342
  const argStr = args.join(" ").trim();
20321
20343
  let testArgs = {};
20322
20344
  if (argStr) {
@@ -22813,7 +22835,7 @@ var SessionHandler = class {
22813
22835
  ...simpleReasoning ? { reasoningContent: simpleReasoning } : {}
22814
22836
  });
22815
22837
  } catch (err) {
22816
- if (err.name === "AbortError") {
22838
+ if (isAbortError(err)) {
22817
22839
  this.send({ type: "info", message: "[interrupted]" });
22818
22840
  } else {
22819
22841
  throw err;
@@ -22830,7 +22852,7 @@ var SessionHandler = class {
22830
22852
  const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
22831
22853
  const autoPauseInterval = typeof autoPauseIntervalRaw === "number" ? autoPauseIntervalRaw : 50;
22832
22854
  const { stable: toolStable, volatile: toolVolatile } = this.buildSystemPrompt();
22833
- const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval });
22855
+ const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval, planMode: this.planMode });
22834
22856
  const systemPrompt = toolStable + TOOL_CALL_REMINDER + roundBudgetHint + (mcpBudgetNote ? `
22835
22857
 
22836
22858
  ${mcpBudgetNote}` : "");
@@ -23133,7 +23155,7 @@ ${summaryContent}`,
23133
23155
  this.send({ type: "info", message: "[interrupted]" });
23134
23156
  }
23135
23157
  } catch (err) {
23136
- if (err.name === "AbortError") {
23158
+ if (isAbortError(err)) {
23137
23159
  this.send({ type: "info", message: "[interrupted]" });
23138
23160
  } else {
23139
23161
  throw err;
@@ -23746,6 +23768,7 @@ Backup saved: ${result.backupPath}` : "";
23746
23768
  };
23747
23769
  }
23748
23770
  getFilteredToolDefs() {
23771
+ this.toolExecutor.planMode = this.planMode;
23749
23772
  if (this.planMode) {
23750
23773
  return {
23751
23774
  toolDefs: this.toolRegistry.getDefinitions().filter((t) => PLAN_MODE_READONLY_TOOLS.has(t.name)),
@@ -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-6HH3KQUQ.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-HA4JE4TF.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  setupProxy,
25
25
  snapshotFile,
26
26
  stripRoutingTags
27
- } from "./chunk-NJDQCQ7P.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-37WBQV3E.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-JBNNJ32H.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-C5UAM4X7.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-5G6HX57U.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-7RC7AN6V.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-6NEEFOVF.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-O4CZPTPU.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-I6DXVJRO.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-UB4ZT5PE.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-CVOE7FAE.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-YAEXKK2C.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-THHSJRNI.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-3QAG7XO7.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-RO2NLIRH.js");
4250
- const { formatCiResult } = await import("./ci-format-GBSRK2J4.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-LFWL5PGH.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-JBNNJ32H.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-O4CZPTPU.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-EYA4IXQJ.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-U4NQ2IRE.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-WQ2YQ5YC.js";
6
- import "./chunk-G5QZS5TN.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-7RC7AN6V.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-O4CZPTPU.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-6NEEFOVF.js";
6
- import "./chunk-O4CZPTPU.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-E66SCDTD.js";
5
- import "./chunk-U4NQ2IRE.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-NJDQCQ7P.js";
84
+ } from "./chunk-BW4H53KI.js";
85
85
  import {
86
86
  CNY_PER_USD,
87
87
  CostTracker,
@@ -126,7 +126,7 @@ import {
126
126
  spawnAgentContext,
127
127
  truncateOutput,
128
128
  undoStack
129
- } from "./chunk-37WBQV3E.js";
129
+ } from "./chunk-AA6PZRJO.js";
130
130
  import {
131
131
  buildReviewPrompt,
132
132
  buildSecurityReviewPrompt
@@ -153,7 +153,7 @@ import {
153
153
  restoreMemoryEntries,
154
154
  updateMemoryApproval,
155
155
  updateMemoryEntry
156
- } from "./chunk-JBNNJ32H.js";
156
+ } from "./chunk-TOH67ARY.js";
157
157
  import "./chunk-4DEMGCK4.js";
158
158
  import "./chunk-UUSRWSSX.js";
159
159
  import "./chunk-CKH4KQ4E.js";
@@ -172,7 +172,7 @@ import {
172
172
  buildDoctorReport,
173
173
  formatDoctorReport,
174
174
  loadContextFiles
175
- } from "./chunk-C5UAM4X7.js";
175
+ } from "./chunk-VIDUFFHT.js";
176
176
  import {
177
177
  describePlugin,
178
178
  getActivePluginAssets,
@@ -187,14 +187,14 @@ import {
187
187
  runTool,
188
188
  setPluginEnabled,
189
189
  trustPlugin
190
- } from "./chunk-5G6HX57U.js";
190
+ } from "./chunk-QL2QACHI.js";
191
191
  import "./chunk-RS7SKYTS.js";
192
192
  import {
193
193
  ProviderRegistry
194
194
  } from "./chunk-ALSSNFNK.js";
195
195
  import {
196
196
  ConfigManager
197
- } from "./chunk-7RC7AN6V.js";
197
+ } from "./chunk-2SQCGJ6H.js";
198
198
  import {
199
199
  CONTENT_ONLY_STREAM_REMINDER,
200
200
  TEE_FINAL_USER_NUDGE,
@@ -206,6 +206,7 @@ import {
206
206
  evaluateTeeContent,
207
207
  freshPriorContent,
208
208
  getDangerLevel,
209
+ isAbortError,
209
210
  runAgentLoop,
210
211
  stripToolCallReminder,
211
212
  teeStreamErrorSummary
@@ -224,7 +225,7 @@ import {
224
225
  maskConfigSecrets
225
226
  } from "./chunk-XNFIYS7G.js";
226
227
  import "./chunk-4BKXL7SM.js";
227
- import "./chunk-6NEEFOVF.js";
228
+ import "./chunk-BDN6ZCPQ.js";
228
229
  import {
229
230
  AGENTIC_BEHAVIOR_GUIDELINE,
230
231
  AUTHOR,
@@ -240,7 +241,7 @@ import {
240
241
  SKILLS_DIR_NAME,
241
242
  VERSION,
242
243
  buildUserIdentityPrompt
243
- } from "./chunk-O4CZPTPU.js";
244
+ } from "./chunk-25VQORAZ.js";
244
245
 
245
246
  // src/web/server.ts
246
247
  import express from "express";
@@ -286,6 +287,14 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
286
287
  sessionAutoApprove = false;
287
288
  /** Session-level Auto Mode: rule-based low-risk auto approval. */
288
289
  sessionAutoMode = false;
290
+ /**
291
+ * Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
292
+ *
293
+ * 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
294
+ * 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
295
+ * 放行——只读保护形同虚设(审计 P2-01)。
296
+ */
297
+ planMode = false;
289
298
  /** Track tool start times for duration calculation */
290
299
  toolStartTimes = /* @__PURE__ */ new Map();
291
300
  /**
@@ -515,6 +524,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
515
524
  permission,
516
525
  networkPermission,
517
526
  hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
527
+ planMode: this.planMode,
518
528
  sessionAutoMode: this.sessionAutoMode,
519
529
  sessionAutoApprove: this.sessionAutoApprove,
520
530
  classify: () => defaultActionClassifier.classify(call, dangerLevel, {
@@ -920,7 +930,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
920
930
  Cost: ${formatCost(cost)}` : "";
921
931
  let memoryLine = "";
922
932
  try {
923
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-4UR27ACM.js");
933
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-7GPL7NSO.js");
924
934
  const pending = countPendingMemories2(ctx.config.getConfigDir());
925
935
  if (pending > 0) memoryLine = `
926
936
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -1844,7 +1854,7 @@ async function handleTest(args, ctx) {
1844
1854
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
1845
1855
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
1846
1856
  }
1847
- const runTests = ctx.runTests ?? (await import("./run-tests-GGNFI7CL.js")).executeTests;
1857
+ const runTests = ctx.runTests ?? (await import("./run-tests-CSAB2M4A.js")).executeTests;
1848
1858
  const report = await runTests(testArgs);
1849
1859
  ctx.send({ type: "info", message: report });
1850
1860
  } catch (err) {
@@ -2119,7 +2129,7 @@ async function handleMemory(args, ctx) {
2119
2129
  }
2120
2130
  if (intent.kind === "status") {
2121
2131
  const { getChatIndexStatus } = await import("./chat-index-2D5GK2DB.js");
2122
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-4UR27ACM.js");
2132
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-7GPL7NSO.js");
2123
2133
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
2124
2134
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
2125
2135
  const view = buildMemoryStatusView({
@@ -2142,7 +2152,7 @@ async function handleMemory(args, ctx) {
2142
2152
  return;
2143
2153
  }
2144
2154
  if (intent.kind === "recall") {
2145
- const { searchPersistentMemories, touchMemoryReferences } = await import("./persistent-memory-4UR27ACM.js");
2155
+ const { searchPersistentMemories, touchMemoryReferences } = await import("./persistent-memory-7GPL7NSO.js");
2146
2156
  const { searchChatMemory } = await import("./chat-index-2D5GK2DB.js");
2147
2157
  const persistentHits = searchPersistentMemories(configDir, intent.query, process.cwd(), 3);
2148
2158
  if (persistentHits.length > 0) {
@@ -2263,7 +2273,7 @@ async function handleMemory(args, ctx) {
2263
2273
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
2264
2274
  } else if (intent.kind === "export") {
2265
2275
  if (args[1] === "md") {
2266
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-4UR27ACM.js");
2276
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-7GPL7NSO.js");
2267
2277
  ctx.send({
2268
2278
  type: "export_data",
2269
2279
  format: "md",
@@ -3269,7 +3279,7 @@ var SessionHandler = class {
3269
3279
  ...simpleReasoning ? { reasoningContent: simpleReasoning } : {}
3270
3280
  });
3271
3281
  } catch (err) {
3272
- if (err.name === "AbortError") {
3282
+ if (isAbortError(err)) {
3273
3283
  this.send({ type: "info", message: "[interrupted]" });
3274
3284
  } else {
3275
3285
  throw err;
@@ -3286,7 +3296,7 @@ var SessionHandler = class {
3286
3296
  const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
3287
3297
  const autoPauseInterval = typeof autoPauseIntervalRaw === "number" ? autoPauseIntervalRaw : 50;
3288
3298
  const { stable: toolStable, volatile: toolVolatile } = this.buildSystemPrompt();
3289
- const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval });
3299
+ const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval, planMode: this.planMode });
3290
3300
  const systemPrompt = toolStable + TOOL_CALL_REMINDER + roundBudgetHint + (mcpBudgetNote ? `
3291
3301
 
3292
3302
  ${mcpBudgetNote}` : "");
@@ -3589,7 +3599,7 @@ ${summaryContent}`,
3589
3599
  this.send({ type: "info", message: "[interrupted]" });
3590
3600
  }
3591
3601
  } catch (err) {
3592
- if (err.name === "AbortError") {
3602
+ if (isAbortError(err)) {
3593
3603
  this.send({ type: "info", message: "[interrupted]" });
3594
3604
  } else {
3595
3605
  throw err;
@@ -4202,6 +4212,7 @@ Backup saved: ${result.backupPath}` : "";
4202
4212
  };
4203
4213
  }
4204
4214
  getFilteredToolDefs() {
4215
+ this.toolExecutor.planMode = this.planMode;
4205
4216
  if (this.planMode) {
4206
4217
  return {
4207
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-37WBQV3E.js";
4
+ } from "./chunk-AA6PZRJO.js";
5
5
  import "./chunk-GHWZVPUV.js";
6
- import "./chunk-JBNNJ32H.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-5G6HX57U.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-6NEEFOVF.js";
27
+ import "./chunk-BDN6ZCPQ.js";
28
28
  import {
29
29
  VERSION
30
- } from "./chunk-O4CZPTPU.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-37WBQV3E.js";
7
+ } from "./chunk-AA6PZRJO.js";
8
8
  import "./chunk-GHWZVPUV.js";
9
- import "./chunk-JBNNJ32H.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-5G6HX57U.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-6NEEFOVF.js";
32
+ import "./chunk-BDN6ZCPQ.js";
33
33
  import {
34
34
  SUBAGENT_ALLOWED_TOOLS
35
- } from "./chunk-O4CZPTPU.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-7RC7AN6V.js";
12
+ } from "./chunk-2SQCGJ6H.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
- import "./chunk-O4CZPTPU.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.288",
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",