jinzd-ai-cli 0.4.307 → 0.4.309

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 (96) hide show
  1. package/README.md +2 -1
  2. package/README.zh-CN.md +1 -1
  3. package/THIRD_PARTY_NOTICES.md +3 -0
  4. package/dist/{agent-client-6GX6QQDU.js → agent-client-TIEAYZXV.js} +4 -1
  5. package/dist/{auth-PE3Z5OHS.js → auth-QTQNZ6IX.js} +2 -2
  6. package/dist/{batch-HMADXNOD.js → batch-H4WWSZQ3.js} +3 -3
  7. package/dist/{chat-index-2D5GK2DB.js → chat-index-7CLR4CBG.js} +4 -3
  8. package/dist/{chat-index-DGUOUUQW.js → chat-index-RLVLQRRC.js} +3 -2
  9. package/dist/{chunk-CIM2PV2F.js → chunk-2E5W2E64.js} +2 -2
  10. package/dist/chunk-2XMUCC42.js +67 -0
  11. package/dist/{chunk-VAV2IJ3R.js → chunk-3CNPJLVI.js} +1 -1
  12. package/dist/{chunk-KRCYR46A.js → chunk-3GEO2LPO.js} +264 -55
  13. package/dist/{chunk-OAXLMF3U.js → chunk-3YVNDYOY.js} +1 -1
  14. package/dist/{chunk-5GQL4TSZ.js → chunk-4BXTGXZ6.js} +2 -2
  15. package/dist/{chunk-RYQBBEMM.js → chunk-4PR5AVJ5.js} +115 -19
  16. package/dist/{chunk-GHWZVPUV.js → chunk-6JHACXB3.js} +7 -5
  17. package/dist/{chunk-IUVDZVZ4.js → chunk-AXTLYOA7.js} +24 -17
  18. package/dist/{chunk-XJOK5353.js → chunk-B3MPYI4E.js} +2 -2
  19. package/dist/chunk-BMLQPSHP.js +69 -0
  20. package/dist/{chunk-NRSYBKWA.js → chunk-C7CKDFJS.js} +1 -1
  21. package/dist/{chunk-SJFZPS65.js → chunk-EAVX3RLD.js} +1 -1
  22. package/dist/{chunk-VXEF2SWG.js → chunk-EHMMBIZT.js} +16 -12
  23. package/dist/chunk-FVXNEZEW.js +161 -0
  24. package/dist/{chunk-AHL6KOGM.js → chunk-HXINWG37.js} +2 -2
  25. package/dist/{chunk-3CKJOTVM.js → chunk-IW6Q66WS.js} +4 -4
  26. package/dist/chunk-JJFJWD35.js +162 -0
  27. package/dist/{chunk-NYNSYLFY.js → chunk-JL44HGZC.js} +1 -1
  28. package/dist/{chunk-3TBXHLSC.js → chunk-K4F7QEGW.js} +1 -1
  29. package/dist/{chunk-NUJTNH76.js → chunk-LBWKMTT3.js} +1 -1
  30. package/dist/{chunk-YKJO3SI4.js → chunk-LONB36SP.js} +16 -3
  31. package/dist/{chunk-WQ3OMEC4.js → chunk-M6HLYG33.js} +1 -1
  32. package/dist/{chunk-I4GQRMFV.js → chunk-M6YV5KSS.js} +6 -4
  33. package/dist/{chunk-KBDKKHXB.js → chunk-O6CGOVD4.js} +2 -2
  34. package/dist/{chunk-L2RJPVHV.js → chunk-O7MMYJAD.js} +266 -512
  35. package/dist/chunk-QMFMST2T.js +39 -0
  36. package/dist/{chunk-AQF6IXSR.js → chunk-RBCKX2FZ.js} +11 -6
  37. package/dist/{chunk-4W6VDVQU.js → chunk-RLERORUI.js} +246 -56
  38. package/dist/{chunk-MI4SFZGX.js → chunk-RMEJR3AW.js} +5 -2
  39. package/dist/{chunk-UFW4S3RU.js → chunk-RVMCY6DP.js} +1 -1
  40. package/dist/{chunk-LF67HWWR.js → chunk-RWRZVQCB.js} +1 -1
  41. package/dist/{chunk-NQJSPMY2.js → chunk-SCG2VBPB.js} +4 -4
  42. package/dist/chunk-SXIJLSVF.js +41 -0
  43. package/dist/{chunk-YFDQIUQ3.js → chunk-T42GXE7Y.js} +18 -18
  44. package/dist/chunk-TDQW2YHK.js +65 -0
  45. package/dist/{chunk-45UVJXFQ.js → chunk-W2UOVGRC.js} +1 -1
  46. package/dist/{ci-QD2Q7NWY.js → ci-H6GPHG4T.js} +7 -7
  47. package/dist/{ci-format-42XIZO5P.js → ci-format-U47GSGYU.js} +2 -2
  48. package/dist/{constants-5CMEFZQB.js → constants-GYJTB6KI.js} +1 -1
  49. package/dist/{constants-NMASHFDL.js → constants-SNJR6546.js} +1 -1
  50. package/dist/doctor-cli-J6LAQ5LU.js +18 -0
  51. package/dist/electron-server.js +922 -842
  52. package/dist/file-checkpoint-64A2AXHE.js +7 -0
  53. package/dist/{file-checkpoint-NKBHGC7L.js → file-checkpoint-VVPUJNCI.js} +2 -1
  54. package/dist/{hub-ZLF6GMQD.js → hub-G5FMMTVZ.js} +3 -3
  55. package/dist/{hub-server-CBKCP5VD.js → hub-server-JLC7CNP7.js} +55 -17
  56. package/dist/index.js +48 -42
  57. package/dist/{indexer-P3FPRTPJ.js → indexer-GKIWSSRP.js} +3 -3
  58. package/dist/indexer-VRXDZ74A.js +10 -0
  59. package/dist/{persist-S77WRVLD.js → persist-ZZXRWFBX.js} +4 -4
  60. package/dist/{persistent-memory-GJE7HKVK.js → persistent-memory-EXJBXL33.js} +3 -3
  61. package/dist/{persistent-memory-MBSBTBGY.js → persistent-memory-LEE454DW.js} +3 -3
  62. package/dist/{pr-SXRW24JG.js → pr-6PUHVJ6K.js} +7 -7
  63. package/dist/{project-trust-MUG325AW.js → project-trust-6CJB5ZMX.js} +1 -1
  64. package/dist/{project-trust-NKYHL3VZ.js → project-trust-KGG2BWKC.js} +1 -1
  65. package/dist/run-tests-2C7MWZBN.js +12 -0
  66. package/dist/run-tests-33ZVQE3Q.js +13 -0
  67. package/dist/{semantic-7GM5M4MU.js → semantic-N227CLSC.js} +4 -4
  68. package/dist/{semantic-QOBAXEQ4.js → semantic-TRQAZSRY.js} +4 -4
  69. package/dist/{server-GGEO7SA2.js → server-AJH5TBVO.js} +231 -103
  70. package/dist/{server-MO3EU2XD.js → server-CYAB56O3.js} +16 -14
  71. package/dist/{store-SIKHCUYJ.js → store-2N6PPPBP.js} +2 -2
  72. package/dist/{store-CMSSWZF7.js → store-76VVFDXM.js} +2 -2
  73. package/dist/{task-orchestrator-JGEEQ2OE.js → task-orchestrator-HNRV3YUD.js} +15 -14
  74. package/dist/{usage-B7RIAPPT.js → usage-ZN5DU6Z7.js} +4 -4
  75. package/dist/{vector-store-JAXWDZYW.js → vector-store-T2DVUMY4.js} +2 -2
  76. package/dist/{vector-store-PWIOQFTP.js → vector-store-V6UGEYWK.js} +2 -2
  77. package/dist/web/client/app.js +7 -0
  78. package/dist/web/client/app.js.br +0 -0
  79. package/dist/web/client/app.js.gz +0 -0
  80. package/dist/web/client/util.js +14 -23
  81. package/dist/web/client/util.js.br +0 -0
  82. package/dist/web/client/util.js.gz +0 -0
  83. package/dist/web/client/vendor/DOMPurify-LICENSE.txt +202 -0
  84. package/dist/web/client/vendor/purify.es.mjs +2722 -0
  85. package/dist/web/client/vendor/purify.es.mjs.br +0 -0
  86. package/dist/web/client/vendor/purify.es.mjs.gz +0 -0
  87. package/package.json +4 -2
  88. package/dist/chunk-4BKXL7SM.js +0 -98
  89. package/dist/chunk-6BUTA5VW.js +0 -38
  90. package/dist/chunk-IW3Q7AE5.js +0 -40
  91. package/dist/chunk-SKET65WZ.js +0 -96
  92. package/dist/doctor-cli-IOVSHBDI.js +0 -18
  93. package/dist/file-checkpoint-CGH6OJVI.js +0 -6
  94. package/dist/indexer-FPKY7LCT.js +0 -10
  95. package/dist/run-tests-EQCAMFQE.js +0 -10
  96. package/dist/run-tests-V3N7YV3P.js +0 -9
