jinzd-ai-cli 0.4.149 → 0.4.151

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/{auth-7KK5BOCA.js → auth-OI4YRVRG.js} +1 -1
  2. package/dist/{batch-FEENWXO3.js → batch-IPWV3DNK.js} +2 -2
  3. package/dist/{chat-index-MY3DJTV3.js → chat-index-BE4TPLFH.js} +1 -1
  4. package/dist/{chat-index-JBF4ZIQI.js → chat-index-LUQWWLKO.js} +1 -1
  5. package/dist/{chunk-2FYSJHDI.js → chunk-75YT3SZI.js} +1 -1
  6. package/dist/{chunk-ONOVJIL2.js → chunk-AIZOARZY.js} +1 -1
  7. package/dist/{chunk-PASCDYMH.js → chunk-D6U75FHP.js} +14 -10
  8. package/dist/{chunk-O7NM4WTS.js → chunk-GXB7YKF2.js} +3 -1
  9. package/dist/{chunk-UQQJWHRV.js → chunk-HDSKW7Q3.js} +1 -1
  10. package/dist/{chunk-6FEGCTFY.js → chunk-K76YV4EL.js} +1 -1
  11. package/dist/{chunk-LXQMV7WL.js → chunk-MEM43AE7.js} +1 -1
  12. package/dist/{chunk-X5ZOA2SJ.js → chunk-MPMEYE43.js} +3 -3
  13. package/dist/{chunk-OWPFDHKC.js → chunk-NXXNLLSG.js} +1 -0
  14. package/dist/{chunk-7ZJN4KLV.js → chunk-RXM76HB7.js} +1 -2
  15. package/dist/{chunk-WJ32NAW3.js → chunk-T5VKNPLD.js} +1 -2
  16. package/dist/{chunk-27XZX7Q5.js → chunk-WCBVNY6D.js} +1 -1
  17. package/dist/{chunk-3JHGCSRE.js → chunk-WXVG56NI.js} +104 -24
  18. package/dist/{chunk-CL3PKT7X.js → chunk-YCF6S3P3.js} +1 -1
  19. package/dist/{chunk-NKR53CPL.js → chunk-YKVFZLSI.js} +1 -1
  20. package/dist/{chunk-2GKXIACT.js → chunk-ZQX2NCQK.js} +1 -1
  21. package/dist/{chunk-2DXY7UGF.js → chunk-ZWVIDFGY.js} +14 -10
  22. package/dist/{ci-FT2ULVM5.js → ci-YDMKYUQC.js} +4 -4
  23. package/dist/{constants-MUKC5IQB.js → constants-GRKJCSZF.js} +1 -1
  24. package/dist/{doctor-cli-S5Y3YC7D.js → doctor-cli-R6ODVYFR.js} +6 -6
  25. package/dist/electron-server.js +119 -36
  26. package/dist/{hub-DJK6P5RR.js → hub-3MKH3BMA.js} +1 -1
  27. package/dist/index.js +24 -24
  28. package/dist/{run-tests-Q4ZIVEOZ.js → run-tests-HYELAYSL.js} +2 -2
  29. package/dist/{run-tests-UGR4ZC72.js → run-tests-XWEHN7DF.js} +1 -1
  30. package/dist/{semantic-V37U4MCW.js → semantic-FKOEXY75.js} +2 -2
  31. package/dist/{semantic-IJKF5ZZC.js → semantic-GJJWTI3A.js} +2 -2
  32. package/dist/{server-QBD57XPD.js → server-32HM2KMX.js} +18 -18
  33. package/dist/{server-DQ2DR4WO.js → server-P7WY7VEX.js} +8 -8
  34. package/dist/{task-orchestrator-65WO3IZA.js → task-orchestrator-EVJVR3HL.js} +8 -8
  35. package/dist/{vector-store-AK6J3RIA.js → vector-store-PLDSXF3V.js} +1 -1
  36. package/dist/{vector-store-MCQ77OOJ.js → vector-store-Z5OF4WWJ.js} +1 -1
  37. package/package.json +172 -172
