jinzd-ai-cli 0.4.334 → 0.4.338

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 (37) hide show
  1. package/dist/{batch-6UJGEEVB.js → batch-N4DOEUEW.js} +2 -2
  2. package/dist/{chunk-W4P2KJZN.js → chunk-7BOHS5IX.js} +72 -0
  3. package/dist/{chunk-SZQ2C3HH.js → chunk-ATOF545W.js} +1 -1
  4. package/dist/{chunk-7GGWVBHG.js → chunk-DCWBDSMO.js} +2 -2
  5. package/dist/{chunk-RQOOEXDU.js → chunk-DOO4QAGJ.js} +2 -2
  6. package/dist/{chunk-XMHVHS2X.js → chunk-DRCN44SZ.js} +4 -4
  7. package/dist/{chunk-YTAYWGS4.js → chunk-JUYK4OML.js} +1 -1
  8. package/dist/{chunk-DPUZ22D7.js → chunk-KGHVSYGI.js} +27 -23
  9. package/dist/{chunk-EOYIIGBJ.js → chunk-NJREBH6A.js} +5 -5
  10. package/dist/{chunk-FHHBPCCZ.js → chunk-NRFAGZVJ.js} +1 -1
  11. package/dist/{chunk-YVEBRHSV.js → chunk-OXVJZLJM.js} +6 -5
  12. package/dist/{chunk-YY4QFBBZ.js → chunk-PKYNCSQC.js} +475 -240
  13. package/dist/{chunk-KSZEQADY.js → chunk-RIDNF4G2.js} +1 -1
  14. package/dist/{chunk-27RTBMY7.js → chunk-TTLLXFJC.js} +40 -3
  15. package/dist/{chunk-DX4Y4CRH.js → chunk-UWEBIOHD.js} +8 -20
  16. package/dist/{chunk-ZK5VCQD2.js → chunk-WQAUMAEV.js} +1 -1
  17. package/dist/{ci-S7WXRTZ6.js → ci-HFAPFMZY.js} +6 -6
  18. package/dist/{ci-format-TPCL2KWQ.js → ci-format-QTRMHY3N.js} +2 -2
  19. package/dist/{constants-WJAUJAQQ.js → constants-JZH2QKMQ.js} +1 -1
  20. package/dist/{constants-5VQMHBFU.js → constants-QJNJFMC6.js} +1 -1
  21. package/dist/{doctor-cli-DYQLNMPT.js → doctor-cli-FZ4IVZ6H.js} +6 -6
  22. package/dist/electron-server.js +622 -285
  23. package/dist/{hub-A7P2ZBYB.js → hub-IRILXTL3.js} +1 -1
  24. package/dist/index.js +25 -23
  25. package/dist/{persistent-memory-WFGBTGWT.js → persistent-memory-UZIZVHRT.js} +2 -2
  26. package/dist/{persistent-memory-SKGOCEGT.js → persistent-memory-VRBNWOWN.js} +2 -2
  27. package/dist/{pr-IPXLVP2K.js → pr-4KNQWYC6.js} +7 -7
  28. package/dist/{run-tests-BG6SGRWQ.js → run-tests-N2VKD7BU.js} +2 -2
  29. package/dist/{run-tests-TUTI7HIN.js → run-tests-UXEOFPAW.js} +2 -2
  30. package/dist/{server-4QJPQBEW.js → server-2VSO2ZX4.js} +6 -6
  31. package/dist/{server-S6OROC7S.js → server-HWKYWQEP.js} +21 -20
  32. package/dist/{task-orchestrator-6JG5GAXU.js → task-orchestrator-SC42LAFG.js} +6 -6
  33. package/dist/{usage-LPQQ6NGG.js → usage-ZVV27BHD.js} +2 -2
  34. package/dist/web/client/vendor/purify.es.mjs +272 -196
  35. package/dist/web/client/vendor/purify.es.mjs.br +0 -0
  36. package/dist/web/client/vendor/purify.es.mjs.gz +0 -0
  37. package/package.json +6 -3
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-RS7SKYTS.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-DPUZ22D7.js";
7
+ } from "./chunk-KGHVSYGI.js";
8
8
  import "./chunk-TU3L3PW7.js";
9
9
  import {
10
10
  atomicWriteFileSync
11
11
  } from "./chunk-BMLQPSHP.js";
12
- import "./chunk-FHHBPCCZ.js";
12
+ import "./chunk-NRFAGZVJ.js";
13
13
 
