jinzd-ai-cli 0.4.86 → 0.4.88

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.
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-YRWBFUYH.js";
4
+ } from "./chunk-QT2KNL3V.js";
5
5
  import "./chunk-2ZD3YTVM.js";
6
- import "./chunk-CKCGAHEF.js";
6
+ import "./chunk-VGXNE37B.js";
7
7
 
8
8
  // src/cli/batch.ts
9
9
  import Anthropic from "@anthropic-ai/sdk";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  schemaToJsonSchema,
4
4
  truncateForPersist
5
- } from "./chunk-M7KYMJT5.js";
5
+ } from "./chunk-YDHIU24C.js";
6
6
  import {
7
7
  AuthError,
8
8
  ProviderError,
@@ -18,7 +18,7 @@ import {
18
18
  MCP_PROTOCOL_VERSION,
19
19
  MCP_TOOL_PREFIX,
20
20
  VERSION
21
- } from "./chunk-CKCGAHEF.js";
21
+ } from "./chunk-VGXNE37B.js";
22
22
 
23
23
  // src/providers/claude.ts
24
24
  import Anthropic from "@anthropic-ai/sdk";
@@ -1291,17 +1291,41 @@ var DeepSeekProvider = class extends OpenAICompatibleProvider {
1291
1291
  // src/providers/zhipu.ts
1292
1292
  var ZhipuProvider = class extends OpenAICompatibleProvider {
1293
1293
  defaultBaseUrl = "https://open.bigmodel.cn/api/paas/v4";
1294
- // GLM-5 等深度思考模型生成长内容需要较长时间,默认 5 分钟
1294
+ // GLM-5 / GLM-5.1 等深度思考模型生成长内容需要较长时间,默认 5 分钟
1295
1295
  defaultTimeout = 3e5;
1296
1296
  info = {
1297
1297
  id: "zhipu",
1298
1298
  displayName: "Zhipu (GLM)",
1299
- defaultModel: "glm-5",
1299
+ // 默认选 GLM-4.6:中文写作口碑最稳 + 200K 上下文 + 价格只有 5.1 的 ~1/2。
1300
+ // 需要 Agent 长跑 / 代码工程时再手动 /model glm-5.1。
1301
+ defaultModel: "glm-4.6",
1300
1302
  apiKeyEnvVar: "AICLI_API_KEY_ZHIPU",
1301
1303
  requiresApiKey: true,
1302
1304
  baseUrl: this.defaultBaseUrl,
1303
1305
  models: [
1304
- // GLM-5 旗舰系列(最新,支持深度思考)
1306
+ // ── GLM-5.1 系列(2026-04 旗舰,主打长程 Agent + 代码工程) ──
1307
+ {
1308
+ id: "glm-5.1",
1309
+ displayName: "GLM-5.1 (2026 Flagship, 200K, Agent+Code)",
1310
+ contextWindow: 204800,
1311
+ supportsStreaming: true,
1312
+ supportsThinking: true
1313
+ },
1314
+ {
1315
+ id: "glm-5.1-reasoning",
1316
+ displayName: "GLM-5.1 Reasoning (Deep Thinking)",
1317
+ contextWindow: 204800,
1318
+ supportsStreaming: true,
1319
+ supportsThinking: true
1320
+ },
1321
+ {
1322
+ id: "glm-5.1-air",
1323
+ displayName: "GLM-5.1 Air (Lightweight 5.1)",
1324
+ contextWindow: 204800,
1325
+ supportsStreaming: true,
1326
+ supportsThinking: true
1327
+ },
1328
+ // ── GLM-5 系列(2026-02) ──
1305
1329
  {
1306
1330
  id: "glm-5",
1307
1331
  displayName: "GLM-5 (Flagship, Deep Thinking)",
@@ -1309,7 +1333,13 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1309
1333
  supportsStreaming: true,
1310
1334
  supportsThinking: true
1311
1335
  },
1312
- // GLM-4.6 系列(视觉 + 思考)
1336
+ // ── GLM-4.6 系列(2025-09,中文写作口碑最佳) ──
1337
+ {
1338
+ id: "glm-4.6",
1339
+ displayName: "GLM-4.6 (200K, \u4E2D\u6587\u5199\u4F5C\u63A8\u8350)",
1340
+ contextWindow: 204800,
1341
+ supportsStreaming: true
1342
+ },
1313
1343
  {
1314
1344
  id: "glm-4.6v",
1315
1345
  displayName: "GLM-4.6V (Vision + Thinking)",
@@ -1317,7 +1347,7 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1317
1347
  supportsStreaming: true,
1318
1348
  supportsThinking: true
1319
1349
  },
1320
- // GLM-Z1 推理系列(支持深度思考)
1350
+ // ── GLM-Z1 推理系列 ──
1321
1351
  {
1322
1352
  id: "glm-z1",
1323
1353
  displayName: "GLM-Z1 (Reasoning Flagship)",
@@ -1339,7 +1369,7 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1339
1369
  supportsStreaming: true,
1340
1370
  supportsThinking: true
1341
1371
  },
1342
- // GLM-4 系列(稳定)
1372
+ // ── GLM-4 系列(稳定,价格低) ──
1343
1373
  {
1344
1374
  id: "glm-4-plus",
1345
1375
  displayName: "GLM-4 Plus",
@@ -2625,6 +2655,108 @@ var Session = class _Session {
2625
2655
  }
2626
2656
  };
2627
2657
 
2658
+ // src/security/redactor.ts
2659
+ var DEFAULT_PATTERNS = [
2660
+ // password: xxx / password = xxx / password="xxx"
2661
+ // Covers YAML / JSON / shell-ish / env-file forms.
2662
+ { kind: "password", regex: /\b(password|passwd|pwd)\s*[:=]\s*["']?([^\s"',;{}]{4,200})["']?/gi },
2663
+ // PGPASSWORD=xxx (explicit bash env-var form, separate rule because no quotes usually)
2664
+ { kind: "pgpassword-env", regex: /\b(PGPASSWORD)=([^\s"']{4,200})/g },
2665
+ // JDBC/PG/MySQL/Mongo connection strings with inline credentials
2666
+ // postgresql://user:pass@host/db → redact pass
2667
+ { kind: "db-uri-password", regex: /(\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp|mssql):\/\/[^:\s]+:)([^@\s]+)(@)/gi },
2668
+ // Anthropic API keys
2669
+ { kind: "anthropic-key", regex: /(sk-ant-[a-zA-Z0-9_-]{90,})/g },
2670
+ // OpenAI / generic sk- keys — requires length ≥32 to avoid eating short identifiers
2671
+ { kind: "openai-key", regex: /(sk-(?:proj-)?[a-zA-Z0-9_-]{32,})/g },
2672
+ // GitHub personal access tokens
2673
+ { kind: "github-pat", regex: /\b(ghp_[a-zA-Z0-9]{36})\b/g },
2674
+ { kind: "github-oauth", regex: /\b(gho_[a-zA-Z0-9]{36})\b/g },
2675
+ { kind: "github-install", regex: /\b(ghs_[a-zA-Z0-9]{36})\b/g },
2676
+ // Slack tokens
2677
+ { kind: "slack-bot", regex: /\b(xoxb-\d+-\d+-[a-zA-Z0-9]+)\b/g },
2678
+ { kind: "slack-user", regex: /\b(xoxp-\d+-\d+-\d+-[a-zA-Z0-9]+)\b/g },
2679
+ // AWS access key IDs (AKIA...) and secret access keys are context-dependent;
2680
+ // we only catch the ID because secret key alone is indistinguishable from random base64.
2681
+ { kind: "aws-access-key-id", regex: /\b(AKIA[0-9A-Z]{16})\b/g },
2682
+ // Google API keys
2683
+ { kind: "google-api-key", regex: /\b(AIza[0-9A-Za-z_-]{35})\b/g },
2684
+ // Generic "api_key": "..." / "apiKey": "..." / api-key=xxx
2685
+ { kind: "api-key", regex: /\b(api[_-]?key)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{16,200})["']?/gi },
2686
+ // Generic token: xxx (only when value looks token-shaped; avoids eating human prose)
2687
+ { kind: "token", regex: /\b(token|access[_-]?token|bearer[_-]?token)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{20,300})["']?/gi },
2688
+ // Bearer <token> in Authorization headers
2689
+ { kind: "bearer", regex: /\b(Authorization:\s*Bearer\s+)([a-zA-Z0-9_\-.=]{20,500})/g },
2690
+ // Private key PEM blocks — catch the header+footer together
2691
+ { kind: "private-key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g }
2692
+ ];
2693
+ function render(placeholder, kind) {
2694
+ return placeholder.replace("{kind}", kind);
2695
+ }
2696
+ function redactString(input, options) {
2697
+ if (!options.enabled || !input) return { redacted: input, hits: [] };
2698
+ const placeholder = options.placeholder ?? "[REDACTED:{kind}]";
2699
+ const patterns = [
2700
+ ...options.patterns ?? DEFAULT_PATTERNS,
2701
+ ...(options.customRegexes ?? []).flatMap((src, i) => {
2702
+ try {
2703
+ const flags = src.match(/^\/.*\/([gimsuy]*)$/)?.[1] ?? "";
2704
+ const body = src.replace(/^\/(.*)\/[gimsuy]*$/, "$1");
2705
+ const regex = new RegExp(body, flags.includes("g") ? flags : flags + "g");
2706
+ return [{ kind: `custom-${i}`, regex }];
2707
+ } catch {
2708
+ return [];
2709
+ }
2710
+ })
2711
+ ];
2712
+ let redacted = input;
2713
+ const hits = [];
2714
+ for (const { kind, regex } of patterns) {
2715
+ const rx = new RegExp(regex.source, regex.flags);
2716
+ redacted = redacted.replace(rx, (...args) => {
2717
+ const match = args[0];
2718
+ const probe = new RegExp(rx.source).exec(match);
2719
+ const captureCount = probe ? probe.length - 1 : 0;
2720
+ const g1 = captureCount >= 1 ? args[1] : void 0;
2721
+ const g2 = captureCount >= 2 ? args[2] : void 0;
2722
+ const offset = args[1 + captureCount];
2723
+ if (captureCount >= 2 && typeof g2 === "string") {
2724
+ hits.push({ kind, start: offset + (g1?.length ?? 0), length: g2.length, secret: g2 });
2725
+ return `${g1}${render(placeholder, kind)}`;
2726
+ }
2727
+ hits.push({ kind, start: offset, length: match.length, secret: g1 ?? match });
2728
+ return render(placeholder, kind);
2729
+ });
2730
+ }
2731
+ return { redacted, hits };
2732
+ }
2733
+ function redactJson(value, options) {
2734
+ if (!options.enabled) return { value, hits: [] };
2735
+ const allHits = [];
2736
+ function walk(v) {
2737
+ if (typeof v === "string") {
2738
+ const r = redactString(v, options);
2739
+ allHits.push(...r.hits);
2740
+ return r.redacted;
2741
+ }
2742
+ if (Array.isArray(v)) return v.map(walk);
2743
+ if (v && typeof v === "object") {
2744
+ const out = {};
2745
+ for (const [k, vv] of Object.entries(v)) {
2746
+ out[k] = walk(vv);
2747
+ }
2748
+ return out;
2749
+ }
2750
+ return v;
2751
+ }
2752
+ const redacted = walk(value);
2753
+ return { value: redacted, hits: allHits };
2754
+ }
2755
+ function scanString(input, options) {
2756
+ const { hits } = redactString(input, { ...options, enabled: true });
2757
+ return hits;
2758
+ }
2759
+
2628
2760
  // src/session/session-manager.ts
2629
2761
  function safeDate(value) {
2630
2762
  const d = new Date(value);
@@ -2638,9 +2770,27 @@ function extractJsonField(header, field) {
2638
2770
  var SessionManager = class {
2639
2771
  _current = null;
2640
2772
  historyDir;
2773
+ config;
2774
+ /** Last save's redaction hit count — exposed for /security status reporting */
2775
+ lastRedactionHits = 0;
2641
2776
  constructor(config) {
2777
+ this.config = config;
2642
2778
  this.historyDir = config.getHistoryDir();
2643
2779
  }
2780
+ /**
2781
+ * Build redaction options from config. Returns `{ enabled: false }` when
2782
+ * `security.redactOnSave` is off or `security.mode` is 'off'.
2783
+ */
2784
+ redactOptionsForSave() {
2785
+ const security = this.config.get("security");
2786
+ if (!security || !security.redactOnSave || security.mode === "off") {
2787
+ return { enabled: false };
2788
+ }
2789
+ return {
2790
+ enabled: true,
2791
+ customRegexes: security.customPatterns ?? []
2792
+ };
2793
+ }
2644
2794
  get current() {
2645
2795
  return this._current;
2646
2796
  }
@@ -2666,8 +2816,12 @@ var SessionManager = class {
2666
2816
  if (!this._current) return;
2667
2817
  mkdirSync(this.historyDir, { recursive: true });
2668
2818
  const filePath = join(this.historyDir, `${this._current.id}.json`);
2819
+ const raw = this._current.toJSON();
2820
+ const opts = this.redactOptionsForSave();
2821
+ const { value: payload, hits } = redactJson(raw, opts);
2822
+ this.lastRedactionHits = hits.length;
2669
2823
  const tmpPath = filePath + ".tmp";
2670
- writeFileSync(tmpPath, JSON.stringify(this._current.toJSON(), null, 2), "utf-8");
2824
+ writeFileSync(tmpPath, JSON.stringify(payload, null, 2), "utf-8");
2671
2825
  renameSync(tmpPath, filePath);
2672
2826
  }
2673
2827
  loadSession(id) {
@@ -3653,7 +3807,15 @@ var PRICING_TABLE = {
3653
3807
  "glm-4": { input: 0.14, output: 0.14 },
3654
3808
  "glm-4-flash": { input: 0, output: 0 },
3655
3809
  "glm-4.5": { input: 0.29, output: 1.14 },
3656
- "glm-4.6": { input: 0.6, output: 2.2 }
3810
+ "glm-4.6": { input: 0.6, output: 2.2 },
3811
+ "glm-4.6v": { input: 0.6, output: 2.2 },
3812
+ "glm-5": { input: 0.85, output: 2.85 },
3813
+ "glm-5.1": { input: 0.95, output: 3.15 },
3814
+ "glm-5.1-reasoning": { input: 1.4, output: 4.4 },
3815
+ "glm-5.1-air": { input: 0.4, output: 1.2 },
3816
+ "glm-z1": { input: 0.5, output: 1.5 },
3817
+ "glm-z1-air": { input: 0.2, output: 0.6 },
3818
+ "glm-z1-flash": { input: 0, output: 0 }
3657
3819
  // ── OpenRouter (pass-through — actual cost depends on underlying model) ──
3658
3820
  // Left empty; callers should resolve via underlying model ID.
3659
3821
  // ── Ollama (local, zero cost) ─────────────────────────────────
@@ -3937,6 +4099,8 @@ export {
3937
4099
  buildPhantomCorrectionMessage,
3938
4100
  ProviderRegistry,
3939
4101
  getContentText,
4102
+ DEFAULT_PATTERNS,
4103
+ scanString,
3940
4104
  SessionManager,
3941
4105
  getGitRoot,
3942
4106
  getGitContext,
@@ -6,7 +6,7 @@ import { platform } from "os";
6
6
  import chalk from "chalk";
7
7
 
8
8
  // src/core/constants.ts
9
- var VERSION = "0.4.86";
9
+ var VERSION = "0.4.88";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-CKCGAHEF.js";
11
+ } from "./chunk-VGXNE37B.js";
12
12
 
13
13
  // src/config/config-manager.ts
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -179,6 +179,24 @@ var ConfigSchema = z.object({
179
179
  // 必须确认插件来源可信后,再设为 true 启用。
180
180
  // 可通过 /config 命令或直接编辑 ~/.aicli/config.json 开启。
181
181
  allowPlugins: z.boolean().default(false),
182
+ // 敏感信息脱敏(v0.4.88+,2026-04 凭据泄漏事件后引入)
183
+ // 会话保存到磁盘 / 发送给 Provider 前,自动将 API key、密码、PEM 私钥等
184
+ // 按正则替换为 [REDACTED:kind] 占位符。模式定义在 src/security/redactor.ts。
185
+ //
186
+ // redactOnSave 默认 true:保存到 ~/.aicli/history/*.json 时脱敏(推荐开启)
187
+ // redactOnSend 默认 false:发送到 Provider 时脱敏(激进,可能影响工具结果)
188
+ // mode:
189
+ // 'default' — 使用内置 13 条模式(推荐)
190
+ // 'strict' — 同 default,但阈值更低(更激进,可能误报)
191
+ // 'off' — 禁用所有模式(等同 redactOnSave=false)
192
+ // customPatterns — 用户补充正则字符串(支持 /pattern/flags 形式),
193
+ // 无效正则会静默跳过,不会中断保存。
194
+ security: z.object({
195
+ redactOnSave: z.boolean().default(true),
196
+ redactOnSend: z.boolean().default(false),
197
+ mode: z.enum(["default", "strict", "off"]).default("default"),
198
+ customPatterns: z.array(z.string()).default([])
199
+ }).default({}),
182
200
  // 智能模型路由(v0.4.68+)
183
201
  // 按用户每轮输入的内容/标签/长度动态选择模型,在同一 provider 内切换,
184
202
  // 例:短问题走 haiku(省钱),planning 走 opus(质量)。
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-CKCGAHEF.js";
4
+ } from "./chunk-VGXNE37B.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.86";
4
+ var VERSION = "0.4.88";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -19,7 +19,7 @@ import {
19
19
  } from "./chunk-6VRJGH25.js";
20
20
  import {
21
21
  runTestsTool
22
- } from "./chunk-ZC4DN6C7.js";
22
+ } from "./chunk-V3NMERIB.js";
23
23
  import {
24
24
  CONFIG_DIR_NAME,
25
25
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
@@ -27,7 +27,7 @@ import {
27
27
  SUBAGENT_ALLOWED_TOOLS,
28
28
  SUBAGENT_DEFAULT_MAX_ROUNDS,
29
29
  SUBAGENT_MAX_ROUNDS_LIMIT
30
- } from "./chunk-CKCGAHEF.js";
30
+ } from "./chunk-VGXNE37B.js";
31
31
 
32
32
  // src/tools/types.ts
33
33
  function isFileWriteTool(name) {
@@ -36,7 +36,7 @@ import {
36
36
  VERSION,
37
37
  buildUserIdentityPrompt,
38
38
  runTestsTool
39
- } from "./chunk-CHJFRDUB.js";
39
+ } from "./chunk-P6EQZKKG.js";
40
40
  import {
41
41
  hasSemanticIndex,
42
42
  semanticSearch
@@ -223,6 +223,24 @@ var ConfigSchema = z.object({
223
223
  // 必须确认插件来源可信后,再设为 true 启用。
224
224
  // 可通过 /config 命令或直接编辑 ~/.aicli/config.json 开启。
225
225
  allowPlugins: z.boolean().default(false),
226
+ // 敏感信息脱敏(v0.4.88+,2026-04 凭据泄漏事件后引入)
227
+ // 会话保存到磁盘 / 发送给 Provider 前,自动将 API key、密码、PEM 私钥等
228
+ // 按正则替换为 [REDACTED:kind] 占位符。模式定义在 src/security/redactor.ts。
229
+ //
230
+ // redactOnSave 默认 true:保存到 ~/.aicli/history/*.json 时脱敏(推荐开启)
231
+ // redactOnSend 默认 false:发送到 Provider 时脱敏(激进,可能影响工具结果)
232
+ // mode:
233
+ // 'default' — 使用内置 13 条模式(推荐)
234
+ // 'strict' — 同 default,但阈值更低(更激进,可能误报)
235
+ // 'off' — 禁用所有模式(等同 redactOnSave=false)
236
+ // customPatterns — 用户补充正则字符串(支持 /pattern/flags 形式),
237
+ // 无效正则会静默跳过,不会中断保存。
238
+ security: z.object({
239
+ redactOnSave: z.boolean().default(true),
240
+ redactOnSend: z.boolean().default(false),
241
+ mode: z.enum(["default", "strict", "off"]).default("default"),
242
+ customPatterns: z.array(z.string()).default([])
243
+ }).default({}),
226
244
  // 智能模型路由(v0.4.68+)
227
245
  // 按用户每轮输入的内容/标签/长度动态选择模型,在同一 provider 内切换,
228
246
  // 例:短问题走 haiku(省钱),planning 走 opus(质量)。
@@ -1779,17 +1797,41 @@ var DeepSeekProvider = class extends OpenAICompatibleProvider {
1779
1797
  // src/providers/zhipu.ts
1780
1798
  var ZhipuProvider = class extends OpenAICompatibleProvider {
1781
1799
  defaultBaseUrl = "https://open.bigmodel.cn/api/paas/v4";
1782
- // GLM-5 等深度思考模型生成长内容需要较长时间,默认 5 分钟
1800
+ // GLM-5 / GLM-5.1 等深度思考模型生成长内容需要较长时间,默认 5 分钟
1783
1801
  defaultTimeout = 3e5;
1784
1802
  info = {
1785
1803
  id: "zhipu",
1786
1804
  displayName: "Zhipu (GLM)",
1787
- defaultModel: "glm-5",
1805
+ // 默认选 GLM-4.6:中文写作口碑最稳 + 200K 上下文 + 价格只有 5.1 的 ~1/2。
1806
+ // 需要 Agent 长跑 / 代码工程时再手动 /model glm-5.1。
1807
+ defaultModel: "glm-4.6",
1788
1808
  apiKeyEnvVar: "AICLI_API_KEY_ZHIPU",
1789
1809
  requiresApiKey: true,
1790
1810
  baseUrl: this.defaultBaseUrl,
1791
1811
  models: [
1792
- // GLM-5 旗舰系列(最新,支持深度思考)
1812
+ // ── GLM-5.1 系列(2026-04 旗舰,主打长程 Agent + 代码工程) ──
1813
+ {
1814
+ id: "glm-5.1",
1815
+ displayName: "GLM-5.1 (2026 Flagship, 200K, Agent+Code)",
1816
+ contextWindow: 204800,
1817
+ supportsStreaming: true,
1818
+ supportsThinking: true
1819
+ },
1820
+ {
1821
+ id: "glm-5.1-reasoning",
1822
+ displayName: "GLM-5.1 Reasoning (Deep Thinking)",
1823
+ contextWindow: 204800,
1824
+ supportsStreaming: true,
1825
+ supportsThinking: true
1826
+ },
1827
+ {
1828
+ id: "glm-5.1-air",
1829
+ displayName: "GLM-5.1 Air (Lightweight 5.1)",
1830
+ contextWindow: 204800,
1831
+ supportsStreaming: true,
1832
+ supportsThinking: true
1833
+ },
1834
+ // ── GLM-5 系列(2026-02) ──
1793
1835
  {
1794
1836
  id: "glm-5",
1795
1837
  displayName: "GLM-5 (Flagship, Deep Thinking)",
@@ -1797,7 +1839,13 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1797
1839
  supportsStreaming: true,
1798
1840
  supportsThinking: true
1799
1841
  },
1800
- // GLM-4.6 系列(视觉 + 思考)
1842
+ // ── GLM-4.6 系列(2025-09,中文写作口碑最佳) ──
1843
+ {
1844
+ id: "glm-4.6",
1845
+ displayName: "GLM-4.6 (200K, \u4E2D\u6587\u5199\u4F5C\u63A8\u8350)",
1846
+ contextWindow: 204800,
1847
+ supportsStreaming: true
1848
+ },
1801
1849
  {
1802
1850
  id: "glm-4.6v",
1803
1851
  displayName: "GLM-4.6V (Vision + Thinking)",
@@ -1805,7 +1853,7 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1805
1853
  supportsStreaming: true,
1806
1854
  supportsThinking: true
1807
1855
  },
1808
- // GLM-Z1 推理系列(支持深度思考)
1856
+ // ── GLM-Z1 推理系列 ──
1809
1857
  {
1810
1858
  id: "glm-z1",
1811
1859
  displayName: "GLM-Z1 (Reasoning Flagship)",
@@ -1827,7 +1875,7 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
1827
1875
  supportsStreaming: true,
1828
1876
  supportsThinking: true
1829
1877
  },
1830
- // GLM-4 系列(稳定)
1878
+ // ── GLM-4 系列(稳定,价格低) ──
1831
1879
  {
1832
1880
  id: "glm-4-plus",
1833
1881
  displayName: "GLM-4 Plus",
@@ -3006,6 +3054,104 @@ var Session = class _Session {
3006
3054
  }
3007
3055
  };
3008
3056
 
3057
+ // src/security/redactor.ts
3058
+ var DEFAULT_PATTERNS = [
3059
+ // password: xxx / password = xxx / password="xxx"
3060
+ // Covers YAML / JSON / shell-ish / env-file forms.
3061
+ { kind: "password", regex: /\b(password|passwd|pwd)\s*[:=]\s*["']?([^\s"',;{}]{4,200})["']?/gi },
3062
+ // PGPASSWORD=xxx (explicit bash env-var form, separate rule because no quotes usually)
3063
+ { kind: "pgpassword-env", regex: /\b(PGPASSWORD)=([^\s"']{4,200})/g },
3064
+ // JDBC/PG/MySQL/Mongo connection strings with inline credentials
3065
+ // postgresql://user:pass@host/db → redact pass
3066
+ { kind: "db-uri-password", regex: /(\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp|mssql):\/\/[^:\s]+:)([^@\s]+)(@)/gi },
3067
+ // Anthropic API keys
3068
+ { kind: "anthropic-key", regex: /(sk-ant-[a-zA-Z0-9_-]{90,})/g },
3069
+ // OpenAI / generic sk- keys — requires length ≥32 to avoid eating short identifiers
3070
+ { kind: "openai-key", regex: /(sk-(?:proj-)?[a-zA-Z0-9_-]{32,})/g },
3071
+ // GitHub personal access tokens
3072
+ { kind: "github-pat", regex: /\b(ghp_[a-zA-Z0-9]{36})\b/g },
3073
+ { kind: "github-oauth", regex: /\b(gho_[a-zA-Z0-9]{36})\b/g },
3074
+ { kind: "github-install", regex: /\b(ghs_[a-zA-Z0-9]{36})\b/g },
3075
+ // Slack tokens
3076
+ { kind: "slack-bot", regex: /\b(xoxb-\d+-\d+-[a-zA-Z0-9]+)\b/g },
3077
+ { kind: "slack-user", regex: /\b(xoxp-\d+-\d+-\d+-[a-zA-Z0-9]+)\b/g },
3078
+ // AWS access key IDs (AKIA...) and secret access keys are context-dependent;
3079
+ // we only catch the ID because secret key alone is indistinguishable from random base64.
3080
+ { kind: "aws-access-key-id", regex: /\b(AKIA[0-9A-Z]{16})\b/g },
3081
+ // Google API keys
3082
+ { kind: "google-api-key", regex: /\b(AIza[0-9A-Za-z_-]{35})\b/g },
3083
+ // Generic "api_key": "..." / "apiKey": "..." / api-key=xxx
3084
+ { kind: "api-key", regex: /\b(api[_-]?key)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{16,200})["']?/gi },
3085
+ // Generic token: xxx (only when value looks token-shaped; avoids eating human prose)
3086
+ { kind: "token", regex: /\b(token|access[_-]?token|bearer[_-]?token)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{20,300})["']?/gi },
3087
+ // Bearer <token> in Authorization headers
3088
+ { kind: "bearer", regex: /\b(Authorization:\s*Bearer\s+)([a-zA-Z0-9_\-.=]{20,500})/g },
3089
+ // Private key PEM blocks — catch the header+footer together
3090
+ { kind: "private-key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g }
3091
+ ];
3092
+ function render(placeholder, kind) {
3093
+ return placeholder.replace("{kind}", kind);
3094
+ }
3095
+ function redactString(input, options) {
3096
+ if (!options.enabled || !input) return { redacted: input, hits: [] };
3097
+ const placeholder = options.placeholder ?? "[REDACTED:{kind}]";
3098
+ const patterns = [
3099
+ ...options.patterns ?? DEFAULT_PATTERNS,
3100
+ ...(options.customRegexes ?? []).flatMap((src, i) => {
3101
+ try {
3102
+ const flags = src.match(/^\/.*\/([gimsuy]*)$/)?.[1] ?? "";
3103
+ const body = src.replace(/^\/(.*)\/[gimsuy]*$/, "$1");
3104
+ const regex = new RegExp(body, flags.includes("g") ? flags : flags + "g");
3105
+ return [{ kind: `custom-${i}`, regex }];
3106
+ } catch {
3107
+ return [];
3108
+ }
3109
+ })
3110
+ ];
3111
+ let redacted = input;
3112
+ const hits = [];
3113
+ for (const { kind, regex } of patterns) {
3114
+ const rx = new RegExp(regex.source, regex.flags);
3115
+ redacted = redacted.replace(rx, (...args) => {
3116
+ const match = args[0];
3117
+ const probe = new RegExp(rx.source).exec(match);
3118
+ const captureCount = probe ? probe.length - 1 : 0;
3119
+ const g1 = captureCount >= 1 ? args[1] : void 0;
3120
+ const g2 = captureCount >= 2 ? args[2] : void 0;
3121
+ const offset = args[1 + captureCount];
3122
+ if (captureCount >= 2 && typeof g2 === "string") {
3123
+ hits.push({ kind, start: offset + (g1?.length ?? 0), length: g2.length, secret: g2 });
3124
+ return `${g1}${render(placeholder, kind)}`;
3125
+ }
3126
+ hits.push({ kind, start: offset, length: match.length, secret: g1 ?? match });
3127
+ return render(placeholder, kind);
3128
+ });
3129
+ }
3130
+ return { redacted, hits };
3131
+ }
3132
+ function redactJson(value, options) {
3133
+ if (!options.enabled) return { value, hits: [] };
3134
+ const allHits = [];
3135
+ function walk(v) {
3136
+ if (typeof v === "string") {
3137
+ const r = redactString(v, options);
3138
+ allHits.push(...r.hits);
3139
+ return r.redacted;
3140
+ }
3141
+ if (Array.isArray(v)) return v.map(walk);
3142
+ if (v && typeof v === "object") {
3143
+ const out = {};
3144
+ for (const [k, vv] of Object.entries(v)) {
3145
+ out[k] = walk(vv);
3146
+ }
3147
+ return out;
3148
+ }
3149
+ return v;
3150
+ }
3151
+ const redacted = walk(value);
3152
+ return { value: redacted, hits: allHits };
3153
+ }
3154
+
3009
3155
  // src/session/session-manager.ts
3010
3156
  function safeDate(value) {
3011
3157
  const d = new Date(value);
@@ -3019,9 +3165,27 @@ function extractJsonField(header, field) {
3019
3165
  var SessionManager = class {
3020
3166
  _current = null;
3021
3167
  historyDir;
3168
+ config;
3169
+ /** Last save's redaction hit count — exposed for /security status reporting */
3170
+ lastRedactionHits = 0;
3022
3171
  constructor(config) {
3172
+ this.config = config;
3023
3173
  this.historyDir = config.getHistoryDir();
3024
3174
  }
3175
+ /**
3176
+ * Build redaction options from config. Returns `{ enabled: false }` when
3177
+ * `security.redactOnSave` is off or `security.mode` is 'off'.
3178
+ */
3179
+ redactOptionsForSave() {
3180
+ const security = this.config.get("security");
3181
+ if (!security || !security.redactOnSave || security.mode === "off") {
3182
+ return { enabled: false };
3183
+ }
3184
+ return {
3185
+ enabled: true,
3186
+ customRegexes: security.customPatterns ?? []
3187
+ };
3188
+ }
3025
3189
  get current() {
3026
3190
  return this._current;
3027
3191
  }
@@ -3047,8 +3211,12 @@ var SessionManager = class {
3047
3211
  if (!this._current) return;
3048
3212
  mkdirSync2(this.historyDir, { recursive: true });
3049
3213
  const filePath = join2(this.historyDir, `${this._current.id}.json`);
3214
+ const raw = this._current.toJSON();
3215
+ const opts = this.redactOptionsForSave();
3216
+ const { value: payload, hits } = redactJson(raw, opts);
3217
+ this.lastRedactionHits = hits.length;
3050
3218
  const tmpPath = filePath + ".tmp";
3051
- writeFileSync2(tmpPath, JSON.stringify(this._current.toJSON(), null, 2), "utf-8");
3219
+ writeFileSync2(tmpPath, JSON.stringify(payload, null, 2), "utf-8");
3052
3220
  renameSync(tmpPath, filePath);
3053
3221
  }
3054
3222
  loadSession(id) {
@@ -9035,7 +9203,15 @@ var PRICING_TABLE = {
9035
9203
  "glm-4": { input: 0.14, output: 0.14 },
9036
9204
  "glm-4-flash": { input: 0, output: 0 },
9037
9205
  "glm-4.5": { input: 0.29, output: 1.14 },
9038
- "glm-4.6": { input: 0.6, output: 2.2 }
9206
+ "glm-4.6": { input: 0.6, output: 2.2 },
9207
+ "glm-4.6v": { input: 0.6, output: 2.2 },
9208
+ "glm-5": { input: 0.85, output: 2.85 },
9209
+ "glm-5.1": { input: 0.95, output: 3.15 },
9210
+ "glm-5.1-reasoning": { input: 1.4, output: 4.4 },
9211
+ "glm-5.1-air": { input: 0.4, output: 1.2 },
9212
+ "glm-z1": { input: 0.5, output: 1.5 },
9213
+ "glm-z1-air": { input: 0.2, output: 0.6 },
9214
+ "glm-z1-flash": { input: 0, output: 0 }
9039
9215
  // ── OpenRouter (pass-through — actual cost depends on underlying model) ──
9040
9216
  // Left empty; callers should resolve via underlying model ID.
9041
9217
  // ── Ollama (local, zero cost) ─────────────────────────────────
@@ -11070,7 +11246,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
11070
11246
  case "test": {
11071
11247
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
11072
11248
  try {
11073
- const { executeTests } = await import("./run-tests-NWQ3YPDN.js");
11249
+ const { executeTests } = await import("./run-tests-JVWIGY7P.js");
11074
11250
  const argStr = args.join(" ").trim();
11075
11251
  let testArgs = {};
11076
11252
  if (argStr) {
@@ -385,7 +385,7 @@ ${content}`);
385
385
  }
386
386
  }
387
387
  async function runTaskMode(config, providers, configManager, topic) {
388
- const { TaskOrchestrator } = await import("./task-orchestrator-YW33QQKO.js");
388
+ const { TaskOrchestrator } = await import("./task-orchestrator-6MI6LD7T.js");
389
389
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
390
390
  let interrupted = false;
391
391
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ DEFAULT_PATTERNS,
3
4
  HALLUCINATION_CORRECTION_MESSAGE,
4
5
  McpManager,
5
6
  ProviderRegistry,
@@ -28,12 +29,13 @@ import {
28
29
  persistToolRound,
29
30
  rebuildExtraMessages,
30
31
  saveDevState,
32
+ scanString,
31
33
  sessionHasMeaningfulContent,
32
34
  setupProxy
33
- } from "./chunk-P6XKBTP4.js";
35
+ } from "./chunk-L3MBIO36.js";
34
36
  import {
35
37
  ConfigManager
36
- } from "./chunk-YRWBFUYH.js";
38
+ } from "./chunk-QT2KNL3V.js";
37
39
  import {
38
40
  ToolExecutor,
39
41
  ToolRegistry,
@@ -49,7 +51,7 @@ import {
49
51
  spawnAgentContext,
50
52
  theme,
51
53
  undoStack
52
- } from "./chunk-M7KYMJT5.js";
54
+ } from "./chunk-YDHIU24C.js";
53
55
  import "./chunk-2ZD3YTVM.js";
54
56
  import {
55
57
  fileCheckpoints
@@ -58,7 +60,7 @@ import "./chunk-NHNWUBXB.js";
58
60
  import "./chunk-CQQQFNND.js";
59
61
  import "./chunk-6VRJGH25.js";
60
62
  import "./chunk-PFYAAX2S.js";
61
- import "./chunk-ZC4DN6C7.js";
63
+ import "./chunk-V3NMERIB.js";
62
64
  import {
63
65
  AGENTIC_BEHAVIOR_GUIDELINE,
64
66
  AUTHOR,
@@ -80,7 +82,7 @@ import {
80
82
  SKILLS_DIR_NAME,
81
83
  VERSION,
82
84
  buildUserIdentityPrompt
83
- } from "./chunk-CKCGAHEF.js";
85
+ } from "./chunk-VGXNE37B.js";
84
86
 
85
87
  // src/index.ts
86
88
  import { program } from "commander";
@@ -980,6 +982,7 @@ function createDefaultCommands() {
980
982
  " /fork [checkpoint] - Fork session from checkpoint or current position",
981
983
  " /branch [list|new|switch|delete|rename|diff|cherry-pick] - Manage conversation branches (fork tree, cross-branch picks)",
982
984
  " /index [status|rebuild|clear|semantic-rebuild|semantic-clear] - Symbol + semantic index (find_symbol / search_code)",
985
+ " /security [status|scan|on|off] - Sensitive-data redaction status & session scan",
983
986
  " /yolo [on|off] - Toggle session auto-approve (skip confirmations)",
984
987
  " /exit - Exit"
985
988
  ] : [];
@@ -2592,7 +2595,7 @@ ${hint}` : "")
2592
2595
  usage: "/test [command|filter]",
2593
2596
  async execute(args, ctx) {
2594
2597
  try {
2595
- const { executeTests } = await import("./run-tests-BQMCZVI4.js");
2598
+ const { executeTests } = await import("./run-tests-FQHDUYOG.js");
2596
2599
  const argStr = args.join(" ").trim();
2597
2600
  let testArgs = {};
2598
2601
  if (argStr) {
@@ -3031,6 +3034,94 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
3031
3034
  }
3032
3035
  }
3033
3036
  },
3037
+ {
3038
+ name: "security",
3039
+ description: "Sensitive-data redaction \u2014 status, scan sessions, toggle on/off",
3040
+ usage: "/security [status|scan [--all]|on|off]",
3041
+ async execute(args, ctx) {
3042
+ const sub = (args[0] || "status").toLowerCase();
3043
+ const security = ctx.config.get("security") ?? {
3044
+ redactOnSave: true,
3045
+ redactOnSend: false,
3046
+ mode: "default",
3047
+ customPatterns: []
3048
+ };
3049
+ if (sub === "status") {
3050
+ console.log(theme.heading(" \u{1F6E1} Security / Redaction"));
3051
+ console.log(` redactOnSave : ${security.redactOnSave ? theme.success("on") : theme.warning("off")}`);
3052
+ console.log(` redactOnSend : ${security.redactOnSend ? theme.success("on") : theme.dim("off")}`);
3053
+ console.log(` mode : ${security.mode}`);
3054
+ console.log(` patterns : ${DEFAULT_PATTERNS.length} built-in + ${security.customPatterns?.length ?? 0} custom`);
3055
+ console.log(` last save : ${ctx.sessions.lastRedactionHits} hit(s) redacted`);
3056
+ console.log();
3057
+ console.log(theme.dim(" /security scan \u2014 scan current session for leaks"));
3058
+ console.log(theme.dim(" /security scan --all \u2014 scan all saved sessions"));
3059
+ console.log(theme.dim(" /security on|off \u2014 toggle redactOnSave"));
3060
+ console.log();
3061
+ return;
3062
+ }
3063
+ if (sub === "on" || sub === "off") {
3064
+ ctx.config.set("security", { ...security, redactOnSave: sub === "on" });
3065
+ console.log(theme.success(` \u2713 redactOnSave = ${sub}`));
3066
+ console.log();
3067
+ return;
3068
+ }
3069
+ if (sub === "scan") {
3070
+ const scanAll = args.includes("--all");
3071
+ const opts = { customRegexes: security.customPatterns ?? [] };
3072
+ let totalHits = 0;
3073
+ let filesWithHits = 0;
3074
+ if (scanAll) {
3075
+ const metas = ctx.sessions.listSessions();
3076
+ console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
3077
+ const { readFileSync: readFileSync5 } = await import("fs");
3078
+ const { join: join6 } = await import("path");
3079
+ const historyDir = ctx.config.getHistoryDir();
3080
+ for (const m of metas) {
3081
+ try {
3082
+ const content = readFileSync5(join6(historyDir, `${m.id}.json`), "utf-8");
3083
+ const hits2 = scanString(content, opts);
3084
+ if (hits2.length) {
3085
+ filesWithHits++;
3086
+ totalHits += hits2.length;
3087
+ const kinds = [...new Set(hits2.map((h) => h.kind))].join(", ");
3088
+ console.log(` ${theme.warning("\u26A0")} ${m.id.slice(0, 8)}\u2026 ${theme.dim(m.title || "")} \u2014 ${hits2.length} hit(s) [${kinds}]`);
3089
+ }
3090
+ } catch {
3091
+ }
3092
+ }
3093
+ console.log();
3094
+ console.log(
3095
+ totalHits === 0 ? theme.success(` \u2713 No secrets found in ${metas.length} session(s).`) : theme.warning(` Found ${totalHits} hit(s) across ${filesWithHits} session(s). Re-save them with redactOnSave=on to sanitize.`)
3096
+ );
3097
+ console.log();
3098
+ return;
3099
+ }
3100
+ const current = ctx.sessions.current;
3101
+ if (!current) {
3102
+ console.log(theme.warning(" No active session to scan."));
3103
+ console.log();
3104
+ return;
3105
+ }
3106
+ const json = JSON.stringify(current.toJSON());
3107
+ const hits = scanString(json, opts);
3108
+ if (hits.length === 0) {
3109
+ console.log(theme.success(" \u2713 Current session: no secrets detected."));
3110
+ } else {
3111
+ const byKind = /* @__PURE__ */ new Map();
3112
+ for (const h of hits) byKind.set(h.kind, (byKind.get(h.kind) ?? 0) + 1);
3113
+ console.log(theme.warning(` \u26A0 Current session: ${hits.length} hit(s)`));
3114
+ for (const [k, n] of byKind) console.log(` \u2022 ${k}: ${n}`);
3115
+ console.log(theme.dim(" (save the session to replace them with placeholders)"));
3116
+ }
3117
+ console.log();
3118
+ return;
3119
+ }
3120
+ console.log(theme.error(` Unknown subcommand: ${sub}`));
3121
+ console.log(theme.dim(" Usage: /security [status|scan [--all]|on|off]"));
3122
+ console.log();
3123
+ }
3124
+ },
3034
3125
  {
3035
3126
  name: "yolo",
3036
3127
  description: "Toggle session auto-approve (skip all confirmations)",
@@ -6485,7 +6576,7 @@ program.command("web").description("Start Web UI server with browser-based chat
6485
6576
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
6486
6577
  process.exit(1);
6487
6578
  }
6488
- const { startWebServer } = await import("./server-GD5OGIOF.js");
6579
+ const { startWebServer } = await import("./server-UWKRV5DK.js");
6489
6580
  await startWebServer({ port, host: options.host });
6490
6581
  });
6491
6582
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
@@ -6608,7 +6699,7 @@ program.command("sessions").description("List recent conversation sessions").act
6608
6699
  });
6609
6700
  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) => {
6610
6701
  try {
6611
- const batch = await import("./batch-KN3ESR3U.js");
6702
+ const batch = await import("./batch-7XCYSPJU.js");
6612
6703
  switch (action) {
6613
6704
  case "submit":
6614
6705
  if (!arg) {
@@ -6651,7 +6742,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
6651
6742
  }
6652
6743
  });
6653
6744
  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) => {
6654
- const { startMcpServer } = await import("./server-73EENVYE.js");
6745
+ const { startMcpServer } = await import("./server-HTVVWKFN.js");
6655
6746
  await startMcpServer({
6656
6747
  allowDestructive: !!options.allowDestructive,
6657
6748
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -6778,7 +6869,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
6778
6869
  }),
6779
6870
  config.get("customProviders")
6780
6871
  );
6781
- const { startHub } = await import("./hub-6GS4DYZO.js");
6872
+ const { startHub } = await import("./hub-IR4INXSU.js");
6782
6873
  await startHub(
6783
6874
  {
6784
6875
  topic: topic ?? "",
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-ZC4DN6C7.js";
6
- import "./chunk-CKCGAHEF.js";
5
+ } from "./chunk-V3NMERIB.js";
6
+ import "./chunk-VGXNE37B.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-CHJFRDUB.js";
4
+ } from "./chunk-P6EQZKKG.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -3,17 +3,17 @@ import {
3
3
  ToolRegistry,
4
4
  getDangerLevel,
5
5
  schemaToJsonSchema
6
- } from "./chunk-M7KYMJT5.js";
6
+ } from "./chunk-YDHIU24C.js";
7
7
  import "./chunk-2ZD3YTVM.js";
8
8
  import "./chunk-4BKXL7SM.js";
9
9
  import "./chunk-NHNWUBXB.js";
10
10
  import "./chunk-CQQQFNND.js";
11
11
  import "./chunk-6VRJGH25.js";
12
12
  import "./chunk-PFYAAX2S.js";
13
- import "./chunk-ZC4DN6C7.js";
13
+ import "./chunk-V3NMERIB.js";
14
14
  import {
15
15
  VERSION
16
- } from "./chunk-CKCGAHEF.js";
16
+ } from "./chunk-VGXNE37B.js";
17
17
 
18
18
  // src/mcp/server.ts
19
19
  import { createInterface } from "readline";
@@ -20,10 +20,10 @@ import {
20
20
  persistToolRound,
21
21
  rebuildExtraMessages,
22
22
  setupProxy
23
- } from "./chunk-P6XKBTP4.js";
23
+ } from "./chunk-L3MBIO36.js";
24
24
  import {
25
25
  ConfigManager
26
- } from "./chunk-YRWBFUYH.js";
26
+ } from "./chunk-QT2KNL3V.js";
27
27
  import {
28
28
  ToolExecutor,
29
29
  ToolRegistry,
@@ -41,14 +41,14 @@ import {
41
41
  spawnAgentContext,
42
42
  truncateOutput,
43
43
  undoStack
44
- } from "./chunk-M7KYMJT5.js";
44
+ } from "./chunk-YDHIU24C.js";
45
45
  import "./chunk-2ZD3YTVM.js";
46
46
  import "./chunk-4BKXL7SM.js";
47
47
  import "./chunk-NHNWUBXB.js";
48
48
  import "./chunk-CQQQFNND.js";
49
49
  import "./chunk-6VRJGH25.js";
50
50
  import "./chunk-PFYAAX2S.js";
51
- import "./chunk-ZC4DN6C7.js";
51
+ import "./chunk-V3NMERIB.js";
52
52
  import {
53
53
  AGENTIC_BEHAVIOR_GUIDELINE,
54
54
  AUTHOR,
@@ -67,7 +67,7 @@ import {
67
67
  SKILLS_DIR_NAME,
68
68
  VERSION,
69
69
  buildUserIdentityPrompt
70
- } from "./chunk-CKCGAHEF.js";
70
+ } from "./chunk-VGXNE37B.js";
71
71
  import {
72
72
  AuthManager
73
73
  } from "./chunk-BYNY5JPB.js";
@@ -2229,7 +2229,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2229
2229
  case "test": {
2230
2230
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2231
2231
  try {
2232
- const { executeTests } = await import("./run-tests-BQMCZVI4.js");
2232
+ const { executeTests } = await import("./run-tests-FQHDUYOG.js");
2233
2233
  const argStr = args.join(" ").trim();
2234
2234
  let testArgs = {};
2235
2235
  if (argStr) {
@@ -4,17 +4,17 @@ import {
4
4
  getDangerLevel,
5
5
  googleSearchContext,
6
6
  truncateOutput
7
- } from "./chunk-M7KYMJT5.js";
7
+ } from "./chunk-YDHIU24C.js";
8
8
  import "./chunk-2ZD3YTVM.js";
9
9
  import "./chunk-4BKXL7SM.js";
10
10
  import "./chunk-NHNWUBXB.js";
11
11
  import "./chunk-CQQQFNND.js";
12
12
  import "./chunk-6VRJGH25.js";
13
13
  import "./chunk-PFYAAX2S.js";
14
- import "./chunk-ZC4DN6C7.js";
14
+ import "./chunk-V3NMERIB.js";
15
15
  import {
16
16
  SUBAGENT_ALLOWED_TOOLS
17
- } from "./chunk-CKCGAHEF.js";
17
+ } from "./chunk-VGXNE37B.js";
18
18
 
19
19
  // src/hub/task-orchestrator.ts
20
20
  import { createInterface } from "readline";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.86",
3
+ "version": "0.4.88",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",