jinzd-ai-cli 0.4.61 → 0.4.62
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-2ZCD5F4X.js → chunk-672OV76Z.js} +92 -1
- package/dist/{chunk-2WGVM2J2.js → chunk-6OTF2ILP.js} +63 -16
- package/dist/{chunk-GA74LZ62.js → chunk-LLI6COMK.js} +1 -1
- package/dist/{chunk-QUD2AVHH.js → chunk-YUUCUJHU.js} +1 -1
- package/dist/{hub-WA2DZCSQ.js → hub-2XLQSZY2.js} +1 -1
- package/dist/index.js +37 -9
- package/dist/{run-tests-672N6ZKM.js → run-tests-HHIQ3HLM.js} +1 -1
- package/dist/{run-tests-CT4PRGGP.js → run-tests-ORVJAUJG.js} +1 -1
- package/dist/{server-YJWIPDF2.js → server-HBAOUOIC.js} +31 -17
- package/dist/{task-orchestrator-W66JWWKF.js → task-orchestrator-2ATTBG2S.js} +2 -2
- package/package.json +1 -1
|
@@ -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-LLI6COMK.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/builtin/bash.ts
|
|
16
16
|
import { execSync } from "child_process";
|
|
@@ -4062,6 +4062,28 @@ var notebookEditTool = {
|
|
|
4062
4062
|
}
|
|
4063
4063
|
};
|
|
4064
4064
|
|
|
4065
|
+
// src/core/token-estimator.ts
|
|
4066
|
+
var CJK_REGEX = /[\u2E80-\u9FFF\uA000-\uA4FF\uAC00-\uD7FF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF]/g;
|
|
4067
|
+
function estimateTokens(text) {
|
|
4068
|
+
if (!text) return 0;
|
|
4069
|
+
const cjkMatches = text.match(CJK_REGEX);
|
|
4070
|
+
const cjkCount = cjkMatches ? cjkMatches.length : 0;
|
|
4071
|
+
const nonCjkCount = text.length - cjkCount;
|
|
4072
|
+
const tokens = cjkCount * 1.5 + nonCjkCount * 0.25;
|
|
4073
|
+
return Math.ceil(tokens) + 4;
|
|
4074
|
+
}
|
|
4075
|
+
function estimateToolDefinitionTokens(def) {
|
|
4076
|
+
let charCount = def.name.length + def.description.length;
|
|
4077
|
+
for (const [key, param] of Object.entries(def.parameters)) {
|
|
4078
|
+
charCount += key.length + param.type.length + param.description.length;
|
|
4079
|
+
if (param.enum) {
|
|
4080
|
+
charCount += param.enum.join(" ").length;
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
const structuralOverhead = 40 + Object.keys(def.parameters).length * 30;
|
|
4084
|
+
return Math.ceil((charCount + structuralOverhead) * 0.25) + 10;
|
|
4085
|
+
}
|
|
4086
|
+
|
|
4065
4087
|
// src/tools/registry.ts
|
|
4066
4088
|
import { pathToFileURL } from "url";
|
|
4067
4089
|
import { existsSync as existsSync12, mkdirSync as mkdirSync4, readdirSync as readdirSync6 } from "fs";
|
|
@@ -4110,6 +4132,74 @@ var ToolRegistry = class {
|
|
|
4110
4132
|
getDefinitions() {
|
|
4111
4133
|
return [...this.tools.values()].map((t) => t.definition);
|
|
4112
4134
|
}
|
|
4135
|
+
/**
|
|
4136
|
+
* Return tool definitions within a token budget, trimming MCP tools if needed.
|
|
4137
|
+
*
|
|
4138
|
+
* Strategy: always include all builtin + plugin tools. If total tokens exceed
|
|
4139
|
+
* the budget, keep only MCP tools that were used in this session (by name),
|
|
4140
|
+
* trimming the rest. Returns { definitions, trimmedCount, systemNote }.
|
|
4141
|
+
*
|
|
4142
|
+
* @param tokenBudget Max tokens for tool definitions (typically 20% of context window)
|
|
4143
|
+
* @param usedToolNames Names of MCP tools already called this session (always kept)
|
|
4144
|
+
*/
|
|
4145
|
+
getDefinitionsWithBudget(tokenBudget, usedToolNames) {
|
|
4146
|
+
const allDefs = this.getDefinitions();
|
|
4147
|
+
let totalTokens = 0;
|
|
4148
|
+
for (const def of allDefs) {
|
|
4149
|
+
totalTokens += estimateToolDefinitionTokens(def);
|
|
4150
|
+
}
|
|
4151
|
+
if (totalTokens <= tokenBudget) {
|
|
4152
|
+
return { definitions: allDefs, trimmedCount: 0, systemNote: null };
|
|
4153
|
+
}
|
|
4154
|
+
const builtinDefs = [];
|
|
4155
|
+
const mcpDefs = [];
|
|
4156
|
+
for (const def of allDefs) {
|
|
4157
|
+
if (this.mcpToolNames.has(def.name)) {
|
|
4158
|
+
mcpDefs.push(def);
|
|
4159
|
+
} else {
|
|
4160
|
+
builtinDefs.push(def);
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
let budget = tokenBudget;
|
|
4164
|
+
for (const def of builtinDefs) {
|
|
4165
|
+
budget -= estimateToolDefinitionTokens(def);
|
|
4166
|
+
}
|
|
4167
|
+
const kept = [...builtinDefs];
|
|
4168
|
+
const used = usedToolNames ?? /* @__PURE__ */ new Set();
|
|
4169
|
+
const remaining = [];
|
|
4170
|
+
for (const def of mcpDefs) {
|
|
4171
|
+
if (used.has(def.name)) {
|
|
4172
|
+
const cost = estimateToolDefinitionTokens(def);
|
|
4173
|
+
budget -= cost;
|
|
4174
|
+
kept.push(def);
|
|
4175
|
+
} else {
|
|
4176
|
+
remaining.push(def);
|
|
4177
|
+
}
|
|
4178
|
+
}
|
|
4179
|
+
let trimmed = 0;
|
|
4180
|
+
for (const def of remaining) {
|
|
4181
|
+
const cost = estimateToolDefinitionTokens(def);
|
|
4182
|
+
if (budget >= cost) {
|
|
4183
|
+
budget -= cost;
|
|
4184
|
+
kept.push(def);
|
|
4185
|
+
} else {
|
|
4186
|
+
trimmed++;
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
let systemNote = null;
|
|
4190
|
+
if (trimmed > 0) {
|
|
4191
|
+
const trimmedServers = /* @__PURE__ */ new Set();
|
|
4192
|
+
const keptNames = new Set(kept.map((d) => d.name));
|
|
4193
|
+
for (const def of mcpDefs) {
|
|
4194
|
+
if (!keptNames.has(def.name)) {
|
|
4195
|
+
const parts = def.name.split("__");
|
|
4196
|
+
if (parts.length >= 2) trimmedServers.add(parts[1]);
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
systemNote = `[MCP Tool Budget] ${trimmed} MCP tool(s) from server(s) [${[...trimmedServers].join(", ")}] were excluded to fit the context window. If you need a specific MCP tool that isn't listed, tell the user to ask for it explicitly.`;
|
|
4200
|
+
}
|
|
4201
|
+
return { definitions: kept, trimmedCount: trimmed, systemNote };
|
|
4202
|
+
}
|
|
4113
4203
|
listAll() {
|
|
4114
4204
|
return [...this.tools.values()];
|
|
4115
4205
|
}
|
|
@@ -4229,5 +4319,6 @@ export {
|
|
|
4229
4319
|
askUserContext,
|
|
4230
4320
|
googleSearchContext,
|
|
4231
4321
|
spawnAgentContext,
|
|
4322
|
+
estimateTokens,
|
|
4232
4323
|
ToolRegistry
|
|
4233
4324
|
};
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
RateLimitError,
|
|
9
9
|
schemaToJsonSchema,
|
|
10
10
|
truncateForPersist
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-672OV76Z.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-LLI6COMK.js";
|
|
25
25
|
|
|
26
26
|
// src/config/config-manager.ts
|
|
27
27
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -2462,14 +2462,25 @@ var Session = class _Session {
|
|
|
2462
2462
|
/**
|
|
2463
2463
|
* 上下文压缩:用摘要消息替换旧消息,保留最近 keepLast 条。
|
|
2464
2464
|
*
|
|
2465
|
+
* Tool-history-aware: if the cut point lands inside a tool round
|
|
2466
|
+
* (assistant+toolCalls followed by tool results), expand to keep the
|
|
2467
|
+
* entire round intact. This prevents orphaned tool results.
|
|
2468
|
+
*
|
|
2465
2469
|
* 压缩后消息结构:
|
|
2466
|
-
* [summaryMsg(user), ackMsg(assistant), ...最近
|
|
2470
|
+
* [summaryMsg(user), ackMsg(assistant), ...最近 N 条原始消息]
|
|
2467
2471
|
*
|
|
2468
2472
|
* @returns 被删除的消息条数
|
|
2469
2473
|
*/
|
|
2470
2474
|
compact(summaryMsg, ackMsg, keepLast) {
|
|
2471
|
-
|
|
2472
|
-
|
|
2475
|
+
let cutIndex = this.messages.length - keepLast;
|
|
2476
|
+
if (cutIndex <= 0) {
|
|
2477
|
+
return 0;
|
|
2478
|
+
}
|
|
2479
|
+
while (cutIndex > 0 && this.messages[cutIndex]?.role === "tool") {
|
|
2480
|
+
cutIndex--;
|
|
2481
|
+
}
|
|
2482
|
+
const preserved = this.messages.slice(cutIndex);
|
|
2483
|
+
const removedCount = cutIndex;
|
|
2473
2484
|
this.messages = [summaryMsg, ackMsg, ...preserved];
|
|
2474
2485
|
this.updated = /* @__PURE__ */ new Date();
|
|
2475
2486
|
return removedCount;
|
|
@@ -3687,6 +3698,7 @@ function formatCost(amount) {
|
|
|
3687
3698
|
}
|
|
3688
3699
|
|
|
3689
3700
|
// src/session/tool-history.ts
|
|
3701
|
+
var SESSION_SIZE_LIMIT = 2 * 1024 * 1024;
|
|
3690
3702
|
function persistToolRound(session, toolCalls, toolResults, opts) {
|
|
3691
3703
|
session.addMessage({
|
|
3692
3704
|
role: "assistant",
|
|
@@ -3757,16 +3769,51 @@ function rebuildExtraMessages(provider, toolHistory) {
|
|
|
3757
3769
|
}
|
|
3758
3770
|
return result;
|
|
3759
3771
|
}
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
const
|
|
3769
|
-
|
|
3772
|
+
function trimOldToolOutput(messages, keepRecentRounds = 10) {
|
|
3773
|
+
const roundStarts = [];
|
|
3774
|
+
for (let i = 0; i < messages.length; i++) {
|
|
3775
|
+
if (messages[i].role === "assistant" && messages[i].toolCalls?.length) {
|
|
3776
|
+
roundStarts.push(i);
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
if (roundStarts.length <= keepRecentRounds) return 0;
|
|
3780
|
+
const cutoffRoundIdx = roundStarts.length - keepRecentRounds;
|
|
3781
|
+
let trimmed = 0;
|
|
3782
|
+
for (let r = 0; r < cutoffRoundIdx; r++) {
|
|
3783
|
+
const start = roundStarts[r];
|
|
3784
|
+
const end = r + 1 < roundStarts.length ? roundStarts[r + 1] : messages.length;
|
|
3785
|
+
const assistantMsg = messages[start];
|
|
3786
|
+
if (typeof assistantMsg.content === "string" && assistantMsg.content.length > 200) {
|
|
3787
|
+
assistantMsg.content = assistantMsg.content.slice(0, 100) + "\u2026 [trimmed for size]";
|
|
3788
|
+
trimmed++;
|
|
3789
|
+
}
|
|
3790
|
+
for (let j = start + 1; j < end; j++) {
|
|
3791
|
+
const msg = messages[j];
|
|
3792
|
+
if (msg.role === "tool") {
|
|
3793
|
+
const status = msg.isError ? "\u2717 error" : "\u2713 ok";
|
|
3794
|
+
const name = msg.toolName ?? "unknown";
|
|
3795
|
+
const currentContent = typeof msg.content === "string" ? msg.content : "";
|
|
3796
|
+
if (currentContent.length > 200) {
|
|
3797
|
+
msg.content = `[${name}: ${status}] (output trimmed for size \u2014 ${currentContent.length} chars)`;
|
|
3798
|
+
trimmed++;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
return trimmed;
|
|
3804
|
+
}
|
|
3805
|
+
function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
3806
|
+
const json = JSON.stringify(session.toJSON());
|
|
3807
|
+
if (json.length <= sizeLimit) return false;
|
|
3808
|
+
let keepRecent = 10;
|
|
3809
|
+
while (keepRecent >= 2) {
|
|
3810
|
+
const trimmed = trimOldToolOutput(session.messages, keepRecent);
|
|
3811
|
+
if (trimmed === 0) break;
|
|
3812
|
+
const newSize = JSON.stringify(session.toJSON()).length;
|
|
3813
|
+
if (newSize <= sizeLimit) return true;
|
|
3814
|
+
keepRecent = Math.max(2, Math.floor(keepRecent / 2));
|
|
3815
|
+
}
|
|
3816
|
+
return true;
|
|
3770
3817
|
}
|
|
3771
3818
|
|
|
3772
3819
|
// src/repl/dev-state.ts
|
|
@@ -3882,7 +3929,7 @@ export {
|
|
|
3882
3929
|
persistToolRound,
|
|
3883
3930
|
extractToolHistory,
|
|
3884
3931
|
rebuildExtraMessages,
|
|
3885
|
-
|
|
3932
|
+
autoTrimSessionIfNeeded,
|
|
3886
3933
|
SNAPSHOT_PROMPT,
|
|
3887
3934
|
sessionHasMeaningfulContent,
|
|
3888
3935
|
saveDevState,
|
|
@@ -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-2ATTBG2S.js");
|
|
389
389
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
390
390
|
let interrupted = false;
|
|
391
391
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
SessionManager,
|
|
9
9
|
SkillManager,
|
|
10
10
|
TOOL_CALL_REMINDER,
|
|
11
|
+
autoTrimSessionIfNeeded,
|
|
11
12
|
buildPhantomCorrectionMessage,
|
|
12
13
|
buildWriteRoundReminder,
|
|
13
14
|
clearDevState,
|
|
14
15
|
computeCost,
|
|
15
16
|
detectsHallucinatedFileOp,
|
|
16
|
-
estimateTokens,
|
|
17
17
|
extractToolHistory,
|
|
18
18
|
extractWrittenFilePaths,
|
|
19
19
|
findPhantomClaims,
|
|
@@ -31,11 +31,12 @@ import {
|
|
|
31
31
|
saveDevState,
|
|
32
32
|
sessionHasMeaningfulContent,
|
|
33
33
|
setupProxy
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-6OTF2ILP.js";
|
|
35
35
|
import {
|
|
36
36
|
ToolExecutor,
|
|
37
37
|
ToolRegistry,
|
|
38
38
|
askUserContext,
|
|
39
|
+
estimateTokens,
|
|
39
40
|
googleSearchContext,
|
|
40
41
|
initTheme,
|
|
41
42
|
lastResponseStore,
|
|
@@ -45,7 +46,7 @@ import {
|
|
|
45
46
|
spawnAgentContext,
|
|
46
47
|
theme,
|
|
47
48
|
undoStack
|
|
48
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-672OV76Z.js";
|
|
49
50
|
import {
|
|
50
51
|
fileCheckpoints
|
|
51
52
|
} from "./chunk-4BKXL7SM.js";
|
|
@@ -70,7 +71,7 @@ import {
|
|
|
70
71
|
SKILLS_DIR_NAME,
|
|
71
72
|
VERSION,
|
|
72
73
|
buildUserIdentityPrompt
|
|
73
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-LLI6COMK.js";
|
|
74
75
|
|
|
75
76
|
// src/index.ts
|
|
76
77
|
import { program } from "commander";
|
|
@@ -2165,7 +2166,7 @@ ${hint}` : "")
|
|
|
2165
2166
|
usage: "/test [command|filter]",
|
|
2166
2167
|
async execute(args, ctx) {
|
|
2167
2168
|
try {
|
|
2168
|
-
const { executeTests } = await import("./run-tests-
|
|
2169
|
+
const { executeTests } = await import("./run-tests-ORVJAUJG.js");
|
|
2169
2170
|
const argStr = args.join(" ").trim();
|
|
2170
2171
|
let testArgs = {};
|
|
2171
2172
|
if (argStr) {
|
|
@@ -3911,6 +3912,11 @@ ${skillContent}`);
|
|
|
3911
3912
|
"4. Current status and tasks not yet completed",
|
|
3912
3913
|
"5. Key details to remember (file paths, config values, error messages, variable names, etc.)",
|
|
3913
3914
|
"",
|
|
3915
|
+
"If the conversation contains tool call rounds (assistant calling tools like read_file, write_file, bash, etc.), ",
|
|
3916
|
+
'summarize each round as a single line: "- [tool_name] target \u2192 result/status". ',
|
|
3917
|
+
'Do NOT include raw tool output. Group consecutive similar operations (e.g., "read 5 files in src/") ',
|
|
3918
|
+
"instead of listing each one individually.",
|
|
3919
|
+
"",
|
|
3914
3920
|
"Requirements: Be well-organized so that subsequent conversation can seamlessly continue from this summary."
|
|
3915
3921
|
];
|
|
3916
3922
|
if (instruction) summaryPromptLines.push("", `Additional requirement: ${instruction}`);
|
|
@@ -4318,6 +4324,9 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4318
4324
|
await this.handleChatSimple(provider, session.messages);
|
|
4319
4325
|
}
|
|
4320
4326
|
if (this.config.get("session").autoSave) {
|
|
4327
|
+
if (autoTrimSessionIfNeeded(session)) {
|
|
4328
|
+
process.stderr.write(theme.dim(" [session] Trimmed old tool output to reduce file size\n"));
|
|
4329
|
+
}
|
|
4321
4330
|
await this.sessions.save();
|
|
4322
4331
|
}
|
|
4323
4332
|
const elapsed = Date.now() - t0;
|
|
@@ -4862,6 +4871,8 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4862
4871
|
async handleChatWithTools(provider, messages) {
|
|
4863
4872
|
const session = this.sessions.current;
|
|
4864
4873
|
let toolDefs;
|
|
4874
|
+
let mcpBudgetNote = null;
|
|
4875
|
+
const usedMcpToolNames = /* @__PURE__ */ new Set();
|
|
4865
4876
|
if (this.planMode) {
|
|
4866
4877
|
toolDefs = this.toolRegistry.getDefinitions().filter((t) => PLAN_MODE_READONLY_TOOLS.has(t.name));
|
|
4867
4878
|
} else {
|
|
@@ -4869,7 +4880,19 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4869
4880
|
if (skillFilter) {
|
|
4870
4881
|
toolDefs = this.toolRegistry.getDefinitions().filter((t) => skillFilter.has(t.name));
|
|
4871
4882
|
} else {
|
|
4872
|
-
|
|
4883
|
+
const contextWindow = this.getContextWindowSize();
|
|
4884
|
+
if (contextWindow > 0) {
|
|
4885
|
+
const toolBudget = Math.floor(contextWindow * 0.2);
|
|
4886
|
+
const { definitions, trimmedCount, systemNote } = this.toolRegistry.getDefinitionsWithBudget(toolBudget, usedMcpToolNames);
|
|
4887
|
+
toolDefs = definitions;
|
|
4888
|
+
mcpBudgetNote = systemNote;
|
|
4889
|
+
if (trimmedCount > 0) {
|
|
4890
|
+
process.stderr.write(theme.dim(` [MCP budget] ${trimmedCount} MCP tool(s) trimmed to fit ${toolBudget.toLocaleString()} token budget
|
|
4891
|
+
`));
|
|
4892
|
+
}
|
|
4893
|
+
} else {
|
|
4894
|
+
toolDefs = this.toolRegistry.getDefinitions();
|
|
4895
|
+
}
|
|
4873
4896
|
}
|
|
4874
4897
|
}
|
|
4875
4898
|
if (this.allowedTools) {
|
|
@@ -4904,7 +4927,9 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
4904
4927
|
- Do NOT read the same file more than once \u2014 use the content from previous reads.
|
|
4905
4928
|
- Prioritize the most critical tasks first in case rounds run out.
|
|
4906
4929
|
- When remaining rounds are low, focus on completing the current task and summarizing.${pauseHint}`;
|
|
4907
|
-
const systemPrompt = baseSystemPrompt + roundBudgetHint
|
|
4930
|
+
const systemPrompt = baseSystemPrompt + roundBudgetHint + (mcpBudgetNote ? `
|
|
4931
|
+
|
|
4932
|
+
${mcpBudgetNote}` : "");
|
|
4908
4933
|
const modelParams = this.getModelParams();
|
|
4909
4934
|
const useStreaming = this.config.get("ui").streaming;
|
|
4910
4935
|
const spinner = this.renderer.showSpinner("Thinking...");
|
|
@@ -5270,6 +5295,9 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
5270
5295
|
const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
|
|
5271
5296
|
const newMsgs = provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent);
|
|
5272
5297
|
extraMessages.push(...newMsgs);
|
|
5298
|
+
for (const tc of result.toolCalls) {
|
|
5299
|
+
if (tc.name.startsWith("mcp__")) usedMcpToolNames.add(tc.name);
|
|
5300
|
+
}
|
|
5273
5301
|
const streamedContent = "content" in result ? result.content : void 0;
|
|
5274
5302
|
persistToolRound(session, result.toolCalls, toolResults, {
|
|
5275
5303
|
assistantContent: streamedContent,
|
|
@@ -5710,7 +5738,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
5710
5738
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
5711
5739
|
process.exit(1);
|
|
5712
5740
|
}
|
|
5713
|
-
const { startWebServer } = await import("./server-
|
|
5741
|
+
const { startWebServer } = await import("./server-HBAOUOIC.js");
|
|
5714
5742
|
await startWebServer({ port, host: options.host });
|
|
5715
5743
|
});
|
|
5716
5744
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -5943,7 +5971,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
5943
5971
|
}),
|
|
5944
5972
|
config.get("customProviders")
|
|
5945
5973
|
);
|
|
5946
|
-
const { startHub } = await import("./hub-
|
|
5974
|
+
const { startHub } = await import("./hub-2XLQSZY2.js");
|
|
5947
5975
|
await startHub(
|
|
5948
5976
|
{
|
|
5949
5977
|
topic: topic ?? "",
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
SessionManager,
|
|
8
8
|
SkillManager,
|
|
9
9
|
TOOL_CALL_REMINDER,
|
|
10
|
+
autoTrimSessionIfNeeded,
|
|
10
11
|
computeCost,
|
|
11
12
|
detectsHallucinatedFileOp,
|
|
12
|
-
estimateTokens,
|
|
13
13
|
extractToolHistory,
|
|
14
14
|
formatCost,
|
|
15
15
|
formatGitContextForPrompt,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
persistToolRound,
|
|
22
22
|
rebuildExtraMessages,
|
|
23
23
|
setupProxy
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-6OTF2ILP.js";
|
|
25
25
|
import {
|
|
26
26
|
AuthManager
|
|
27
27
|
} from "./chunk-BYNY5JPB.js";
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
ToolRegistry,
|
|
31
31
|
askUserContext,
|
|
32
32
|
checkPermission,
|
|
33
|
+
estimateTokens,
|
|
33
34
|
getDangerLevel,
|
|
34
35
|
googleSearchContext,
|
|
35
36
|
isFileWriteTool,
|
|
@@ -40,7 +41,7 @@ import {
|
|
|
40
41
|
spawnAgentContext,
|
|
41
42
|
truncateOutput,
|
|
42
43
|
undoStack
|
|
43
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-672OV76Z.js";
|
|
44
45
|
import "./chunk-4BKXL7SM.js";
|
|
45
46
|
import {
|
|
46
47
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -60,7 +61,7 @@ import {
|
|
|
60
61
|
SKILLS_DIR_NAME,
|
|
61
62
|
VERSION,
|
|
62
63
|
buildUserIdentityPrompt
|
|
63
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-LLI6COMK.js";
|
|
64
65
|
|
|
65
66
|
// src/web/server.ts
|
|
66
67
|
import express from "express";
|
|
@@ -697,6 +698,7 @@ var SessionHandler = class _SessionHandler {
|
|
|
697
698
|
/** Save session only if it exists and has messages (never persist empty "Untitled" sessions). */
|
|
698
699
|
saveIfNeeded() {
|
|
699
700
|
if (this.sessions.current && this.sessions.current.messages.length > 0) {
|
|
701
|
+
autoTrimSessionIfNeeded(this.sessions.current);
|
|
700
702
|
const id = this.sessions.current.id;
|
|
701
703
|
this.sessions.save();
|
|
702
704
|
this.unsavedSessions.delete(id);
|
|
@@ -754,9 +756,9 @@ var SessionHandler = class _SessionHandler {
|
|
|
754
756
|
return;
|
|
755
757
|
}
|
|
756
758
|
const hasToolSupport = typeof provider.chatWithTools === "function";
|
|
757
|
-
const toolDefs = hasToolSupport ? this.getFilteredToolDefs() : [];
|
|
759
|
+
const { toolDefs, mcpBudgetNote } = hasToolSupport ? this.getFilteredToolDefs() : { toolDefs: [], mcpBudgetNote: null };
|
|
758
760
|
if (hasToolSupport && toolDefs.length > 0) {
|
|
759
|
-
await this.handleChatWithTools(provider, session.messages, toolDefs);
|
|
761
|
+
await this.handleChatWithTools(provider, session.messages, toolDefs, mcpBudgetNote);
|
|
760
762
|
} else {
|
|
761
763
|
await this.handleChatSimple(provider, session.messages);
|
|
762
764
|
}
|
|
@@ -821,7 +823,7 @@ var SessionHandler = class _SessionHandler {
|
|
|
821
823
|
this.abortController = null;
|
|
822
824
|
}
|
|
823
825
|
}
|
|
824
|
-
async handleChatWithTools(provider, messages, toolDefs) {
|
|
826
|
+
async handleChatWithTools(provider, messages, toolDefs, mcpBudgetNote) {
|
|
825
827
|
const session = this.sessions.current;
|
|
826
828
|
const { baseMessages: cleanMessages, toolHistory } = extractToolHistory(messages);
|
|
827
829
|
const apiMessages = [...cleanMessages];
|
|
@@ -839,7 +841,9 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
839
841
|
- Prefer batch operations (e.g. global find-and-replace) over repetitive single edits.
|
|
840
842
|
- Prioritize the most critical tasks first in case rounds run out.
|
|
841
843
|
- When remaining rounds are low, focus on completing the current task and summarizing.${pauseHint}`;
|
|
842
|
-
const systemPrompt = baseSystemPrompt + roundBudgetHint
|
|
844
|
+
const systemPrompt = baseSystemPrompt + roundBudgetHint + (mcpBudgetNote ? `
|
|
845
|
+
|
|
846
|
+
${mcpBudgetNote}` : "");
|
|
843
847
|
const modelParams = this.getModelParams();
|
|
844
848
|
const roundUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
845
849
|
const supportsStreamingTools = typeof provider.chatWithToolsStream === "function";
|
|
@@ -1929,7 +1933,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1929
1933
|
case "test": {
|
|
1930
1934
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
1931
1935
|
try {
|
|
1932
|
-
const { executeTests } = await import("./run-tests-
|
|
1936
|
+
const { executeTests } = await import("./run-tests-ORVJAUJG.js");
|
|
1933
1937
|
const argStr = args.join(" ").trim();
|
|
1934
1938
|
let testArgs = {};
|
|
1935
1939
|
if (argStr) {
|
|
@@ -2517,16 +2521,26 @@ Add .md files to create commands.` });
|
|
|
2517
2521
|
};
|
|
2518
2522
|
}
|
|
2519
2523
|
getFilteredToolDefs() {
|
|
2520
|
-
let defs = this.toolRegistry.getDefinitions();
|
|
2521
2524
|
if (this.planMode) {
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2525
|
+
return {
|
|
2526
|
+
toolDefs: this.toolRegistry.getDefinitions().filter((t) => PLAN_MODE_READONLY_TOOLS.has(t.name)),
|
|
2527
|
+
mcpBudgetNote: null
|
|
2528
|
+
};
|
|
2529
|
+
}
|
|
2530
|
+
const skillFilter = this.skillManager?.getActiveToolFilter();
|
|
2531
|
+
if (skillFilter) {
|
|
2532
|
+
return {
|
|
2533
|
+
toolDefs: this.toolRegistry.getDefinitions().filter((t) => skillFilter.has(t.name)),
|
|
2534
|
+
mcpBudgetNote: null
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
const contextWindow = this.getContextWindowSize();
|
|
2538
|
+
if (contextWindow > 0) {
|
|
2539
|
+
const toolBudget = Math.floor(contextWindow * 0.2);
|
|
2540
|
+
const { definitions, systemNote } = this.toolRegistry.getDefinitionsWithBudget(toolBudget);
|
|
2541
|
+
return { toolDefs: definitions, mcpBudgetNote: systemNote };
|
|
2528
2542
|
}
|
|
2529
|
-
return
|
|
2543
|
+
return { toolDefs: this.toolRegistry.getDefinitions(), mcpBudgetNote: null };
|
|
2530
2544
|
}
|
|
2531
2545
|
/**
|
|
2532
2546
|
* Find first matching context file in a directory.
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-672OV76Z.js";
|
|
8
8
|
import "./chunk-4BKXL7SM.js";
|
|
9
9
|
import {
|
|
10
10
|
SUBAGENT_ALLOWED_TOOLS
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LLI6COMK.js";
|
|
12
12
|
|
|
13
13
|
// src/hub/task-orchestrator.ts
|
|
14
14
|
import { createInterface } from "readline";
|