14
14
  // src/cli/batch.ts
15
15
  import Anthropic from "@anthropic-ai/sdk";
@@ -4,6 +4,77 @@
4
4
  function isFileWriteTool(name) {
5
5
  return name === "write_file" || name === "edit_file" || name === "notebook_edit";
6
6
  }
7
+ var READ_ONLY_CMDLETS = new Set([
8
+ "Get-ChildItem",
9
+ "gci",
10
+ "Get-Content",
11
+ "gc",
12
+ "Get-Item",
13
+ "gi",
14
+ "Get-ItemProperty",
15
+ "gp",
16
+ "Get-ItemPropertyValue",
17
+ "Get-Location",
18
+ "gl",
19
+ "Test-Path",
20
+ "Resolve-Path",
21
+ "Split-Path",
22
+ "Join-Path",
23
+ "Get-Command",
24
+ "gcm",
25
+ "Get-Service",
26
+ "gsv",
27
+ "Get-Process",
28
+ "gps",
29
+ "Get-Date",
30
+ "Get-Alias",
31
+ "Get-Module",
32
+ "Get-PSDrive",
33
+ "Get-Acl",
34
+ "Get-FileHash",
35
+ "Get-CimInstance",
36
+ "Get-NetTCPConnection",
37
+ "Get-NetIPAddress",
38
+ "Get-WinEvent",
39
+ "Get-ComputerInfo",
40
+ "Get-Culture",
41
+ "Get-ExecutionPolicy",
42
+ "Get-Unique",
43
+ "Select-Object",
44
+ "select",
45
+ "Where-Object",
46
+ "Sort-Object",
47
+ "Measure-Object",
48
+ "Group-Object",
49
+ "Compare-Object",
50
+ "Select-String",
51
+ "sls",
52
+ "Format-Table",
53
+ "ft",
54
+ "Format-List",
55
+ "fl",
56
+ "Format-Wide",
57
+ "Out-String",
58
+ "Write-Output",
59
+ "Write-Host",
60
+ // Waiting is harmless on its own; chained segments still have to pass this list (v0.4.338).
61
+ "Start-Sleep",
62
+ // ls is read-only both as the PowerShell alias and as the Unix binary; models pair it with
63
+ // Start-Sleep to poll an output folder (2026-11-05 lecture-video run).
64
+ "ls",
65
+ "ConvertTo-Json",
66
+ "ConvertFrom-Json",
67
+ "ConvertTo-Csv",
68
+ "ConvertFrom-Csv"
69
+ ].map((name) => name.toLowerCase()));
70
+ function isReadOnlyCmdletChain(cmd) {
71
+ const normalized = cmd.trim().replace(/\s2>\s*\$null\b/gi, " ").replace(/\s2>&1\b/g, " ").replace(/\$(?:env:\w+|null|true|false)\b/gi, "X");
72
+ if (!normalized || /[&`$<>\n\r(){}]|::/.test(normalized)) return false;
73
+ return normalized.split(/[;|]/).every((segment) => {
74
+ const name = segment.trim().split(/\s+/)[0].toLowerCase();
75
+ return READ_ONLY_CMDLETS.has(name);
76
+ });
77
+ }
7
78
  function getDangerLevel(toolName, args) {
8
79
  if (toolName.startsWith("mcp__")) {
9
80
  const rawName = toolName.split("__").pop() ?? "";
@@ -33,6 +104,7 @@ function getDangerLevel(toolName, args) {
33
104
  if (/\b(python3?|node|deno|bun|perl|ruby|php|bash|sh|zsh|pwsh|powershell)(\.exe)?\b[^\n]*?\s-(?:Command|EncodedCommand|c|e|p|r)\b/i.test(cmd)) return "write";
34
105
  if (/\bcmd(\.exe)?\s+\/[ck]\b/i.test(cmd)) return "write";
35
106
  if (!/[;&|`$<>\n\r(){}]/.test(cmd) && (/^(?:pwd|ls|cat|head|tail|wc|Get-ChildItem|Get-Location|Get-Content)(?:\s+[\w ./\\:*?=,@'"-]+)?\s*$/i.test(cmd.trim()) || /^echo(?:\s+[\w .,'"-]+)?\s*$/.test(cmd.trim()) || /^(?:node|python3?)\s+(?:-v|--version)\s*$/.test(cmd.trim()) || /^git\s+(?:status|log)(?:\s+(?:--short|--porcelain|--oneline|-\d+))*\s*$/.test(cmd.trim()))) return "safe";
107
+ if (isReadOnlyCmdletChain(cmd)) return "safe";
36
108
  return "write";
37
109
  }
38
110
  if (toolName === "run_tests") return "write";
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.334";
2
+ var VERSION = "0.4.338";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-QMFMST2T.js";
5
5
  import {
6
6
  TEST_TIMEOUT
7
- } from "./chunk-SZQ2C3HH.js";
7
+ } from "./chunk-ATOF545W.js";
8
8
 
9
9
  // src/tools/builtin/run-tests.ts
10
10
  import { spawn as spawn2 } from "child_process";
@@ -20,7 +20,7 @@ import { platform } from "os";
20
20
  import { existsSync } from "fs";
21
21
  import { spawn } from "child_process";
22
22
  var IS_WINDOWS = platform() === "win32";
23
- var WIN_UTF8_PREAMBLE = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; ";
23
+ var WIN_UTF8_PREAMBLE = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; $PSDefaultParameterValues['Get-Content:Encoding'] = 'UTF8'; ";
24
24
  function posixShell() {
25
25
  if (existsSync("/bin/bash")) return "/bin/bash";
26
26
  return process.env["SHELL"] ?? "/bin/sh";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-FHHBPCCZ.js";
4
+ } from "./chunk-NRFAGZVJ.js";
5
5
  import {
6
6
  getExecutionConfigDir,
7
7
  getExecutionSignal
@@ -35,7 +35,7 @@ import { platform } from "os";
35
35
  import { existsSync } from "fs";
36
36
  import { spawn } from "child_process";
37
37
  var IS_WINDOWS = platform() === "win32";
38
- var WIN_UTF8_PREAMBLE = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; ";
38
+ var WIN_UTF8_PREAMBLE = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; $PSDefaultParameterValues['Get-Content:Encoding'] = 'UTF8'; ";
39
39
  function posixShell() {
40
40
  if (existsSync("/bin/bash")) return "/bin/bash";
41
41
  return process.env["SHELL"] ?? "/bin/sh";
@@ -8,13 +8,13 @@ import {
8
8
  listHooks,
9
9
  listInstalledPlugins,
10
10
  resetStats
11
- } from "./chunk-EOYIIGBJ.js";
11
+ } from "./chunk-NJREBH6A.js";
12
12
  import {
13
13
  ProviderRegistry
14
- } from "./chunk-27RTBMY7.js";
14
+ } from "./chunk-TTLLXFJC.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-DPUZ22D7.js";
17
+ } from "./chunk-KGHVSYGI.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-FHHBPCCZ.js";
29
+ } from "./chunk-NRFAGZVJ.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -12,7 +12,7 @@ import {
12
12
  MEMORY_FILE_NAME,
13
13
  MEMORY_MAX_CHARS,
14
14
  MEMORY_STORE_FILE_NAME
15
- } from "./chunk-SZQ2C3HH.js";
15
+ } from "./chunk-ATOF545W.js";
16
16
 