@@ -0,0 +1,39 @@
1
+ // src/tools/session-context.ts
2
+ import { AsyncLocalStorage } from "async_hooks";
3
+ import { homedir } from "os";
4
+ import { join } from "path";
5
+ var als = new AsyncLocalStorage();
6
+ var defaultState = /* @__PURE__ */ new Map();
7
+ function getExecutionConfigDir() {
8
+ return als.getStore()?.configDir ?? join(homedir(), ".aicli");
9
+ }
10
+ function getExecutionSignal() {
11
+ return als.getStore()?.signal;
12
+ }
13
+ function scopedState(key, create) {
14
+ const state = als.getStore()?.state ?? defaultState;
15
+ if (!state.has(key)) state.set(key, create());
16
+ return state.get(key);
17
+ }
18
+ function runWithExecutionContext(context, fn) {
19
+ return als.run({ sessionKey: DEFAULT_SESSION_KEY, ...als.getStore(), ...context }, fn);
20
+ }
21
+ var DEFAULT_SESSION_KEY = "__default__";
22
+ function getCurrentSessionKey() {
23
+ const ctx = als.getStore();
24
+ if (!ctx || !ctx.sessionKey) return DEFAULT_SESSION_KEY;
25
+ return ctx.sessionKey;
26
+ }
27
+ function runWithSessionKey(sessionKey, fn) {
28
+ const key = sessionKey && sessionKey.length > 0 ? sessionKey : DEFAULT_SESSION_KEY;
29
+ return als.run({ ...als.getStore(), sessionKey: key }, fn);
30
+ }
31
+
32
+ export {
33
+ getExecutionConfigDir,
34
+ getExecutionSignal,
35
+ scopedState,
36
+ runWithExecutionContext,
37
+ getCurrentSessionKey,
38
+ runWithSessionKey
39
+ };
@@ -5,13 +5,13 @@ import {
5
5
  } from "./chunk-TU3L3PW7.js";
