jinzd-ai-cli 0.4.63 → 0.4.65
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 +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/{chunk-EYRPTNVI.js → chunk-2B2EVU6Z.js} +19 -6
- package/dist/{chunk-MLEM56CR.js → chunk-AQNAV4H4.js} +1 -1
- package/dist/{chunk-E45EGVSY.js → chunk-SKN6HBBT.js} +12 -5
- package/dist/{chunk-GUD733DE.js → chunk-UNLZJRCY.js} +1 -1
- package/dist/{hub-R6ID4F6J.js → hub-TKYPJZEX.js} +1 -1
- package/dist/index.js +13 -8
- package/dist/{run-tests-KRGPFYPF.js → run-tests-C4CEOYZP.js} +1 -1
- package/dist/{run-tests-A53KBZPJ.js → run-tests-KATYWRVQ.js} +1 -1
- package/dist/{server-BGMUORHT.js → server-CDRR3DC7.js} +21 -9
- package/dist/{task-orchestrator-LNJWNTSJ.js → task-orchestrator-4DCUYIRI.js} +2 -2
- 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
|
|
|
@@ -378,11 +378,11 @@ The Web UI (`aicli web`) provides a full-featured browser interface:
|
|
|
378
378
|
## Testing
|
|
379
379
|
|
|
380
380
|
```bash
|
|
381
|
-
npm test # Run all
|
|
381
|
+
npm test # Run all 396 tests
|
|
382
382
|
npm run test:watch # Watch mode
|
|
383
383
|
```
|
|
384
384
|
|
|
385
|
-
|
|
385
|
+
26 test suites covering: authentication, sessions, tool types & danger levels, permissions, output truncation, diff rendering, edit-file similarity, error hierarchy, config management, env loading, provider registry, web-fetch, grep-files, hub renderer, hub discussion, hub presets, dev-state, token estimator, tool registry budget, parallel tool execution, cost tracker, session tool history.
|
|
386
386
|
|
|
387
387
|
## Documentation
|
|
388
388
|
|
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
|
|
|
@@ -391,11 +391,11 @@ Web UI(`aicli web`)提供功能完备的浏览器界面:
|
|
|
391
391
|
## 测试
|
|
392
392
|
|
|
393
393
|
```bash
|
|
394
|
-
npm test # 运行全部
|
|
394
|
+
npm test # 运行全部 396 个测试
|
|
395
395
|
npm run test:watch # 监听模式
|
|
396
396
|
```
|
|
397
397
|
|
|
398
|
-
|
|
398
|
+
26 个测试套件覆盖:认证、会话、工具类型与危险级别、权限、输出截断、diff 渲染、edit-file 相似度、错误层级、配置管理、环境变量、Provider 注册、web-fetch、grep-files、Hub 渲染、Hub 讨论、Hub 预设、开发状态、Token 估算、工具注册表预算、并行工具执行、费用追踪、会话工具历史。
|
|
399
399
|
|
|
400
400
|
## 文档
|
|
401
401
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
RateLimitError,
|
|
9
9
|
schemaToJsonSchema,
|
|
10
10
|
truncateForPersist
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SKN6HBBT.js";
|
|
12
12
|
import {
|
|
13
13
|
APP_NAME,
|
|
14
14
|
CONFIG_DIR_NAME,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
MCP_TOOL_PREFIX,
|
|
22
22
|
PLUGINS_DIR_NAME,
|
|
23
23
|
VERSION
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-AQNAV4H4.js";
|
|
25
25
|
|
|
26
26
|
// src/config/config-manager.ts
|
|
27
27
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -3752,16 +3752,29 @@ function rebuildExtraMessages(provider, toolHistory) {
|
|
|
3752
3752
|
let j = i + 1;
|
|
3753
3753
|
while (j < toolHistory.length && toolHistory[j].role === "tool") {
|
|
3754
3754
|
const tm = toolHistory[j];
|
|
3755
|
+
if (!tm.toolCallId) {
|
|
3756
|
+
console.warn(
|
|
3757
|
+
`[rebuildExtraMessages] Skipping malformed tool message (missing toolCallId) at index ${j}; tool name="${toolCalls.find((_tc) => true)?.name ?? "unknown"}"`
|
|
3758
|
+
);
|
|
3759
|
+
j++;
|
|
3760
|
+
continue;
|
|
3761
|
+
}
|
|
3755
3762
|
toolResults.push({
|
|
3756
|
-
callId: tm.toolCallId
|
|
3763
|
+
callId: tm.toolCallId,
|
|
3757
3764
|
content: typeof tm.content === "string" ? tm.content : getContentText(tm.content),
|
|
3758
3765
|
isError: tm.isError ?? false
|
|
3759
3766
|
});
|
|
3760
3767
|
j++;
|
|
3761
3768
|
}
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3769
|
+
if (toolResults.length > 0) {
|
|
3770
|
+
result.push(
|
|
3771
|
+
...provider.buildToolResultMessages(toolCalls, toolResults, msg.reasoningContent)
|
|
3772
|
+
);
|
|
3773
|
+
} else {
|
|
3774
|
+
console.warn(
|
|
3775
|
+
`[rebuildExtraMessages] Dropping assistant turn with ${toolCalls.length} toolCalls but no valid tool results`
|
|
3776
|
+
);
|
|
3777
|
+
}
|
|
3765
3778
|
i = j;
|
|
3766
3779
|
} else {
|
|
3767
3780
|
result.push({
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
11
11
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
12
12
|
runTestsTool
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-AQNAV4H4.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/builtin/bash.ts
|
|
16
16
|
import { execSync } from "child_process";
|
|
@@ -1386,12 +1386,19 @@ var ToolExecutor = class {
|
|
|
1386
1386
|
}
|
|
1387
1387
|
const results = new Array(calls.length);
|
|
1388
1388
|
const t0 = Date.now();
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1389
|
+
const wrapExec = async (idx, call) => {
|
|
1390
|
+
try {
|
|
1391
|
+
results[idx] = await this.execute(call);
|
|
1392
|
+
} catch (err) {
|
|
1393
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1394
|
+
console.error(`[executor] Unexpected error in tool "${call.name}":`, err);
|
|
1395
|
+
results[idx] = { callId: call.id, content: `Tool execution failed: ${msg}`, isError: true };
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
const parallelPhase = safeParallel.length > 0 ? Promise.all(safeParallel.map(({ idx, call }) => wrapExec(idx, call))) : Promise.resolve();
|
|
1392
1399
|
const bashPhase = (async () => {
|
|
1393
1400
|
for (const { idx, call } of safeBash) {
|
|
1394
|
-
|
|
1401
|
+
await wrapExec(idx, call);
|
|
1395
1402
|
}
|
|
1396
1403
|
})();
|
|
1397
1404
|
await Promise.all([parallelPhase, bashPhase]);
|
|
@@ -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-4DCUYIRI.js");
|
|
389
389
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
390
390
|
let interrupted = false;
|
|
391
391
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
saveDevState,
|
|
32
32
|
sessionHasMeaningfulContent,
|
|
33
33
|
setupProxy
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-2B2EVU6Z.js";
|
|
35
35
|
import {
|
|
36
36
|
ToolExecutor,
|
|
37
37
|
ToolRegistry,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
spawnAgentContext,
|
|
47
47
|
theme,
|
|
48
48
|
undoStack
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-SKN6HBBT.js";
|
|
50
50
|
import {
|
|
51
51
|
fileCheckpoints
|
|
52
52
|
} from "./chunk-4BKXL7SM.js";
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
SKILLS_DIR_NAME,
|
|
72
72
|
VERSION,
|
|
73
73
|
buildUserIdentityPrompt
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-AQNAV4H4.js";
|
|
75
75
|
|
|
76
76
|
// src/index.ts
|
|
77
77
|
import { program } from "commander";
|
|
@@ -249,7 +249,7 @@ var Renderer = class {
|
|
|
249
249
|
console.log(theme.dim(" /yolo /exit"));
|
|
250
250
|
console.log(HR);
|
|
251
251
|
console.log(theme.dim(" Key Features:"));
|
|
252
|
-
console.log(feat("Agentic loop (up to
|
|
252
|
+
console.log(feat("Agentic loop (up to 200 tool-call rounds, configurable via config/CLI, final answer streamed)"));
|
|
253
253
|
console.log(feat("Multimodal input: @filepath to inline images (base64) or text into messages"));
|
|
254
254
|
console.log(feat("Git context awareness: auto-inject branch name and file change status on startup"));
|
|
255
255
|
console.log(feat("Project context files: auto-load AICLI.md / CLAUDE.md (3 levels: global/project/subdir)"));
|
|
@@ -306,6 +306,11 @@ var Renderer = class {
|
|
|
306
306
|
console.log(feat("Context injection: aicli hub -c doc.md \u2014 inject external documents for all agents"));
|
|
307
307
|
console.log(feat("Task Mode: aicli hub --task \u2014 agents plan, write code, and execute with tools (plan\u2192approve\u2192execute\u2192review)"));
|
|
308
308
|
console.log(feat("Ollama local models: built-in provider, no API key, auto-discovers installed models via /v1/models"));
|
|
309
|
+
console.log(feat("MCP tool budget: auto-trim MCP tool definitions when exceeding 20% context window, prioritize used tools"));
|
|
310
|
+
console.log(feat("Smart compact: tool-history-aware compression preserves full tool call rounds (no mid-round splits)"));
|
|
311
|
+
console.log(feat("Session size control: auto-trim old tool output when session exceeds 2MB, keep recent rounds intact"));
|
|
312
|
+
console.log(feat("Crash recovery: detect incomplete agentic loops on /resume, warn and offer continuation"));
|
|
313
|
+
console.log(feat("Cost dashboard: /cost history shows cross-session daily/weekly/monthly spend with budget progress bar"));
|
|
309
314
|
console.log();
|
|
310
315
|
}
|
|
311
316
|
printPrompt(provider, _model) {
|
|
@@ -938,7 +943,7 @@ function createDefaultCommands() {
|
|
|
938
943
|
" /config [set|get|show] - Config wizard, or get/set values, show all",
|
|
939
944
|
" /copy - Copy last AI response to clipboard",
|
|
940
945
|
" /paste [description] - Read image from clipboard and send to AI",
|
|
941
|
-
" /cost [reset]
|
|
946
|
+
" /cost [reset | history] - Show session token usage, reset, or cross-session cost dashboard",
|
|
942
947
|
" /init [--force] - Generate AICLI.md by scanning project structure",
|
|
943
948
|
" /skill [name|off|list] - Manage agent skills (reusable prompt packs)",
|
|
944
949
|
" /checkpoint [save|restore|delete] <name> - Session checkpoints",
|
|
@@ -2188,7 +2193,7 @@ ${hint}` : "")
|
|
|
2188
2193
|
usage: "/test [command|filter]",
|
|
2189
2194
|
async execute(args, ctx) {
|
|
2190
2195
|
try {
|
|
2191
|
-
const { executeTests } = await import("./run-tests-
|
|
2196
|
+
const { executeTests } = await import("./run-tests-C4CEOYZP.js");
|
|
2192
2197
|
const argStr = args.join(" ").trim();
|
|
2193
2198
|
let testArgs = {};
|
|
2194
2199
|
if (argStr) {
|
|
@@ -5900,7 +5905,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
5900
5905
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
5901
5906
|
process.exit(1);
|
|
5902
5907
|
}
|
|
5903
|
-
const { startWebServer } = await import("./server-
|
|
5908
|
+
const { startWebServer } = await import("./server-CDRR3DC7.js");
|
|
5904
5909
|
await startWebServer({ port, host: options.host });
|
|
5905
5910
|
});
|
|
5906
5911
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -6133,7 +6138,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
6133
6138
|
}),
|
|
6134
6139
|
config.get("customProviders")
|
|
6135
6140
|
);
|
|
6136
|
-
const { startHub } = await import("./hub-
|
|
6141
|
+
const { startHub } = await import("./hub-TKYPJZEX.js");
|
|
6137
6142
|
await startHub(
|
|
6138
6143
|
{
|
|
6139
6144
|
topic: topic ?? "",
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
persistToolRound,
|
|
22
22
|
rebuildExtraMessages,
|
|
23
23
|
setupProxy
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2B2EVU6Z.js";
|
|
25
25
|
import {
|
|
26
26
|
AuthManager
|
|
27
27
|
} from "./chunk-BYNY5JPB.js";
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
spawnAgentContext,
|
|
42
42
|
truncateOutput,
|
|
43
43
|
undoStack
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-SKN6HBBT.js";
|
|
45
45
|
import "./chunk-4BKXL7SM.js";
|
|
46
46
|
import {
|
|
47
47
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
SKILLS_DIR_NAME,
|
|
62
62
|
VERSION,
|
|
63
63
|
buildUserIdentityPrompt
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-AQNAV4H4.js";
|
|
65
65
|
|
|
66
66
|
// src/web/server.ts
|
|
67
67
|
import express from "express";
|
|
@@ -345,12 +345,19 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
const results = new Array(calls.length);
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
348
|
+
const wrapExec = async (idx, call) => {
|
|
349
|
+
try {
|
|
350
|
+
results[idx] = await this.execute(call);
|
|
351
|
+
} catch (err) {
|
|
352
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
353
|
+
console.error(`[tool-executor-web] Unexpected error in tool "${call.name}":`, err);
|
|
354
|
+
results[idx] = { callId: call.id, content: `Tool execution failed: ${msg}`, isError: true };
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
const parallelPhase = safeParallel.length > 0 ? Promise.all(safeParallel.map(({ idx, call }) => wrapExec(idx, call))) : Promise.resolve();
|
|
351
358
|
const bashPhase = (async () => {
|
|
352
359
|
for (const { idx, call } of safeBash) {
|
|
353
|
-
|
|
360
|
+
await wrapExec(idx, call);
|
|
354
361
|
}
|
|
355
362
|
})();
|
|
356
363
|
await Promise.all([parallelPhase, bashPhase]);
|
|
@@ -527,6 +534,8 @@ var SessionHandler = class _SessionHandler {
|
|
|
527
534
|
activeSystemPrompt;
|
|
528
535
|
/** Directories added via /add-dir */
|
|
529
536
|
addedDirs = /* @__PURE__ */ new Set();
|
|
537
|
+
/** Track MCP tool names used across this session (for MCP budget prioritization) */
|
|
538
|
+
usedMcpToolNames = /* @__PURE__ */ new Set();
|
|
530
539
|
/**
|
|
531
540
|
* 未保存会话的内存缓存(per-handler)。
|
|
532
541
|
* 当客户端通过 `session new` 创建新会话时,会话仅存在于 SessionManager._current 中,
|
|
@@ -1038,6 +1047,9 @@ Details: ${errMsg.split("\n")[0]}
|
|
|
1038
1047
|
round: round + 1,
|
|
1039
1048
|
tools: result.toolCalls.map((tc) => tc.name)
|
|
1040
1049
|
});
|
|
1050
|
+
for (const tc of result.toolCalls) {
|
|
1051
|
+
if (tc.name.startsWith("mcp__")) this.usedMcpToolNames.add(tc.name);
|
|
1052
|
+
}
|
|
1041
1053
|
googleSearchContext.configManager = this.config;
|
|
1042
1054
|
spawnAgentContext.provider = provider;
|
|
1043
1055
|
spawnAgentContext.model = this.currentModel;
|
|
@@ -1959,7 +1971,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1959
1971
|
case "test": {
|
|
1960
1972
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
1961
1973
|
try {
|
|
1962
|
-
const { executeTests } = await import("./run-tests-
|
|
1974
|
+
const { executeTests } = await import("./run-tests-C4CEOYZP.js");
|
|
1963
1975
|
const argStr = args.join(" ").trim();
|
|
1964
1976
|
let testArgs = {};
|
|
1965
1977
|
if (argStr) {
|
|
@@ -2563,7 +2575,7 @@ Add .md files to create commands.` });
|
|
|
2563
2575
|
const contextWindow = this.getContextWindowSize();
|
|
2564
2576
|
if (contextWindow > 0) {
|
|
2565
2577
|
const toolBudget = Math.floor(contextWindow * 0.2);
|
|
2566
|
-
const { definitions, systemNote } = this.toolRegistry.getDefinitionsWithBudget(toolBudget);
|
|
2578
|
+
const { definitions, systemNote } = this.toolRegistry.getDefinitionsWithBudget(toolBudget, this.usedMcpToolNames);
|
|
2567
2579
|
return { toolDefs: definitions, mcpBudgetNote: systemNote };
|
|
2568
2580
|
}
|
|
2569
2581
|
return { toolDefs: this.toolRegistry.getDefinitions(), mcpBudgetNote: null };
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SKN6HBBT.js";
|
|
8
8
|
import "./chunk-4BKXL7SM.js";
|
|
9
9
|
import {
|
|
10
10
|
SUBAGENT_ALLOWED_TOOLS
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-AQNAV4H4.js";
|
|
12
12
|
|
|
13
13
|
// src/hub/task-orchestrator.ts
|
|
14
14
|
import { createInterface } from "readline";
|