jinzd-ai-cli 0.4.210 → 0.4.211

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.
@@ -154,7 +154,7 @@ ${content}`);
154
154
  }
155
155
  }
156
156
  async function runTaskMode(config, providers, configManager, topic) {
157
- const { TaskOrchestrator } = await import("./task-orchestrator-BFDSTSOH.js");
157
+ const { TaskOrchestrator } = await import("./task-orchestrator-OV4O25MX.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  scanProject,
16
16
  sessionHasMeaningfulContent,
17
17
  setupProxy
18
- } from "./chunk-7JWT3KXO.js";
18
+ } from "./chunk-C3OU2OPF.js";
19
19
  import {
20
20
  buildReviewPrompt,
21
21
  buildSecurityReviewPrompt
@@ -26,6 +26,7 @@ import {
26
26
  askUserContext,
27
27
  cleanupRejectedTeeFile,
28
28
  estimateTokens,
29
+ formatPermissionProfileWarning,
29
30
  googleSearchContext,
30
31
  initTheme,
31
32
  isInterrupted,
@@ -39,10 +40,10 @@ import {
39
40
  spawnAgentContext,
40
41
  theme,
41
42
  undoStack
42
- } from "./chunk-NEPFADHX.js";
43
+ } from "./chunk-ZOPYREL5.js";
43
44
  import "./chunk-T2NL5ZIA.js";
44
45
  import "./chunk-BXP6YZ2P.js";
45
- import "./chunk-E2ZWWE6Q.js";
46
+ import "./chunk-6NS6643Y.js";
46
47
  import {
47
48
  SessionManager,
48
49
  getContentText
@@ -59,7 +60,7 @@ import {
59
60
  getConfigDirUsage,
60
61
  listRecentCrashes,
61
62
  writeCrashLog
62
- } from "./chunk-NWP7C6CC.js";
63
+ } from "./chunk-BE6ERF7M.js";
63
64
  import {
64
65
  ProviderRegistry
65
66
  } from "./chunk-QMXC327F.js";
@@ -68,7 +69,7 @@ import {
68
69
  getTopFailingTools,
69
70
  getTopUsedTools,
70
71
  installFlushOnExit
71
- } from "./chunk-DJ35G5VO.js";
72
+ } from "./chunk-JBWA73GK.js";
72
73
  import {
73
74
  CONTENT_ONLY_STREAM_REMINDER,
74
75
  TEE_FINAL_USER_NUDGE,
@@ -90,7 +91,7 @@ import {
90
91
  } from "./chunk-XPBEJB27.js";
91
92
  import {
92
93
  ConfigManager
93
- } from "./chunk-P6MTFCXB.js";
94
+ } from "./chunk-UOROWTGG.js";
94
95
  import {
95
96
  AuthError,
96
97
  ProviderError,
@@ -116,7 +117,7 @@ import {
116
117
  SKILLS_DIR_NAME,
117
118
  VERSION,
118
119
  buildUserIdentityPrompt
119
- } from "./chunk-GRJNQJA5.js";
120
+ } from "./chunk-E5XCM4A6.js";
120
121
  import {
121
122
  formatGitContextForPrompt,
122
123
  getGitContext,
@@ -1353,6 +1354,8 @@ No commands match "${filter}".
1353
1354
  console.log(` Provider : ${ctx.getCurrentProvider()}`);
1354
1355
  console.log(` Model : ${currentModel}`);
1355
1356
  console.log(` Ctx Win : ${ctxStr}`);
1357
+ console.log(" PermProf : " + (ctx.config.get("defaultPermissionProfile") ?? "legacy"));
1358
+ console.log(" Network : " + (ctx.config.get("networkPolicy")?.enabled ?? false ? "on" : "off"));
1356
1359
  console.log(` Messages : ${session?.messages.length ?? 0}`);
1357
1360
  console.log(` Session : ${session?.id.slice(0, 8) ?? "none"}`);
1358
1361
  if (layers.length > 0) {
@@ -1646,7 +1649,7 @@ No tools match "${filter}".
1646
1649
  const { join: join5 } = await import("path");
1647
1650
  const { existsSync: existsSync5 } = await import("fs");
1648
1651
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1649
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-47OR72MV.js");
1652
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-AWTIQIWG.js");
1650
1653
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1651
1654
  const cwd = process.cwd();
1652
1655
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2705,7 +2708,7 @@ ${hint}` : "")
2705
2708
  usage: "/test [command|filter]",
