jinzd-ai-cli 0.4.90 → 0.4.92
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 +6 -2
- package/README.zh-CN.md +6 -2
- package/dist/{batch-3MJ56YAA.js → batch-SK2YCZEY.js} +2 -2
- package/dist/{chunk-WPQ4D6T3.js → chunk-5IL2BHSD.js} +1 -1
- package/dist/{chunk-BJXGZFE6.js → chunk-A4TUAW4J.js} +1 -1
- package/dist/{chunk-G65IDWVP.js → chunk-CNI26J5Z.js} +174 -44
- package/dist/{chunk-AB2LA33A.js → chunk-ING3NMVR.js} +1 -1
- package/dist/{chunk-EEEAFWNK.js → chunk-KLSISB52.js} +1 -1
- package/dist/{chunk-DJGP7AR6.js → chunk-KPX72DTU.js} +2 -2
- package/dist/electron-server.js +164 -51
- package/dist/{hub-B7NJSCWF.js → hub-YRYUBSEQ.js} +1 -1
- package/dist/index.js +39 -16
- package/dist/{run-tests-37FEBJTR.js → run-tests-4XJLQNUW.js} +1 -1
- package/dist/{run-tests-2DYVHTIH.js → run-tests-JROEDZES.js} +2 -2
- package/dist/{server-S6JYNMMF.js → server-DB4GMBDN.js} +3 -3
- package/dist/{server-FCTPLKGO.js → server-WHTZFKVB.js} +6 -6
- package/dist/{task-orchestrator-K6HDX4YE.js → task-orchestrator-IQTIXEOM.js} +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/jinzd-ai-cli)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](https://nodejs.org)
|
|
10
|
-
[]()
|
|
11
11
|
[](https://github.com/jinzhengdong/ai-cli/releases)
|
|
12
12
|
[](https://github.com/jinzhengdong/ai-cli/actions/workflows/ci.yml)
|
|
13
13
|
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
- **Conversation Branching** *(v0.4.74+)* — `/branch list/new/switch/delete/rename` inside the REPL, plus a 🌿 "fork here" button on every replay step — explore alternate directions without losing the original thread
|
|
32
32
|
- **Symbol Index** *(v0.4.76+)* — persistent tree-sitter index for TS/JS/TSX/Python powers three new AI tools: `find_symbol`, `get_outline`, `find_references`. Orders of magnitude faster than grep for definition lookups; background refresh on REPL startup, `/index status|rebuild|clear` to manage
|
|
33
33
|
- **Semantic Code Search** *(v0.4.77+)* — `search_code` tool finds code by meaning, not name. Local sentence embeddings (multilingual MiniLM, 117 MB one-time download) score symbols by cosine similarity against natural-language queries in English or Chinese ("where are users authenticated", "哪里做了速率限制"). No API key, runs on CPU. Manage with `/index semantic-rebuild|semantic-clear`
|
|
34
|
+
- **MCP Server Mode** *(v0.4.84+)* — `aicli mcp-serve` reverses ai-cli into an MCP server (JSON-RPC 2.0 over stdio), exposing its 26 built-in tools (incl. `find_symbol` / `search_code` / `run_tests`) to Claude Desktop / Cursor / any MCP client. Opt-in destructive-tool allow, `--tools` whitelist, `--cwd` override
|
|
35
|
+
- **Session Sensitive-Data Redaction** *(v0.4.88+)* — unified redactor scrubs `password=` / `api_key` / bearer tokens / OpenAI-style keys from every message **before it hits disk**. Query text is redacted too, so secrets never reach embeddings or logs. `/security status` + `/security scan` to audit
|
|
36
|
+
- **Human-like Long-Term Memory** *(v0.4.89+, B4)* — semantic index over every past chat session + `recall_memory` AI tool + `/memory rebuild|refresh|status|recall` commands. AI is prompted to auto-recall when it sees "last time" / "之前" / ambiguous references. Reuses the same MiniLM embedder as semantic code search
|
|
37
|
+
- **Web UI Memory Panel** *(v0.4.90+, B4)* — new 🧠 Memory sidebar tab with semantic search across past chats; each hit has **➕ Inject** (quotes the snippet into the chat input as a markdown blockquote so you can review/edit before sending — no silent context injection) and **↗ Load** (jumps to source session). Bulk "Inject top 3" for recall bundles
|
|
34
38
|
- **Streaming Tool Use** — Real-time streaming of AI reasoning and tool calls as they happen
|
|
35
39
|
- **Sub-Agents** — Delegate complex subtasks to isolated child agents with independent tool loops
|
|
36
40
|
- **Extended Thinking** — Claude deep reasoning mode with `/think` toggle
|
|
@@ -41,7 +45,7 @@
|
|
|
41
45
|
- **PWA Support** — Install Web UI as a desktop/mobile app, accessible over LAN
|
|
42
46
|
- **Hierarchical Context** — 3-layer context files (global / project / subdirectory) auto-injected
|
|
43
47
|
- **Headless Mode** — `ai-cli -p "prompt"` for CI/CD pipelines and scripting
|
|
44
|
-
- **
|
|
48
|
+
- **43 REPL Commands** — Session management, checkpointing, code review, security review/scan, rewind, scaffolding, cross-session history search, chat-memory recall, and more
|
|
45
49
|
- **GitHub Actions CI/CD** — Automated testing on Node 20/22 + npm publish on release tags
|
|
46
50
|
- **Cross-Platform** — Windows, macOS, Linux
|
|
47
51
|
|
package/README.zh-CN.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/jinzd-ai-cli)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](https://nodejs.org)
|
|
10
|
-
[]()
|
|
11
11
|
[](https://github.com/jinzhengdong/ai-cli/releases)
|
|
12
12
|
[](https://github.com/jinzhengdong/ai-cli/actions/workflows/ci.yml)
|
|
13
13
|
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
- **对话分支**(v0.4.74+)— REPL 内 `/branch list/new/switch/delete/rename/diff/cherry-pick`,Web UI 回放面板每条消息旁 🌿 "fork here" 按钮,任意位置开辟新分支探索不同方向,原对话保持不变;v0.4.81 起所有子命令支持 id / title / 唯一前缀
|
|
24
24
|
- **符号索引**(v0.4.76+,C1)— tree-sitter 持久化索引(TS/JS/TSX/JSX/Python)+ 3 个只读 AI 工具(`find_symbol` / `get_outline` / `find_references`)+ `/index status/rebuild/clear`;启动后台增量刷新,`write_file` 后自动 upsert
|
|
25
25
|
- **语义代码搜索**(v0.4.77+,C2)— `search_code` AI 工具 + 本地 sentence embedding(`paraphrase-multilingual-MiniLM-L12-v2`,117 MB 一次性下载,384 维,CPU 运行);支持中英文自然语言查询代码;`/index semantic-rebuild/semantic-clear` 管理
|
|
26
|
+
- **MCP Server 模式**(v0.4.84+,E1)— `aicli mcp-serve` 把 aicli 反转为 MCP 服务器(JSON-RPC 2.0 over stdio),把 26 个内置工具(含 `find_symbol` / `search_code` / `run_tests`)输出给 Claude Desktop / Cursor / 任何 MCP 客户端;支持 `--tools` 白名单、`--cwd` 覆盖、`--allow-destructive`
|
|
27
|
+
- **Session 敏感数据脱敏**(v0.4.88+)— 统一 redactor 在 session **落盘前**自动替换 `password=` / `api_key` / bearer token / OpenAI key 为 `[REDACTED:*]`;查询文本也走脱敏,secret 不会进 embedding 或日志;`/security status` + `/security scan` 审计
|
|
28
|
+
- **类人长期记忆**(v0.4.89+,B4)— 聊天记录语义索引跨 session 可召回 + `recall_memory` AI 工具 + `/memory rebuild/refresh/status/recall/index-clear`;AI 看到"上次"/"之前"/指代不明时自动回忆。复用 C2 的 MiniLM embedder
|
|
29
|
+
- **Web UI Memory 面板**(v0.4.90+,B4)— sidebar 新增 🧠 Memory 标签页,跨 session 语义搜索;每条 hit 带 **➕ Inject**(把片段作为 markdown 引用块塞进聊天输入框,用户可在上面继续打字编辑——不是静默注入上下文)和 **↗ Load**(跳转对应 session);顶部"➕ Inject top 3"一键批量
|
|
26
30
|
- **流式工具调用** — 实时流式展示 AI 推理过程和工具调用
|
|
27
31
|
- **子代理系统** — 将复杂子任务委派给独立子代理执行
|
|
28
32
|
- **深度推理** — Claude Extended Thinking,`/think` 一键切换
|
|
@@ -33,7 +37,7 @@
|
|
|
33
37
|
- **PWA 支持** — Web UI 可安装为桌面/移动应用,支持局域网访问
|
|
34
38
|
- **三层级上下文** — 全局 / 项目 / 子目录上下文文件自动注入
|
|
35
39
|
- **无头模式** — `aicli -p "提示词"` 用于 CI/CD 管道和脚本
|
|
36
|
-
- **
|
|
40
|
+
- **43 个 REPL 命令** — 会话管理、检查点、代码审查、安全审查/扫描、对话回退、脚手架、聊天记忆召回等
|
|
37
41
|
- **GitHub Actions CI/CD** — Node 20/22 自动测试 + Release tag 自动发布 npm
|
|
38
42
|
- **跨平台** — Windows、macOS、Linux
|
|
39
43
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ING3NMVR.js";
|
|
5
5
|
import "./chunk-2ZD3YTVM.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-5IL2BHSD.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/batch.ts
|
|
9
9
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "./chunk-6VRJGH25.js";
|
|
24
24
|
import {
|
|
25
25
|
runTestsTool
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-KLSISB52.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-5IL2BHSD.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,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
schemaToJsonSchema,
|
|
4
4
|
truncateForPersist
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CNI26J5Z.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-5IL2BHSD.js";
|
|
25
25
|
|
|
26
26
|
// src/providers/claude.ts
|
|
27
27
|
import Anthropic from "@anthropic-ai/sdk";
|
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-A4TUAW4J.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -3304,7 +3304,7 @@ var SessionManager = class {
|
|
|
3304
3304
|
};
|
|
3305
3305
|
|
|
3306
3306
|
// src/tools/builtin/bash.ts
|
|
3307
|
-
import {
|
|
3307
|
+
import { spawn } from "child_process";
|
|
3308
3308
|
import { existsSync as existsSync4, readdirSync as readdirSync2, statSync } from "fs";
|
|
3309
3309
|
import { platform } from "os";
|
|
3310
3310
|
import { resolve } from "path";
|
|
@@ -3424,6 +3424,12 @@ var UndoStack = class {
|
|
|
3424
3424
|
};
|
|
3425
3425
|
var undoStack = new UndoStack();
|
|
3426
3426
|
|
|
3427
|
+
// src/core/interrupt.ts
|
|
3428
|
+
var controller = new AbortController();
|
|
3429
|
+
function currentAbortSignal() {
|
|
3430
|
+
return controller.signal;
|
|
3431
|
+
}
|
|
3432
|
+
|
|
3427
3433
|
// src/tools/builtin/bash.ts
|
|
3428
3434
|
var IS_WINDOWS = platform() === "win32";
|
|
3429
3435
|
var SHELL = IS_WINDOWS ? "powershell.exe" : process.env["SHELL"] ?? "/bin/bash";
|
|
@@ -3506,21 +3512,40 @@ Important rules:
|
|
|
3506
3512
|
parsedTargetsBefore.set(t, existsSync4(t));
|
|
3507
3513
|
}
|
|
3508
3514
|
try {
|
|
3509
|
-
const
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3515
|
+
const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
|
|
3516
|
+
actualCommand,
|
|
3517
|
+
{
|
|
3518
|
+
timeout,
|
|
3519
|
+
cwd: effectiveCwd,
|
|
3520
|
+
env: {
|
|
3521
|
+
...process.env,
|
|
3522
|
+
PYTHONUTF8: "1",
|
|
3523
|
+
PYTHONIOENCODING: "utf-8"
|
|
3524
|
+
}
|
|
3519
3525
|
}
|
|
3520
|
-
|
|
3526
|
+
);
|
|
3527
|
+
if (aborted) {
|
|
3528
|
+
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
3529
|
+
throw new ToolError(
|
|
3530
|
+
"bash",
|
|
3531
|
+
`Command interrupted by user (Ctrl+C).
|
|
3532
|
+
|
|
3533
|
+
[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.]`
|
|
3534
|
+
);
|
|
3535
|
+
}
|
|
3536
|
+
if (status !== 0 || timedOut) {
|
|
3537
|
+
throw {
|
|
3538
|
+
status,
|
|
3539
|
+
signal,
|
|
3540
|
+
code: timedOut ? "ETIMEDOUT" : void 0,
|
|
3541
|
+
stdout,
|
|
3542
|
+
stderr,
|
|
3543
|
+
message: timedOut ? "ETIMEDOUT" : `exit ${status}`
|
|
3544
|
+
};
|
|
3545
|
+
}
|
|
3521
3546
|
updateCwdFromCommand(command, effectiveCwd);
|
|
3522
3547
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
3523
|
-
const result = IS_WINDOWS && Buffer.isBuffer(
|
|
3548
|
+
const result = IS_WINDOWS && Buffer.isBuffer(stdout) ? stdout.toString("utf-8") : stdout;
|
|
3524
3549
|
return result || "(command completed with no output)";
|
|
3525
3550
|
} catch (err) {
|
|
3526
3551
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
@@ -3640,6 +3665,84 @@ function pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, cwd) {
|
|
|
3640
3665
|
}
|
|
3641
3666
|
}
|
|
3642
3667
|
}
|
|
3668
|
+
function runShell(command, opts) {
|
|
3669
|
+
return new Promise((resolvePromise) => {
|
|
3670
|
+
const shellArgs = IS_WINDOWS ? ["-NoProfile", "-NonInteractive", "-Command", command] : ["-c", command];
|
|
3671
|
+
const child = spawn(SHELL, shellArgs, {
|
|
3672
|
+
cwd: opts.cwd,
|
|
3673
|
+
env: opts.env,
|
|
3674
|
+
windowsHide: true,
|
|
3675
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
3676
|
+
});
|
|
3677
|
+
const stdoutChunks = [];
|
|
3678
|
+
const stderrChunks = [];
|
|
3679
|
+
let timedOut = false;
|
|
3680
|
+
let aborted = false;
|
|
3681
|
+
let settled = false;
|
|
3682
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
3683
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
3684
|
+
const timeoutTimer = setTimeout(() => {
|
|
3685
|
+
timedOut = true;
|
|
3686
|
+
killChild(child);
|
|
3687
|
+
}, opts.timeout);
|
|
3688
|
+
const signal = currentAbortSignal();
|
|
3689
|
+
const onAbort = () => {
|
|
3690
|
+
aborted = true;
|
|
3691
|
+
killChild(child);
|
|
3692
|
+
};
|
|
3693
|
+
if (signal.aborted) {
|
|
3694
|
+
onAbort();
|
|
3695
|
+
} else {
|
|
3696
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3697
|
+
}
|
|
3698
|
+
const cleanup = () => {
|
|
3699
|
+
clearTimeout(timeoutTimer);
|
|
3700
|
+
signal.removeEventListener("abort", onAbort);
|
|
3701
|
+
};
|
|
3702
|
+
child.on("error", (err) => {
|
|
3703
|
+
if (settled) return;
|
|
3704
|
+
settled = true;
|
|
3705
|
+
cleanup();
|
|
3706
|
+
stderrChunks.push(Buffer.from(String(err.message ?? err)));
|
|
3707
|
+
resolvePromise({
|
|
3708
|
+
stdout: Buffer.concat(stdoutChunks),
|
|
3709
|
+
stderr: Buffer.concat(stderrChunks),
|
|
3710
|
+
status: null,
|
|
3711
|
+
signal: null,
|
|
3712
|
+
timedOut,
|
|
3713
|
+
aborted
|
|
3714
|
+
});
|
|
3715
|
+
});
|
|
3716
|
+
child.on("close", (code, sig) => {
|
|
3717
|
+
if (settled) return;
|
|
3718
|
+
settled = true;
|
|
3719
|
+
cleanup();
|
|
3720
|
+
resolvePromise({
|
|
3721
|
+
stdout: Buffer.concat(stdoutChunks),
|
|
3722
|
+
stderr: Buffer.concat(stderrChunks),
|
|
3723
|
+
status: code,
|
|
3724
|
+
signal: sig,
|
|
3725
|
+
timedOut,
|
|
3726
|
+
aborted
|
|
3727
|
+
});
|
|
3728
|
+
});
|
|
3729
|
+
});
|
|
3730
|
+
}
|
|
3731
|
+
function killChild(child) {
|
|
3732
|
+
if (child.killed || child.exitCode !== null) return;
|
|
3733
|
+
try {
|
|
3734
|
+
child.kill("SIGTERM");
|
|
3735
|
+
} catch {
|
|
3736
|
+
}
|
|
3737
|
+
setTimeout(() => {
|
|
3738
|
+
if (!child.killed && child.exitCode === null) {
|
|
3739
|
+
try {
|
|
3740
|
+
child.kill("SIGKILL");
|
|
3741
|
+
} catch {
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
}, 500).unref();
|
|
3745
|
+
}
|
|
3643
3746
|
function updateCwdFromCommand(command, baseCwd) {
|
|
3644
3747
|
const cdMatches = [...command.matchAll(/(?:^|[;&|])\s*cd\s+(['"]?)([^\s;&|'"]+)\1/g)];
|
|
3645
3748
|
if (cdMatches.length === 0) return;
|
|
@@ -4233,7 +4336,7 @@ function simpleDiff(oldLines, newLines) {
|
|
|
4233
4336
|
}
|
|
4234
4337
|
|
|
4235
4338
|
// src/tools/hooks.ts
|
|
4236
|
-
import { execSync
|
|
4339
|
+
import { execSync } from "child_process";
|
|
4237
4340
|
function shellEscape(value) {
|
|
4238
4341
|
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
4239
4342
|
}
|
|
@@ -4245,7 +4348,7 @@ function runHook(template, vars) {
|
|
|
4245
4348
|
cmd = cmd.replace(/\{args\}/g, shellEscape(vars.args ?? ""));
|
|
4246
4349
|
cmd = cmd.replace(/\{status\}/g, shellEscape(vars.status ?? ""));
|
|
4247
4350
|
try {
|
|
4248
|
-
|
|
4351
|
+
execSync(cmd, {
|
|
4249
4352
|
timeout: 5e3,
|
|
4250
4353
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4251
4354
|
encoding: "utf-8"
|
|
@@ -4429,6 +4532,11 @@ var ToolExecutor = class {
|
|
|
4429
4532
|
* 防止用户输入 "y"+Enter 被同时触发 once('line') 和主循环 on('line')。
|
|
4430
4533
|
*/
|
|
4431
4534
|
confirming = false;
|
|
4535
|
+
/**
|
|
4536
|
+
* Tool 执行进行中标志(executeAll 的生命周期)。
|
|
4537
|
+
* repl.ts 的 SIGINT handler 在此为 true 时触发全局 interrupt(而不是退出程序)。
|
|
4538
|
+
*/
|
|
4539
|
+
running = false;
|
|
4432
4540
|
/** 在 confirm 期间用户输入的 slash 命令,由 repl.ts 主循环消费 */
|
|
4433
4541
|
pendingSlashCommand = null;
|
|
4434
4542
|
/** confirm() 的取消回调,由 SIGINT handler 调用 */
|
|
@@ -4563,25 +4671,30 @@ var ToolExecutor = class {
|
|
|
4563
4671
|
}
|
|
4564
4672
|
}
|
|
4565
4673
|
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];
|
|
4674
|
+
this.running = true;
|
|
4675
|
+
try {
|
|
4676
|
+
const phase = groupCallsByPhase(calls);
|
|
4677
|
+
const results = new Array(calls.length);
|
|
4678
|
+
const elapsed = await runSafePhases(phase, (c) => this.execute(c), results, "executor");
|
|
4679
|
+
if (phase.safeParallel.length >= 2) {
|
|
4680
|
+
console.log(theme.dim(` \u26A1 ${phase.safeParallel.length} tools executed in parallel (${elapsed}ms)`));
|
|
4579
4681
|
}
|
|
4682
|
+
if (phase.fileWriteCalls.length === 1) {
|
|
4683
|
+
const { idx, call } = phase.fileWriteCalls[0];
|
|
4684
|
+
results[idx] = await this.execute(call);
|
|
4685
|
+
} else if (phase.fileWriteCalls.length >= 2) {
|
|
4686
|
+
const batchResults = await this.executeBatchFileWrites(phase.fileWriteCalls.map((f) => f.call));
|
|
4687
|
+
for (let i = 0; i < phase.fileWriteCalls.length; i++) {
|
|
4688
|
+
results[phase.fileWriteCalls[i].idx] = batchResults[i];
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
for (const { idx, call } of phase.otherCalls) {
|
|
4692
|
+
results[idx] = await this.execute(call);
|
|
4693
|
+
}
|
|
4694
|
+
return results;
|
|
4695
|
+
} finally {
|
|
4696
|
+
this.running = false;
|
|
4580
4697
|
}
|
|
4581
|
-
for (const { idx, call } of phase.otherCalls) {
|
|
4582
|
-
results[idx] = await this.execute(call);
|
|
4583
|
-
}
|
|
4584
|
-
return results;
|
|
4585
4698
|
}
|
|
4586
4699
|
/**
|
|
4587
4700
|
* 批量文件写入:展示所有文件的编号列表 + diff 预览,
|
|
@@ -5925,7 +6038,7 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
|
|
|
5925
6038
|
}
|
|
5926
6039
|
|
|
5927
6040
|
// src/tools/builtin/run-interactive.ts
|
|
5928
|
-
import { spawn } from "child_process";
|
|
6041
|
+
import { spawn as spawn2 } from "child_process";
|
|
5929
6042
|
import { platform as platform2 } from "os";
|
|
5930
6043
|
var IS_WINDOWS2 = platform2() === "win32";
|
|
5931
6044
|
var runInteractiveTool = {
|
|
@@ -5989,7 +6102,7 @@ var runInteractiveTool = {
|
|
|
5989
6102
|
};
|
|
5990
6103
|
const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
|
|
5991
6104
|
return new Promise((resolve6) => {
|
|
5992
|
-
const child =
|
|
6105
|
+
const child = spawn2(executable, cmdArgs.map(String), {
|
|
5993
6106
|
cwd: process.cwd(),
|
|
5994
6107
|
env,
|
|
5995
6108
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -6159,8 +6272,8 @@ var webFetchTool = {
|
|
|
6159
6272
|
if (e.message.startsWith("Blocked:")) throw e;
|
|
6160
6273
|
throw new NetworkError(`Invalid URL: "${url}"`);
|
|
6161
6274
|
}
|
|
6162
|
-
const
|
|
6163
|
-
const timeoutId = setTimeout(() =>
|
|
6275
|
+
const controller2 = new AbortController();
|
|
6276
|
+
const timeoutId = setTimeout(() => controller2.abort(), 2e4);
|
|
6164
6277
|
let rawHtml;
|
|
6165
6278
|
let finalUrl;
|
|
6166
6279
|
let contentType;
|
|
@@ -6180,7 +6293,7 @@ var webFetchTool = {
|
|
|
6180
6293
|
}
|
|
6181
6294
|
await resolveAndCheck(parsedHop.hostname);
|
|
6182
6295
|
const r = await fetch(currentUrl, {
|
|
6183
|
-
signal:
|
|
6296
|
+
signal: controller2.signal,
|
|
6184
6297
|
headers: FETCH_HEADERS,
|
|
6185
6298
|
redirect: "manual"
|
|
6186
6299
|
// 手动控制重定向
|
|
@@ -6531,15 +6644,15 @@ var googleSearchTool = {
|
|
|
6531
6644
|
url.searchParams.set("cx", cx);
|
|
6532
6645
|
url.searchParams.set("q", query);
|
|
6533
6646
|
url.searchParams.set("num", String(numResults));
|
|
6534
|
-
const
|
|
6535
|
-
const timeout = setTimeout(() =>
|
|
6647
|
+
const controller2 = new AbortController();
|
|
6648
|
+
const timeout = setTimeout(() => controller2.abort(), REQUEST_TIMEOUT_MS);
|
|
6536
6649
|
try {
|
|
6537
6650
|
const response = await fetch(url.toString(), {
|
|
6538
6651
|
method: "GET",
|
|
6539
6652
|
headers: {
|
|
6540
6653
|
"Accept": "application/json"
|
|
6541
6654
|
},
|
|
6542
|
-
signal:
|
|
6655
|
+
signal: controller2.signal
|
|
6543
6656
|
});
|
|
6544
6657
|
if (!response.ok) {
|
|
6545
6658
|
const errorBody = await response.text().catch(() => "");
|
|
@@ -6923,7 +7036,7 @@ var spawnAgentTool = {
|
|
|
6923
7036
|
};
|
|
6924
7037
|
|
|
6925
7038
|
// src/tools/builtin/task-manager.ts
|
|
6926
|
-
import { spawn as
|
|
7039
|
+
import { spawn as spawn3 } from "child_process";
|
|
6927
7040
|
import { randomUUID } from "crypto";
|
|
6928
7041
|
import { platform as platform3 } from "os";
|
|
6929
7042
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
@@ -6948,7 +7061,7 @@ function createTask(command, description) {
|
|
|
6948
7061
|
const isWin = platform3() === "win32";
|
|
6949
7062
|
const shell = isWin ? "cmd" : "sh";
|
|
6950
7063
|
const shellFlag = isWin ? "/c" : "-c";
|
|
6951
|
-
const proc =
|
|
7064
|
+
const proc = spawn3(shell, [shellFlag, command], {
|
|
6952
7065
|
stdio: ["ignore", "pipe", "pipe"],
|
|
6953
7066
|
detached: false,
|
|
6954
7067
|
env: { ...process.env, PYTHONUTF8: "1" }
|
|
@@ -8070,7 +8183,7 @@ var ToolRegistry = class {
|
|
|
8070
8183
|
};
|
|
8071
8184
|
|
|
8072
8185
|
// src/mcp/client.ts
|
|
8073
|
-
import { spawn as
|
|
8186
|
+
import { spawn as spawn4 } from "child_process";
|
|
8074
8187
|
var McpClient = class {
|
|
8075
8188
|
serverId;
|
|
8076
8189
|
config;
|
|
@@ -8108,7 +8221,7 @@ var McpClient = class {
|
|
|
8108
8221
|
async connect() {
|
|
8109
8222
|
const timeout = this.config.timeout ?? MCP_CONNECT_TIMEOUT;
|
|
8110
8223
|
try {
|
|
8111
|
-
this.process =
|
|
8224
|
+
this.process = spawn4(this.config.command, this.config.args ?? [], {
|
|
8112
8225
|
stdio: ["pipe", "pipe", "pipe"],
|
|
8113
8226
|
env: { ...process.env, ...this.config.env },
|
|
8114
8227
|
// Windows 上 npx 等是 .cmd 脚本,需要 shell 模式
|
|
@@ -9374,15 +9487,15 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
|
9374
9487
|
// src/web/session-handler.ts
|
|
9375
9488
|
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
9489
|
import { join as join13, resolve as resolve4 } from "path";
|
|
9377
|
-
import { execSync as
|
|
9490
|
+
import { execSync as execSync3 } from "child_process";
|
|
9378
9491
|
|
|
9379
9492
|
// src/tools/git-context.ts
|
|
9380
|
-
import { execSync as
|
|
9493
|
+
import { execSync as execSync2 } from "child_process";
|
|
9381
9494
|
import { existsSync as existsSync19 } from "fs";
|
|
9382
9495
|
import { join as join12 } from "path";
|
|
9383
9496
|
function runGit2(cmd, cwd) {
|
|
9384
9497
|
try {
|
|
9385
|
-
return
|
|
9498
|
+
return execSync2(`git ${cmd}`, {
|
|
9386
9499
|
cwd,
|
|
9387
9500
|
encoding: "utf-8",
|
|
9388
9501
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -11112,7 +11225,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11112
11225
|
let diff;
|
|
11113
11226
|
try {
|
|
11114
11227
|
const cmd = staged ? "git diff --staged" : "git diff";
|
|
11115
|
-
diff =
|
|
11228
|
+
diff = execSync3(cmd, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
11116
11229
|
} catch {
|
|
11117
11230
|
this.send({ type: "error", message: "Failed to run git diff." });
|
|
11118
11231
|
break;
|
|
@@ -11151,7 +11264,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11151
11264
|
let secDiff;
|
|
11152
11265
|
try {
|
|
11153
11266
|
const cmd = secStaged ? "git diff --staged" : "git diff";
|
|
11154
|
-
secDiff =
|
|
11267
|
+
secDiff = execSync3(cmd, { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
11155
11268
|
} catch {
|
|
11156
11269
|
this.send({ type: "error", message: "Failed to run git diff." });
|
|
11157
11270
|
break;
|
|
@@ -11229,7 +11342,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
11229
11342
|
case "test": {
|
|
11230
11343
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
11231
11344
|
try {
|
|
11232
|
-
const { executeTests } = await import("./run-tests-
|
|
11345
|
+
const { executeTests } = await import("./run-tests-4XJLQNUW.js");
|
|
11233
11346
|
const argStr = args.join(" ").trim();
|
|
11234
11347
|
let testArgs = {};
|
|
11235
11348
|
if (argStr) {
|
|
@@ -385,7 +385,7 @@ ${content}`);
|
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
388
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
388
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-IQTIXEOM.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-KPX72DTU.js";
|
|
34
34
|
import {
|
|
35
35
|
ConfigManager
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-ING3NMVR.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-CNI26J5Z.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-KLSISB52.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-5IL2BHSD.js";
|
|
93
96
|
|
|
94
97
|
// src/index.ts
|
|
95
98
|
import { program } from "commander";
|
|
@@ -227,7 +230,7 @@ var Renderer = class {
|
|
|
227
230
|
console.log(theme.dim(" Gemini (Google) \xB7 Zhipu (GLM) \xB7 OpenRouter \xB7 Ollama (Local, no API key)"));
|
|
228
231
|
console.log(HR);
|
|
229
232
|
const mcpToolCount = mcpInfo?.tools ?? 0;
|
|
230
|
-
const toolTotal =
|
|
233
|
+
const toolTotal = 29 + pluginCount + mcpToolCount;
|
|
231
234
|
const extras = [];
|
|
232
235
|
if (pluginCount > 0) extras.push(`${pluginCount} plugin(s)`);
|
|
233
236
|
if (mcpToolCount > 0) extras.push(`${mcpToolCount} MCP`);
|
|
@@ -261,14 +264,15 @@ var Renderer = class {
|
|
|
261
264
|
console.log(tool("get_outline", "Enumerate all top-level declarations in one source file"));
|
|
262
265
|
console.log(tool("find_references", "Search indexed files for references to a symbol name"));
|
|
263
266
|
console.log(tool("search_code", 'Semantic (meaning-based) code search via local embeddings \u2014 "grep by meaning", bilingual'));
|
|
267
|
+
console.log(tool("recall_memory", 'Semantic recall over past chat sessions \u2014 "remember when we discussed X" across history (v0.4.89+)'));
|
|
264
268
|
console.log(HR);
|
|
265
|
-
console.log(theme.dim(" REPL Commands (
|
|
269
|
+
console.log(theme.dim(" REPL Commands (43):"));
|
|
266
270
|
console.log(theme.dim(" /help /about /provider /model /clear /compact /plan /session"));
|
|
267
271
|
console.log(theme.dim(" /system /context /status /search /undo /export /copy /paste"));
|
|
268
272
|
console.log(theme.dim(" /cost /init /skill /tools /plugins /mcp /config /checkpoint"));
|
|
269
|
-
console.log(theme.dim(" /review /security-review /rewind /commands /test
|
|
270
|
-
console.log(theme.dim(" /add-dir /memory /profile /doctor /bug /think
|
|
271
|
-
console.log(theme.dim(" /branch /index /yolo /exit"));
|
|
273
|
+
console.log(theme.dim(" /review /security-review /security /rewind /commands /test"));
|
|
274
|
+
console.log(theme.dim(" /scaffold /add-dir /memory /profile /doctor /bug /think"));
|
|
275
|
+
console.log(theme.dim(" /diff /fork /branch /index /yolo /exit"));
|
|
272
276
|
console.log(HR);
|
|
273
277
|
console.log(theme.dim(" Key Features:"));
|
|
274
278
|
console.log(feat("Agentic loop (up to 200 tool-call rounds, configurable via config/CLI, final answer streamed)"));
|
|
@@ -338,6 +342,12 @@ var Renderer = class {
|
|
|
338
342
|
console.log(feat("Anthropic Batches API (A3, v0.4.73+): aicli batch submit/list/status/results/cancel \u2014 50% off, 24h window"));
|
|
339
343
|
console.log(feat("Session Replay (B1, v0.4.71+): Web UI \u{1F3AC} button \u2014 timeline view of every message, tool call, reasoning, and cache-aware token usage"));
|
|
340
344
|
console.log(feat("Conversation Branching (B2, v0.4.74+): /branch list/new/switch/delete/rename \u2014 fork the conversation at any message; Web UI replay \u{1F33F} fork-here button"));
|
|
345
|
+
console.log(feat("Branch tree sidebar (B2 polish, v0.4.75+): Web UI \u{1F33F} Branches tab with tree-indented picker, click to switch, hover to rename/delete, + Fork button"));
|
|
346
|
+
console.log(feat("Cross-branch ops (B3, v0.4.80+): /branch diff and /branch cherry-pick \u2014 compare branches and pick messages across forks; v0.4.81 accepts id/title/prefix"));
|
|
347
|
+
console.log(feat("MCP Server mode (E1, v0.4.84+): aicli mcp-serve \u2014 reverse aicli into an MCP server so Claude Desktop/Cursor/any MCP client can use its 26 built-in tools (including find_symbol/search_code)"));
|
|
348
|
+
console.log(feat("Session sensitive-data redaction (v0.4.88+): unified redactor scrubs passwords/tokens/keys from every message before it hits disk; /security status and scan to audit"));
|
|
349
|
+
console.log(feat('Chat memory recall (B4, v0.4.89+): "human-like long-term memory" \u2014 semantic index over all past sessions + recall_memory AI tool + /memory rebuild|refresh|status|recall, AI auto-recalls on "last time"/"\u4E0A\u6B21"'));
|
|
350
|
+
console.log(feat("Web UI Memory panel (B4, v0.4.90+): \u{1F9E0} Memory sidebar tab \u2014 cross-session semantic search with \u2795 Inject-to-input (quotes hit into chat box for user-reviewed recall) and \u2197 jump-to-session"));
|
|
341
351
|
console.log();
|
|
342
352
|
}
|
|
343
353
|
printPrompt(provider, _model) {
|
|
@@ -982,7 +992,7 @@ function createDefaultCommands() {
|
|
|
982
992
|
" /scaffold <description> - Generate project scaffolding with AI",
|
|
983
993
|
" /add-dir [path|remove] - Add/remove a directory from AI context",
|
|
984
994
|
" /profile [show|set|clear] - View or edit your identity (AI knows who you are)",
|
|
985
|
-
" /memory [show|add|clear] -
|
|
995
|
+
" /memory [show|add|clear|path|rebuild|refresh|status|recall <q>|index-clear] - Persistent memory + chat memory recall index (v0.4.89+)",
|
|
986
996
|
" /doctor - Health check (API keys, config, MCP status)",
|
|
987
997
|
" /bug [--copy] - Generate bug report template (--copy to clipboard)",
|
|
988
998
|
" /diff [--stats] - Show all file modifications in this session",
|
|
@@ -2602,7 +2612,7 @@ ${hint}` : "")
|
|
|
2602
2612
|
usage: "/test [command|filter]",
|
|
2603
2613
|
async execute(args, ctx) {
|
|
2604
2614
|
try {
|
|
2605
|
-
const { executeTests } = await import("./run-tests-
|
|
2615
|
+
const { executeTests } = await import("./run-tests-JROEDZES.js");
|
|
2606
2616
|
const argStr = args.join(" ").trim();
|
|
2607
2617
|
let testArgs = {};
|
|
2608
2618
|
if (argStr) {
|
|
@@ -5090,6 +5100,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5090
5100
|
this.rl.on("SIGINT", () => {
|
|
5091
5101
|
if (this.streamAbortController) {
|
|
5092
5102
|
this.streamAbortController.abort();
|
|
5103
|
+
requestInterrupt();
|
|
5093
5104
|
return;
|
|
5094
5105
|
}
|
|
5095
5106
|
if (this.toolExecutor.confirming) {
|
|
@@ -5100,6 +5111,11 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5100
5111
|
askUserContext.cancelFn();
|
|
5101
5112
|
return;
|
|
5102
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
|
+
}
|
|
5103
5119
|
this.handleExit();
|
|
5104
5120
|
});
|
|
5105
5121
|
this.showPrompt();
|
|
@@ -5230,6 +5246,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5230
5246
|
`)
|
|
5231
5247
|
);
|
|
5232
5248
|
}
|
|
5249
|
+
resetInterrupt();
|
|
5233
5250
|
const t0 = Date.now();
|
|
5234
5251
|
try {
|
|
5235
5252
|
const provider = this.providers.get(this.currentProvider);
|
|
@@ -6233,6 +6250,12 @@ ${systemPromptVolatile}` : systemPrompt;
|
|
|
6233
6250
|
spawnAgentContext.configManager = this.config;
|
|
6234
6251
|
ToolExecutor.currentMessageIndex = session.messages.length;
|
|
6235
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
|
+
}
|
|
6236
6259
|
const thisRoundTools = result.toolCalls.map((tc) => tc.name);
|
|
6237
6260
|
roundToolHistory.push({ round: round + 1, tools: thisRoundTools });
|
|
6238
6261
|
const readFileCalls = result.toolCalls.filter((tc) => tc.name === "read_file");
|
|
@@ -6715,7 +6738,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
6715
6738
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
6716
6739
|
process.exit(1);
|
|
6717
6740
|
}
|
|
6718
|
-
const { startWebServer } = await import("./server-
|
|
6741
|
+
const { startWebServer } = await import("./server-WHTZFKVB.js");
|
|
6719
6742
|
await startWebServer({ port, host: options.host });
|
|
6720
6743
|
});
|
|
6721
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) => {
|
|
@@ -6838,7 +6861,7 @@ program.command("sessions").description("List recent conversation sessions").act
|
|
|
6838
6861
|
});
|
|
6839
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) => {
|
|
6840
6863
|
try {
|
|
6841
|
-
const batch = await import("./batch-
|
|
6864
|
+
const batch = await import("./batch-SK2YCZEY.js");
|
|
6842
6865
|
switch (action) {
|
|
6843
6866
|
case "submit":
|
|
6844
6867
|
if (!arg) {
|
|
@@ -6881,7 +6904,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
6881
6904
|
}
|
|
6882
6905
|
});
|
|
6883
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) => {
|
|
6884
|
-
const { startMcpServer } = await import("./server-
|
|
6907
|
+
const { startMcpServer } = await import("./server-DB4GMBDN.js");
|
|
6885
6908
|
await startMcpServer({
|
|
6886
6909
|
allowDestructive: !!options.allowDestructive,
|
|
6887
6910
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7008,7 +7031,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7008
7031
|
}),
|
|
7009
7032
|
config.get("customProviders")
|
|
7010
7033
|
);
|
|
7011
|
-
const { startHub } = await import("./hub-
|
|
7034
|
+
const { startHub } = await import("./hub-YRYUBSEQ.js");
|
|
7012
7035
|
await startHub(
|
|
7013
7036
|
{
|
|
7014
7037
|
topic: topic ?? "",
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
schemaToJsonSchema
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CNI26J5Z.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-KLSISB52.js";
|
|
16
16
|
import {
|
|
17
17
|
VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-5IL2BHSD.js";
|
|
19
19
|
|
|
20
20
|
// src/mcp/server.ts
|
|
21
21
|
import { createInterface } from "readline";
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
persistToolRound,
|
|
24
24
|
rebuildExtraMessages,
|
|
25
25
|
setupProxy
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-KPX72DTU.js";
|
|
27
27
|
import {
|
|
28
28
|
ConfigManager
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ING3NMVR.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-CNI26J5Z.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-KLSISB52.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-5IL2BHSD.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-JROEDZES.js");
|
|
2241
2241
|
const argStr = args.join(" ").trim();
|
|
2242
2242
|
let testArgs = {};
|
|
2243
2243
|
if (argStr) {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-CNI26J5Z.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-KLSISB52.js";
|
|
17
17
|
import {
|
|
18
18
|
SUBAGENT_ALLOWED_TOOLS
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-5IL2BHSD.js";
|
|
20
20
|
|
|
21
21
|
// src/hub/task-orchestrator.ts
|
|
22
22
|
import { createInterface } from "readline";
|