17
17
  // src/memory/persistent-memory.ts
18
18
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -11,7 +11,7 @@ import {
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-FHHBPCCZ.js";
14
+ } from "./chunk-NRFAGZVJ.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -66,32 +66,36 @@ var UserProfileSchema = z.object({
66
66
  locale: z.string().max(20).optional(),
67
67
  /** 自定义人设补充(自由格式,直接注入 system prompt) */
68
68
  extra: z.string().max(5e3).optional()
69
- }).default({});
69
+ }).prefault({});
70
70
  var ConfigSchema = z.object({
71
71
  version: z.string().default("1.0.0"),
72
72
  // 用户身份档案 — 跨 Provider 的 "灵魂"
73
73
  userProfile: UserProfileSchema,
74
74
  defaultProvider: z.string().default("claude"),
75
75
  // 每个 provider 的默认模型(key 为 provider ID)
76
- defaultModels: z.record(z.string()).default({}),
76
+ defaultModels: z.record(z.string(), z.string()).default({}),
77
77
  // API Keys:放宽为任意 record,支持自定义 provider ID
78
- apiKeys: z.record(z.string()).default({}),
79
- customBaseUrls: z.record(z.string()).default({}),
78
+ apiKeys: z.record(z.string(), z.string()).default({}),
79
+ customBaseUrls: z.record(z.string(), z.string()).default({}),
80
80
  // Per-provider timeout in ms (e.g. { deepseek: 60000 })
81
81
  // ⚠️ Timeout 优先级说明(L5):
82
82
  // 1. modelParams[modelId].timeout — 最高优先级,精确到具体模型(如 deepseek-reasoner 需要更长超时)
83
83
  // 2. timeouts[providerId] — Provider 级默认,覆盖内置默认值
84
84
  // 3. 内置 Provider 的硬编码默认值 — 最低兜底(如 OpenAI 兼容系列默认 60000ms)
85
85
  // 实现位置:src/providers/registry.ts initialize(),将 timeouts[id] 注入 provider
86
- timeouts: z.record(z.number()).default({}),
86
+ timeouts: z.record(z.string(), z.number()).default({}),
87
87
  // HTTP/HTTPS 代理地址(Node.js 不自动使用系统代理,需显式配置)
88
88
  // 例:http://127.0.0.1:10809
89
89
  // 也可通过环境变量 HTTPS_PROXY / HTTP_PROXY 覆盖
90
90
  proxy: z.string().max(500).optional(),
91
+ // 不走代理的 API 主机(后缀匹配,如 "deepseek.com" 也覆盖 api.deepseek.com;"*" = 全部直连)。
92
+ // 不填 = 内置国内模型清单(DeepSeek/智谱/Kimi/Qwen/MiniMax 直连,见 core/proxy.ts);
93
+ // 填 [] = 所有 Provider 都走代理(公司网络只能经代理出网时用)。
94
+ noProxy: z.array(z.string().max(200)).max(100).optional(),
91
95
  // 自定义 Provider 列表(OpenAI 兼容接口,无需改代码)
92
96
  customProviders: z.array(CustomProviderConfigSchema).default([]),
93
97
  // 按模型 ID 存储的推理参数(key 为模型 ID,如 "deepseek-chat")
94
- modelParams: z.record(ModelParamsSchema).default({}),
98
+ modelParams: z.record(z.string(), ModelParamsSchema).default({}),
95
99
  ui: z.object({
96
100
  streaming: z.boolean().default(true),
97
101
  markdownRendering: z.boolean().default(true),
@@ -125,12 +129,12 @@ var ConfigSchema = z.object({
125
129
  toolResult: z.string().optional(),
126
130
  heading: z.string().optional()
127
131
  }).optional()
128
- }).default({}),
132
+ }).prefault({}),
129
133
  session: z.object({
130
134
  autoSave: z.boolean().default(true),
131
135
  maxHistoryDays: z.number().default(30),
132
136
  systemPrompt: z.string().max(1e5).optional()
133
- }).default({}),
137
+ }).prefault({}),
134
138
  // 项目上下文文件配置
