jinzd-ai-cli 0.4.307 → 0.4.308
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.
- package/README.md +1 -0
- package/THIRD_PARTY_NOTICES.md +3 -0
- package/dist/{agent-client-6GX6QQDU.js → agent-client-TIEAYZXV.js} +4 -1
- package/dist/{auth-PE3Z5OHS.js → auth-QTQNZ6IX.js} +2 -2
- package/dist/{batch-HMADXNOD.js → batch-S7XLEEOH.js} +3 -3
- package/dist/{chat-index-2D5GK2DB.js → chat-index-7CLR4CBG.js} +4 -3
- package/dist/{chat-index-DGUOUUQW.js → chat-index-RLVLQRRC.js} +3 -2
- package/dist/{chunk-SJFZPS65.js → chunk-2DYQDLLF.js} +1 -1
- package/dist/{chunk-VAV2IJ3R.js → chunk-2MNUMLN4.js} +1 -1
- package/dist/chunk-2XMUCC42.js +67 -0
- package/dist/{chunk-5GQL4TSZ.js → chunk-3537CQ5M.js} +2 -2
- package/dist/{chunk-OAXLMF3U.js → chunk-3YVNDYOY.js} +1 -1
- package/dist/{chunk-RYQBBEMM.js → chunk-4PR5AVJ5.js} +115 -19
- package/dist/{chunk-GHWZVPUV.js → chunk-6JHACXB3.js} +7 -5
- package/dist/{chunk-CIM2PV2F.js → chunk-7OHXFTZO.js} +2 -2
- package/dist/{chunk-IUVDZVZ4.js → chunk-AXTLYOA7.js} +24 -17
- package/dist/{chunk-XJOK5353.js → chunk-B3MPYI4E.js} +2 -2
- package/dist/{chunk-3CKJOTVM.js → chunk-BGZN4K7Q.js} +4 -4
- package/dist/chunk-BMLQPSHP.js +69 -0
- package/dist/{chunk-NRSYBKWA.js → chunk-C7CKDFJS.js} +1 -1
- package/dist/{chunk-NQJSPMY2.js → chunk-E2PNXNKI.js} +4 -4
- package/dist/chunk-FVXNEZEW.js +161 -0
- package/dist/{chunk-YKJO3SI4.js → chunk-G6DVGQ4I.js} +1 -1
- package/dist/{chunk-YFDQIUQ3.js → chunk-HC33C4U3.js} +18 -18
- package/dist/chunk-JJFJWD35.js +162 -0
- package/dist/{chunk-KRCYR46A.js → chunk-JJNUASMJ.js} +264 -55
- package/dist/{chunk-NYNSYLFY.js → chunk-JL44HGZC.js} +1 -1
- package/dist/{chunk-NUJTNH76.js → chunk-LBWKMTT3.js} +1 -1
- package/dist/{chunk-AHL6KOGM.js → chunk-LR3TGZWQ.js} +2 -2
- package/dist/{chunk-WQ3OMEC4.js → chunk-M6HLYG33.js} +1 -1
- package/dist/{chunk-I4GQRMFV.js → chunk-M6YV5KSS.js} +6 -4
- package/dist/{chunk-3TBXHLSC.js → chunk-NLK45GUS.js} +1 -1
- package/dist/{chunk-KBDKKHXB.js → chunk-O6CGOVD4.js} +2 -2
- package/dist/chunk-QMFMST2T.js +39 -0
- package/dist/{chunk-MI4SFZGX.js → chunk-RMEJR3AW.js} +5 -2
- package/dist/{chunk-UFW4S3RU.js → chunk-RVMCY6DP.js} +1 -1
- package/dist/{chunk-LF67HWWR.js → chunk-RWRZVQCB.js} +1 -1
- package/dist/chunk-SXIJLSVF.js +41 -0
- package/dist/chunk-TDQW2YHK.js +65 -0
- package/dist/{chunk-L2RJPVHV.js → chunk-TPTFV3Y6.js} +266 -512
- package/dist/{chunk-45UVJXFQ.js → chunk-W2UOVGRC.js} +1 -1
- package/dist/{chunk-VXEF2SWG.js → chunk-WT252ZDV.js} +2 -2
- package/dist/{chunk-4W6VDVQU.js → chunk-WVEIUSXE.js} +246 -56
- package/dist/{chunk-AQF6IXSR.js → chunk-YBZM7PHI.js} +4 -4
- package/dist/{ci-QD2Q7NWY.js → ci-5HONSUAS.js} +7 -7
- package/dist/{ci-format-42XIZO5P.js → ci-format-URUH3ZZ5.js} +2 -2
- package/dist/{constants-NMASHFDL.js → constants-BLDBI7IG.js} +1 -1
- package/dist/{constants-5CMEFZQB.js → constants-FG27DQMS.js} +1 -1
- package/dist/doctor-cli-QQLMNJN7.js +18 -0
- package/dist/electron-server.js +886 -828
- package/dist/file-checkpoint-64A2AXHE.js +7 -0
- package/dist/{file-checkpoint-NKBHGC7L.js → file-checkpoint-VVPUJNCI.js} +2 -1
- package/dist/{hub-ZLF6GMQD.js → hub-GGFW3DCC.js} +3 -3
- package/dist/{hub-server-CBKCP5VD.js → hub-server-JLC7CNP7.js} +55 -17
- package/dist/index.js +42 -40
- package/dist/{indexer-P3FPRTPJ.js → indexer-GKIWSSRP.js} +3 -3
- package/dist/indexer-VRXDZ74A.js +10 -0
- package/dist/{persist-S77WRVLD.js → persist-ZZXRWFBX.js} +4 -4
- package/dist/{persistent-memory-GJE7HKVK.js → persistent-memory-UNLCXUWH.js} +3 -3
- package/dist/{persistent-memory-MBSBTBGY.js → persistent-memory-YYWIN6BG.js} +3 -3
- package/dist/{pr-SXRW24JG.js → pr-YCFGPFI7.js} +7 -7
- package/dist/{project-trust-MUG325AW.js → project-trust-6CJB5ZMX.js} +1 -1
- package/dist/{project-trust-NKYHL3VZ.js → project-trust-KGG2BWKC.js} +1 -1
- package/dist/run-tests-GHY4BYDE.js +13 -0
- package/dist/run-tests-KRNMFXAN.js +12 -0
- package/dist/{semantic-7GM5M4MU.js → semantic-N227CLSC.js} +4 -4
- package/dist/{semantic-QOBAXEQ4.js → semantic-TRQAZSRY.js} +4 -4
- package/dist/{server-MO3EU2XD.js → server-73UBHSFV.js} +16 -14
- package/dist/{server-GGEO7SA2.js → server-QRAWSG4Z.js} +231 -103
- package/dist/{store-SIKHCUYJ.js → store-2N6PPPBP.js} +2 -2
- package/dist/{store-CMSSWZF7.js → store-76VVFDXM.js} +2 -2
- package/dist/{task-orchestrator-JGEEQ2OE.js → task-orchestrator-GI3RGLZI.js} +15 -14
- package/dist/{usage-B7RIAPPT.js → usage-GWTIGZF5.js} +4 -4
- package/dist/{vector-store-JAXWDZYW.js → vector-store-T2DVUMY4.js} +2 -2
- package/dist/{vector-store-PWIOQFTP.js → vector-store-V6UGEYWK.js} +2 -2
- package/dist/web/client/app.js +7 -0
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/dist/web/client/util.js +14 -23
- package/dist/web/client/util.js.br +0 -0
- package/dist/web/client/util.js.gz +0 -0
- package/dist/web/client/vendor/DOMPurify-LICENSE.txt +202 -0
- package/dist/web/client/vendor/purify.es.mjs +2722 -0
- package/dist/web/client/vendor/purify.es.mjs.br +0 -0
- package/dist/web/client/vendor/purify.es.mjs.gz +0 -0
- package/package.json +4 -2
- package/dist/chunk-4BKXL7SM.js +0 -98
- package/dist/chunk-6BUTA5VW.js +0 -38
- package/dist/chunk-IW3Q7AE5.js +0 -40
- package/dist/chunk-SKET65WZ.js +0 -96
- package/dist/doctor-cli-IOVSHBDI.js +0 -18
- package/dist/file-checkpoint-CGH6OJVI.js +0 -6
- package/dist/indexer-FPKY7LCT.js +0 -10
- package/dist/run-tests-EQCAMFQE.js +0 -10
- package/dist/run-tests-V3N7YV3P.js +0 -9
|
@@ -1,15 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import {
|
|
2
3
|
TEST_TIMEOUT
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2MNUMLN4.js";
|
|
5
|
+
import {
|
|
6
|
+
getExecutionConfigDir,
|
|
7
|
+
getExecutionSignal
|
|
8
|
+
} from "./chunk-SXIJLSVF.js";
|
|
9
|
+
|
|
10
|
+
// src/tools/builtin/run-tests.ts
|
|
11
|
+
import { spawn as spawn2 } from "child_process";
|
|
12
|
+
|
|
13
|
+
// src/core/interrupt.ts
|
|
14
|
+
var controller = new AbortController();
|
|
15
|
+
var interrupted = false;
|
|
16
|
+
function currentAbortSignal() {
|
|
17
|
+
return getExecutionSignal() ?? controller.signal;
|
|
18
|
+
}
|
|
19
|
+
function isInterrupted() {
|
|
20
|
+
return interrupted;
|
|
21
|
+
}
|
|
22
|
+
function requestInterrupt() {
|
|
23
|
+
interrupted = true;
|
|
24
|
+
if (!controller.signal.aborted) {
|
|
25
|
+
controller.abort(new DOMException("User interrupted (Ctrl+C)", "AbortError"));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function resetInterrupt() {
|
|
29
|
+
controller = new AbortController();
|
|
30
|
+
interrupted = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/tools/win-shell.ts
|
|
34
|
+
import { platform } from "os";
|
|
35
|
+
import { spawn } from "child_process";
|
|
36
|
+
var IS_WINDOWS = platform() === "win32";
|
|
37
|
+
var WIN_UTF8_PREAMBLE = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; ";
|
|
38
|
+
function shellInvocation(command) {
|
|
39
|
+
if (IS_WINDOWS) {
|
|
40
|
+
return {
|
|
41
|
+
shell: "powershell.exe",
|
|
42
|
+
args: ["-NoProfile", "-NonInteractive", "-Command", WIN_UTF8_PREAMBLE + command]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return { shell: process.env["SHELL"] ?? "/bin/bash", args: ["-c", command] };
|
|
46
|
+
}
|
|
47
|
+
function decodeWindowsBuffer(buf) {
|
|
48
|
+
const utf8 = buf.toString("utf-8");
|
|
49
|
+
if (!utf8.includes("\uFFFD")) return utf8;
|
|
50
|
+
try {
|
|
51
|
+
return new TextDecoder("gbk").decode(buf);
|
|
52
|
+
} catch {
|
|
53
|
+
return utf8;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
var GBK_MOJIBAKE_FINGERPRINTS = [
|
|
57
|
+
"\uFFFD",
|
|
58
|
+
"\u9215",
|
|
59
|
+
"\u951B",
|
|
60
|
+
"\u9983",
|
|
61
|
+
"\u9241",
|
|
62
|
+
"\u6D93",
|
|
63
|
+
"\u935B",
|
|
64
|
+
"\u9428",
|
|
65
|
+
"\u7EFE",
|
|
66
|
+
"\u95AB",
|
|
67
|
+
"\u9593",
|
|
68
|
+
"\u95BF",
|
|
69
|
+
"\u68E3",
|
|
70
|
+
"\u95B4",
|
|
71
|
+
"\u5A11",
|
|
72
|
+
"\u95B8",
|
|
73
|
+
"\u95BB",
|
|
74
|
+
"\u7F01",
|
|
75
|
+
"\u95C1"
|
|
76
|
+
];
|
|
77
|
+
var gbkReverse = null;
|
|
78
|
+
function gbkReverseMap() {
|
|
79
|
+
if (gbkReverse) return gbkReverse;
|
|
80
|
+
const map = /* @__PURE__ */ new Map();
|
|
81
|
+
try {
|
|
82
|
+
const dec = new TextDecoder("gbk");
|
|
83
|
+
for (let hi = 129; hi <= 254; hi++) {
|
|
84
|
+
for (let lo = 64; lo <= 254; lo++) {
|
|
85
|
+
if (lo === 127) continue;
|
|
86
|
+
const ch = dec.decode(new Uint8Array([hi, lo]));
|
|
87
|
+
if (ch.length === 1 && ch !== "\uFFFD" && !map.has(ch)) map.set(ch, [hi, lo]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
gbkReverse = map;
|
|
93
|
+
return map;
|
|
94
|
+
}
|
|
95
|
+
function decodeRunAsChinese(bytes) {
|
|
96
|
+
for (let start = 0; start <= 2 && start < bytes.length; start++) {
|
|
97
|
+
for (let end = 0; end <= 2 && bytes.length - end > start; end++) {
|
|
98
|
+
const slice = bytes.slice(start, bytes.length - end);
|
|
99
|
+
if (slice.length < 6) continue;
|
|
100
|
+
try {
|
|
101
|
+
const out = new TextDecoder("utf-8", { fatal: true }).decode(new Uint8Array(slice));
|
|
102
|
+
if (/[一-鿿]/.test(out)) return out;
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function recoverGbkMojibake(text) {
|
|
110
|
+
if (!text) return null;
|
|
111
|
+
const map = gbkReverseMap();
|
|
112
|
+
if (map.size === 0) return null;
|
|
113
|
+
let run = [];
|
|
114
|
+
let best = null;
|
|
115
|
+
const flush = () => {
|
|
116
|
+
if (run.length >= 4) {
|
|
117
|
+
const bytes = [];
|
|
118
|
+
for (const p of run) bytes.push(p[0], p[1]);
|
|
119
|
+
const out = decodeRunAsChinese(bytes);
|
|
120
|
+
if (out && (!best || out.length > best.length)) best = out;
|
|
121
|
+
}
|
|
122
|
+
run = [];
|
|
123
|
+
};
|
|
124
|
+
for (const ch of text) {
|
|
125
|
+
const pair = ch.codePointAt(0) < 128 ? void 0 : map.get(ch);
|
|
126
|
+
if (pair) run.push(pair);
|
|
127
|
+
else flush();
|
|
128
|
+
}
|
|
129
|
+
flush();
|
|
130
|
+
return best;
|
|
131
|
+
}
|
|
132
|
+
function looksLikeGbkMojibake(text) {
|
|
133
|
+
if (recoverGbkMojibake(text) !== null) return true;
|
|
134
|
+
let hits = 0;
|
|
135
|
+
for (const ch of GBK_MOJIBAKE_FINGERPRINTS) {
|
|
136
|
+
if (text.includes(ch) && ++hits >= 2) return true;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
function killProcessTree(proc, processGroup = false) {
|
|
141
|
+
if (proc.killed || proc.exitCode !== null) return;
|
|
142
|
+
if (IS_WINDOWS && proc.pid) {
|
|
143
|
+
try {
|
|
144
|
+
const tk = spawn("taskkill", ["/PID", String(proc.pid), "/T", "/F"], {
|
|
145
|
+
windowsHide: true,
|
|
146
|
+
stdio: "ignore"
|
|
147
|
+
});
|
|
148
|
+
tk.on("exit", () => {
|
|
149
|
+
try {
|
|
150
|
+
proc.kill();
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
tk.on("error", () => {
|
|
155
|
+
try {
|
|
156
|
+
proc.kill();
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
} catch {
|
|
161
|
+
try {
|
|
162
|
+
proc.kill();
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const signal = (value) => {
|
|
169
|
+
if (processGroup && proc.pid) process.kill(-proc.pid, value);
|
|
170
|
+
else proc.kill(value);
|
|
171
|
+
};
|
|
172
|
+
try {
|
|
173
|
+
signal("SIGTERM");
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
176
|
+
setTimeout(() => {
|
|
177
|
+
if (processGroup || proc.exitCode === null) {
|
|
178
|
+
try {
|
|
179
|
+
signal("SIGKILL");
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}, 500).unref();
|
|
184
|
+
}
|
|
4
185
|
|
|
5
186
|
// src/tools/builtin/run-tests.ts
|
|
6
|
-
import { execSync, spawnSync } from "child_process";
|
|
7
187
|
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
8
188
|
import { join } from "path";
|
|
9
|
-
import { platform } from "os";
|
|
189
|
+
import { platform as platform2 } from "os";
|
|
10
190
|
import chalk from "chalk";
|
|
11
|
-
var FILTER_WHITELIST = /^[\w
|
|
12
|
-
var
|
|
191
|
+
var FILTER_WHITELIST = /^[\w.\-/:# *?\[\]@+]{1,200}$/;
|
|
192
|
+
var IS_WINDOWS2 = platform2() === "win32";
|
|
13
193
|
function detectNodeTestFramework(cwd, pkg) {
|
|
14
194
|
const devDeps = pkg.devDependencies ?? {};
|
|
15
195
|
const deps = pkg.dependencies ?? {};
|
|
@@ -79,11 +259,11 @@ function safeReadPackageJson(cwd) {
|
|
|
79
259
|
}
|
|
80
260
|
function detectProject(cwd) {
|
|
81
261
|
if (existsSync(join(cwd, "pom.xml"))) {
|
|
82
|
-
return { type: "java", framework: "Maven (JUnit)", command:
|
|
262
|
+
return { type: "java", framework: "Maven (JUnit)", command: IS_WINDOWS2 ? "mvn.cmd test" : "mvn test" };
|
|
83
263
|
}
|
|
84
264
|
if (existsSync(join(cwd, "build.gradle")) || existsSync(join(cwd, "build.gradle.kts"))) {
|
|
85
|
-
const wrapper =
|
|
86
|
-
const cmd = existsSync(join(cwd,
|
|
265
|
+
const wrapper = IS_WINDOWS2 ? "gradlew.bat" : "./gradlew";
|
|
266
|
+
const cmd = existsSync(join(cwd, IS_WINDOWS2 ? "gradlew.bat" : "gradlew")) ? `${wrapper} test` : "gradle test";
|
|
87
267
|
return { type: "java", framework: "Gradle (JUnit)", command: cmd };
|
|
88
268
|
}
|
|
89
269
|
if (existsSync(join(cwd, "package.json"))) {
|
|
@@ -239,7 +419,7 @@ function renderColorReport(summary, framework) {
|
|
|
239
419
|
console.log();
|
|
240
420
|
}
|
|
241
421
|
function needsWindowsShell(file) {
|
|
242
|
-
if (!
|
|
422
|
+
if (!IS_WINDOWS2) return false;
|
|
243
423
|
const lower = file.toLowerCase();
|
|
244
424
|
return lower.endsWith(".cmd") || lower.endsWith(".bat") || lower === "mvn" || lower === "gradle" || lower === "npm" || lower === "npx";
|
|
245
425
|
}
|
|
@@ -306,51 +486,9 @@ Got: ${filter.slice(0, 60)}${filter.length > 60 ? "..." : ""}`;
|
|
|
306
486
|
framework = detected.framework;
|
|
307
487
|
argv = buildArgv(detected, filter);
|
|
308
488
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const r = spawnSync(argv.file, argv.args, {
|
|
313
|
-
cwd,
|
|
314
|
-
timeout: TEST_TIMEOUT,
|
|
315
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
316
|
-
// shell:false is the default for spawnSync; on Windows .cmd/.bat
|
|
317
|
-
// requires shell:true, so we opt-in only for known wrapper names.
|
|
318
|
-
shell: needsWindowsShell(argv.file),
|
|
319
|
-
env: {
|
|
320
|
-
...process.env,
|
|
321
|
-
...IS_WINDOWS ? {} : { FORCE_COLOR: "0" }
|
|
322
|
-
},
|
|
323
|
-
encoding: "utf-8",
|
|
324
|
-
maxBuffer: 64 * 1024 * 1024
|
|
325
|
-
});
|
|
326
|
-
if (r.error) {
|
|
327
|
-
output = `Failed to launch test runner: ${r.error.message}`;
|
|
328
|
-
exitCode = 1;
|
|
329
|
-
} else {
|
|
330
|
-
exitCode = r.status ?? 1;
|
|
331
|
-
output = (r.stdout ?? "") + (r.stderr ? "\n" + r.stderr : "");
|
|
332
|
-
}
|
|
333
|
-
} else {
|
|
334
|
-
try {
|
|
335
|
-
const buf = execSync(command, {
|
|
336
|
-
cwd,
|
|
337
|
-
timeout: TEST_TIMEOUT,
|
|
338
|
-
encoding: "buffer",
|
|
339
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
340
|
-
env: {
|
|
341
|
-
...process.env,
|
|
342
|
-
...IS_WINDOWS ? {} : { FORCE_COLOR: "0" }
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
output = buf.toString("utf-8");
|
|
346
|
-
} catch (err) {
|
|
347
|
-
const e = err;
|
|
348
|
-
exitCode = e.status ?? 1;
|
|
349
|
-
const stdout = e.stdout?.toString("utf-8") ?? "";
|
|
350
|
-
const stderr = e.stderr?.toString("utf-8") ?? "";
|
|
351
|
-
output = stdout + (stderr ? "\n" + stderr : "");
|
|
352
|
-
}
|
|
353
|
-
}
|
|
489
|
+
const result = await runTestProcess(argv, command, cwd, currentAbortSignal());
|
|
490
|
+
const output = result.output;
|
|
491
|
+
const exitCode = result.exitCode;
|
|
354
492
|
let summary = {
|
|
355
493
|
tests: 0,
|
|
356
494
|
passed: 0,
|
|
@@ -389,6 +527,7 @@ Got: ${filter.slice(0, 60)}${filter.length > 60 ? "..." : ""}`;
|
|
|
389
527
|
}
|
|
390
528
|
}
|
|
391
529
|
}
|
|
530
|
+
if (exitCode !== 0 && summary.failures + summary.errors === 0) summary.errors = 1;
|
|
392
531
|
renderColorReport(summary, framework);
|
|
393
532
|
return formatReport(summary, framework, output, exitCode);
|
|
394
533
|
}
|
|
@@ -413,8 +552,78 @@ var runTestsTool = {
|
|
|
413
552
|
return executeTests(args);
|
|
414
553
|
}
|
|
415
554
|
};
|
|
555
|
+
var MAX_TEST_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
556
|
+
var activeTestProcesses = 0;
|
|
557
|
+
var activeTestsByOwner = /* @__PURE__ */ new Map();
|
|
558
|
+
async function runTestProcess(argv, command, cwd, signal) {
|
|
559
|
+
if (signal.aborted) throw new Error("Test run cancelled");
|
|
560
|
+
const owner = getExecutionConfigDir();
|
|
561
|
+
if ((activeTestsByOwner.get(owner) ?? 0) >= 2) throw new Error("Test runner capacity reached (2 per user).");
|
|
562
|
+
if (activeTestProcesses >= 4) throw new Error("Test runner capacity reached (4). Try again after a run finishes.");
|
|
563
|
+
activeTestProcesses++;
|
|
564
|
+
activeTestsByOwner.set(owner, (activeTestsByOwner.get(owner) ?? 0) + 1);
|
|
565
|
+
try {
|
|
566
|
+
return await new Promise((resolve, reject) => {
|
|
567
|
+
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"] });
|
|
568
|
+
const chunks = [];
|
|
569
|
+
let bytes = 0;
|
|
570
|
+
let stopped = "";
|
|
571
|
+
let settled = false;
|
|
572
|
+
const stop = (reason) => {
|
|
573
|
+
if (stopped) return;
|
|
574
|
+
stopped = reason;
|
|
575
|
+
killProcessTree(child, true);
|
|
576
|
+
};
|
|
577
|
+
const onAbort = () => stop("Test run cancelled");
|
|
578
|
+
const timer = setTimeout(() => stop("Test run timed out"), TEST_TIMEOUT);
|
|
579
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
580
|
+
if (signal.aborted) onAbort();
|
|
581
|
+
const append = (chunk) => {
|
|
582
|
+
const take = Math.min(chunk.length, MAX_TEST_OUTPUT_BYTES - bytes);
|
|
583
|
+
if (take > 0) chunks.push(chunk.subarray(0, take));
|
|
584
|
+
bytes += take;
|
|
585
|
+
if (bytes >= MAX_TEST_OUTPUT_BYTES) stop("Test output exceeded 4 MiB limit");
|
|
586
|
+
};
|
|
587
|
+
child.stdout?.on("data", append);
|
|
588
|
+
child.stderr?.on("data", append);
|
|
589
|
+
const clean = () => {
|
|
590
|
+
clearTimeout(timer);
|
|
591
|
+
signal.removeEventListener("abort", onAbort);
|
|
592
|
+
};
|
|
593
|
+
child.once("error", (error) => {
|
|
594
|
+
if (settled) return;
|
|
595
|
+
settled = true;
|
|
596
|
+
clean();
|
|
597
|
+
reject(error);
|
|
598
|
+
});
|
|
599
|
+
child.once("close", (code) => {
|
|
600
|
+
if (settled) return;
|
|
601
|
+
settled = true;
|
|
602
|
+
clean();
|
|
603
|
+
resolve({ output: Buffer.concat(chunks).toString("utf8") + (stopped ? "\n" + stopped : ""), exitCode: stopped ? 1 : code ?? 1 });
|
|
604
|
+
});
|
|
605
|
+
});
|
|
606
|
+
} finally {
|
|
607
|
+
activeTestProcesses--;
|
|
608
|
+
const remaining = (activeTestsByOwner.get(owner) ?? 1) - 1;
|
|
609
|
+
if (remaining) activeTestsByOwner.set(owner, remaining);
|
|
610
|
+
else activeTestsByOwner.delete(owner);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
416
613
|
|
|
417
614
|
export {
|
|
615
|
+
IS_WINDOWS,
|
|
616
|
+
WIN_UTF8_PREAMBLE,
|
|
617
|
+
shellInvocation,
|
|
618
|
+
decodeWindowsBuffer,
|
|
619
|
+
recoverGbkMojibake,
|
|
620
|
+
looksLikeGbkMojibake,
|
|
621
|
+
killProcessTree,
|
|
622
|
+
currentAbortSignal,
|
|
623
|
+
isInterrupted,
|
|
624
|
+
requestInterrupt,
|
|
625
|
+
resetInterrupt,
|
|
418
626
|
executeTests,
|
|
419
|
-
runTestsTool
|
|
627
|
+
runTestsTool,
|
|
628
|
+
runTestProcess
|
|
420
629
|
};
|
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
} from "./chunk-HOSJZMQS.js";
|
|
9
9
|
import {
|
|
10
10
|
atomicWriteFileSync
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BMLQPSHP.js";
|
|
12
12
|
import {
|
|
13
13
|
MEMORY_FILE_NAME,
|
|
14
14
|
MEMORY_MAX_CHARS,
|
|
15
15
|
MEMORY_STORE_FILE_NAME
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2MNUMLN4.js";
|
|
17
17
|
|
|
18
18
|
// src/memory/persistent-memory.ts
|
|
19
19
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
@@ -8,12 +8,14 @@ import {
|
|
|
8
8
|
} from "./chunk-FSC6KEWU.js";
|
|
9
9
|
import {
|
|
10
10
|
atomicWriteFileSync
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-2XMUCC42.js";
|
|
12
|
+
import {
|
|
13
|
+
getExecutionConfigDir
|
|
14
|
+
} from "./chunk-QMFMST2T.js";
|
|
12
15
|
|
|
13
16
|
// src/memory/chat-index.ts
|
|
14
17
|
import fs from "fs";
|
|
15
18
|
import path from "path";
|
|
16
|
-
import os from "os";
|
|
17
19
|
import crypto from "crypto";
|
|
18
20
|
|
|
19
21
|
// src/session/session-index.ts
|
|
@@ -311,7 +313,7 @@ var VEC_MAGIC = 1094929750;
|
|
|
311
313
|
var VEC_VERSION = 1;
|
|
312
314
|
var VEC_HEADER_BYTES = 16;
|
|
313
315
|
function memoryIndexDir() {
|
|
314
|
-
return path.join(
|
|
316
|
+
return path.join(getExecutionConfigDir(), MEMORY_DIR_NAME);
|
|
315
317
|
}
|
|
316
318
|
function chunksPath() {
|
|
317
319
|
return path.join(memoryIndexDir(), CHUNKS_FILE);
|
|
@@ -320,7 +322,7 @@ function vectorsPath() {
|
|
|
320
322
|
return path.join(memoryIndexDir(), VECTORS_FILE);
|
|
321
323
|
}
|
|
322
324
|
function historyDir() {
|
|
323
|
-
return path.join(
|
|
325
|
+
return path.join(getExecutionConfigDir(), "history");
|
|
324
326
|
}
|
|
325
327
|
var MAX_CHUNK_CHARS = 1200;
|
|
326
328
|
var MIN_CHUNK_CHARS = 40;
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
loadVectorStore,
|
|
3
3
|
saveVectorStore,
|
|
4
4
|
searchVectorStore
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3YVNDYOY.js";
|
|
6
6
|
import {
|
|
7
7
|
EMBEDDING_DIM,
|
|
8
8
|
embed,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
loadIndex,
|
|
13
13
|
symbolFingerprint
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-W2UOVGRC.js";
|
|
15
15
|
|
|
16
16
|
// src/symbols/semantic.ts
|
|
17
17
|
function pathTokens(absFile, root) {
|
|
@@ -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
|
+
};
|
|
@@ -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"
|
|
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) {
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/web/access.ts
|
|
4
|
+
import { randomBytes, timingSafeEqual } from "crypto";
|
|
5
|
+
import { networkInterfaces } from "os";
|
|
6
|
+
function equalToken(a, b) {
|
|
7
|
+
if (typeof a !== "string" || a.length > 4096) return false;
|
|
8
|
+
const left = Buffer.from(a), right = Buffer.from(b);
|
|
9
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
10
|
+
}
|
|
11
|
+
var WebAccess = class {
|
|
12
|
+
constructor(host, externalOrigin) {
|
|
13
|
+
this.externalOrigin = externalOrigin;
|
|
14
|
+
if (!["0.0.0.0", "::"].includes(host)) this.hosts.add(host.includes(":") ? `[${host}]` : host.toLowerCase());
|
|
15
|
+
else for (const interfaces of Object.values(networkInterfaces())) for (const entry of interfaces ?? []) {
|
|
16
|
+
this.hosts.add(entry.address.includes(":") ? `[${entry.address}]` : entry.address);
|
|
17
|
+
}
|
|
18
|
+
if (externalOrigin && new URL(externalOrigin).origin !== externalOrigin) throw new Error("External origin must be an exact http(s) origin");
|
|
19
|
+
if (externalOrigin && !/^https?:\/\//.test(externalOrigin)) throw new Error("External origin must use HTTP(S)");
|
|
20
|
+
}
|
|
21
|
+
externalOrigin;
|
|
22
|
+
localToken = randomBytes(32).toString("base64url");
|
|
23
|
+
hosts = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
24
|
+
accepts(req) {
|
|
25
|
+
const host = req.headers.host;
|
|
26
|
+
if (!host) return false;
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(`http://${host}`);
|
|
29
|
+
const internal = this.hosts.has(url.hostname.toLowerCase()) && Number(url.port || 80) === req.socket.localPort;
|
|
30
|
+
const external = this.externalOrigin && new URL(this.externalOrigin).host === host;
|
|
31
|
+
if (!internal && !external) return false;
|
|
32
|
+
const origin = req.headers.origin;
|
|
33
|
+
return !origin || origin === (external ? this.externalOrigin : `http://${host}`);
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var AuthRateLimiter = class {
|
|
40
|
+
ips = /* @__PURE__ */ new Map();
|
|
41
|
+
start = 0;
|
|
42
|
+
count = 0;
|
|
43
|
+
take(ip) {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
if (now - this.start >= 6e4) {
|
|
46
|
+
this.start = now;
|
|
47
|
+
this.count = 0;
|
|
48
|
+
}
|
|
49
|
+
if (++this.count > 120) return false;
|
|
50
|
+
for (const [key, value] of this.ips) if (now - value.start >= 6e4) this.ips.delete(key);
|
|
51
|
+
let bucket = this.ips.get(ip);
|
|
52
|
+
if (!bucket) {
|
|
53
|
+
if (this.ips.size >= 2048) return false;
|
|
54
|
+
bucket = { start: now, count: 0 };
|
|
55
|
+
this.ips.set(ip, bucket);
|
|
56
|
+
}
|
|
57
|
+
return ++bucket.count <= 30;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
equalToken,
|
|
63
|
+
WebAccess,
|
|
64
|
+
AuthRateLimiter
|
|
65
|
+
};
|