6
6
  import {
7
7
  atomicWriteFileSync
8
- } from "./chunk-IW3Q7AE5.js";
8
+ } from "./chunk-BMLQPSHP.js";
9
9
  import {
10
10
  CONFIG_DIR_NAME,
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-VAV2IJ3R.js";
14
+ } from "./chunk-3CNPJLVI.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -381,8 +381,13 @@ ${err}`
381
381
  * @returns true if config was modified and should be persisted.
382
382
  */
383
383
  migrateLegacyModels() {
384
- const LEGACY_DEEPSEEK = /* @__PURE__ */ new Set(["deepseek-chat", "deepseek-reasoner"]);
385
- const DEEPSEEK_TARGET = "deepseek-v4-flash";
384
+ const LEGACY_DEEPSEEK = /* @__PURE__ */ new Set([
385
+ "deepseek-chat",
386
+ "deepseek-reasoner",
387
+ "deepseek-v4-flash",
388
+ "deepseek-v4-flash-vision-exp"
389
+ ]);
390
+ const DEEPSEEK_TARGET = "deepseek-flash";
386
391
  const LEGACY_KIMI = /* @__PURE__ */ new Set(["kimi-k2-0711-preview", "kimi-k2-turbo-preview"]);
387
392
  const KIMI_TARGET = "kimi-k2.6";
388
393
  let changed = false;
@@ -427,8 +432,8 @@ ${err}`
427
432
  return changed;
428
433
  }
429
434
  save() {
430
- mkdirSync(this.configDir, { recursive: true });
431
- atomicWriteFileSync(this.configPath, JSON.stringify(this.config, null, 2));
435
+ mkdirSync(this.configDir, { recursive: true, mode: 448 });
436
+ atomicWriteFileSync(this.configPath, JSON.stringify(this.config, null, 2), { mode: 384 });
432
437
  }
433
438
  getApiKey(providerId) {
434
439
  const envKey = EnvLoader.getApiKey(providerId);
@@ -1,16 +1,180 @@
1
- #!/usr/bin/env node
1
+ import {
2
+ getExecutionConfigDir,
3
+ getExecutionSignal
4
+ } from "./chunk-QMFMST2T.js";
2
5
  import {
3
6
  TEST_TIMEOUT
4
- } from "./chunk-VAV2IJ3R.js";
7
+ } from "./chunk-EAVX3RLD.js";
8
+
9
+ // src/tools/builtin/run-tests.ts
10
+ import { spawn as spawn2 } from "child_process";
11
+
12
+ // src/core/interrupt.ts
13
+ var controller = new AbortController();
14
+ function currentAbortSignal() {
15
+ return getExecutionSignal() ?? controller.signal;
16
+ }
17
+
18
+ // src/tools/win-shell.ts
19
+ import { platform } from "os";
20
+ import { spawn } from "child_process";
21
+ var IS_WINDOWS = platform() === "win32";
22
+ var WIN_UTF8_PREAMBLE = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; ";
23
+ function shellInvocation(command) {
24
+ if (IS_WINDOWS) {
25
+ return {
26
+ shell: "powershell.exe",
27
+ args: ["-NoProfile", "-NonInteractive", "-Command", WIN_UTF8_PREAMBLE + command]
28
+ };
29
+ }
30
+ return { shell: process.env["SHELL"] ?? "/bin/bash", args: ["-c", command] };
31
+ }
32
+ function decodeWindowsBuffer(buf) {
33
+ const utf8 = buf.toString("utf-8");
34
+ if (!utf8.includes("\uFFFD")) return utf8;
35
+ try {
36
+ return new TextDecoder("gbk").decode(buf);
37
+ } catch {
38
+ return utf8;
39
+ }
40
+ }
41
+ var GBK_MOJIBAKE_FINGERPRINTS = [
42
+ "\uFFFD",
43
+ "\u9215",
44
+ "\u951B",
45
+ "\u9983",
46
+ "\u9241",
47
+ "\u6D93",
48
+ "\u935B",
49
+ "\u9428",
50
+ "\u7EFE",
51
+ "\u95AB",
52
+ "\u9593",
53
+ "\u95BF",
54
+ "\u68E3",
55
+ "\u95B4",
56
+ "\u5A11",
57
+ "\u95B8",
58
+ "\u95BB",
59
+ "\u7F01",
60
+ "\u95C1"
61
+ ];
62
+ var gbkReverse = null;
63
+ function gbkReverseMap() {
64
+ if (gbkReverse) return gbkReverse;
65
+ const map = /* @__PURE__ */ new Map();
66
+ try {
67
+ const dec = new TextDecoder("gbk");
68
+ for (let hi = 129; hi <= 254; hi++) {
69
+ for (let lo = 64; lo <= 254; lo++) {
70
+ if (lo === 127) continue;
71
+ const ch = dec.decode(new Uint8Array([hi, lo]));
72
+ if (ch.length === 1 && ch !== "\uFFFD" && !map.has(ch)) map.set(ch, [hi, lo]);
73
+ }
74
+ }
75
+ } catch {
76
+ }
77
+ gbkReverse = map;
78
+ return map;
79
+ }
80
+ function decodeRunAsChinese(bytes) {
81
+ for (let start = 0; start <= 2 && start < bytes.length; start++) {
82
+ for (let end = 0; end <= 2 && bytes.length - end > start; end++) {
83
+ const slice = bytes.slice(start, bytes.length - end);
84
+ if (slice.length < 6) continue;
85
+ try {
86
+ const out = new TextDecoder("utf-8", { fatal: true }).decode(new Uint8Array(slice));
87
+ if (/[一-鿿]/.test(out)) return out;
88
+ } catch {
89
+ }
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+ function recoverGbkMojibake(text) {
95
+ if (!text) return null;
96
+ const map = gbkReverseMap();
97
+ if (map.size === 0) return null;
98
+ let run = [];
99
+ let best = null;
100
+ const flush = () => {
101
+ if (run.length >= 4) {
102
+ const bytes = [];
103
+ for (const p of run) bytes.push(p[0], p[1]);
104
+ const out = decodeRunAsChinese(bytes);
105
+ if (out && (!best || out.length > best.length)) best = out;
106
+ }
107
+ run = [];
108
+ };
109
+ for (const ch of text) {
110
+ const pair = ch.codePointAt(0) < 128 ? void 0 : map.get(ch);
111
+ if (pair) run.push(pair);
112
+ else flush();
113
+ }
114
+ flush();
115
+ return best;
116
+ }
117
+ function looksLikeGbkMojibake(text) {
118
+ if (recoverGbkMojibake(text) !== null) return true;
119
+ let hits = 0;
120
+ for (const ch of GBK_MOJIBAKE_FINGERPRINTS) {
121
+ if (text.includes(ch) && ++hits >= 2) return true;
122
+ }
123
+ return false;
124
+ }
125
+ function killProcessTree(proc, processGroup = false) {
126
+ if (proc.killed || proc.exitCode !== null) return;
127
+ if (IS_WINDOWS && proc.pid) {
128
+ try {
129
+ const tk = spawn("taskkill", ["/PID", String(proc.pid), "/T", "/F"], {
130
+ windowsHide: true,
131
+ stdio: "ignore"
132
+ });
133
+ tk.on("exit", () => {
134
+ try {
135
+ proc.kill();
136
+ } catch {
137
+ }
138
+ });
139
+ tk.on("error", () => {
140
+ try {
141
+ proc.kill();
142
+ } catch {
143
+ }
144
+ });
145
+ } catch {
146
+ try {
147
+ proc.kill();
148
+ } catch {
149
+ }
150
+ }
151
+ return;
152
+ }
153
+ const signal = (value) => {
154
+ if (processGroup && proc.pid) process.kill(-proc.pid, value);
155
+ else proc.kill(value);
156
+ };
157
+ try {
158
+ signal("SIGTERM");
159
+ } catch {
160
+ }
161
+ setTimeout(() => {
162
+ if (processGroup || proc.exitCode === null) {
163
+ try {
164
+ signal("SIGKILL");
165
+ } catch {
166
+ }
167
+ }
168
+ }, 500).unref();
169
+ }
5
170
 
6
171
  // src/tools/builtin/run-tests.ts
7
- import { execSync, spawnSync } from "child_process";
8
172
  import { existsSync, readFileSync, readdirSync } from "fs";
9
173
  import { join } from "path";
10
- import { platform } from "os";
174
+ import { platform as platform2 } from "os";
11
175
  import chalk from "chalk";
12
- var FILTER_WHITELIST = /^[\w.\-/:#\s*?()\[\]@+]{1,200}$/;
13
- var IS_WINDOWS = platform() === "win32";
176
+ var FILTER_WHITELIST = /^[\w.\-/:# *?\[\]@+]{1,200}$/;
177
+ var IS_WINDOWS2 = platform2() === "win32";
14
178
  function detectNodeTestFramework(cwd, pkg) {
15
179
  const devDeps = pkg.devDependencies ?? {};
16
180
  const deps = pkg.dependencies ?? {};
@@ -80,11 +244,11 @@ function safeReadPackageJson(cwd) {
80
244
  }
81
245
  function detectProject(cwd) {
82
246
  if (existsSync(join(cwd, "pom.xml"))) {
83
- return { type: "java", framework: "Maven (JUnit)", command: IS_WINDOWS ? "mvn.cmd test" : "mvn test" };
247
+ return { type: "java", framework: "Maven (JUnit)", command: IS_WINDOWS2 ? "mvn.cmd test" : "mvn test" };
84
248
  }
85
249
  if (existsSync(join(cwd, "build.gradle")) || existsSync(join(cwd, "build.gradle.kts"))) {
86
- const wrapper = IS_WINDOWS ? "gradlew.bat" : "./gradlew";
87
- const cmd = existsSync(join(cwd, IS_WINDOWS ? "gradlew.bat" : "gradlew")) ? `${wrapper} test` : "gradle test";
250
+ const wrapper = IS_WINDOWS2 ? "gradlew.bat" : "./gradlew";
251
+ const cmd = existsSync(join(cwd, IS_WINDOWS2 ? "gradlew.bat" : "gradlew")) ? `${wrapper} test` : "gradle test";
88
252
  return { type: "java", framework: "Gradle (JUnit)", command: cmd };
89
253
  }
90
254
  if (existsSync(join(cwd, "package.json"))) {
@@ -240,7 +404,7 @@ function renderColorReport(summary, framework) {
240
404
  console.log();
241
405
  }
242
406
  function needsWindowsShell(file) {
243
- if (!IS_WINDOWS) return false;
407
+ if (!IS_WINDOWS2) return false;
244
408
  const lower = file.toLowerCase();
245
409
  return lower.endsWith(".cmd") || lower.endsWith(".bat") || lower === "mvn" || lower === "gradle" || lower === "npm" || lower === "npx";
246
410
  }
@@ -307,51 +471,9 @@ Got: ${filter.slice(0, 60)}${filter.length > 60 ? "..." : ""}`;
307
471
  framework = detected.framework;
308
472
  argv = buildArgv(detected, filter);
309
473
  }