135
139
  // 启动时自动读取并注入 system prompt,类似 Claude Code 的 CLAUDE.md / Codex AGENTS.md 机制
136
140
  // 默认按顺序查找:AICLI.override.md → AGENTS.override.md → AICLI.md → CLAUDE.md → AGENTS.md
@@ -140,13 +144,13 @@ var ConfigSchema = z.object({
140
144
  projectDocFallbackFilenames: z.array(z.string().max(500)).max(20).default([]),
141
145
  projectDocMaxBytes: z.number().int().positive().default(32 * 1024),
142
146
  showLoadedContextSources: z.boolean().default(false)
143
- }).default({}),
147
+ }).prefault({}),
144
148
  // 持久记忆注入配置(MEM-005)
145
149
  // maxChars: 注入 system prompt 的字符预算,超出丢最老条目并显式标注截断。
146
150
  // 注意 CJK ≈ 1 字符/token——中文记忆的 token 开销约等于字符数。
147
151
  memory: z.object({
148
152
  maxChars: z.number().int().positive().max(2e5).default(1e4)
149
- }).default({}),
153
+ }).prefault({}),
150
154
  // Google Custom Search API 的 Search Engine ID (cx 参数)
151
155
  // API Key 通过 apiKeys['google-search'] 或 AICLI_API_KEY_GOOGLESEARCH 环境变量配置
152
156
  // CX 也可通过 AICLI_GOOGLE_CX 环境变量覆盖
@@ -158,7 +162,7 @@ var ConfigSchema = z.object({
158
162
  // 仍想用 API 版?把 enabled 设为 true,并务必到 GCP Console 把 Custom Search Quota 设硬上限。
159
163
  googleSearch: z.object({
160
164
  enabled: z.boolean().default(false)
161
- }).default({ enabled: false }),
165
+ }).prefault({ enabled: false }),
162
166
  // MCP (Model Context Protocol) 全局开关(v0.4.135+)