2706
2709
  async execute(args, ctx) {
2707
2710
  try {
2708
- const { executeTests } = await import("./run-tests-UT7RZ7Y3.js");
2711
+ const { executeTests } = await import("./run-tests-3MHWUF43.js");
2709
2712
  const argStr = args.join(" ").trim();
2710
2713
  let testArgs = {};
2711
2714
  if (argStr) {
@@ -3301,6 +3304,8 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
3301
3304
  console.log(` redactOnSave : ${security.redactOnSave ? theme.success("on") : theme.warning("off")}`);
3302
3305
  console.log(` redactOnSend : ${security.redactOnSend ? theme.success("on") : theme.dim("off")}`);
3303
3306
  console.log(` mode : ${security.mode}`);
3307
+ console.log(" profile : " + (ctx.config.get("defaultPermissionProfile") ?? "legacy"));
3308
+ console.log(" network : " + (ctx.config.get("networkPolicy")?.enabled ?? false ? "on" : "off"));
3304
3309
  console.log(` patterns : ${DEFAULT_PATTERNS.length} built-in + ${security.customPatterns?.length ?? 0} custom`);
3305
3310
  console.log(` last save : ${ctx.sessions.lastRedactionHits} hit(s) redacted`);
3306
3311
  console.log();
@@ -4456,10 +4461,17 @@ var Repl = class {
4456
4461
  this.toolRegistry = new ToolRegistry();
4457
4462
  this.toolExecutor = new ToolExecutor(this.toolRegistry);
4458
4463
  this.toolExecutor.setReadline(this.rl);
4464
+ const permissionProfileName = this.config.get("defaultPermissionProfile") ?? "legacy";
4465
+ const permissionProfiles = this.config.get("permissionProfiles") ?? {};
4459
4466
  this.toolExecutor.setConfig({
4460
4467
  hookConfig: this.config.get("hooks") ?? void 0,
4461
4468
  permissionRules: this.config.get("permissionRules") ?? [],
4462
- defaultPermission: this.config.get("defaultPermission") ?? "confirm"
4469
+ defaultPermission: this.config.get("defaultPermission") ?? "confirm",
4470
+ permissionProfileName,
4471
+ permissionProfile: permissionProfiles[permissionProfileName],
4472
+ allowedPermissionProfiles: this.config.get("allowedPermissionProfiles") ?? [],
4473
+ workspaceRoot: process.cwd(),
4474
+ networkPolicy: this.config.get("networkPolicy")
4463
4475
  });
4464
4476
  if (this.config.get("alwaysYolo") === true) {
4465
4477
  this.toolExecutor.sessionAutoApprove = true;
@@ -5130,6 +5142,11 @@ Session '${this.resumeSessionId}' not found.
5130
5142
  theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014 write tools auto-approved; destructive tools still require confirmation.\n")
5131
5143
  );
5132
5144
  }
5145
+ const permissionProfileWarning = formatPermissionProfileWarning(this.config.get("defaultPermissionProfile") ?? "legacy");
5146
+ if (permissionProfileWarning) {
5147
+ process.stdout.write(theme.warning(` ${permissionProfileWarning}
5148
+ `));
5149
+ }
5133
5150
  const cfgOutputCap = this.config.get("maxToolOutputChars");
5134
5151
  if (typeof cfgOutputCap === "number" && cfgOutputCap > 0) setMaxOutputCap(cfgOutputCap);
5135
5152
  if (welcomeModelInfo?.contextWindow) setContextWindow(welcomeModelInfo.contextWindow);
@@ -7003,7 +7020,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7003
7020
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7004
7021
  process.exit(1);
7005
7022
  }
7006
- const { startWebServer } = await import("./server-E5D54DIZ.js");
7023
+ const { startWebServer } = await import("./server-BTSKOPQI.js");
7007
7024
  await startWebServer({ port, host: options.host });
7008
7025
  });
7009
7026
  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) => {
@@ -7170,16 +7187,16 @@ program.command("sessions").description("List recent conversation sessions").opt
7170
7187
  console.log(footer + "\n");
7171
7188
  });