@@ -3,7 +3,7 @@ import {
3
3
  AuthManager,
4
4
  TOKEN_EXPIRY_MS,
5
5
  __resetLoginAttemptsForTests
6
- } from "./chunk-O7NM4WTS.js";
6
+ } from "./chunk-GXB7YKF2.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
  export {
9
9
  AuthManager,
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-LXQMV7WL.js";
4
+ } from "./chunk-MEM43AE7.js";
5
5
  import "./chunk-2ZD3YTVM.js";
6
- import "./chunk-2GKXIACT.js";
6
+ import "./chunk-ZQX2NCQK.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
 
9
9
  // src/cli/batch.ts
@@ -5,7 +5,7 @@ import {
5
5
  getChatIndexStatus,
6
6
  loadChatIndex,
7
7
  searchChatMemory
8
- } from "./chunk-WJ32NAW3.js";
8
+ } from "./chunk-T5VKNPLD.js";
9
9
  import "./chunk-JV5N65KN.js";
10
10
  import "./chunk-3RG5ZIWI.js";
11
11
  export {
@@ -6,7 +6,7 @@ import {
6
6
  getChatIndexStatus,
7
7
  loadChatIndex,
8
8
  searchChatMemory
9
- } from "./chunk-7ZJN4KLV.js";
9
+ } from "./chunk-RXM76HB7.js";
10
10
  import "./chunk-KHYD3WXE.js";
11
11
  import "./chunk-PDX44BCA.js";
12
12
  export {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  VERSION
5
- } from "./chunk-2GKXIACT.js";
5
+ } from "./chunk-ZQX2NCQK.js";
6
6
 
7
7
  // src/diagnostics/crash-log.ts
8
8
  import {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  schemaToJsonSchema
4
- } from "./chunk-OWPFDHKC.js";
4
+ } from "./chunk-NXXNLLSG.js";
5
5
  import {
6
6
  AuthError,
7
7
  ProviderError,
@@ -91,14 +91,12 @@ function searchVectorStore(store, queryVec, k) {
91
91
  throw new Error(`searchVectorStore: dim mismatch (query=${queryVec.length}, store=${store.dim})`);
92
92
  }
93
93
  const { count, dim, vectors, symbolIdx } = store;
94
- const heap = [];
95
- const push = (hit) => {
96
- if (heap.length < k) {
97
- heap.push(hit);
98
- heap.sort((a, b) => a.score - b.score);
99
- } else if (hit.score > heap[0].score) {
100
- heap[0] = hit;
101
- heap.sort((a, b) => a.score - b.score);
94
+ const top = [];
95
+ let minSlot = -1;
96
+ const recomputeMin = () => {
97
+ minSlot = 0;
98
+ for (let i = 1; i < top.length; i++) {
99
+ if (top[i].score < top[minSlot].score) minSlot = i;
102
100
  }
103
101
  };
104
102
  for (let row = 0; row < count; row++) {
@@ -107,9 +105,15 @@ function searchVectorStore(store, queryVec, k) {
107
105
  for (let d = 0; d < dim; d++) {
108
106
  score += vectors[base + d] * queryVec[d];
109
107
  }
110
- push({ row, symbolIdx: symbolIdx[row], score });
108
+ if (top.length < k) {
109
+ top.push({ row, symbolIdx: symbolIdx[row], score });
110
+ if (top.length === k) recomputeMin();
111
+ } else if (score > top[minSlot].score) {
112
+ top[minSlot] = { row, symbolIdx: symbolIdx[row], score };
113
+ recomputeMin();
114
+ }
111
115
  }
112
- return heap.sort((a, b) => b.score - a.score);
116
+ return top.sort((a, b) => b.score - a.score);
113
117
  }
114
118
 
115
119
  export {
@@ -132,7 +132,9 @@ var AuthManager = class {
132
132
  if (parts.length !== 2) return null;
133
133
  const [payloadB64, signature] = parts;
134
134
  const expectedSig = this.sign(payloadB64);
135
- if (signature !== expectedSig) return null;
135
+ const sigBuf = Buffer.from(signature ?? "", "utf-8");
136
+ const expBuf = Buffer.from(expectedSig, "utf-8");
137
+ if (sigBuf.length !== expBuf.length || !timingSafeEqual(sigBuf, expBuf)) return null;
136
138
  const payload = JSON.parse(
137
139
  Buffer.from(payloadB64, "base64url").toString("utf-8")
138
140
  );
@@ -3,7 +3,7 @@ import {
3
3
  loadVectorStore,
4
4
  saveVectorStore,
5
5
  searchVectorStore
6
- } from "./chunk-2DXY7UGF.js";
6
+ } from "./chunk-ZWVIDFGY.js";
7
7
  import {
8
8
  EMBEDDING_DIM,
9
9
  embed,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-2GKXIACT.js";
4
+ } from "./chunk-ZQX2NCQK.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-2GKXIACT.js";
11
+ } from "./chunk-ZQX2NCQK.js";
12
12
 
13
13
  // src/config/config-manager.ts
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-3JHGCSRE.js";
4
+ } from "./chunk-WXVG56NI.js";
5
5
  import {
6
6
  APP_NAME,
7
7
  CONFIG_DIR_NAME,
@@ -11,10 +11,10 @@ import {
11
11
  MCP_PROTOCOL_VERSION,
12
12
  MCP_TOOL_PREFIX,
13
13
  VERSION
14
- } from "./chunk-2GKXIACT.js";
14
+ } from "./chunk-ZQX2NCQK.js";
15
15
  import {
16
16
  redactJson
17
- } from "./chunk-7ZJN4KLV.js";
17
+ } from "./chunk-RXM76HB7.js";
18
18
 
19
19
  // src/session/session-manager.ts
20
20
  import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync, renameSync, openSync, readSync, closeSync } from "fs";