163
167
  // false 时启动跳过 connectAll(),所有 MCP 服务器都不连,节省冷启动时间 + 工具定义 token。
164
168
  // 对应你的 skills(whitelist 不依赖 MCP 工具时)完全不受影响。
@@ -167,10 +171,10 @@ var ConfigSchema = z.object({
167
171
  // 声明外部 MCP 服务器,启动时自动连接、发现工具并注册
168
172
  // 配置格式兼容 Claude Desktop(command + args + env)
169
173
  // 示例:{ "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"] } }
170
- mcpServers: z.record(z.object({
174
+ mcpServers: z.record(z.string(), z.object({
171
175
  command: z.string().max(500),
172
176
  args: z.array(z.string()).max(100).default([]),
173
- env: z.record(z.string()).optional(),
177
+ env: z.record(z.string(), z.string()).optional(),
174
178
  timeout: z.number().int().min(100).max(3e5).default(3e4)
175
179
  })).default({}),
176
180
  // Hooks 生命周期(v0.4.212+):兼容旧 pre/post 字符串,同时支持 events.<EventName> 结构化 JSON hook。
@@ -178,7 +182,7 @@ var ConfigSchema = z.object({
178
182
  enabled: z.boolean().default(true),
179
183
  preToolExecution: z.string().optional(),
180
184
  postToolExecution: z.string().optional(),
181
- events: z.record(z.union([
185
+ events: z.record(z.string(), z.union([
182
186
  z.string(),
183
187
  z.object({
184
188
  command: z.string(),
@@ -216,12 +220,12 @@ var ConfigSchema = z.object({
216
220
  google_search: z.enum(["allow", "confirm", "deny"]).optional(),
217
221
  shell: z.enum(["allow", "confirm", "deny"]).optional(),
218
222
  mcp: z.enum(["allow", "confirm", "deny"]).optional()
219
- }).default({})
220
- }).default({ enabled: false, defaultAction: "confirm", allowDomains: [], denyDomains: [], allowPorts: [], denyPorts: [], allowPrivateNetwork: false, tools: {} }),
223
+ }).prefault({})
224
+ }).prefault({ enabled: false, defaultAction: "confirm", allowDomains: [], denyDomains: [], allowPorts: [], denyPorts: [], allowPrivateNetwork: false, tools: {} }),
221
225
  // 权限 Profile(v0.4.211+):legacy 保持旧行为;其余 profile 提供更清晰的安全边界。
222
226
  defaultPermissionProfile: z.enum(["legacy", "read-only", "workspace-write", "danger-full-access"]).default("legacy"),
223
227
  allowedPermissionProfiles: z.array(z.string().max(50)).max(20).default(["legacy", "read-only", "workspace-write", "danger-full-access"]),
224
- permissionProfiles: z.record(z.object({
228
+ permissionProfiles: z.record(z.string(), z.object({
225
229
  extends: z.enum(["legacy", "read-only", "workspace-write", "danger-full-access"]).optional(),
226
230
  defaultAction: z.enum(["auto-approve", "deny", "confirm"]).optional(),
227
231
  workspaceRoots: z.array(z.string()).optional(),
@@ -296,7 +300,7 @@ var ConfigSchema = z.object({
296
300
  redactOnSend: z.boolean().default(false),
297
301
  mode: z.enum(["default", "strict", "off"]).default("default"),
298
302
  customPatterns: z.array(z.string().max(200)).max(50).default([])
299
- }).default({}),
303
+ }).prefault({}),
300
304
  // 智能模型路由(v0.4.68+)
301
305
  // 按用户每轮输入的内容/标签/长度动态选择模型,在同一 provider 内切换,
302
306
  // 例:短问题走 haiku(省钱),planning 走 opus(质量)。
@@ -316,7 +320,7 @@ var ConfigSchema = z.object({
316
320
  name: z.string().max(100).optional()
317
321
  })).default([]),
318
322
  fallback: z.string().optional()
319
- }).default({ enabled: false, rules: [] }),
323
+ }).prefault({ enabled: false, rules: [] }),
320
324
  // Provider 容错(v0.4.144+):网络抖动 / 5xx / 429 时,先在当前 provider 上做指数退避重试,
321
325
  // 仍失败则按顺序尝试 chain 里的 fallback provider。auth / 400 / 422 等"硬失败"直接跳过同
322
326
  // provider 重试,但仍会尝试 chain(不同 key/schema 可能能成功)。
@@ -336,7 +340,7 @@ var ConfigSchema = z.object({
336
340
  provider: z.string().max(100),
337
341
  model: z.string().optional()
338
342
  })).default([])
339
- }).default({ enabled: false, retries: 2, initialBackoffMs: 500, maxBackoffMs: 8e3, chain: [] })
343
+ }).prefault({ enabled: false, retries: 2, initialBackoffMs: 500, maxBackoffMs: 8e3, chain: [] })
340
344
  });
341
345
 
342
346
  // src/config/config-manager.ts
@@ -503,7 +507,7 @@ ${err}`
503
507
  const draft = { ...this.config, [key]: value };
504
508
  const result = ConfigSchema.safeParse(draft);
505
509
  if (!result.success) {
506
- const firstErr = result.error.errors[0];
510
+ const firstErr = result.error.issues[0];
507
511
  throw new ConfigError(
508
512
  `Invalid transient config value for "${String(key)}": ${firstErr?.message ?? "validation failed"}`
509
513
  );
@@ -555,7 +559,7 @@ ${err}`
555
559
  current[keys[keys.length - 1]] = value;
556
560
  const result = ConfigSchema.safeParse(draft);
557
561
  if (!result.success) {
558
- const firstErr = result.error.errors[0];
562
+ const firstErr = result.error.issues[0];
559
563
  throw new ConfigError(`Invalid config value for "${path}": ${firstErr?.message ?? "validation failed"}`);
560
564
  }
561
565
  this.config = result.data;
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  CONFIG_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-FHHBPCCZ.js";
11
+ } from "./chunk-NRFAGZVJ.js";
12
12
 