310
- let output;
311
- let exitCode = 0;
312
- if (argv) {
313
- const r = spawnSync(argv.file, argv.args, {
314
- cwd,
315
- timeout: TEST_TIMEOUT,
316
- stdio: ["pipe", "pipe", "pipe"],
317
- // shell:false is the default for spawnSync; on Windows .cmd/.bat
318
- // requires shell:true, so we opt-in only for known wrapper names.
319
- shell: needsWindowsShell(argv.file),
320
- env: {
321
- ...process.env,
322
- ...IS_WINDOWS ? {} : { FORCE_COLOR: "0" }
323
- },
324
- encoding: "utf-8",
325
- maxBuffer: 64 * 1024 * 1024
326
- });
327
- if (r.error) {
328
- output = `Failed to launch test runner: ${r.error.message}`;
329
- exitCode = 1;
330
- } else {
331
- exitCode = r.status ?? 1;
332
- output = (r.stdout ?? "") + (r.stderr ? "\n" + r.stderr : "");
333
- }
334
- } else {
335
- try {
336
- const buf = execSync(command, {
337
- cwd,
338
- timeout: TEST_TIMEOUT,
339
- encoding: "buffer",
340
- stdio: ["pipe", "pipe", "pipe"],
341
- env: {
342
- ...process.env,
343
- ...IS_WINDOWS ? {} : { FORCE_COLOR: "0" }
344
- }
345
- });
346
- output = buf.toString("utf-8");
347
- } catch (err) {
348
- const e = err;
349
- exitCode = e.status ?? 1;
350
- const stdout = e.stdout?.toString("utf-8") ?? "";
351
- const stderr = e.stderr?.toString("utf-8") ?? "";
352
- output = stdout + (stderr ? "\n" + stderr : "");
353
- }
354
- }
474
+ const result = await runTestProcess(argv, command, cwd, currentAbortSignal());
475
+ const output = result.output;
476
+ const exitCode = result.exitCode;
355
477
  let summary = {
356
478
  tests: 0,
357
479
  passed: 0,
@@ -390,6 +512,7 @@ Got: ${filter.slice(0, 60)}${filter.length > 60 ? "..." : ""}`;
390
512
  }
391
513
  }
392
514
  }
515
+ if (exitCode !== 0 && summary.failures + summary.errors === 0) summary.errors = 1;
393
516
  renderColorReport(summary, framework);
394
517
  return formatReport(summary, framework, output, exitCode);
395
518
  }
@@ -414,8 +537,75 @@ var runTestsTool = {
414
537
  return executeTests(args);
415
538
  }
416
539
  };
540
+ var MAX_TEST_OUTPUT_BYTES = 4 * 1024 * 1024;
541
+ var activeTestProcesses = 0;
542
+ var activeTestsByOwner = /* @__PURE__ */ new Map();
543
+ async function runTestProcess(argv, command, cwd, signal) {
544
+ if (signal.aborted) throw new Error("Test run cancelled");
545
+ const owner = getExecutionConfigDir();
546
+ if ((activeTestsByOwner.get(owner) ?? 0) >= 2) throw new Error("Test runner capacity reached (2 per user).");
547
+ if (activeTestProcesses >= 4) throw new Error("Test runner capacity reached (4). Try again after a run finishes.");
548
+ activeTestProcesses++;
549
+ activeTestsByOwner.set(owner, (activeTestsByOwner.get(owner) ?? 0) + 1);
550
+ try {
551
+ return await new Promise((resolve, reject) => {
552
+ const child = argv ? spawn2(argv.file, argv.args, { cwd, shell: needsWindowsShell(argv.file), windowsHide: true, detached: !IS_WINDOWS2, stdio: ["ignore", "pipe", "pipe"] }) : spawn2(command, { cwd, shell: true, windowsHide: true, detached: !IS_WINDOWS2, stdio: ["ignore", "pipe", "pipe"] });
553
+ const chunks = [];
554
+ let bytes = 0;
555
+ let stopped = "";
556
+ let settled = false;
557
+ const stop = (reason) => {
558
+ if (stopped) return;
559
+ stopped = reason;
560
+ killProcessTree(child, true);
561
+ };
562
+ const onAbort = () => stop("Test run cancelled");
563
+ const timer = setTimeout(() => stop("Test run timed out"), TEST_TIMEOUT);
564
+ signal.addEventListener("abort", onAbort, { once: true });
565
+ if (signal.aborted) onAbort();
566
+ const append = (chunk) => {
567
+ const take = Math.min(chunk.length, MAX_TEST_OUTPUT_BYTES - bytes);
568
+ if (take > 0) chunks.push(chunk.subarray(0, take));
569
+ bytes += take;
570
+ if (bytes >= MAX_TEST_OUTPUT_BYTES) stop("Test output exceeded 4 MiB limit");
571
+ };
572
+ child.stdout?.on("data", append);
573
+ child.stderr?.on("data", append);
574
+ const clean = () => {
575
+ clearTimeout(timer);
576
+ signal.removeEventListener("abort", onAbort);
577
+ };
578
+ child.once("error", (error) => {
579
+ if (settled) return;
580
+ settled = true;
581
+ clean();
582
+ reject(error);
583
+ });
584
+ child.once("close", (code) => {
585
+ if (settled) return;
586
+ settled = true;
587
+ clean();
588
+ resolve({ output: Buffer.concat(chunks).toString("utf8") + (stopped ? "\n" + stopped : ""), exitCode: stopped ? 1 : code ?? 1 });
589
+ });
590
+ });
591
+ } finally {
592
+ activeTestProcesses--;
593
+ const remaining = (activeTestsByOwner.get(owner) ?? 1) - 1;
594
+ if (remaining) activeTestsByOwner.set(owner, remaining);
595
+ else activeTestsByOwner.delete(owner);
596
+ }
597
+ }
417
598
 
418
599
  export {
600
+ currentAbortSignal,
601
+ IS_WINDOWS,
602
+ WIN_UTF8_PREAMBLE,
603
+ shellInvocation,
604
+ decodeWindowsBuffer,
605
+ recoverGbkMojibake,
606
+ looksLikeGbkMojibake,
607
+ killProcessTree,
419
608
  executeTests,
420
- runTestsTool
609
+ runTestsTool,
610
+ runTestProcess
421
611
  };
@@ -1146,6 +1146,7 @@ function getDangerLevel(toolName, args) {
1146
1146
  }
1147
1147
  if (toolName === "bash") {
1148
1148
  const cmd = String(args["command"] ?? "");
1149
+ if (/\bgit\s+(?:clean\b|reset\s+--hard\b|push\b[^\n]*(?:--force\b|\s-f\b))/i.test(cmd)) return "destructive";
1149
1150
  if (/\brm\s+[^\n]*(?:-\w*[rRfF]\w*|--recursive|--force)\b/.test(cmd)) return "destructive";
1150
1151
  if (/\brm\s+\S/.test(cmd)) return "destructive";
1151
1152
  if (/\brmdir\b|\bformat\b|\bmkfs\b|\bdd\s+if=|\bshred\b|\bfdisk\b|\bparted\b/.test(cmd)) return "destructive";
@@ -1161,8 +1162,10 @@ function getDangerLevel(toolName, args) {
1161
1162
  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";
1162
1163
  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";
1163
1164
  if (/\bcmd(\.exe)?\s+\/[ck]\b/i.test(cmd)) return "write";
1164
- return "safe";
1165
+ 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";
1166
+ return "write";
1165
1167
  }
1168
+ if (toolName === "run_tests") return "write";
1166
1169
  if (toolName === "write_file") return "write";
1167
1170
  if (toolName === "edit_file") return "write";
1168
1171
  if (toolName === "save_last_response") return "write";
@@ -1177,7 +1180,7 @@ function getDangerLevel(toolName, args) {
1177
1180
  if (toolName === "git_commit") return "write";
1178
1181
  if (toolName === "git_status" || toolName === "git_diff" || toolName === "git_log") return "safe";
1179
1182
  if (toolName === "notebook_edit") return "write";
1180
- if (toolName === "read_file" || toolName === "list_dir" || toolName === "grep_files" || toolName === "glob_files" || toolName === "web_fetch" || toolName === "save_memory" || toolName === "ask_user" || toolName === "write_todos" || toolName === "google_search" || toolName === "spawn_agent" || toolName === "run_tests") return "safe";
1183
+ if (toolName === "read_file" || toolName === "list_dir" || toolName === "grep_files" || toolName === "glob_files" || toolName === "web_fetch" || toolName === "save_memory" || toolName === "ask_user" || toolName === "write_todos" || toolName === "google_search" || toolName === "spawn_agent") return "safe";
1181
1184
  return "write";
1182
1185
  }
1183
1186
  function schemaToJsonSchema(schema) {
@@ -5,7 +5,7 @@ import {
5
5
  removeFile,
6
6
  saveIndex,
7
7
  upsertFileSymbols
8
- } from "./chunk-45UVJXFQ.js";
8
+ } from "./chunk-W2UOVGRC.js";
9
9
 
10
10
  // src/symbols/indexer.ts
11
11
  import fs2 from "fs";
@@ -6,7 +6,7 @@ import {
6
6
  removeFile,
7
7
  saveIndex,
8
8
  upsertFileSymbols
9
- } from "./chunk-WQ3OMEC4.js";
9
+ } from "./chunk-M6HLYG33.js";
10
10
 
11
11
  // src/symbols/indexer.ts
12
12
  import fs2 from "fs";
@@ -8,13 +8,13 @@ import {
8
8
  listHooks,
9
9
  listInstalledPlugins,
10
10
  resetStats
11
- } from "./chunk-5GQL4TSZ.js";
11
+ } from "./chunk-4BXTGXZ6.js";
12
12
  import {
13
13
  ProviderRegistry
14
- } from "./chunk-VXEF2SWG.js";
14
+ } from "./chunk-EHMMBIZT.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-AQF6IXSR.js";
17
+ } from "./chunk-RBCKX2FZ.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-VAV2IJ3R.js";
29
+ } from "./chunk-3CNPJLVI.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/tools/session-context.ts
4
+ import { AsyncLocalStorage } from "async_hooks";
5
+ import { homedir } from "os";
6
+ import { join } from "path";
7
+ var als = new AsyncLocalStorage();
8
+ var defaultState = /* @__PURE__ */ new Map();
9
+ function getExecutionConfigDir() {
10
+ return als.getStore()?.configDir ?? join(homedir(), ".aicli");
11
+ }
12
+ function getExecutionSignal() {
13
+ return als.getStore()?.signal;
14
+ }
15
+ function scopedState(key, create) {
16
+ const state = als.getStore()?.state ?? defaultState;
17
+ if (!state.has(key)) state.set(key, create());
18
+ return state.get(key);
19
+ }
20
+ function runWithExecutionContext(context, fn) {
21
+ return als.run({ sessionKey: DEFAULT_SESSION_KEY, ...als.getStore(), ...context }, fn);
22
+ }
23
+ var DEFAULT_SESSION_KEY = "__default__";
24
+ function getCurrentSessionKey() {
25
+ const ctx = als.getStore();
26
+ if (!ctx || !ctx.sessionKey) return DEFAULT_SESSION_KEY;
27
+ return ctx.sessionKey;
28
+ }
29
+ function runWithSessionKey(sessionKey, fn) {
30
+ const key = sessionKey && sessionKey.length > 0 ? sessionKey : DEFAULT_SESSION_KEY;
31
+ return als.run({ ...als.getStore(), sessionKey: key }, fn);
32
+ }
33
+
34
+ export {
35
+ getExecutionConfigDir,
36
+ getExecutionSignal,
37
+ scopedState,
38
+ runWithExecutionContext,
39
+ getCurrentSessionKey,
40
+ runWithSessionKey
41
+ };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  computeCost,
4
4
  formatCost
5
- } from "./chunk-YKJO3SI4.js";
5
+ } from "./chunk-LONB36SP.js";
6
6
  import {
7
7
  clearRecentlyDeniedAutoActions,
8
8
  estimateTokens,
@@ -16,7 +16,7 @@ import {
16
16
  setPreferredAgentName,
17
17
  truncateForPersist,
18
18
  undoStack
19
- } from "./chunk-L2RJPVHV.js";
19
+ } from "./chunk-O7MMYJAD.js";
20
20
  import {
21
21
  buildReviewPrompt,
22
22
  buildSecurityReviewPrompt
@@ -26,7 +26,7 @@ import {
26
26
  clearChatIndex,
27
27
  getChatIndexStatus,
28
28
  searchChatMemory
29
- } from "./chunk-GHWZVPUV.js";
29
+ } from "./chunk-6JHACXB3.js";
30
30
  import {
31
31
  addMemoryEntry,
32
32
  backupMemoryStore,
@@ -51,13 +51,13 @@ import {
51
51
  touchMemoryReferences,
52
52
  updateMemoryApproval,
53
53
  updateMemoryEntry
54
- } from "./chunk-AHL6KOGM.js";
54
+ } from "./chunk-HXINWG37.js";
55
55
  import {
56
56
  theme
57
57
  } from "./chunk-5C76XDDF.js";
58
58
  import {
59
59
  getContentText
60
- } from "./chunk-IUVDZVZ4.js";
60
+ } from "./chunk-AXTLYOA7.js";
61
61
  import {
62
62
  DEFAULT_PATTERNS,
63
63
  scanString
@@ -65,7 +65,7 @@ import {
65
65
  import {
66
66
  buildDoctorReport,
67
67
  formatDoctorReport
68
- } from "./chunk-NQJSPMY2.js";
68
+ } from "./chunk-SCG2VBPB.js";
69
69
  import {
70
70
  describePlugin,
71
71
  getActivePluginAssets,
@@ -80,24 +80,24 @@ import {
80
80
  trustHook,
81
81
  trustPlugin,
82
82
  untrustHook
83
- } from "./chunk-5GQL4TSZ.js";
83
+ } from "./chunk-4BXTGXZ6.js";
84
84
  import {
85
85
  isCleanDocumentBody,
86
86
  stripOuterCodeFence
87
- } from "./chunk-MI4SFZGX.js";
87
+ } from "./chunk-RMEJR3AW.js";
88
88
  import {
89
89
  formatGitContextForPrompt,
90
90
  getGitContext
91
91
  } from "./chunk-HOSJZMQS.js";
92
92
  import {
93
93
  atomicWriteFileSync
94
- } from "./chunk-IW3Q7AE5.js";
94
+ } from "./chunk-BMLQPSHP.js";
95
95
  import {
96
96
  applyConfigCommand
97
97
  } from "./chunk-XNFIYS7G.js";
98
98
  import {
99
99
  fileCheckpoints
100
- } from "./chunk-4BKXL7SM.js";
100
+ } from "./chunk-JJFJWD35.js";
101
101
  import {
102
102
  APP_NAME,
103
103
  CONFIG_DIR_NAME,
@@ -109,7 +109,7 @@ import {
109
109
  MCP_TOOL_PREFIX,
110
110
  REPO_URL,
111
111
  VERSION
112
- } from "./chunk-VAV2IJ3R.js";
112
+ } from "./chunk-3CNPJLVI.js";
113
113
 
114
114
  // src/skills/manager.ts
115
115
  import { existsSync, readdirSync, mkdirSync, statSync } from "fs";
@@ -2426,8 +2426,8 @@ No tools match "${filter}".
2426
2426
  const { join: join6 } = await import("path");
2427
2427
  const { existsSync: existsSync6 } = await import("fs");
2428
2428
  const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
2429
- const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-NMASHFDL.js");
2430
- const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
2429
+ const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-SNJR6546.js");
2430
+ const { approveProject, hashMcpFile } = await import("./project-trust-KGG2BWKC.js");
2431
2431
  const cwd = process.cwd();
2432
2432
  const projectRoot = getGitRoot(cwd) ?? cwd;
2433
2433
  const mcpPath = join6(projectRoot, MCP_PROJECT_CONFIG_NAME);
@@ -3534,7 +3534,7 @@ function createReviewCommands() {
3534
3534
  usage: "/test [command|filter]",
3535
3535
  async execute(args, ctx) {
3536
3536
  try {
3537
- const { executeTests } = await import("./run-tests-EQCAMFQE.js");
3537
+ const { executeTests } = await import("./run-tests-33ZVQE3Q.js");
3538
3538
  const argStr = args.join(" ").trim();
3539
3539
  let testArgs = {};
3540
3540
  if (argStr) {
@@ -3900,9 +3900,9 @@ function createMemoryCommands() {
3900
3900
  async execute(args, ctx) {
3901
3901
  const sub = (args[0] ?? "status").toLowerCase();
3902
3902
  const root = process.cwd();
3903
- const { loadIndex, clearIndex } = await import("./store-CMSSWZF7.js");
3904
- const { indexProject } = await import("./indexer-P3FPRTPJ.js");
3905
- const { loadVectorStore, clearVectorStore } = await import("./vector-store-PWIOQFTP.js");
3903
+ const { loadIndex, clearIndex } = await import("./store-76VVFDXM.js");
3904
+ const { indexProject } = await import("./indexer-GKIWSSRP.js");
3905
+ const { loadVectorStore, clearVectorStore } = await import("./vector-store-V6UGEYWK.js");
3906
3906
  if (sub === "status") {
3907
3907
  const idx = loadIndex(root);
3908
3908
  const vec = loadVectorStore(root);
@@ -3962,7 +3962,7 @@ function createMemoryCommands() {
3962
3962
  }
3963
3963
  console.log(theme.dim(` Building semantic index for ${idx.symbolCount} symbols\u2026`));
3964
3964
  console.log(theme.dim(" (First run downloads ~117 MB embedding model to ~/.aicli/models/)"));
3965
- const { rebuildSemanticIndex } = await import("./semantic-7GM5M4MU.js");
3965
+ const { rebuildSemanticIndex } = await import("./semantic-N227CLSC.js");
3966
3966
  try {
3967
3967
  const stats = await rebuildSemanticIndex(root, {
3968
3968
  onProgress: (done, total) => {