7172
7189
  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) => {
7173
- const { runUsageCli } = await import("./usage-P4B2RZKL.js");
7190
+ const { runUsageCli } = await import("./usage-T2P6FTE7.js");
7174
7191
  await runUsageCli(options);
7175
7192
  });
7176
7193
  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) => {
7177
- const { runDoctorCli } = await import("./doctor-cli-32COMA5K.js");
7194
+ const { runDoctorCli } = await import("./doctor-cli-SSI6ETFT.js");
7178
7195
  await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
7179
7196
  });
7180
7197
  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) => {
7181
7198
  try {
7182
- const batch = await import("./batch-MFPYHOIL.js");
7199
+ const batch = await import("./batch-DE4RXKZD.js");
7183
7200
  switch (action) {
7184
7201
  case "submit":
7185
7202
  if (!arg) {
@@ -7222,7 +7239,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7222
7239
  }
7223
7240
  });
7224
7241
  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) => {
7225
- const { startMcpServer } = await import("./server-AIHVMLNU.js");
7242
+ const { startMcpServer } = await import("./server-7USZJJAH.js");
7226
7243
  await startMcpServer({
7227
7244
  allowDestructive: !!options.allowDestructive,
7228
7245
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7231,7 +7248,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
7231
7248
  });
7232
7249
  });
7233
7250
  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; diff fetched via `gh pr diff <num>`", (v) => parseInt(v, 10)).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)").action(async (options) => {
7234
- const { runCi } = await import("./ci-QLJUDLMY.js");
7251
+ const { runCi } = await import("./ci-XMUEX526.js");
7235
7252
  const result = await runCi({
7236
7253
  pr: options.pr,
7237
7254
  base: options.base,
@@ -7377,7 +7394,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7377
7394
  }),
7378
7395
  config.get("customProviders")
7379
7396
  );
7380
- const { startHub } = await import("./hub-3NWJUCLK.js");
7397
+ const { startHub } = await import("./hub-INUJND2G.js");
7381
7398
  await startHub(
7382
7399
  {
7383
7400
  topic: topic ?? "",
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-E2ZWWE6Q.js";
6
- import "./chunk-GRJNQJA5.js";
5
+ } from "./chunk-6NS6643Y.js";
6
+ import "./chunk-E5XCM4A6.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-HZQVX7VF.js";
4
+ } from "./chunk-ZY2N2N6T.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-NEPFADHX.js";
4
+ } from "./chunk-ZOPYREL5.js";
5
5
  import "./chunk-T2NL5ZIA.js";
6
6
  import "./chunk-BXP6YZ2P.js";