13
13
  // src/diagnostics/tool-stats.ts
14
14
  import { mkdirSync } from "fs";
@@ -164,7 +164,7 @@ var HookEventNameSchema = z.enum([
164
164
  var McpServerSchema = z.object({
165
165
  command: z.string(),
166
166
  args: z.array(z.string()).default([]),
167
- env: z.record(z.string()).optional(),
167
+ env: z.record(z.string(), z.string()).optional(),
168
168
  timeout: z.number().default(3e4)
169
169
  });
170
170
  var PluginManifestSchema = z.object({
@@ -174,10 +174,10 @@ var PluginManifestSchema = z.object({
174
174
  skills: z.array(z.string()).default([]),
175
175
  hooks: z.object({
176
176
  enabled: z.boolean().optional(),
177
- events: z.record(HookEventNameSchema, HookCommandSchema).default({})
178
- }).default({ events: {} }),
177
+ events: z.partialRecord(HookEventNameSchema, HookCommandSchema).default({})
178
+ }).prefault({ events: {} }),
179
179
  commands: z.array(z.string()).default([]),
180
- mcpServers: z.record(McpServerSchema).default({}),
180
+ mcpServers: z.record(z.string(), McpServerSchema).default({}),
181
181
  agents: z.array(z.string()).default([]),
182
182
  permissionHints: z.array(z.string()).default([])
183
183
  }).strict();
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.334";
4
+ var VERSION = "0.4.338";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-KSZEQADY.js";
5
+ } from "./chunk-RIDNF4G2.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -13,13 +13,13 @@ import {
13
13
  } from "./chunk-6YZEZFX5.js";
14
14
  import {
15
15
  ProviderRegistry
16
- } from "./chunk-27RTBMY7.js";
16
+ } from "./chunk-TTLLXFJC.js";
17
17
  import {
18
18
  ConfigManager
19
- } from "./chunk-DPUZ22D7.js";
19
+ } from "./chunk-KGHVSYGI.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-FHHBPCCZ.js";
22
+ } from "./chunk-NRFAGZVJ.js";
23
23
 
24
24
  // src/cli/ci.ts
25
25
  import { execFileSync } from "child_process";
@@ -161,7 +161,8 @@ async function runCi(opts) {
161
161
  (id) => ({
162
162
  baseUrl: config.get("customBaseUrls")[id],
163
163
  timeout: config.get("timeouts")[id],
164
- proxy: config.get("proxy")
164
+ proxy: config.get("proxy"),
165
+ noProxy: config.get("noProxy")
165
166
  }),
166
167
  config.get("customProviders"),
167
168
  config.getConfigDir()