@@ -21,6 +21,7 @@ function getDangerLevel(toolName, args) {
21
21
  if (/\btee\b|\bcp\b|\bmv\b|\bln\s+-s/.test(cmd)) return "write";
22
22
  if (/\bchmod\b|\bchown\b/.test(cmd)) return "write";
23
23
  if (/\bSet-Content\b|\bOut-File\b|\bAdd-Content\b|\bCopy-Item\b|\bMove-Item\b|\bSet-ItemProperty\b|\bNew-ItemProperty\b/i.test(cmd)) return "write";
24
+ if (/\b(python3?|node|deno|bun|perl|ruby|php)\b[^\n]*?\s-(?:c|e|p|r)\b/i.test(cmd)) return "write";
24
25
  return "safe";
25
26
  }
26
27
  if (toolName === "write_file") return "write";
@@ -80,10 +80,9 @@ function redactString(input, options) {
80
80
  const hits = [];
81
81
  for (const { kind, regex } of patterns) {
82
82
  const rx = new RegExp(regex.source, regex.flags);
83
+ const captureCount = new RegExp(rx.source + "|").exec("").length - 1;
83
84
  redacted = redacted.replace(rx, (...args) => {
84
85
  const match = args[0];
85
- const probe = new RegExp(rx.source).exec(match);
86
- const captureCount = probe ? probe.length - 1 : 0;
87
86
  const g1 = captureCount >= 1 ? args[1] : void 0;
88
87
  const g2 = captureCount >= 2 ? args[2] : void 0;
89
88
  const offset = args[1 + captureCount];
@@ -79,10 +79,9 @@ function redactString(input, options) {
79
79
  const hits = [];
80
80
  for (const { kind, regex } of patterns) {
81
81
  const rx = new RegExp(regex.source, regex.flags);
82
+ const captureCount = new RegExp(rx.source + "|").exec("").length - 1;
82
83
  redacted = redacted.replace(rx, (...args) => {
83
84
  const match = args[0];
84
- const probe = new RegExp(rx.source).exec(match);
85
- const captureCount = probe ? probe.length - 1 : 0;
86
85
  const g1 = captureCount >= 1 ? args[1] : void 0;
87
86
  const g2 = captureCount >= 2 ? args[2] : void 0;
88
87
  const offset = args[1 + captureCount];
@@ -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.149";
9
+ var VERSION = "0.4.151";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -2,17 +2,17 @@
2
2
  import {
3
3
  hasSemanticIndex,
4
4
  semanticSearch
5
- } from "./chunk-UQQJWHRV.js";
5
+ } from "./chunk-HDSKW7Q3.js";
6
6
  import {
7
7
  runTestsTool
8
- } from "./chunk-6FEGCTFY.js";
8
+ } from "./chunk-K76YV4EL.js";
9
9
  import {
10
10
  runTool
11
- } from "./chunk-CL3PKT7X.js";
11
+ } from "./chunk-YCF6S3P3.js";
12
12
  import {
13
13
  getDangerLevel,
14
14
  isFileWriteTool
15
- } from "./chunk-OWPFDHKC.js";
15
+ } from "./chunk-NXXNLLSG.js";
16
16
  import {
17
17
  EnvLoader,
18
18
  NetworkError,
@@ -25,14 +25,14 @@ import {
25
25
  SUBAGENT_ALLOWED_TOOLS,
26
26
  SUBAGENT_DEFAULT_MAX_ROUNDS,
27
27
  SUBAGENT_MAX_ROUNDS_LIMIT
28
- } from "./chunk-2GKXIACT.js";
28
+ } from "./chunk-ZQX2NCQK.js";
29
29
  import {
30
30
  fileCheckpoints
31
31
  } from "./chunk-4BKXL7SM.js";
32
32
  import {
33
33
  loadChatIndex,
34
34
  searchChatMemory
35
- } from "./chunk-7ZJN4KLV.js";
35
+ } from "./chunk-RXM76HB7.js";
36
36
  import {
37
37
  indexProject
38
38
  } from "./chunk-VNNYHW6N.js";
@@ -425,6 +425,11 @@ function buildErrorHint(command, stderr) {
425
425
  `Hint: On Windows, "-ErrorAction SilentlyContinue" silences the error MESSAGE but does NOT change the exit code \u2014 the process still exits 1 when the path doesn't exist (because powershell.exe -NonInteractive flips the exit code on any non-terminating error, silenced or not). If you're just probing for existence, use Test-Path instead \u2014 it returns $true/$false without raising: \`if (Test-Path ./mydir) { Get-ChildItem ./mydir }\` or unconditionally use \`New-Item -ItemType Directory -Force -Path ./mydir\` which is idempotent. Don't retry the same -ErrorAction SilentlyContinue probe expecting a different result.`
426
426
  );
427
427
  }
428
+ if (IS_WINDOWS && /\bWrite-(?:Content|File)\b/i.test(command) && /(not recognized|无法将.*识别|不是.*cmdlet|CommandNotFoundException)/i.test(stderr)) {
429
+ hints.push(
430
+ `Hint: 'Write-Content' / 'Write-File' are NOT PowerShell cmdlets (common LLM hallucination). To write a file, prefer the built-in 'write_file' tool \u2014 it handles encoding/escaping cleanly and supports diff preview. If you must stay in bash: use 'Set-Content -Path <file> -Value <string> -Encoding utf8' (overwrites) or 'Add-Content' (appends) or 'Out-File -FilePath <file> -Encoding utf8'.`
431
+ );
432
+ }
428
433
  const colMissing = stderr.match(/column "([^"]+)" does not exist/i);
429
434
  if (colMissing) {
430
435
  hints.push(
@@ -1220,7 +1225,7 @@ function checkPermission(toolName, args, dangerLevel, rules, defaultAction = "co
1220
1225
  if (rule.when.pathPattern) {
1221
1226
  if (toolName === "bash" && rule.action === "auto-approve") {
1222
1227
  const cmd = String(args["command"] ?? "").trim();
1223
- if (/[;&|`$<>]/.test(cmd) || /\$\(/.test(cmd)) continue;
1228
+ if (/[;&|`$<>\n\r]/.test(cmd) || /\$\(/.test(cmd)) continue;
1224
1229
  if (!cmd.startsWith(rule.when.pathPattern)) continue;
1225
1230
  } else {
1226
1231
  const path3 = String(args["path"] ?? args["command"] ?? "");
@@ -3198,6 +3203,8 @@ ${stderr}`);
3198
3203
 
3199
3204
  // src/tools/builtin/web-fetch.ts
3200
3205
  import { promises as dnsPromises } from "dns";
3206
+ import net from "net";
3207
+ import { Agent } from "undici";
3201
3208
  function htmlToText(html) {
3202
3209
  let text = html.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<style[\s\S]*?<\/style>/gi, "").replace(/<noscript[\s\S]*?<\/noscript>/gi, "").replace(/<svg[\s\S]*?<\/svg>/gi, "");
3203
3210
  const HTML_REGEX_LIMIT = 2e5;
@@ -3241,34 +3248,100 @@ function extractDescription(html) {
3241
3248
  return m ? m[1].trim() : "";
3242
3249
  }
3243
3250
  var MAX_OUTPUT = 16e3;
3251
+ function parseIpPart(s) {
3252
+ if (/^0x[0-9a-f]+$/i.test(s)) return parseInt(s, 16);
3253
+ if (/^0[0-7]+$/.test(s)) return parseInt(s, 8);
3254
+ if (/^[1-9]\d*$/.test(s) || s === "0") return parseInt(s, 10);
3255
+ return null;
3256
+ }
3257
+ function normalizeIpv4(h) {
3258
+ const parts = h.split(".");
3259
+ if (parts.length === 1) {
3260
+ const n = parseIpPart(parts[0]);
3261
+ if (n === null || n < 0 || n > 4294967295) return null;
3262
+ return [n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255].join(".");
3263
+ }
3264
+ if (parts.length === 4) {
3265
+ const nums = parts.map(parseIpPart);
3266
+ if (nums.some((n) => n === null || n < 0 || n > 255)) return null;
3267
+ return nums.join(".");
3268
+ }
3269
+ return null;
3270
+ }
3271
+ function isPrivateIpv4(ip) {
3272
+ const m = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
3273
+ if (!m) return false;
3274
+ const [o1, o2] = [Number(m[1]), Number(m[2])];
3275
+ if (o1 === 127) return true;
3276
+ if (o1 === 10) return true;
3277
+ if (o1 === 172 && o2 >= 16 && o2 <= 31) return true;
3278
+ if (o1 === 192 && o2 === 168) return true;
3279
+ if (o1 === 169 && o2 === 254) return true;
3280
+ if (o1 === 0) return true;
3281
+ if (o1 >= 224) return true;
3282
+ return false;
3283
+ }
3284
+ function isPrivateIpv6(ip) {
3285
+ const h = ip.toLowerCase().replace(/%.*$/, "");
3286
+ if (h === "::1" || h === "::") return true;
3287
+ const first = h.split(":")[0] ?? "";
3288
+ if (/^f[cd]/.test(first)) return true;
3289
+ if (/^fe[89ab]/.test(first)) return true;
3290
+ const mapped = h.match(/::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
3291
+ if (mapped) return isPrivateIpv4(mapped[1]);
3292
+ const mappedHex = h.match(/::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
3293
+ if (mappedHex) {
3294
+ const hi = parseInt(mappedHex[1], 16), lo = parseInt(mappedHex[2], 16);
3295
+ const v4 = [hi >> 8 & 255, hi & 255, lo >> 8 & 255, lo & 255].join(".");
3296
+ return isPrivateIpv4(v4);
3297
+ }
3298
+ return false;
3299
+ }
3300
+ function isPrivateAddr(ip) {
3301
+ if (net.isIPv4(ip)) return isPrivateIpv4(ip);
3302
+ if (net.isIPv6(ip)) return isPrivateIpv6(ip);
3303
+ return false;
3304
+ }
3244
3305
  function isPrivateHost(hostname) {
3245
3306
  const h = hostname.toLowerCase().replace(/^\[|\]$/g, "");
3246
- if (h === "localhost" || h === "0.0.0.0" || h === "::1") return true;
3247
- if (h.startsWith("fe80:")) return true;
3248
- const m = h.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
3249
- if (m) {
3250
- const [o1, o2] = [Number(m[1]), Number(m[2])];
3251
- if (o1 === 127) return true;
3252
- if (o1 === 10) return true;
3253
- if (o1 === 172 && o2 >= 16 && o2 <= 31) return true;
3254
- if (o1 === 192 && o2 === 168) return true;
3255
- if (o1 === 169 && o2 === 254) return true;
3256
- if (o1 === 0) return true;
3257
- }
3307
+ if (h === "localhost" || h === "") return true;
3308
+ const v4 = normalizeIpv4(h);
3309
+ if (v4) return isPrivateIpv4(v4);
3310
+ if (net.isIPv6(h)) return isPrivateIpv6(h);
3258
3311
  return false;
3259
3312
  }
3260
3313
  async function resolveAndCheck(hostname) {
3261
3314
  const h = hostname.replace(/^\[|\]$/g, "");
3262
- if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h) || h.includes(":")) return;
3315
+ if (net.isIP(h) !== 0 || normalizeIpv4(h)) return;
3263
3316
  try {
3264
- const { address } = await dnsPromises.lookup(h);
3265
- if (isPrivateHost(address)) {
3266
- throw new NetworkError(`Blocked: "${hostname}" resolves to private address ${address}. web_fetch is restricted to public URLs.`);
3317
+ const addrs = await dnsPromises.lookup(h, { all: true, verbatim: true });
3318
+ for (const { address } of addrs) {
3319
+ if (isPrivateAddr(address)) {
3320
+ throw new NetworkError(`Blocked: "${hostname}" resolves to private address ${address}. web_fetch is restricted to public URLs.`);
3321
+ }
3267
3322
  }
3268
3323
  } catch (e) {
3269
3324
  if (e.message.startsWith("Blocked:")) throw e;
3270
3325
  }
3271
3326
  }
3327
+ function ssrfSafeDispatcher() {
3328
+ return new Agent({
3329
+ connect: {
3330
+ lookup: (hostname, options, cb) => {
3331
+ dnsPromises.lookup(hostname, { all: true, verbatim: true }).then((addrs) => {
3332
+ for (const a of addrs) {
3333
+ if (isPrivateAddr(a.address)) {
3334
+ cb(new NetworkError(`Blocked: "${hostname}" resolves to private address ${a.address}.`), null);
3335
+ return;
3336
+ }
3337
+ }
3338
+ if (options && options.all) cb(null, addrs);
3339
+ else cb(null, addrs[0].address, addrs[0].family);
3340
+ }).catch((err) => cb(err, null));
3341
+ }
3342
+ }
3343
+ });
3344
+ }
3272
3345
  var webFetchTool = {
3273
3346
  definition: {
3274
3347
  name: "web_fetch",
@@ -3313,6 +3386,7 @@ var webFetchTool = {
3313
3386
  Accept: "text/html,application/xhtml+xml,text/plain,*/*",
3314
3387
  "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
3315
3388
  };
3389
+ const dispatcher = ssrfSafeDispatcher();
3316
3390
  try {
3317
3391
  let currentUrl = url;
3318
3392
  let resp = null;
@@ -3325,8 +3399,9 @@ var webFetchTool = {
3325
3399
  const r = await fetch(currentUrl, {
3326
3400
  signal: controller2.signal,
3327
3401
  headers: FETCH_HEADERS,
3328
- redirect: "manual"
3402
+ redirect: "manual",
3329
3403
  // 手动控制重定向
3404
+ dispatcher
3330
3405
  });
3331
3406
  if (r.status >= 300 && r.status < 400) {
3332
3407
  if (hop >= MAX_REDIRECTS) {
@@ -3357,7 +3432,12 @@ var webFetchTool = {
3357
3432
  if (err.name === "AbortError") {
3358
3433
  throw new NetworkError(`Request timed out after 20s: ${url}`, void 0, err);
3359
3434
  }
3435
+ const cause = err.cause;
3436
+ if (cause?.message?.startsWith("Blocked:")) throw new NetworkError(cause.message);
3360
3437
  throw err;
3438
+ } finally {
3439
+ void dispatcher.close().catch(() => {
3440
+ });
3361
3441
  }
3362
3442
  let text;
3363
3443
  if (contentType.includes("text/plain") || contentType.includes("application/json")) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CONFIG_DIR_NAME
4
- } from "./chunk-2GKXIACT.js";
4
+ } from "./chunk-ZQX2NCQK.js";
5
5
 
6
6
  // src/diagnostics/tool-stats.ts
7
7
  import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from "fs";
@@ -5,7 +5,7 @@ import {
5
5
  loadVectorStore,
6
6
  saveVectorStore,
7
7
  searchVectorStore
8
- } from "./chunk-PASCDYMH.js";
8
+ } from "./chunk-D6U75FHP.js";
9
9
  import {
10
10
  EMBEDDING_DIM,
11
11
  embed,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.149";
4
+ var VERSION = "0.4.151";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -92,14 +92,12 @@ function searchVectorStore(store, queryVec, k) {
92
92
  throw new Error(`searchVectorStore: dim mismatch (query=${queryVec.length}, store=${store.dim})`);
93
93
  }
94
94
  const { count, dim, vectors, symbolIdx } = store;
95
- const heap = [];
96
- const push = (hit) => {
97
- if (heap.length < k) {
98
- heap.push(hit);
99
- heap.sort((a, b) => a.score - b.score);
100
- } else if (hit.score > heap[0].score) {
101
- heap[0] = hit;
102
- heap.sort((a, b) => a.score - b.score);
95
+ const top = [];
96
+ let minSlot = -1;
97
+ const recomputeMin = () => {
98
+ minSlot = 0;
99
+ for (let i = 1; i < top.length; i++) {
100
+ if (top[i].score < top[minSlot].score) minSlot = i;
103
101
  }
104
102
  };
105
103
  for (let row = 0; row < count; row++) {
@@ -108,9 +106,15 @@ function searchVectorStore(store, queryVec, k) {
108
106
  for (let d = 0; d < dim; d++) {
109
107
  score += vectors[base + d] * queryVec[d];
110
108
  }
111
- push({ row, symbolIdx: symbolIdx[row], score });
109
+ if (top.length < k) {
110
+ top.push({ row, symbolIdx: symbolIdx[row], score });
111
+ if (top.length === k) recomputeMin();
112
+ } else if (score > top[minSlot].score) {
113
+ top[minSlot] = { row, symbolIdx: symbolIdx[row], score };
114
+ recomputeMin();
115
+ }
112
116
  }
113
- return heap.sort((a, b) => b.score - a.score);
117
+ return top.sort((a, b) => b.score - a.score);
114
118
  }
115
119
 
116
120
  export {
@@ -6,15 +6,15 @@ import {
6
6
  } from "./chunk-HLWUDRBO.js";
7
7
  import {
8
8
  ProviderRegistry
9
- } from "./chunk-ONOVJIL2.js";
9
+ } from "./chunk-AIZOARZY.js";
10
10
  import {
11
11
  ConfigManager
12
- } from "./chunk-LXQMV7WL.js";
13
- import "./chunk-OWPFDHKC.js";
12
+ } from "./chunk-MEM43AE7.js";
13
+ import "./chunk-NXXNLLSG.js";
14
14
  import "./chunk-2ZD3YTVM.js";
15
15
  import {
16
16
  VERSION
17
- } from "./chunk-2GKXIACT.js";
17
+ } from "./chunk-ZQX2NCQK.js";
18
18
  import "./chunk-PDX44BCA.js";
19
19
 
20
20
  // src/cli/ci.ts
@@ -36,7 +36,7 @@ import {
36
36
  TEST_TIMEOUT,
37
37
  VERSION,
38
38
  buildUserIdentityPrompt
39
- } from "./chunk-2GKXIACT.js";
39
+ } from "./chunk-ZQX2NCQK.js";
40
40
  import "./chunk-PDX44BCA.js";
41
41
  export {
42
42
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -2,26 +2,26 @@
2
2
  import {
3
3
  getConfigDirUsage,
4
4
  listRecentCrashes
5
- } from "./chunk-2FYSJHDI.js";
5
+ } from "./chunk-75YT3SZI.js";
6
6
  import {
7
7
  ProviderRegistry
8
- } from "./chunk-ONOVJIL2.js";
8
+ } from "./chunk-AIZOARZY.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-LXQMV7WL.js";
11
+ } from "./chunk-MEM43AE7.js";
12
12
  import {
13
13
  getStatsSnapshot,
14
14
  getTopFailingTools,
15
15
  getTopUsedTools,
16
16
  resetStats
17
- } from "./chunk-CL3PKT7X.js";
18
- import "./chunk-OWPFDHKC.js";
17
+ } from "./chunk-YCF6S3P3.js";
18
+ import "./chunk-NXXNLLSG.js";
19
19
  import "./chunk-2ZD3YTVM.js";
20
20
  import {
21
21
  DEV_STATE_FILE_NAME,
22
22
  MEMORY_FILE_NAME,
23
23
  VERSION
24
- } from "./chunk-2GKXIACT.js";
24
+ } from "./chunk-ZQX2NCQK.js";
25
25
  import "./chunk-PDX44BCA.js";
26
26
 
27
27
  // src/diagnostics/doctor-cli.ts