jinzd-ai-cli 0.4.91 → 0.4.93
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/dist/{batch-KZQHKPE5.js → batch-NAPWSE3V.js} +2 -2
- package/dist/{chunk-MYQANQ6F.js → chunk-3CU4NKPD.js} +9 -6
- package/dist/{chunk-US6MQO6W.js → chunk-3SRJBTIY.js} +3 -1
- package/dist/{chunk-Z2V6EYPQ.js → chunk-5D7LG2TY.js} +174 -44
- package/dist/{chunk-IGNYJUZU.js → chunk-OL6TUUBE.js} +1 -1
- package/dist/{chunk-AKCXRW2Q.js → chunk-WR4M4TXV.js} +1 -1
- package/dist/{chunk-XQHCCV3A.js → chunk-ZTBXPEG2.js} +1 -1
- package/dist/electron-server.js +174 -56
- package/dist/{hub-A66CLTFF.js → hub-LJAXL2LO.js} +1 -1
- package/dist/index.js +27 -11
- package/dist/{run-tests-KHJ6YCPH.js → run-tests-LKZFHPQK.js} +1 -1
- package/dist/{run-tests-MKBVRMBA.js → run-tests-RO24F4Z2.js} +2 -2
- package/dist/{server-J7BPHI7D.js → server-YHECGYRX.js} +7 -7
- package/dist/{server-B6U5GMZ7.js → server-YXETATAI.js} +3 -3
- package/dist/{task-orchestrator-JB5TZNBK.js → task-orchestrator-3LZHLZCG.js} +3 -3
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3SRJBTIY.js";
|
|
5
5
|
import "./chunk-2ZD3YTVM.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-WR4M4TXV.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-
|
|
5
|
+
} from "./chunk-5D7LG2TY.js";
|
|
6
6
|
import {
|
|
7
7
|
AuthError,
|
|
8
8
|
ProviderError,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
MCP_PROTOCOL_VERSION,
|
|
22
22
|
MCP_TOOL_PREFIX,
|
|
23
23
|
VERSION
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-WR4M4TXV.js";
|
|
25
25
|
|
|
26
26
|
// src/providers/claude.ts
|
|
27
27
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -3556,13 +3556,16 @@ function parseSkillFile(filePath) {
|
|
|
3556
3556
|
}
|
|
3557
3557
|
|
|
3558
3558
|
// src/skills/manager.ts
|
|
3559
|
-
var
|
|
3559
|
+
var SKILL_CONTENT_WARN_CHARS_DEFAULT = 1e4;
|
|
3560
3560
|
var SkillManager = class {
|
|
3561
3561
|
skills = /* @__PURE__ */ new Map();
|
|
3562
3562
|
activeSkill = null;
|
|
3563
3563
|
skillsDir;
|
|
3564
|
-
|
|
3564
|
+
/** 超大技能文件警告阈值,由调用方从 config 传入;0 = 静默,undefined = 用默认 10000 */
|
|
3565
|
+
warnThreshold;
|
|
3566
|
+
constructor(skillsDir, warnThreshold) {
|
|
3565
3567
|
this.skillsDir = skillsDir;
|
|
3568
|
+
this.warnThreshold = warnThreshold ?? SKILL_CONTENT_WARN_CHARS_DEFAULT;
|
|
3566
3569
|
}
|
|
3567
3570
|
/** 发现并加载 skillsDir 下所有 .md 文件,返回加载数量 */
|
|
3568
3571
|
loadSkills() {
|
|
@@ -3607,9 +3610,9 @@ var SkillManager = class {
|
|
|
3607
3610
|
skill.meta.name = entry;
|
|
3608
3611
|
}
|
|
3609
3612
|
this.skills.set(skill.meta.name, skill);
|
|
3610
|
-
if (skill.content.length >
|
|
3613
|
+
if (this.warnThreshold > 0 && skill.content.length > this.warnThreshold) {
|
|
3611
3614
|
process.stderr.write(
|
|
3612
|
-
`\u26A0 Skill '${skill.meta.name}' is ${skill.content.length} chars (>${
|
|
3615
|
+
`\u26A0 Skill '${skill.meta.name}' is ${skill.content.length} chars (>${this.warnThreshold}). Only consumed when activated via /skill. Adjust with: /config set ui.skillSizeWarn <n|0>
|
|
3613
3616
|
`
|
|
3614
3617
|
);
|
|
3615
3618
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
CONFIG_FILE_NAME,
|
|
9
9
|
HISTORY_DIR_NAME,
|
|
10
10
|
PLUGINS_DIR_NAME
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WR4M4TXV.js";
|
|
12
12
|
|
|
13
13
|
// src/config/config-manager.ts
|
|
14
14
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -95,6 +95,8 @@ var ConfigSchema = z.object({
|
|
|
95
95
|
notificationThreshold: z.number().default(1e4),
|
|
96
96
|
/** 终端输出折行宽度。0 = 自动(使用终端宽度),>0 = 固定列宽。默认 0 */
|
|
97
97
|
wordWrap: z.number().int().min(0).default(0),
|
|
98
|
+
/** Skill 文件过大警告阈值(字符数)。超过此值的 skill 在启动加载时打印警告。0 = 静默。默认 10000 */
|
|
99
|
+
skillSizeWarn: z.number().int().min(0).default(1e4),
|
|
98
100
|
/** 颜色主题:'dark'(默认)| 'light' | 'custom' */
|
|
99
101
|
theme: z.enum(["dark", "light", "custom"]).default("dark"),
|
|
100
102
|
/** 自定义颜色覆盖(仅在 theme='custom' 时生效)。值为 chalk 颜色名或 '#hex',支持 'bold.cyan' 组合 */
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "./chunk-6VRJGH25.js";
|
|
24
24
|
import {
|
|
25
25
|
runTestsTool
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-OL6TUUBE.js";
|
|
27
27
|
import {
|
|
28
28
|
CONFIG_DIR_NAME,
|
|
29
29
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
SUBAGENT_ALLOWED_TOOLS,
|
|
32
32
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
33
33
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-WR4M4TXV.js";
|
|
35
35
|
|
|
36
36
|
// src/tools/types.ts
|
|
37
37
|
function isFileWriteTool(name) {
|
|
@@ -83,7 +83,7 @@ function schemaToJsonSchema(schema) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// src/tools/builtin/bash.ts
|
|
86
|
-
import {
|
|
86
|
+
import { spawn } from "child_process";
|
|
87
87
|
import { existsSync as existsSync2, readdirSync, statSync } from "fs";
|
|
88
88
|
import { platform } from "os";
|
|
89
89
|
import { resolve } from "path";
|
|
@@ -203,6 +203,26 @@ var UndoStack = class {
|
|
|
203
203
|
};
|
|
204
204
|
var undoStack = new UndoStack();
|
|
205
205
|
|
|
206
|
+
// src/core/interrupt.ts
|
|
207
|
+
var controller = new AbortController();
|
|
208
|
+
var interrupted = false;
|
|
209
|
+
function currentAbortSignal() {
|
|
210
|
+
return controller.signal;
|
|
211
|
+
}
|
|
212
|
+
function isInterrupted() {
|
|
213
|
+
return interrupted;
|
|
214
|
+
}
|
|
215
|
+
function requestInterrupt() {
|
|
216
|
+
interrupted = true;
|
|
217
|
+
if (!controller.signal.aborted) {
|
|
218
|
+
controller.abort(new DOMException("User interrupted (Ctrl+C)", "AbortError"));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function resetInterrupt() {
|
|
222
|
+
controller = new AbortController();
|
|
223
|
+
interrupted = false;
|
|
224
|
+
}
|
|
225
|
+
|
|
206
226
|
// src/tools/builtin/bash.ts
|
|
207
227
|
var IS_WINDOWS = platform() === "win32";
|
|
208
228
|
var SHELL = IS_WINDOWS ? "powershell.exe" : process.env["SHELL"] ?? "/bin/bash";
|
|
@@ -285,21 +305,40 @@ Important rules:
|
|
|
285
305
|
parsedTargetsBefore.set(t, existsSync2(t));
|
|
286
306
|
}
|
|
287
307
|
try {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
308
|
+
const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
|
|
309
|
+
actualCommand,
|
|
310
|
+
{
|
|
311
|
+
timeout,
|
|
312
|
+
cwd: effectiveCwd,
|
|
313
|
+
env: {
|
|
314
|
+
...process.env,
|
|
315
|
+
PYTHONUTF8: "1",
|
|
316
|
+
PYTHONIOENCODING: "utf-8"
|
|
317
|
+
}
|
|
298
318
|
}
|
|
299
|
-
|
|
319
|
+
);
|
|
320
|
+
if (aborted) {
|
|
321
|
+
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
322
|
+
throw new ToolError(
|
|
323
|
+
"bash",
|
|
324
|
+
`Command interrupted by user (Ctrl+C).
|
|
325
|
+
|
|
326
|
+
[The user pressed Ctrl+C while this command was running. Stop the current task, summarize what was done so far, and wait for the user's next instruction. Do NOT retry this command or continue with further tool calls unless explicitly asked.]`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
if (status !== 0 || timedOut) {
|
|
330
|
+
throw {
|
|
331
|
+
status,
|
|
332
|
+
signal,
|
|
333
|
+
code: timedOut ? "ETIMEDOUT" : void 0,
|
|
334
|
+
stdout,
|
|
335
|
+
stderr,
|
|
336
|
+
message: timedOut ? "ETIMEDOUT" : `exit ${status}`
|
|
337
|
+
};
|
|
338
|
+
}
|
|
300
339
|
updateCwdFromCommand(command, effectiveCwd);
|
|
301
340
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
302
|
-
const result = IS_WINDOWS && Buffer.isBuffer(
|
|
341
|
+
const result = IS_WINDOWS && Buffer.isBuffer(stdout) ? stdout.toString("utf-8") : stdout;
|
|
303
342
|
return result || "(command completed with no output)";
|
|
304
343
|
} catch (err) {
|
|
305
344
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
@@ -419,6 +458,84 @@ function pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, cwd) {
|
|
|
419
458
|
}
|
|
420
459
|
}
|
|
421
460
|
}
|
|
461
|
+
function runShell(command, opts) {
|
|
462
|
+
return new Promise((resolvePromise) => {
|
|
463
|
+
const shellArgs = IS_WINDOWS ? ["-NoProfile", "-NonInteractive", "-Command", command] : ["-c", command];
|
|
464
|
+
const child = spawn(SHELL, shellArgs, {
|
|
465
|
+
cwd: opts.cwd,
|
|
466
|
+
env: opts.env,
|
|
467
|
+
windowsHide: true,
|
|
468
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
469
|
+
});
|
|
470
|
+
const stdoutChunks = [];
|
|
471
|
+
const stderrChunks = [];
|
|
472
|
+
let timedOut = false;
|
|
473
|
+
let aborted = false;
|
|
474
|
+
let settled = false;
|
|
475
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
476
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
477
|
+
const timeoutTimer = setTimeout(() => {
|
|
478
|
+
timedOut = true;
|
|
479
|
+
killChild(child);
|
|
480
|
+
}, opts.timeout);
|
|
481
|
+
const signal = currentAbortSignal();
|
|
482
|
+
const onAbort = () => {
|
|
483
|
+
aborted = true;
|
|
484
|
+
killChild(child);
|
|
485
|
+
};
|
|
486
|
+
if (signal.aborted) {
|
|
487
|
+
onAbort();
|
|
488
|
+
} else {
|
|
489
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
490
|
+
}
|
|
491
|
+
const cleanup = () => {
|
|
492
|
+
clearTimeout(timeoutTimer);
|
|
493
|
+
signal.removeEventListener("abort", onAbort);
|
|
494
|
+
};
|
|
495
|
+
child.on("error", (err) => {
|
|
496
|
+
if (settled) return;
|
|
497
|
+
settled = true;
|
|
498
|
+
cleanup();
|
|
499
|
+
stderrChunks.push(Buffer.from(String(err.message ?? err)));
|
|
500
|
+
resolvePromise({
|
|
501
|
+
stdout: Buffer.concat(stdoutChunks),
|
|
502
|
+
stderr: Buffer.concat(stderrChunks),
|
|
503
|
+
status: null,
|
|
504
|
+
signal: null,
|
|
505
|
+
timedOut,
|
|
506
|
+
aborted
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
child.on("close", (code, sig) => {
|
|
510
|
+
if (settled) return;
|
|
511
|
+
settled = true;
|
|
512
|
+
cleanup();
|
|
513
|
+
resolvePromise({
|
|
514
|
+
stdout: Buffer.concat(stdoutChunks),
|
|
515
|
+
stderr: Buffer.concat(stderrChunks),
|
|
516
|
+
status: code,
|
|
517
|
+
signal: sig,
|
|
518
|
+
timedOut,
|
|
519
|
+
aborted
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
function killChild(child) {
|
|
525
|
+
if (child.killed || child.exitCode !== null) return;
|
|
526
|
+
try {
|
|
527
|
+
child.kill("SIGTERM");
|
|
528
|
+
} catch {
|
|
529
|
+
}
|
|
530
|
+
setTimeout(() => {
|
|
531
|
+
if (!child.killed && child.exitCode === null) {
|
|
532
|
+
try {
|
|
533
|
+
child.kill("SIGKILL");
|
|
534
|
+
} catch {
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}, 500).unref();
|
|
538
|
+
}
|
|
422
539
|
function updateCwdFromCommand(command, baseCwd) {
|
|
423
540
|
const cdMatches = [...command.matchAll(/(?:^|[;&|])\s*cd\s+(['"]?)([^\s;&|'"]+)\1/g)];
|
|
424
541
|
if (cdMatches.length === 0) return;
|
|
@@ -1012,7 +1129,7 @@ function simpleDiff(oldLines, newLines) {
|
|
|
1012
1129
|
}
|
|
1013
1130
|
|
|
1014
1131
|
// src/tools/hooks.ts
|
|
1015
|
-
import { execSync
|
|
1132
|
+
import { execSync } from "child_process";
|
|
1016
1133
|
function shellEscape(value) {
|
|
1017
1134
|
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
1018
1135
|
}
|
|
@@ -1024,7 +1141,7 @@ function runHook(template, vars) {
|
|
|
1024
1141
|
cmd = cmd.replace(/\{args\}/g, shellEscape(vars.args ?? ""));
|
|
1025
1142
|
cmd = cmd.replace(/\{status\}/g, shellEscape(vars.status ?? ""));
|
|
1026
1143
|
try {
|
|
1027
|
-
|
|
1144
|
+
execSync(cmd, {
|
|
1028
1145
|
timeout: 5e3,
|
|
1029
1146
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1030
1147
|
encoding: "utf-8"
|
|
@@ -1247,6 +1364,11 @@ var ToolExecutor = class {
|
|
|
1247
1364
|
* 防止用户输入 "y"+Enter 被同时触发 once('line') 和主循环 on('line')。
|
|
1248
1365
|
*/
|
|
1249
1366
|
confirming = false;
|
|
1367
|
+
/**
|
|
1368
|
+
* Tool 执行进行中标志(executeAll 的生命周期)。
|
|
1369
|
+
* repl.ts 的 SIGINT handler 在此为 true 时触发全局 interrupt(而不是退出程序)。
|
|
1370
|
+
*/
|
|
1371
|
+
running = false;
|
|
1250
1372
|
/** 在 confirm 期间用户输入的 slash 命令,由 repl.ts 主循环消费 */
|
|
1251
1373
|
pendingSlashCommand = null;
|
|
1252
1374
|
/** confirm() 的取消回调,由 SIGINT handler 调用 */
|
|
@@ -1381,25 +1503,30 @@ var ToolExecutor = class {
|
|
|
1381
1503
|
}
|
|
1382
1504
|
}
|
|
1383
1505
|
async executeAll(calls) {
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
const { idx, call } = phase.fileWriteCalls[0];
|
|
1392
|
-
results[idx] = await this.execute(call);
|
|
1393
|
-
} else if (phase.fileWriteCalls.length >= 2) {
|
|
1394
|
-
const batchResults = await this.executeBatchFileWrites(phase.fileWriteCalls.map((f) => f.call));
|
|
1395
|
-
for (let i = 0; i < phase.fileWriteCalls.length; i++) {
|
|
1396
|
-
results[phase.fileWriteCalls[i].idx] = batchResults[i];
|
|
1506
|
+
this.running = true;
|
|
1507
|
+
try {
|
|
1508
|
+
const phase = groupCallsByPhase(calls);
|
|
1509
|
+
const results = new Array(calls.length);
|
|
1510
|
+
const elapsed = await runSafePhases(phase, (c) => this.execute(c), results, "executor");
|
|
1511
|
+
if (phase.safeParallel.length >= 2) {
|
|
1512
|
+
console.log(theme.dim(` \u26A1 ${phase.safeParallel.length} tools executed in parallel (${elapsed}ms)`));
|
|
1397
1513
|
}
|
|
1514
|
+
if (phase.fileWriteCalls.length === 1) {
|
|
1515
|
+
const { idx, call } = phase.fileWriteCalls[0];
|
|
1516
|
+
results[idx] = await this.execute(call);
|
|
1517
|
+
} else if (phase.fileWriteCalls.length >= 2) {
|
|
1518
|
+
const batchResults = await this.executeBatchFileWrites(phase.fileWriteCalls.map((f) => f.call));
|
|
1519
|
+
for (let i = 0; i < phase.fileWriteCalls.length; i++) {
|
|
1520
|
+
results[phase.fileWriteCalls[i].idx] = batchResults[i];
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
for (const { idx, call } of phase.otherCalls) {
|
|
1524
|
+
results[idx] = await this.execute(call);
|
|
1525
|
+
}
|
|
1526
|
+
return results;
|
|
1527
|
+
} finally {
|
|
1528
|
+
this.running = false;
|
|
1398
1529
|
}
|
|
1399
|
-
for (const { idx, call } of phase.otherCalls) {
|
|
1400
|
-
results[idx] = await this.execute(call);
|
|
1401
|
-
}
|
|
1402
|
-
return results;
|
|
1403
1530
|
}
|
|
1404
1531
|
/**
|
|
1405
1532
|
* 批量文件写入:展示所有文件的编号列表 + diff 预览,
|
|
@@ -2743,7 +2870,7 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
|
|
|
2743
2870
|
}
|
|
2744
2871
|
|
|
2745
2872
|
// src/tools/builtin/run-interactive.ts
|
|
2746
|
-
import { spawn } from "child_process";
|
|
2873
|
+
import { spawn as spawn2 } from "child_process";
|
|
2747
2874
|
import { platform as platform2 } from "os";
|
|
2748
2875
|
var IS_WINDOWS2 = platform2() === "win32";
|
|
2749
2876
|
var runInteractiveTool = {
|
|
@@ -2807,7 +2934,7 @@ var runInteractiveTool = {
|
|
|
2807
2934
|
};
|
|
2808
2935
|
const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
|
|
2809
2936
|
return new Promise((resolve4) => {
|
|
2810
|
-
const child =
|
|
2937
|
+
const child = spawn2(executable, cmdArgs.map(String), {
|
|
2811
2938
|
cwd: process.cwd(),
|
|
2812
2939
|
env,
|
|
2813
2940
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -2977,8 +3104,8 @@ var webFetchTool = {
|
|
|
2977
3104
|
if (e.message.startsWith("Blocked:")) throw e;
|
|
2978
3105
|
throw new NetworkError(`Invalid URL: "${url}"`);
|
|
2979
3106
|
}
|
|
2980
|
-
const
|
|
2981
|
-
const timeoutId = setTimeout(() =>
|
|
3107
|
+
const controller2 = new AbortController();
|
|
3108
|
+
const timeoutId = setTimeout(() => controller2.abort(), 2e4);
|
|
2982
3109
|
let rawHtml;
|
|
2983
3110
|
let finalUrl;
|
|
2984
3111
|
let contentType;
|
|
@@ -2998,7 +3125,7 @@ var webFetchTool = {
|
|
|
2998
3125
|
}
|
|
2999
3126
|
await resolveAndCheck(parsedHop.hostname);
|
|
3000
3127
|
const r = await fetch(currentUrl, {
|
|
3001
|
-
signal:
|
|
3128
|
+
signal: controller2.signal,
|
|
3002
3129
|
headers: FETCH_HEADERS,
|
|
3003
3130
|
redirect: "manual"
|
|
3004
3131
|
// 手动控制重定向
|
|
@@ -3349,15 +3476,15 @@ var googleSearchTool = {
|
|
|
3349
3476
|
url.searchParams.set("cx", cx);
|
|
3350
3477
|
url.searchParams.set("q", query);
|
|
3351
3478
|
url.searchParams.set("num", String(numResults));
|
|
3352
|
-
const
|
|
3353
|
-
const timeout = setTimeout(() =>
|
|
3479
|
+
const controller2 = new AbortController();
|
|
3480
|
+
const timeout = setTimeout(() => controller2.abort(), REQUEST_TIMEOUT_MS);
|
|
3354
3481
|
try {
|
|
3355
3482
|
const response = await fetch(url.toString(), {
|
|
3356
3483
|
method: "GET",
|
|
3357
3484
|
headers: {
|
|
3358
3485
|
"Accept": "application/json"
|
|
3359
3486
|
},
|
|
3360
|
-
signal:
|
|
3487
|
+
signal: controller2.signal
|
|
3361
3488
|
});
|
|
3362
3489
|
if (!response.ok) {
|
|
3363
3490
|
const errorBody = await response.text().catch(() => "");
|
|
@@ -3741,7 +3868,7 @@ var spawnAgentTool = {
|
|
|
3741
3868
|
};
|
|
3742
3869
|
|
|
3743
3870
|
// src/tools/builtin/task-manager.ts
|
|
3744
|
-
import { spawn as
|
|
3871
|
+
import { spawn as spawn3 } from "child_process";
|
|
3745
3872
|
import { randomUUID } from "crypto";
|
|
3746
3873
|
import { platform as platform3 } from "os";
|
|
3747
3874
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
@@ -3766,7 +3893,7 @@ function createTask(command, description) {
|
|
|
3766
3893
|
const isWin = platform3() === "win32";
|
|
3767
3894
|
const shell = isWin ? "cmd" : "sh";
|
|
3768
3895
|
const shellFlag = isWin ? "/c" : "-c";
|
|
3769
|
-
const proc =
|
|
3896
|
+
const proc = spawn3(shell, [shellFlag, command], {
|
|
3770
3897
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3771
3898
|
detached: false,
|
|
3772
3899
|
env: { ...process.env, PYTHONUTF8: "1" }
|
|
@@ -4894,6 +5021,9 @@ export {
|
|
|
4894
5021
|
theme,
|
|
4895
5022
|
undoStack,
|
|
4896
5023
|
renderDiff,
|
|
5024
|
+
isInterrupted,
|
|
5025
|
+
requestInterrupt,
|
|
5026
|
+
resetInterrupt,
|
|
4897
5027
|
rlInternal,
|
|
4898
5028
|
groupCallsByPhase,
|
|
4899
5029
|
runSafePhases,
|
package/dist/electron-server.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
VERSION,
|
|
37
37
|
buildUserIdentityPrompt,
|
|
38
38
|
runTestsTool
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-ZTBXPEG2.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -145,6 +145,8 @@ var ConfigSchema = z.object({
|
|
|
145
145
|
notificationThreshold: z.number().default(1e4),
|
|
146
146
|
/** 终端输出折行宽度。0 = 自动(使用终端宽度),>0 = 固定列宽。默认 0 */
|
|
147
147
|
wordWrap: z.number().int().min(0).default(0),
|
|
148
|
+
/** Skill 文件过大警告阈值(字符数)。超过此值的 skill 在启动加载时打印警告。0 = 静默。默认 10000 */
|
|
149
|
+
skillSizeWarn: z.number().int().min(0).default(1e4),
|
|
148
150
|
/** 颜色主题:'dark'(默认)| 'light' | 'custom' */
|
|
149
151
|
theme: z.enum(["dark", "light", "custom"]).default("dark"),
|
|
150
152
|
/** 自定义颜色覆盖(仅在 theme='custom' 时生效)。值为 chalk 颜色名或 '#hex',支持 'bold.cyan' 组合 */
|
|
@@ -3304,7 +3306,7 @@ var SessionManager = class {
|
|
|
3304
3306
|
};
|
|
3305
3307
|
|
|
3306
3308
|
// src/tools/builtin/bash.ts
|
|
3307
|
-
import {
|
|
3309
|
+
import { spawn } from "child_process";
|
|
3308
3310
|
import { existsSync as existsSync4, readdirSync as readdirSync2, statSync } from "fs";
|
|
3309
3311
|
import { platform } from "os";
|
|
3310
3312
|
import { resolve } from "path";
|
|
@@ -3424,6 +3426,12 @@ var UndoStack = class {
|
|
|
3424
3426
|
};
|
|
3425
3427
|
var undoStack = new UndoStack();
|
|
3426
3428
|
|
|
3429
|
+
// src/core/interrupt.ts
|
|
3430
|
+
var controller = new AbortController();
|
|
3431
|
+
function currentAbortSignal() {
|
|
3432
|
+
return controller.signal;
|
|
3433
|
+
}
|
|
3434
|
+
|
|
3427
3435
|
// src/tools/builtin/bash.ts
|
|
3428
3436
|
var IS_WINDOWS = platform() === "win32";
|
|
3429
3437
|
var SHELL = IS_WINDOWS ? "powershell.exe" : process.env["SHELL"] ?? "/bin/bash";
|
|
@@ -3506,21 +3514,40 @@ Important rules:
|
|
|
3506
3514
|
parsedTargetsBefore.set(t, existsSync4(t));
|
|
3507
3515
|
}
|
|
3508
3516
|
try {
|
|
3509
|
-
const
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3517
|
+
const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
|
|
3518
|
+
actualCommand,
|
|
3519
|
+
{
|
|
3520
|
+
timeout,
|
|
3521
|
+
cwd: effectiveCwd,
|
|
3522
|
+
env: {
|
|
3523
|
+
...process.env,
|
|
3524
|
+
PYTHONUTF8: "1",
|
|
3525
|
+
PYTHONIOENCODING: "utf-8"
|
|
3526
|
+
}
|
|
3519
3527
|
}
|
|
3520
|
-
|
|
3528
|
+
);
|
|
3529
|
+
if (aborted) {
|
|
3530
|
+
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
3531
|
+
throw new ToolError(
|
|
3532
|
+
"bash",
|
|
3533
|
+
`Command interrupted by user (Ctrl+C).
|
|
3534
|
+
|
|
3535
|
+
[The user pressed Ctrl+C while this command was running. Stop the current task, summarize what was done so far, and wait for the user's next instruction. Do NOT retry this command or continue with further tool calls unless explicitly asked.]`
|
|
3536
|
+
);
|
|
3537
|
+
}
|
|
3538
|
+
if (status !== 0 || timedOut) {
|
|
3539
|
+
throw {
|
|
3540
|
+
status,
|
|
3541
|
+
signal,
|
|
3542
|
+
code: timedOut ? "ETIMEDOUT" : void 0,
|
|
3543
|
+
stdout,
|
|
3544
|
+
stderr,
|
|
3545
|
+
message: timedOut ? "ETIMEDOUT" : `exit ${status}`
|
|
3546
|
+
};
|
|
3547
|
+
}
|
|
3521
3548
|
updateCwdFromCommand(command, effectiveCwd);
|
|
3522
3549
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
3523
|
-
const result = IS_WINDOWS && Buffer.isBuffer(
|
|
3550
|
+
const result = IS_WINDOWS && Buffer.isBuffer(stdout) ? stdout.toString("utf-8") : stdout;
|
|
3524
3551
|
return result || "(command completed with no output)";
|
|
3525
3552
|
} catch (err) {
|
|
3526
3553
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
@@ -3640,6 +3667,84 @@ function pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, cwd) {
|
|
|
3640
3667
|
}
|
|
3641
3668
|
}
|
|
3642
3669
|
}
|
|
3670
|
+
function runShell(command, opts) {
|
|
3671
|
+
return new Promise((resolvePromise) => {
|
|
3672
|
+
const shellArgs = IS_WINDOWS ? ["-NoProfile", "-NonInteractive", "-Command", command] : ["-c", command];
|
|
3673
|
+
const child = spawn(SHELL, shellArgs, {
|
|
3674
|
+
cwd: opts.cwd,
|
|
3675
|
+
env: opts.env,
|
|
3676
|
+
windowsHide: true,
|
|
3677
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
3678
|
+
});
|
|
3679
|
+
const stdoutChunks = [];
|
|
3680
|
+
const stderrChunks = [];
|
|
3681
|
+
let timedOut = false;
|
|
3682
|
+
let aborted = false;
|
|
3683
|
+
let settled = false;
|
|
3684
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
3685
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
3686
|
+
const timeoutTimer = setTimeout(() => {
|
|
3687
|
+
timedOut = true;
|
|
3688
|
+
killChild(child);
|
|
3689
|
+
}, opts.timeout);
|
|
3690
|
+
const signal = currentAbortSignal();
|
|
3691
|
+
const onAbort = () => {
|
|
3692
|
+
aborted = true;
|
|
3693
|
+
killChild(child);
|
|
3694
|
+
};
|
|
3695
|
+
if (signal.aborted) {
|
|
3696
|
+
onAbort();
|
|
3697
|
+
} else {
|
|
3698
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3699
|
+
}
|
|
3700
|
+
const cleanup = () => {
|
|
3701
|
+
clearTimeout(timeoutTimer);
|
|
3702
|
+
signal.removeEventListener("abort", onAbort);
|
|
3703
|
+
};
|
|
3704
|
+
child.on("error", (err) => {
|
|
3705
|
+
if (settled) return;
|
|
3706
|
+
settled = true;
|
|
3707
|
+
cleanup();
|
|
3708
|
+
stderrChunks.push(Buffer.from(String(err.message ?? err)));
|
|
3709
|
+
resolvePromise({
|
|
3710
|
+
stdout: Buffer.concat(stdoutChunks),
|
|
3711
|
+
stderr: Buffer.concat(stderrChunks),
|
|
3712
|
+
status: null,
|
|
3713
|
+
signal: null,
|
|
3714
|
+
timedOut,
|
|
3715
|
+
aborted
|
|
3716
|
+
});
|
|
3717
|
+
});
|
|
3718
|
+
child.on("close", (code, sig) => {
|
|
3719
|
+
if (settled) return;
|
|
3720
|
+
settled = true;
|
|
3721
|
+
cleanup();
|
|
3722
|
+
resolvePromise({
|
|
3723
|
+
stdout: Buffer.concat(stdoutChunks),
|
|
3724
|
+
stderr: Buffer.concat(stderrChunks),
|
|
3725
|
+
status: code,
|
|
3726
|
+
signal: sig,
|
|
3727
|
+
timedOut,
|
|
3728
|
+
aborted
|
|
3729
|
+
});
|
|
3730
|
+
});
|
|
3731
|
+
});
|
|
3732
|
+
}
|
|
3733
|
+
function killChild(child) {
|
|
3734
|
+
if (child.killed || child.exitCode !== null) return;
|
|
3735
|
+
try {
|
|
3736
|
+
child.kill("SIGTERM");
|
|
3737
|
+
} catch {
|
|
3738
|
+
}
|
|
3739
|
+
setTimeout(() => {
|
|
3740
|
+
if (!child.killed && child.exitCode === null) {
|
|
3741
|
+
try {
|
|
3742
|
+
child.kill("SIGKILL");
|
|
3743
|
+
} catch {
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
}, 500).unref();
|
|
3747
|
+
}
|
|
3643
3748
|
function updateCwdFromCommand(command, baseCwd) {
|
|
3644
3749
|
const cdMatches = [...command.matchAll(/(?:^|[;&|])\s*cd\s+(['"]?)([^\s;&|'"]+)\1/g)];
|
|
3645
3750
|
if (cdMatches.length === 0) return;
|
|
@@ -4233,7 +4338,7 @@ function simpleDiff(oldLines, newLines) {
|
|
|
4233
4338
|
}
|
|
4234
4339
|
|
|
4235
4340
|
// src/tools/hooks.ts
|
|
4236
|
-
import { execSync
|
|
4341
|
+
import { execSync } from "child_process";
|
|
4237
4342
|
function shellEscape(value) {
|
|
4238
4343
|
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
4239
4344
|
}
|
|
@@ -4245,7 +4350,7 @@ function runHook(template, vars) {
|
|
|
4245
4350
|
cmd = cmd.replace(/\{args\}/g, shellEscape(vars.args ?? ""));
|
|
4246
4351
|
cmd = cmd.replace(/\{status\}/g, shellEscape(vars.status ?? ""));
|
|
4247
4352
|
try {
|
|
4248
|
-
|
|
4353
|
+
execSync(cmd, {
|
|
4249
4354
|
timeout: 5e3,
|
|
4250
4355
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4251
4356
|
encoding: "utf-8"
|
|
@@ -4429,6 +4534,11 @@ var ToolExecutor = class {
|
|
|
4429
4534
|
* 防止用户输入 "y"+Enter 被同时触发 once('line') 和主循环 on('line')。
|
|
4430
4535
|
*/
|
|
4431
4536
|
confirming = false;
|
|
4537
|
+
/**
|
|
4538
|
+
* Tool 执行进行中标志(executeAll 的生命周期)。
|
|
4539
|
+
* repl.ts 的 SIGINT handler 在此为 true 时触发全局 interrupt(而不是退出程序)。
|
|
4540
|
+
*/
|
|
4541
|
+
running = false;
|
|
4432
4542
|
/** 在 confirm 期间用户输入的 slash 命令,由 repl.ts 主循环消费 */
|
|
4433
4543
|
pendingSlashCommand = null;
|
|
4434
4544
|
/** confirm() 的取消回调,由 SIGINT handler 调用 */
|
|
@@ -4563,25 +4673,30 @@ var ToolExecutor = class {
|
|
|
4563
4673
|
}
|
|
4564
4674
|
}
|
|
4565
4675
|
async executeAll(calls) {
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
const { idx, call } = phase.fileWriteCalls[0];
|
|
4574
|
-
results[idx] = await this.execute(call);
|
|
4575
|
-
} else if (phase.fileWriteCalls.length >= 2) {
|
|
4576
|
-
const batchResults = await this.executeBatchFileWrites(phase.fileWriteCalls.map((f) => f.call));
|
|
4577
|
-
for (let i = 0; i < phase.fileWriteCalls.length; i++) {
|
|
4578
|
-
results[phase.fileWriteCalls[i].idx] = batchResults[i];
|
|
4676
|
+
this.running = true;
|
|
4677
|
+
try {
|
|
4678
|
+
const phase = groupCallsByPhase(calls);
|
|
4679
|
+
const results = new Array(calls.length);
|
|
4680
|
+
const elapsed = await runSafePhases(phase, (c) => this.execute(c), results, "executor");
|
|
4681
|
+
if (phase.safeParallel.length >= 2) {
|
|
4682
|
+
console.log(theme.dim(` \u26A1 ${phase.safeParallel.length} tools executed in parallel (${elapsed}ms)`));
|
|
4579
4683
|
}
|
|
4684
|
+
if (phase.fileWriteCalls.length === 1) {
|
|
4685
|
+
const { idx, call } = phase.fileWriteCalls[0];
|
|
4686
|
+
results[idx] = await this.execute(call);
|
|
4687
|
+
} else if (phase.fileWriteCalls.length >= 2) {
|
|
4688
|
+
const batchResults = await this.executeBatchFileWrites(phase.fileWriteCalls.map((f) => f.call));
|
|
4689
|
+
for (let i = 0; i < phase.fileWriteCalls.length; i++) {
|
|
4690
|
+
results[phase.fileWriteCalls[i].idx] = batchResults[i];
|
|
4691
|
+
}
|
|
4692
|
+
}
|
|
4693
|
+
for (const { idx, call } of phase.otherCalls) {
|
|
4694
|
+
results[idx] = await this.execute(call);
|
|
4695
|
+
}
|
|
4696
|
+
return results;
|
|
4697
|
+
} finally {
|
|
4698
|
+
this.running = false;
|
|
4580
4699
|
}
|
|
4581
|
-
for (const { idx, call } of phase.otherCalls) {
|
|
4582
|
-
results[idx] = await this.execute(call);
|
|
4583
|
-
}
|
|
4584
|
-
return results;
|
|
4585
4700
|
}
|
|
4586
4701
|
/**
|
|
4587
4702
|
* 批量文件写入:展示所有文件的编号列表 + diff 预览,
|
|
@@ -5925,7 +6040,7 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
|
|
|
5925
6040
|
}
|
|
5926
6041
|
|
|
5927
6042
|
// src/tools/builtin/run-interactive.ts
|
|
5928
|
-
import { spawn } from "child_process";
|
|
6043
|
+
import { spawn as spawn2 } from "child_process";
|
|
5929
6044
|
import { platform as platform2 } from "os";
|
|
5930
6045
|
var IS_WINDOWS2 = platform2() === "win32";
|
|
5931
6046
|
var runInteractiveTool = {
|
|
@@ -5989,7 +6104,7 @@ var runInteractiveTool = {
|
|
|
5989
6104
|
};
|
|
5990
6105
|
const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
|
|
5991
6106
|
return new Promise((resolve6) => {
|
|
5992
|
-
const child =
|
|
6107
|
+
const child = spawn2(executable, cmdArgs.map(String), {
|
|
5993
6108
|
cwd: process.cwd(),
|
|
5994
6109
|
env,
|
|
5995
6110
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -6159,8 +6274,8 @@ var webFetchTool = {
|
|
|
6159
6274
|
if (e.message.startsWith("Blocked:")) throw e;
|
|
6160
6275
|
throw new NetworkError(`Invalid URL: "${url}"`);
|
|
6161
6276
|
}
|
|
6162
|
-
const
|
|
6163
|
-
const timeoutId = setTimeout(() =>
|
|
6277
|
+
const controller2 = new AbortController();
|
|
6278
|
+
const timeoutId = setTimeout(() => controller2.abort(), 2e4);
|
|
6164
6279
|
let rawHtml;
|
|
6165
6280
|
let finalUrl;
|
|
6166
6281
|
let contentType;
|
|
@@ -6180,7 +6295,7 @@ var webFetchTool = {
|
|
|
6180
6295
|
}
|
|
6181
6296
|
await resolveAndCheck(parsedHop.hostname);
|
|
6182
6297
|
const r = await fetch(currentUrl, {
|
|
6183
|
-
signal:
|
|
6298
|
+
signal: controller2.signal,
|
|
6184
6299
|
headers: FETCH_HEADERS,
|
|
6185
6300
|
redirect: "manual"
|
|
6186
6301
|
// 手动控制重定向
|
|
@@ -6531,15 +6646,15 @@ var googleSearchTool = {
|
|
|
6531
6646
|
url.searchParams.set("cx", cx);
|
|
6532
6647
|
url.searchParams.set("q", query);
|
|
6533
6648
|
url.searchParams.set("num", String(numResults));
|
|
6534
|
-
const
|
|
6535
|
-
const timeout = setTimeout(() =>
|
|
6649
|
+
const controller2 = new AbortController();
|
|
6650
|
+
const timeout = setTimeout(() => controller2.abort(), REQUEST_TIMEOUT_MS);
|
|
6536
6651
|
try {
|
|
6537
6652
|
const response = await fetch(url.toString(), {
|
|
6538
6653
|
method: "GET",
|
|
6539
6654
|
headers: {
|
|
6540
6655
|
"Accept": "application/json"
|
|
6541
6656
|
},
|
|
6542
|
-
signal:
|
|
6657
|
+
signal: controller2.signal
|
|
6543
6658
|
});
|
|
6544
6659
|
if (!response.ok) {
|
|
6545
6660
|
const errorBody = await response.text().catch(() => "");
|
|
@@ -6923,7 +7038,7 @@ var spawnAgentTool = {
|
|
|
6923
7038
|
};
|
|
6924
7039
|
|
|
6925
7040
|
// src/tools/builtin/task-manager.ts
|
|
6926
|
-
import { spawn as
|
|
7041
|
+
import { spawn as spawn3 } from "child_process";
|
|
6927
7042
|
import { randomUUID } from "crypto";
|
|
6928
7043
|
import { platform as platform3 } from "os";
|
|
6929
7044
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
@@ -6948,7 +7063,7 @@ function createTask(command, description) {
|
|
|
6948
7063
|
const isWin = platform3() === "win32";
|
|
6949
7064
|
const shell = isWin ? "cmd" : "sh";
|
|
6950
7065
|
const shellFlag = isWin ? "/c" : "-c";
|
|
6951
|
-
const proc =
|
|
7066
|
+
const proc = spawn3(shell, [shellFlag, command], {
|
|
6952
7067
|
stdio: ["ignore", "pipe", "pipe"],
|
|
6953
7068
|
detached: false,
|
|
6954
7069
|
env: { ...process.env, PYTHONUTF8: "1" }
|
|
@@ -8070,7 +8185,7 @@ var ToolRegistry = class {
|
|
|
8070
8185
|
};
|
|
8071
8186
|
|
|
8072
8187
|
// src/mcp/client.ts
|
|
8073
|
-
import { spawn as
|
|
8188
|
+
import { spawn as spawn4 } from "child_process";
|
|
8074
8189
|
var McpClient = class {
|
|
8075
8190
|
serverId;
|
|
8076
8191
|
config;
|
|
@@ -8108,7 +8223,7 @@ var McpClient = class {
|
|
|
8108
8223
|
async connect() {
|
|
8109
8224
|
const timeout = this.config.timeout ?? MCP_CONNECT_TIMEOUT;
|
|
8110
8225
|
try {
|
|
8111
|
-
this.process =
|
|
8226
|
+
this.process = spawn4(this.config.command, this.config.args ?? [], {
|
|
8112
8227
|
stdio: ["pipe", "pipe", "pipe"],
|
|
8113
8228
|
env: { ...process.env, ...this.config.env },
|
|
8114
8229
|
// Windows 上 npx 等是 .cmd 脚本,需要 shell 模式
|
|
@@ -8634,13 +8749,16 @@ function parseSkillFile(filePath) {
|
|
|
8634
8749
|
}
|
|
8635
8750
|
|
|
8636
8751
|
// src/skills/manager.ts
|
|
8637
|
-
var
|
|
8752
|
+
var SKILL_CONTENT_WARN_CHARS_DEFAULT = 1e4;
|
|
8638
8753
|
var SkillManager = class {
|
|
8639
8754
|
skills = /* @__PURE__ */ new Map();
|
|
8640
8755
|
activeSkill = null;
|
|
8641
8756
|
skillsDir;
|
|
8642
|
-
|
|
8757
|
+
/** 超大技能文件警告阈值,由调用方从 config 传入;0 = 静默,undefined = 用默认 10000 */
|
|
8758
|
+
warnThreshold;
|
|
8759
|
+
constructor(skillsDir, warnThreshold) {
|
|
8643
8760
|
this.skillsDir = skillsDir;
|
|
8761
|
+
this.warnThreshold = warnThreshold ?? SKILL_CONTENT_WARN_CHARS_DEFAULT;
|
|
8644
8762
|
}
|
|
8645
8763
|
/** 发现并加载 skillsDir 下所有 .md 文件,返回加载数量 */
|
|
8646
8764
|
loadSkills() {
|
|
@@ -8685,9 +8803,9 @@ var SkillManager = class {
|
|
|
8685
8803
|
skill.meta.name = entry;
|
|
8686
8804
|
}
|
|
8687
8805
|
this.skills.set(skill.meta.name, skill);
|
|
8688
|
-
if (skill.content.length >
|
|
8806
|
+
if (this.warnThreshold > 0 && skill.content.length > this.warnThreshold) {
|
|
8689
8807
|
process.stderr.write(
|
|
8690
|
-
`\u26A0 Skill '${skill.meta.name}' is ${skill.content.length} chars (>${
|
|
8808
|
+
`\u26A0 Skill '${skill.meta.name}' is ${skill.content.length} chars (>${this.warnThreshold}). Only consumed when activated via /skill. Adjust with: /config set ui.skillSizeWarn <n|0>
|
|
8691
8809
|
`
|
|
8692
8810
|
);
|
|
8693
8811
|
}
|
|
@@ -9374,15 +9492,15 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
|
9374
9492
|
// src/web/session-handler.ts
|
|
9375
9493
|
import { existsSync as existsSync20, readFileSync as readFileSync13, appendFileSync as appendFileSync3, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, readdirSync as readdirSync9, statSync as statSync8 } from "fs";
|
|
9376
9494
|
import { join as join13, resolve as resolve4 } from "path";
|
|
9377
|
-
import { execSync as
|
|
9495
|
+
import { execSync as execSync3 } from "child_process";
|
|
9378
9496
|
|
|
9379
9497
|
// src/tools/git-context.ts
|
|
9380
|
-
import { execSync as
|
|
9498
|
+
import { execSync as execSync2 } from "child_process";
|
|
9381
9499
|
import { existsSync as existsSync19 } from "fs";
|
|
9382
9500
|
import { join as join12 } from "path";
|
|
9383
9501
|
function runGit2(cmd, cwd) {
|
|
9384
9502
|
try {
|
|
9385
|
-
return
|
|
9503
|
+
return execSync2(`git ${cmd}`, {
|
|
9386
9504
|
cwd,
|
|
9387
9505
|
encoding: "utf-8",
|
|
9388
9506
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -11112,7 +11230,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11112
11230
|
let diff;
|
|
11113
11231
|
try {
|
|
11114
11232
|
const cmd = staged ? "git diff --staged" : "git diff";
|
|
11115
|
-
diff =
|
|
11233
|
+
diff = execSync3(cmd, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
11116
11234
|
} catch {
|
|
11117
11235
|
this.send({ type: "error", message: "Failed to run git diff." });
|
|
11118
11236
|
break;
|
|
@@ -11151,7 +11269,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11151
11269
|
let secDiff;
|
|
11152
11270
|
try {
|
|
11153
11271
|
const cmd = secStaged ? "git diff --staged" : "git diff";
|
|
11154
|
-
secDiff =
|
|
11272
|
+
secDiff = execSync3(cmd, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
11155
11273
|
} catch {
|
|
11156
11274
|
this.send({ type: "error", message: "Failed to run git diff." });
|
|
11157
11275
|
break;
|
|
@@ -11229,7 +11347,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11229
11347
|
case "test": {
|
|
11230
11348
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
11231
11349
|
try {
|
|
11232
|
-
const { executeTests } = await import("./run-tests-
|
|
11350
|
+
const { executeTests } = await import("./run-tests-LKZFHPQK.js");
|
|
11233
11351
|
const argStr = args.join(" ").trim();
|
|
11234
11352
|
let testArgs = {};
|
|
11235
11353
|
if (argStr) {
|
|
@@ -12480,7 +12598,7 @@ async function startWebServer(options = {}) {
|
|
|
12480
12598
|
let skillManager = null;
|
|
12481
12599
|
const skillsDir = join15(config.getConfigDir(), SKILLS_DIR_NAME);
|
|
12482
12600
|
if (existsSync22(skillsDir)) {
|
|
12483
|
-
skillManager = new SkillManager(skillsDir);
|
|
12601
|
+
skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
|
|
12484
12602
|
skillManager.loadSkills();
|
|
12485
12603
|
const count = skillManager.listSkills().length;
|
|
12486
12604
|
if (count > 0) {
|
|
@@ -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-
|
|
388
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-3LZHLZCG.js");
|
|
389
389
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
390
390
|
let interrupted = false;
|
|
391
391
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -30,10 +30,10 @@ import {
|
|
|
30
30
|
saveDevState,
|
|
31
31
|
sessionHasMeaningfulContent,
|
|
32
32
|
setupProxy
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-3CU4NKPD.js";
|
|
34
34
|
import {
|
|
35
35
|
ConfigManager
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-3SRJBTIY.js";
|
|
37
37
|
import {
|
|
38
38
|
ToolExecutor,
|
|
39
39
|
ToolRegistry,
|
|
@@ -41,15 +41,18 @@ import {
|
|
|
41
41
|
estimateTokens,
|
|
42
42
|
googleSearchContext,
|
|
43
43
|
initTheme,
|
|
44
|
+
isInterrupted,
|
|
44
45
|
lastResponseStore,
|
|
45
46
|
renderDiff,
|
|
47
|
+
requestInterrupt,
|
|
48
|
+
resetInterrupt,
|
|
46
49
|
rlInternal,
|
|
47
50
|
setContextWindow,
|
|
48
51
|
setMaxOutputCap,
|
|
49
52
|
spawnAgentContext,
|
|
50
53
|
theme,
|
|
51
54
|
undoStack
|
|
52
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-5D7LG2TY.js";
|
|
53
56
|
import "./chunk-2ZD3YTVM.js";
|
|
54
57
|
import {
|
|
55
58
|
fileCheckpoints
|
|
@@ -67,7 +70,7 @@ import "./chunk-KJLJPUY2.js";
|
|
|
67
70
|
import "./chunk-6VRJGH25.js";
|
|
68
71
|
import "./chunk-2DXY7UGF.js";
|
|
69
72
|
import "./chunk-KHYD3WXE.js";
|
|
70
|
-
import "./chunk-
|
|
73
|
+
import "./chunk-OL6TUUBE.js";
|
|
71
74
|
import {
|
|
72
75
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
73
76
|
AUTHOR,
|
|
@@ -89,7 +92,7 @@ import {
|
|
|
89
92
|
SKILLS_DIR_NAME,
|
|
90
93
|
VERSION,
|
|
91
94
|
buildUserIdentityPrompt
|
|
92
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-WR4M4TXV.js";
|
|
93
96
|
|
|
94
97
|
// src/index.ts
|
|
95
98
|
import { program } from "commander";
|
|
@@ -2609,7 +2612,7 @@ ${hint}` : "")
|
|
|
2609
2612
|
usage: "/test [command|filter]",
|
|
2610
2613
|
async execute(args, ctx) {
|
|
2611
2614
|
try {
|
|
2612
|
-
const { executeTests } = await import("./run-tests-
|
|
2615
|
+
const { executeTests } = await import("./run-tests-RO24F4Z2.js");
|
|
2613
2616
|
const argStr = args.join(" ").trim();
|
|
2614
2617
|
let testArgs = {};
|
|
2615
2618
|
if (argStr) {
|
|
@@ -4997,7 +5000,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4997
5000
|
`));
|
|
4998
5001
|
}
|
|
4999
5002
|
const skillsDir = join5(this.config.getConfigDir(), SKILLS_DIR_NAME);
|
|
5000
|
-
this.skillManager = new SkillManager(skillsDir);
|
|
5003
|
+
this.skillManager = new SkillManager(skillsDir, this.config.get("ui").skillSizeWarn);
|
|
5001
5004
|
const skillCount = this.skillManager.loadSkills();
|
|
5002
5005
|
if (skillCount > 0) {
|
|
5003
5006
|
process.stdout.write(theme.dim(` \u{1F3AF} Skills: ${skillCount} available (use /skill to manage)
|
|
@@ -5097,6 +5100,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5097
5100
|
this.rl.on("SIGINT", () => {
|
|
5098
5101
|
if (this.streamAbortController) {
|
|
5099
5102
|
this.streamAbortController.abort();
|
|
5103
|
+
requestInterrupt();
|
|
5100
5104
|
return;
|
|
5101
5105
|
}
|
|
5102
5106
|
if (this.toolExecutor.confirming) {
|
|
@@ -5107,6 +5111,11 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5107
5111
|
askUserContext.cancelFn();
|
|
5108
5112
|
return;
|
|
5109
5113
|
}
|
|
5114
|
+
if (this.toolExecutor.running) {
|
|
5115
|
+
process.stdout.write(theme.warning("\n\u26A1 Ctrl+C \u2014 interrupting tool execution...\n"));
|
|
5116
|
+
requestInterrupt();
|
|
5117
|
+
return;
|
|
5118
|
+
}
|
|
5110
5119
|
this.handleExit();
|
|
5111
5120
|
});
|
|
5112
5121
|
this.showPrompt();
|
|
@@ -5237,6 +5246,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5237
5246
|
`)
|
|
5238
5247
|
);
|
|
5239
5248
|
}
|
|
5249
|
+
resetInterrupt();
|
|
5240
5250
|
const t0 = Date.now();
|
|
5241
5251
|
try {
|
|
5242
5252
|
const provider = this.providers.get(this.currentProvider);
|
|
@@ -6240,6 +6250,12 @@ ${systemPromptVolatile}` : systemPrompt;
|
|
|
6240
6250
|
spawnAgentContext.configManager = this.config;
|
|
6241
6251
|
ToolExecutor.currentMessageIndex = session.messages.length;
|
|
6242
6252
|
const toolResults = await this.toolExecutor.executeAll(result.toolCalls);
|
|
6253
|
+
if (isInterrupted()) {
|
|
6254
|
+
spinner.stop();
|
|
6255
|
+
process.stdout.write(theme.warning("\n\u26A1 Interrupted by user (Ctrl+C) \u2014 agentic loop stopped.\n"));
|
|
6256
|
+
this.teardownInterjectionListener();
|
|
6257
|
+
return;
|
|
6258
|
+
}
|
|
6243
6259
|
const thisRoundTools = result.toolCalls.map((tc) => tc.name);
|
|
6244
6260
|
roundToolHistory.push({ round: round + 1, tools: thisRoundTools });
|
|
6245
6261
|
const readFileCalls = result.toolCalls.filter((tc) => tc.name === "read_file");
|
|
@@ -6722,7 +6738,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
6722
6738
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
6723
6739
|
process.exit(1);
|
|
6724
6740
|
}
|
|
6725
|
-
const { startWebServer } = await import("./server-
|
|
6741
|
+
const { startWebServer } = await import("./server-YHECGYRX.js");
|
|
6726
6742
|
await startWebServer({ port, host: options.host });
|
|
6727
6743
|
});
|
|
6728
6744
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -6845,7 +6861,7 @@ program.command("sessions").description("List recent conversation sessions").act
|
|
|
6845
6861
|
});
|
|
6846
6862
|
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) => {
|
|
6847
6863
|
try {
|
|
6848
|
-
const batch = await import("./batch-
|
|
6864
|
+
const batch = await import("./batch-NAPWSE3V.js");
|
|
6849
6865
|
switch (action) {
|
|
6850
6866
|
case "submit":
|
|
6851
6867
|
if (!arg) {
|
|
@@ -6888,7 +6904,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
6888
6904
|
}
|
|
6889
6905
|
});
|
|
6890
6906
|
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) => {
|
|
6891
|
-
const { startMcpServer } = await import("./server-
|
|
6907
|
+
const { startMcpServer } = await import("./server-YXETATAI.js");
|
|
6892
6908
|
await startMcpServer({
|
|
6893
6909
|
allowDestructive: !!options.allowDestructive,
|
|
6894
6910
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7015,7 +7031,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7015
7031
|
}),
|
|
7016
7032
|
config.get("customProviders")
|
|
7017
7033
|
);
|
|
7018
|
-
const { startHub } = await import("./hub-
|
|
7034
|
+
const { startHub } = await import("./hub-LJAXL2LO.js");
|
|
7019
7035
|
await startHub(
|
|
7020
7036
|
{
|
|
7021
7037
|
topic: topic ?? "",
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
persistToolRound,
|
|
24
24
|
rebuildExtraMessages,
|
|
25
25
|
setupProxy
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-3CU4NKPD.js";
|
|
27
27
|
import {
|
|
28
28
|
ConfigManager
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-3SRJBTIY.js";
|
|
30
30
|
import {
|
|
31
31
|
ToolExecutor,
|
|
32
32
|
ToolRegistry,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
spawnAgentContext,
|
|
45
45
|
truncateOutput,
|
|
46
46
|
undoStack
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-5D7LG2TY.js";
|
|
48
48
|
import "./chunk-2ZD3YTVM.js";
|
|
49
49
|
import "./chunk-4BKXL7SM.js";
|
|
50
50
|
import "./chunk-ANYYM4CF.js";
|
|
@@ -53,7 +53,7 @@ import "./chunk-KJLJPUY2.js";
|
|
|
53
53
|
import "./chunk-6VRJGH25.js";
|
|
54
54
|
import "./chunk-2DXY7UGF.js";
|
|
55
55
|
import "./chunk-KHYD3WXE.js";
|
|
56
|
-
import "./chunk-
|
|
56
|
+
import "./chunk-OL6TUUBE.js";
|
|
57
57
|
import {
|
|
58
58
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
59
59
|
AUTHOR,
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
SKILLS_DIR_NAME,
|
|
73
73
|
VERSION,
|
|
74
74
|
buildUserIdentityPrompt
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-WR4M4TXV.js";
|
|
76
76
|
|
|
77
77
|
// src/web/server.ts
|
|
78
78
|
import express from "express";
|
|
@@ -2237,7 +2237,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2237
2237
|
case "test": {
|
|
2238
2238
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2239
2239
|
try {
|
|
2240
|
-
const { executeTests } = await import("./run-tests-
|
|
2240
|
+
const { executeTests } = await import("./run-tests-RO24F4Z2.js");
|
|
2241
2241
|
const argStr = args.join(" ").trim();
|
|
2242
2242
|
let testArgs = {};
|
|
2243
2243
|
if (argStr) {
|
|
@@ -3266,7 +3266,7 @@ async function startWebServer(options = {}) {
|
|
|
3266
3266
|
let skillManager = null;
|
|
3267
3267
|
const skillsDir = join3(config.getConfigDir(), SKILLS_DIR_NAME);
|
|
3268
3268
|
if (existsSync4(skillsDir)) {
|
|
3269
|
-
skillManager = new SkillManager(skillsDir);
|
|
3269
|
+
skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
|
|
3270
3270
|
skillManager.loadSkills();
|
|
3271
3271
|
const count = skillManager.listSkills().length;
|
|
3272
3272
|
if (count > 0) {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
schemaToJsonSchema
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5D7LG2TY.js";
|
|
7
7
|
import "./chunk-2ZD3YTVM.js";
|
|
8
8
|
import "./chunk-4BKXL7SM.js";
|
|
9
9
|
import "./chunk-ANYYM4CF.js";
|
|
@@ -12,10 +12,10 @@ import "./chunk-KJLJPUY2.js";
|
|
|
12
12
|
import "./chunk-6VRJGH25.js";
|
|
13
13
|
import "./chunk-2DXY7UGF.js";
|
|
14
14
|
import "./chunk-KHYD3WXE.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-OL6TUUBE.js";
|
|
16
16
|
import {
|
|
17
17
|
VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WR4M4TXV.js";
|
|
19
19
|
|
|
20
20
|
// src/mcp/server.ts
|
|
21
21
|
import { createInterface } from "readline";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-5D7LG2TY.js";
|
|
8
8
|
import "./chunk-2ZD3YTVM.js";
|
|
9
9
|
import "./chunk-4BKXL7SM.js";
|
|
10
10
|
import "./chunk-ANYYM4CF.js";
|
|
@@ -13,10 +13,10 @@ import "./chunk-KJLJPUY2.js";
|
|
|
13
13
|
import "./chunk-6VRJGH25.js";
|
|
14
14
|
import "./chunk-2DXY7UGF.js";
|
|
15
15
|
import "./chunk-KHYD3WXE.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-OL6TUUBE.js";
|
|
17
17
|
import {
|
|
18
18
|
SUBAGENT_ALLOWED_TOOLS
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-WR4M4TXV.js";
|
|
20
20
|
|
|
21
21
|
// src/hub/task-orchestrator.ts
|
|
22
22
|
import { createInterface } from "readline";
|