7
- import "./chunk-E2ZWWE6Q.js";
7
+ import "./chunk-6NS6643Y.js";
8
8
  import {
9
9
  runTool
10
- } from "./chunk-DJ35G5VO.js";
10
+ } from "./chunk-JBWA73GK.js";
11
11
  import {
12
12
  getDangerLevel,
13
13
  schemaToJsonSchema
@@ -15,7 +15,7 @@ import {
15
15
  import "./chunk-TZQHYZKT.js";
16
16
  import {
17
17
  VERSION
18
- } from "./chunk-GRJNQJA5.js";
18
+ } from "./chunk-E5XCM4A6.js";
19
19
  import "./chunk-4BKXL7SM.js";
20
20
  import "./chunk-TB4W4Y4T.js";
21
21
  import "./chunk-KHYD3WXE.js";
@@ -24,7 +24,7 @@ import {
24
24
  scanDirTree,
25
25
  scanProject,
26
26
  setupProxy
27
- } from "./chunk-7JWT3KXO.js";
27
+ } from "./chunk-C3OU2OPF.js";
28
28
  import {
29
29
  buildReviewPrompt,
30
30
  buildSecurityReviewPrompt
@@ -33,9 +33,11 @@ import {
33
33
  ToolExecutor,
34
34
  ToolRegistry,
35
35
  askUserContext,
36
- checkPermission,
36
+ checkNetworkPolicy,
37
+ checkPermissionWithProfile,
37
38
  cleanupRejectedTeeFile,
38
39
  estimateTokens,
40
+ formatPermissionProfileWarning,
39
41
  googleSearchContext,
40
42
  groupCallsByPhase,
41
43
  renderDiff,
@@ -47,10 +49,10 @@ import {
47
49
  spawnAgentContext,
48
50
  truncateOutput,
49
51
  undoStack
50
- } from "./chunk-NEPFADHX.js";
52
+ } from "./chunk-ZOPYREL5.js";
51
53
  import "./chunk-T2NL5ZIA.js";
52
54
  import "./chunk-BXP6YZ2P.js";
53
- import "./chunk-E2ZWWE6Q.js";
55
+ import "./chunk-6NS6643Y.js";
54
56
  import {
55
57
  SessionManager,
56
58
  getContentText
@@ -64,7 +66,7 @@ import {
64
66
  } from "./chunk-QMXC327F.js";
65
67
  import {
66
68
  runTool
67
- } from "./chunk-DJ35G5VO.js";
69
+ } from "./chunk-JBWA73GK.js";
68
70
  import {
69
71
  CONTENT_ONLY_STREAM_REMINDER,
70
72
  TEE_FINAL_USER_NUDGE,
@@ -83,7 +85,7 @@ import {
83
85
  } from "./chunk-XPBEJB27.js";
84
86
  import {
85
87
  ConfigManager
86
- } from "./chunk-P6MTFCXB.js";
88
+ } from "./chunk-UOROWTGG.js";
87
89
  import "./chunk-TZQHYZKT.js";
88
90
  import {
89
91
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -102,7 +104,7 @@ import {
102
104
  SKILLS_DIR_NAME,
103
105
  VERSION,
104
106
  buildUserIdentityPrompt
105
- } from "./chunk-GRJNQJA5.js";
107
+ } from "./chunk-E5XCM4A6.js";
106
108
  import {
107
109
  formatGitContextForPrompt,
108
110
  getGitContext,
@@ -128,6 +130,7 @@ import { networkInterfaces } from "os";
128
130
 
129
131
  // src/web/tool-executor-web.ts
130
132
  import { randomUUID } from "crypto";
133
+ import { tmpdir } from "os";
131
134
  import { existsSync, readFileSync } from "fs";
132
135
  var ToolExecutorWeb = class _ToolExecutorWeb {
133
136
  constructor(registry, ws) {
@@ -139,6 +142,11 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
139
142
  hookConfig;
140
143
  permissionRules = [];
141
144
  defaultPermission = "confirm";
145
+ permissionProfileName = "legacy";
146
+ permissionProfile;
147
+ allowedPermissionProfiles = [];
148
+ workspaceRoot = process.cwd();
149
+ networkPolicy;
142
150
  /** Pending confirm promises keyed by requestId */
143
151
  pendingConfirms = /* @__PURE__ */ new Map();
144
152
  /** Pending batch confirm promises */
@@ -173,6 +181,11 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
173
181
  this.hookConfig = opts.hookConfig;
174
182
  if (opts.permissionRules) this.permissionRules = opts.permissionRules;
175
183
  if (opts.defaultPermission) this.defaultPermission = opts.defaultPermission;
184
+ if (opts.permissionProfileName) this.permissionProfileName = opts.permissionProfileName;
185
+ if (opts.permissionProfile) this.permissionProfile = opts.permissionProfile;
186
+ if (opts.allowedPermissionProfiles) this.allowedPermissionProfiles = opts.allowedPermissionProfiles;
187
+ if (opts.workspaceRoot) this.workspaceRoot = opts.workspaceRoot;
188
+ if (opts.networkPolicy) this.networkPolicy = opts.networkPolicy;
176
189
  }
177
190
  /** Clear M7 timeout timer for a requestId */
178
191
  clearPendingTimer(requestId) {
@@ -221,6 +234,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
221
234
  }
222
235
  sendToolCallStart(call) {
223
236
  const dangerLevel = getDangerLevel(call.name, call.arguments);
237
+ let toolCallStarted = false;
224
238
  const startTime = Date.now();
225
239
  this.toolStartTimes.set(call.id, startTime);
226
240
  const msg = {
@@ -329,30 +343,66 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
329
343
  return { callId: call.id, content: `Unknown tool: ${call.name}`, isError: true };
330
344
  }
331
345
  const dangerLevel = getDangerLevel(call.name, call.arguments);
346
+ let toolCallStarted = false;
332
347
  runHook(this.hookConfig?.preToolExecution, {
333
348
  tool: call.name,
334
349
  dangerLevel,
335
350
  args: JSON.stringify(call.arguments).slice(0, 200)
336
351
  });
337
- if (this.permissionRules.length > 0) {
338
- const action = checkPermission(call.name, call.arguments, dangerLevel, this.permissionRules, this.defaultPermission);
339
- if (action === "deny") {
340
- return { callId: call.id, content: `[Permission denied] Tool ${call.name} is blocked by permission rules. Do not retry.`, isError: true };
352
+ const permission = checkPermissionWithProfile(
353
+ call.name,
354
+ call.arguments,
355
+ dangerLevel,
356
+ this.permissionRules,
357
+ this.defaultPermission,
358
+ {
359
+ profileName: this.permissionProfileName,
360
+ profile: this.permissionProfile,
361
+ allowedProfiles: this.allowedPermissionProfiles,
362
+ workspaceRoot: this.workspaceRoot,
363
+ tempDirs: [tmpdir()]
341
364
  }
342
- if (action === "auto-approve") {
343
- this.sendToolCallStart(call);
344
- try {
345
- const rawContent = await runTool(tool, call.arguments, call.name);
346
- const content = truncateOutput(rawContent, call.name);
347
- this.sendToolCallResult(call, rawContent, false);
348
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
349
- return { callId: call.id, content, isError: false };
350
- } catch (err) {
351
- const message = err instanceof Error ? err.message : String(err);
352
- this.sendToolCallResult(call, message, true);
353
- runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
354
- return { callId: call.id, content: message, isError: true };
355
- }
365
+ );
366
+ const networkPermission = checkNetworkPolicy(call.name, call.arguments, this.networkPolicy);
367
+ if (networkPermission?.action === "deny") {
368
+ const reason = networkPermission.reason ? ` (${networkPermission.reason})` : "";
369
+ return {
370
+ callId: call.id,
371
+ content: `[Permission denied] Tool ${call.name} is blocked by networkPolicy${reason}. Do not retry.`,
372
+ isError: true
373
+ };
374
+ }
375
+ if (permission.action === "deny") {
376
+ const reason = permission.reason ? ` (${permission.reason})` : "";
377
+ return {
378
+ callId: call.id,
379
+ content: `[Permission denied] Tool ${call.name} is blocked by permission profile "${permission.profileName}"${reason}. Do not retry.`,
380
+ isError: true
381
+ };
382
+ }
383
+ if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
384
+ this.sendToolCallStart(call);
385
+ try {
386
+ const rawContent = await runTool(tool, call.arguments, call.name);
387
+ const content = truncateOutput(rawContent, call.name);
388
+ this.sendToolCallResult(call, rawContent, false);
389
+ runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
390
+ return { callId: call.id, content, isError: false };
391
+ } catch (err) {
392
+ const message = err instanceof Error ? err.message : String(err);
393
+ this.sendToolCallResult(call, message, true);
394
+ runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
395
+ return { callId: call.id, content: message, isError: true };
396
+ }
397
+ }
398
+ if (networkPermission?.action === "confirm" && dangerLevel === "safe") {
399
+ this.sendToolCallStart(call);
400
+ toolCallStarted = true;
401
+ const confirmed = await this.confirm(call, "write");
402
+ if (!confirmed) {
403
+ const rejectionMsg = `[User cancelled] The user declined network access for ${call.name}. Do not retry without asking.`;
404
+ this.sendToolCallResult(call, rejectionMsg, true);
405
+ return { callId: call.id, content: rejectionMsg, isError: true };
356
406
  }
357
407
  }
358
408
  this.sendToolCallStart(call);
@@ -411,6 +461,9 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
411
461
  return results;
412
462
  }
413
463
  async executeBatchFileWrites(items) {
464
+ if (this.permissionProfileName !== "legacy" || this.permissionRules.length > 0) {
465
+ return Promise.all(items.map(({ call }) => this.execute(call)));
466
+ }
414
467
  const calls = items.map((i) => i.call);
415
468
  const decision = this.sessionAutoApprove ? "all" : await this.batchConfirm(calls);
416
469
  const results = new Array(calls.length);
@@ -624,7 +677,22 @@ var SessionHandler = class {
624
677
  const hooks = this.config.get("hooks");
625
678
  const permissionRules = this.config.get("permissionRules");
626
679
  const defaultPermission = this.config.get("defaultPermission");
627
- this.toolExecutor.setConfig({ hookConfig: hooks, permissionRules, defaultPermission });
680
+ const permissionProfileName = this.config.get("defaultPermissionProfile") ?? "legacy";
681
+ const permissionProfiles = this.config.get("permissionProfiles") ?? {};
682
+ this.toolExecutor.setConfig({
683
+ hookConfig: hooks,
684
+ permissionRules,
685
+ defaultPermission,
686
+ permissionProfileName,
687
+ permissionProfile: permissionProfiles[permissionProfileName],
688
+ allowedPermissionProfiles: this.config.get("allowedPermissionProfiles") ?? [],
689
+ workspaceRoot: process.cwd(),
690
+ networkPolicy: this.config.get("networkPolicy")
691
+ });
692
+ const permissionProfileWarning = formatPermissionProfileWarning(permissionProfileName);
693
+ if (permissionProfileWarning) {
694
+ this.send({ type: "info", message: permissionProfileWarning });
695
+ }
628
696
  this.sendStatus();
629
697
  askUserContext.rl = null;
630
698
  askUserContext.prompting = false;
@@ -659,6 +727,7 @@ var SessionHandler = class {
659
727
  messageCount: this.sessions.current?.messages.length ?? 0,
660
728
  planMode: this.planMode,
661
729
  thinkingMode: this.runtimeThinking ?? false,
730
+ permissionProfile: this.config.get("defaultPermissionProfile") ?? "legacy",
662
731
  tokenUsage: { ...this.sessionTokenUsage },
663
732
  costUsd,
664
733
  providers: providerList,
@@ -2464,7 +2533,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2464
2533
  case "test": {
2465
2534
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2466
2535
  try {
2467
- const { executeTests } = await import("./run-tests-UT7RZ7Y3.js");
2536
+ const { executeTests } = await import("./run-tests-3MHWUF43.js");
2468
2537
  const argStr = args.join(" ").trim();
2469
2538
  let testArgs = {};
2470
2539
  if (argStr) {
@@ -3,13 +3,13 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-NEPFADHX.js";
6
+ } from "./chunk-ZOPYREL5.js";
7
7
  import "./chunk-T2NL5ZIA.js";
8
8
  import "./chunk-BXP6YZ2P.js";
9
- import "./chunk-E2ZWWE6Q.js";
9
+ import "./chunk-6NS6643Y.js";
10
10
  import {
11
11
  runTool
12
- } from "./chunk-DJ35G5VO.js";
12
+ } from "./chunk-JBWA73GK.js";
13
13
  import {
14
14
  getDangerLevel,
15
15
  runLeanAgentLoop
@@ -17,7 +17,7 @@ import {
17
17
  import "./chunk-TZQHYZKT.js";
18
18
  import {
19
19
  SUBAGENT_ALLOWED_TOOLS
20
- } from "./chunk-GRJNQJA5.js";
20
+ } from "./chunk-E5XCM4A6.js";
21
21
  import "./chunk-4BKXL7SM.js";
22
22
  import "./chunk-TB4W4Y4T.js";
23
23
  import "./chunk-KHYD3WXE.js";
@@ -8,9 +8,9 @@ import {
8
8
  } from "./chunk-E44DTERW.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-P6MTFCXB.js";
11
+ } from "./chunk-UOROWTGG.js";
12
12
  import "./chunk-TZQHYZKT.js";
13
- import "./chunk-GRJNQJA5.js";
13
+ import "./chunk-E5XCM4A6.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
 
16
16
  // src/cli/usage.ts
@@ -548,7 +548,7 @@ function handleStatus(msg) {
548
548
  // Active tab: full UI reflection
549
549
  btnThink.classList.toggle('btn-active-toggle', msg.thinkingMode);
550
550
  btnPlan.classList.toggle('btn-active-toggle', msg.planMode);
551
- statusSession.textContent = `📋 ${msg.sessionId?.slice(0, 8) || '—'} (${msg.messageCount} msgs)`;
551
+ statusSession.textContent = '📋 ' + (msg.sessionId?.slice(0, 8) || '—') + ' (' + msg.messageCount + ' msgs) · ' + (msg.permissionProfile || 'legacy') + (msg.networkPolicyEnabled ? ' · net:on' : '');
552
552
  if (msg.tokenUsage) {
553
553
  const u = msg.tokenUsage;
554
554
  const cacheRead = u.cacheReadTokens || 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.210",
3
+ "version": "0.4.211",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",