jinzd-ai-cli 0.2.8 → 0.2.10
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/{chunk-2BG44VOT.js → chunk-MBIHQ34V.js} +3 -2
- package/dist/{chunk-DE3WM5PH.js → chunk-OOLIOMNF.js} +8 -1
- package/dist/index.js +86 -7
- package/dist/{run-tests-QZXMPFFF.js → run-tests-RAXI3LMY.js} +1 -1
- package/dist/{server-NYO2HSST.js → server-HYAIDK7B.js} +19 -3
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
17
17
|
VERSION,
|
|
18
18
|
runTestsTool
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-OOLIOMNF.js";
|
|
20
20
|
|
|
21
21
|
// src/config/config-manager.ts
|
|
22
22
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -1482,7 +1482,8 @@ var DeepSeekProvider = class extends OpenAICompatibleProvider {
|
|
|
1482
1482
|
*/
|
|
1483
1483
|
async chatWithTools(request, tools) {
|
|
1484
1484
|
const result = await super.chatWithTools(request, tools);
|
|
1485
|
-
|
|
1485
|
+
const hasBashTool = tools.some((t) => t.name === "bash");
|
|
1486
|
+
if (hasBashTool && "content" in result && result.content && detectsCodeBlockPseudoCall(result.content)) {
|
|
1486
1487
|
process.stderr.write(
|
|
1487
1488
|
`[deepseek] \u26A0 Detected code block pseudo-tool-call (DeepSeek wrote code in text instead of calling a tool). Forcing retry...
|
|
1488
1489
|
`
|
|
@@ -8,7 +8,7 @@ import { platform } from "os";
|
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/core/constants.ts
|
|
11
|
-
var VERSION = "0.2.
|
|
11
|
+
var VERSION = "0.2.10";
|
|
12
12
|
var APP_NAME = "ai-cli";
|
|
13
13
|
var CONFIG_DIR_NAME = ".aicli";
|
|
14
14
|
var CONFIG_FILE_NAME = "config.json";
|
|
@@ -54,6 +54,13 @@ You are currently in read-only planning (Plan) mode.
|
|
|
54
54
|
- Execution order and dependencies
|
|
55
55
|
- Potential risks and considerations
|
|
56
56
|
|
|
57
|
+
**CRITICAL RULES**:
|
|
58
|
+
- Do NOT attempt to call bash, write_file, edit_file, or any disabled tool \u2014 they will fail silently.
|
|
59
|
+
- Do NOT write shell commands, SQL queries, or code in your text response as a substitute for tool calls \u2014 the user's system will misinterpret this as a pseudo-tool-call error.
|
|
60
|
+
- If the user asks you to run commands, test connections, or modify files, respond with: "This requires execution tools. Please type \`/plan execute\` to switch to execute mode, then I can perform these operations."
|
|
61
|
+
- Do NOT call write_todos repeatedly with the same content \u2014 call it once, then give a text response.
|
|
62
|
+
- Focus your analysis on reading files and producing actionable plans.
|
|
63
|
+
|
|
57
64
|
Once planning is complete, clearly inform the user: type \`/plan execute\` to begin executing the plan, or \`/plan exit\` to discard it.`;
|
|
58
65
|
var SUBAGENT_DEFAULT_MAX_ROUNDS = 10;
|
|
59
66
|
var SUBAGENT_MAX_ROUNDS_LIMIT = 15;
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
theme,
|
|
36
36
|
truncateOutput,
|
|
37
37
|
undoStack
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-MBIHQ34V.js";
|
|
39
39
|
import {
|
|
40
40
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
41
41
|
AUTHOR,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
REPO_URL,
|
|
56
56
|
SKILLS_DIR_NAME,
|
|
57
57
|
VERSION
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-OOLIOMNF.js";
|
|
59
59
|
|
|
60
60
|
// src/index.ts
|
|
61
61
|
import { program } from "commander";
|
|
@@ -1904,7 +1904,7 @@ ${hint}` : "")
|
|
|
1904
1904
|
description: "Run project tests and show structured report",
|
|
1905
1905
|
usage: "/test [command|filter]",
|
|
1906
1906
|
async execute(args, _ctx) {
|
|
1907
|
-
const { executeTests } = await import("./run-tests-
|
|
1907
|
+
const { executeTests } = await import("./run-tests-RAXI3LMY.js");
|
|
1908
1908
|
const argStr = args.join(" ").trim();
|
|
1909
1909
|
let testArgs = {};
|
|
1910
1910
|
if (argStr) {
|
|
@@ -3311,7 +3311,9 @@ ${content}
|
|
|
3311
3311
|
}
|
|
3312
3312
|
var MAX_TOOL_ROUNDS = 25;
|
|
3313
3313
|
var FREE_ROUND_TOOLS = /* @__PURE__ */ new Set(["write_todos"]);
|
|
3314
|
-
var MAX_CONSECUTIVE_FREE_ROUNDS =
|
|
3314
|
+
var MAX_CONSECUTIVE_FREE_ROUNDS = 3;
|
|
3315
|
+
var MAX_REPEATED_TOOL_CALLS = 2;
|
|
3316
|
+
var AUTO_PAUSE_INTERVAL = 10;
|
|
3315
3317
|
function fmtTokens(n) {
|
|
3316
3318
|
if (n >= 1e6) return `${Math.round(n / 1e5) / 10}M`;
|
|
3317
3319
|
if (n >= 1e3) return `${Math.round(n / 1024)}K`;
|
|
@@ -4801,13 +4803,24 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4801
4803
|
}
|
|
4802
4804
|
const apiMessages = [...messages];
|
|
4803
4805
|
const extraMessages = [];
|
|
4804
|
-
const
|
|
4806
|
+
const baseSystemPrompt = (this.buildCurrentSystemPrompt() ?? "") + TOOL_CALL_REMINDER;
|
|
4807
|
+
const roundBudgetHint = `
|
|
4808
|
+
|
|
4809
|
+
[Tool Round Budget]
|
|
4810
|
+
You have a maximum of ${MAX_TOOL_ROUNDS} tool call rounds for this task. Plan efficiently:
|
|
4811
|
+
- Prefer batch operations (e.g. global find-and-replace) over repetitive single edits.
|
|
4812
|
+
- Prioritize the most critical tasks first in case rounds run out.
|
|
4813
|
+
- When remaining rounds are low (\u22645), focus on completing the current task and summarizing.
|
|
4814
|
+
- Every ${AUTO_PAUSE_INTERVAL} rounds the user will be asked whether to continue \u2014 use this as a natural checkpoint to report progress.`;
|
|
4815
|
+
const systemPrompt = baseSystemPrompt + roundBudgetHint;
|
|
4805
4816
|
const modelParams = this.getModelParams();
|
|
4806
4817
|
const useStreaming = this.config.get("ui").streaming;
|
|
4807
4818
|
const spinner = this.renderer.showSpinner("Thinking...");
|
|
4808
4819
|
const roundUsage = { inputTokens: 0, outputTokens: 0 };
|
|
4809
4820
|
const supportsStreamingTools = useStreaming && typeof provider.chatWithToolsStream === "function";
|
|
4810
4821
|
let consecutiveFreeRounds = 0;
|
|
4822
|
+
let lastToolCallSignature = "";
|
|
4823
|
+
let repeatedToolCallCount = 0;
|
|
4811
4824
|
this.setupInterjectionListener();
|
|
4812
4825
|
process.stdout.write(theme.dim(" (Type a message + Enter to redirect AI at any time)\n"));
|
|
4813
4826
|
try {
|
|
@@ -4827,6 +4840,15 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4827
4840
|
`));
|
|
4828
4841
|
extraMessages.push({ role: "user", content: cmd });
|
|
4829
4842
|
}
|
|
4843
|
+
const roundsLeft = MAX_TOOL_ROUNDS - round;
|
|
4844
|
+
if (roundsLeft === 5) {
|
|
4845
|
+
extraMessages.push({
|
|
4846
|
+
role: "user",
|
|
4847
|
+
content: `\u26A0\uFE0F Budget warning: Only ${roundsLeft} tool rounds remaining. Prioritize completing the most critical task. If you cannot finish everything, summarize what's done and what remains.`
|
|
4848
|
+
});
|
|
4849
|
+
process.stdout.write(theme.warning(` \u26A0\uFE0F Low budget: ${roundsLeft} rounds remaining
|
|
4850
|
+
`));
|
|
4851
|
+
}
|
|
4830
4852
|
if (this._userInterjection) {
|
|
4831
4853
|
const msg = this._userInterjection;
|
|
4832
4854
|
this._userInterjection = null;
|
|
@@ -4882,7 +4904,8 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4882
4904
|
if ("content" in result) {
|
|
4883
4905
|
const hasWriteTools = toolDefs.some((t) => t.name === "write_file" || t.name === "edit_file");
|
|
4884
4906
|
const alreadyWrote = hadPreviousWriteToolCalls(extraMessages);
|
|
4885
|
-
if (
|
|
4907
|
+
if (!this.planMode && // Plan Mode 下跳过虚假声明检测
|
|
4908
|
+
hasWriteTools && !alreadyWrote && result.content && detectsHallucinatedFileOp(result.content) && round < MAX_TOOL_ROUNDS - 1) {
|
|
4886
4909
|
const providerName = this.currentProvider;
|
|
4887
4910
|
process.stderr.write(
|
|
4888
4911
|
`[${providerName}] \u26A0 Hallucinated completion detected (AI claimed file was written but no tool was called), forcing retry...
|
|
@@ -5024,6 +5047,28 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5024
5047
|
} else {
|
|
5025
5048
|
consecutiveFreeRounds = 0;
|
|
5026
5049
|
}
|
|
5050
|
+
const currentSignature = result.toolCalls.map((tc) => `${tc.name}:${JSON.stringify(tc.arguments)}`).join("|");
|
|
5051
|
+
if (currentSignature === lastToolCallSignature) {
|
|
5052
|
+
repeatedToolCallCount++;
|
|
5053
|
+
if (repeatedToolCallCount >= MAX_REPEATED_TOOL_CALLS) {
|
|
5054
|
+
spinner.stop();
|
|
5055
|
+
process.stderr.write(
|
|
5056
|
+
theme.warning(`
|
|
5057
|
+
\u26A0 Detected ${repeatedToolCallCount + 1} identical consecutive tool calls \u2014 breaking loop.
|
|
5058
|
+
`)
|
|
5059
|
+
);
|
|
5060
|
+
extraMessages.push({
|
|
5061
|
+
role: "user",
|
|
5062
|
+
content: "You are stuck in a loop calling the same tool with the same arguments repeatedly. Stop calling tools and give the user a final text response summarizing what you found and what needs to be done next. " + (this.planMode ? "If you need to execute commands (bash, psql, etc.), tell the user to type `/plan execute` first." : "")
|
|
5063
|
+
});
|
|
5064
|
+
repeatedToolCallCount = 0;
|
|
5065
|
+
lastToolCallSignature = "";
|
|
5066
|
+
continue;
|
|
5067
|
+
}
|
|
5068
|
+
} else {
|
|
5069
|
+
lastToolCallSignature = currentSignature;
|
|
5070
|
+
repeatedToolCallCount = 0;
|
|
5071
|
+
}
|
|
5027
5072
|
if (this._userInterjection) {
|
|
5028
5073
|
const msg = this._userInterjection;
|
|
5029
5074
|
this._userInterjection = null;
|
|
@@ -5031,6 +5076,40 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5031
5076
|
`));
|
|
5032
5077
|
extraMessages.push({ role: "user", content: msg });
|
|
5033
5078
|
}
|
|
5079
|
+
const effectiveRound = round + 1;
|
|
5080
|
+
const remaining = MAX_TOOL_ROUNDS - effectiveRound;
|
|
5081
|
+
if (AUTO_PAUSE_INTERVAL > 0 && effectiveRound > 0 && effectiveRound % AUTO_PAUSE_INTERVAL === 0 && remaining > 0) {
|
|
5082
|
+
spinner.stop();
|
|
5083
|
+
process.stdout.write("\n");
|
|
5084
|
+
process.stdout.write(theme.warning(`\u23F8 Auto-pause: ${effectiveRound}/${MAX_TOOL_ROUNDS} rounds used, ${remaining} remaining
|
|
5085
|
+
`));
|
|
5086
|
+
process.stdout.write(theme.dim(" Press ") + theme.info("y") + theme.dim(" to continue, or ") + theme.info("type a message") + theme.dim(" to redirect AI:\n"));
|
|
5087
|
+
process.stdout.write(theme.dim(" (Press ") + theme.info("n") + theme.dim(" or ") + theme.info("Esc") + theme.dim(" to stop)\n"));
|
|
5088
|
+
this.teardownInterjectionListener();
|
|
5089
|
+
const pauseResponse = await new Promise((resolve3) => {
|
|
5090
|
+
const savedOutput = this.rl.output;
|
|
5091
|
+
this.rl.output = process.stdout;
|
|
5092
|
+
this.rl.question(theme.warning(" \u25B8 "), (answer) => {
|
|
5093
|
+
this.rl.output = savedOutput;
|
|
5094
|
+
resolve3(answer.trim());
|
|
5095
|
+
});
|
|
5096
|
+
});
|
|
5097
|
+
this.setupInterjectionListener();
|
|
5098
|
+
if (pauseResponse === "n" || pauseResponse === "N" || pauseResponse === "\x1B") {
|
|
5099
|
+
process.stdout.write(theme.warning("\u26A1 Stopped by user at auto-pause checkpoint\n"));
|
|
5100
|
+
extraMessages.push({
|
|
5101
|
+
role: "user",
|
|
5102
|
+
content: `The user has stopped the task at round ${effectiveRound}/${MAX_TOOL_ROUNDS}. Do not call any more tools. Summarize what has been completed and what remains.`
|
|
5103
|
+
});
|
|
5104
|
+
break;
|
|
5105
|
+
} else if (pauseResponse && pauseResponse !== "y" && pauseResponse !== "Y" && pauseResponse !== "") {
|
|
5106
|
+
process.stdout.write(theme.warning(`\u26A1 Redirect: "${pauseResponse}"
|
|
5107
|
+
`));
|
|
5108
|
+
extraMessages.push({ role: "user", content: pauseResponse });
|
|
5109
|
+
}
|
|
5110
|
+
process.stdout.write(theme.success(`\u25B6 Continuing... (${remaining} rounds left)
|
|
5111
|
+
`));
|
|
5112
|
+
}
|
|
5034
5113
|
const nextRound = round + 2;
|
|
5035
5114
|
spinner.start(
|
|
5036
5115
|
nextRound <= MAX_TOOL_ROUNDS ? `Thinking... (round ${nextRound}/${MAX_TOOL_ROUNDS})` : "Thinking..."
|
|
@@ -5358,7 +5437,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
5358
5437
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
5359
5438
|
process.exit(1);
|
|
5360
5439
|
}
|
|
5361
|
-
const { startWebServer } = await import("./server-
|
|
5440
|
+
const { startWebServer } = await import("./server-HYAIDK7B.js");
|
|
5362
5441
|
await startWebServer({ port, host: options.host });
|
|
5363
5442
|
});
|
|
5364
5443
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
setupProxy,
|
|
24
24
|
spawnAgentContext,
|
|
25
25
|
truncateOutput
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-MBIHQ34V.js";
|
|
27
27
|
import {
|
|
28
28
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
29
29
|
CONTEXT_FILE_CANDIDATES,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
PLAN_MODE_SYSTEM_ADDON,
|
|
36
36
|
SKILLS_DIR_NAME,
|
|
37
37
|
VERSION
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-OOLIOMNF.js";
|
|
39
39
|
import {
|
|
40
40
|
AuthManager
|
|
41
41
|
} from "./chunk-CPLT6CD3.js";
|
|
@@ -641,7 +641,15 @@ var SessionHandler = class {
|
|
|
641
641
|
const session = this.sessions.current;
|
|
642
642
|
const apiMessages = [...messages];
|
|
643
643
|
const extraMessages = [];
|
|
644
|
-
const
|
|
644
|
+
const baseSystemPrompt = (this.buildSystemPrompt() ?? "") + TOOL_CALL_REMINDER;
|
|
645
|
+
const roundBudgetHint = `
|
|
646
|
+
|
|
647
|
+
[Tool Round Budget]
|
|
648
|
+
You have a maximum of ${MAX_TOOL_ROUNDS} tool call rounds for this task. Plan efficiently:
|
|
649
|
+
- Prefer batch operations (e.g. global find-and-replace) over repetitive single edits.
|
|
650
|
+
- Prioritize the most critical tasks first in case rounds run out.
|
|
651
|
+
- When remaining rounds are low (\u22645), focus on completing the current task and summarizing.`;
|
|
652
|
+
const systemPrompt = baseSystemPrompt + roundBudgetHint;
|
|
645
653
|
const modelParams = this.getModelParams();
|
|
646
654
|
const roundUsage = { inputTokens: 0, outputTokens: 0 };
|
|
647
655
|
const supportsStreamingTools = typeof provider.chatWithToolsStream === "function";
|
|
@@ -653,6 +661,14 @@ var SessionHandler = class {
|
|
|
653
661
|
if (ac.signal.aborted) break;
|
|
654
662
|
this.toolExecutor.setRoundInfo(round + 1, MAX_TOOL_ROUNDS);
|
|
655
663
|
this.send({ type: "round_progress", current: round + 1, total: MAX_TOOL_ROUNDS });
|
|
664
|
+
const roundsLeft = MAX_TOOL_ROUNDS - round;
|
|
665
|
+
if (roundsLeft === 5) {
|
|
666
|
+
extraMessages.push({
|
|
667
|
+
role: "user",
|
|
668
|
+
content: `\u26A0\uFE0F Budget warning: Only ${roundsLeft} tool rounds remaining. Prioritize completing the most critical task. If you cannot finish everything, summarize what's done and what remains.`
|
|
669
|
+
});
|
|
670
|
+
this.send({ type: "info", message: `\u26A0\uFE0F Low budget: ${roundsLeft} rounds remaining` });
|
|
671
|
+
}
|
|
656
672
|
if (this.userInterjection) {
|
|
657
673
|
const msg = this.userInterjection;
|
|
658
674
|
this.userInterjection = null;
|