@amical/aiagent-sdk 0.1.9 → 0.1.11
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/index.d.mts +88 -9
- package/dist/index.d.ts +88 -9
- package/dist/index.js +305 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +302 -31
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/nodeRuntime.d.mts +1 -1
- package/dist/runtime/nodeRuntime.d.ts +1 -1
- package/dist/runtime/nodeRuntime.js +309 -31
- package/dist/runtime/nodeRuntime.js.map +1 -1
- package/dist/runtime/nodeRuntime.mjs +306 -32
- package/dist/runtime/nodeRuntime.mjs.map +1 -1
- package/dist/runtime/webRuntime.d.mts +1 -1
- package/dist/runtime/webRuntime.d.ts +1 -1
- package/dist/runtime/webRuntime.js +309 -31
- package/dist/runtime/webRuntime.js.map +1 -1
- package/dist/runtime/webRuntime.mjs +306 -32
- package/dist/runtime/webRuntime.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IApiHandler, ApiProviderInfo, AgentMessage, ApiStreamChunk, IPromptManager, IMcpManager, McpServerInfo, McpTool, McpToolCallResult, IAgentRuntime, ClineAgent } from '../index.mjs';
|
|
2
|
-
export { AgentDefaultTool, AgentOptions, AgentState, AssistantMessageContent, IMemoryManager, READ_ONLY_TOOLS, ReasoningStreamContent, TOOL_RESULT_BLOCK, TextStreamContent, ToolParamName, ToolUse, VERSION, defaultTools, getToolUseNames, parseAssistantMessageV2, setDynamicToolUseNames, toolParamNames, toolUseNames } from '../index.mjs';
|
|
2
|
+
export { AgentDefaultTool, AgentOptions, AgentState, AssistantMessageContent, CustomToolDefinition, IMemoryManager, READ_ONLY_TOOLS, ReasoningStreamContent, TOOL_RESULT_BLOCK, TextStreamContent, ToolParamName, ToolUse, VERSION, collectCustomToolNames, defaultTools, getToolUseNames, isCustomToolGroup, parseAssistantMessageV2, renderCustomToolPrompt, renderCustomToolsPrompt, setDynamicToolUseNames, toolParamNames, toolUseNames } from '../index.mjs';
|
|
3
3
|
import { W as WebMemoryManager } from '../WebMemoryManager-Bk19j8i6.mjs';
|
|
4
4
|
|
|
5
5
|
interface WebApiHandlerConfig {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IApiHandler, ApiProviderInfo, AgentMessage, ApiStreamChunk, IPromptManager, IMcpManager, McpServerInfo, McpTool, McpToolCallResult, IAgentRuntime, ClineAgent } from '../index.js';
|
|
2
|
-
export { AgentDefaultTool, AgentOptions, AgentState, AssistantMessageContent, IMemoryManager, READ_ONLY_TOOLS, ReasoningStreamContent, TOOL_RESULT_BLOCK, TextStreamContent, ToolParamName, ToolUse, VERSION, defaultTools, getToolUseNames, parseAssistantMessageV2, setDynamicToolUseNames, toolParamNames, toolUseNames } from '../index.js';
|
|
2
|
+
export { AgentDefaultTool, AgentOptions, AgentState, AssistantMessageContent, CustomToolDefinition, IMemoryManager, READ_ONLY_TOOLS, ReasoningStreamContent, TOOL_RESULT_BLOCK, TextStreamContent, ToolParamName, ToolUse, VERSION, collectCustomToolNames, defaultTools, getToolUseNames, isCustomToolGroup, parseAssistantMessageV2, renderCustomToolPrompt, renderCustomToolsPrompt, setDynamicToolUseNames, toolParamNames, toolUseNames } from '../index.js';
|
|
3
3
|
import { W as WebMemoryManager } from '../WebMemoryManager-DXxLUDBB.js';
|
|
4
4
|
|
|
5
5
|
interface WebApiHandlerConfig {
|
|
@@ -24,6 +24,7 @@ var AgentDefaultTool = /* @__PURE__ */ ((AgentDefaultTool2) => {
|
|
|
24
24
|
AgentDefaultTool2["FILE_DELETE"] = "agent_delete_file";
|
|
25
25
|
AgentDefaultTool2["DIR_DELETE"] = "agent_delete_directory";
|
|
26
26
|
AgentDefaultTool2["SEARCH"] = "agent_search_files";
|
|
27
|
+
AgentDefaultTool2["SEARCH_CONTENT"] = "agent_search_file_content";
|
|
27
28
|
AgentDefaultTool2["LIST_FILES"] = "agent_list_files";
|
|
28
29
|
AgentDefaultTool2["LIST_CODE_DEF"] = "agent_list_code_definition_names";
|
|
29
30
|
AgentDefaultTool2["BROWSER"] = "agent_browser_action";
|
|
@@ -197,11 +198,22 @@ return (
|
|
|
197
198
|
},
|
|
198
199
|
{
|
|
199
200
|
name: "agent_search_files" /* SEARCH */,
|
|
200
|
-
description: "Search for files in a directory
|
|
201
|
+
description: "Search for files or directories by name in a directory tree, matching the name against a regex (and optionally a glob). Directories are traversed level by level: all matches in the current level are returned before descending into deeper levels. Use this tool only to locate files/directories by name.",
|
|
201
202
|
params: {
|
|
202
203
|
path: "(required) The absolute or relative directory path to search.",
|
|
203
|
-
regex: "(required) The regex pattern to match
|
|
204
|
-
file_pattern: "(optional) glob pattern like *.ts."
|
|
204
|
+
regex: "(required) The regex pattern to match file or directory names against.",
|
|
205
|
+
file_pattern: "(optional) glob pattern like *.ts.",
|
|
206
|
+
include_node_modules: "(optional) set to true to include node_modules in the search. Defaults to false, so node_modules is skipped."
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "agent_search_file_content" /* SEARCH_CONTENT */,
|
|
211
|
+
description: "Search the contents of files in a directory tree for a regex pattern. Use this tool when you need to find text or code inside files rather than matching file or directory names.",
|
|
212
|
+
params: {
|
|
213
|
+
path: "(required) The absolute or relative directory path to search.",
|
|
214
|
+
regex: "(required) The regex pattern to match file content against.",
|
|
215
|
+
file_pattern: "(optional) glob pattern like *.ts to limit which files are searched.",
|
|
216
|
+
include_node_modules: "(optional) set to true to include node_modules in the search. Defaults to false, so node_modules is skipped."
|
|
205
217
|
}
|
|
206
218
|
},
|
|
207
219
|
{
|
|
@@ -270,6 +282,7 @@ var READ_ONLY_TOOLS = [
|
|
|
270
282
|
"agent_list_files" /* LIST_FILES */,
|
|
271
283
|
"agent_read_file" /* FILE_READ */,
|
|
272
284
|
"agent_search_files" /* SEARCH */,
|
|
285
|
+
"agent_search_file_content" /* SEARCH_CONTENT */,
|
|
273
286
|
"agent_list_code_definition_names" /* LIST_CODE_DEF */,
|
|
274
287
|
"agent_browser_action" /* BROWSER */,
|
|
275
288
|
"agent_ask_followup_question" /* ASK */,
|
|
@@ -439,6 +452,7 @@ var toolParamNames = [
|
|
|
439
452
|
"diff",
|
|
440
453
|
"regex",
|
|
441
454
|
"file_pattern",
|
|
455
|
+
"include_node_modules",
|
|
442
456
|
"recursive",
|
|
443
457
|
"action",
|
|
444
458
|
"url",
|
|
@@ -477,6 +491,104 @@ var toolParamNames = [
|
|
|
477
491
|
"start_line",
|
|
478
492
|
"end_line"
|
|
479
493
|
];
|
|
494
|
+
|
|
495
|
+
// src/shared/custom-tools.ts
|
|
496
|
+
function isCustomToolGroup(tool) {
|
|
497
|
+
return Array.isArray(tool.children) && tool.children.length > 0;
|
|
498
|
+
}
|
|
499
|
+
function collectCustomToolNames(tools) {
|
|
500
|
+
const names = [];
|
|
501
|
+
const visit = (list) => {
|
|
502
|
+
for (const tool of list) {
|
|
503
|
+
names.push(tool.name);
|
|
504
|
+
if (Array.isArray(tool.children) && tool.children.length > 0) {
|
|
505
|
+
visit(tool.children);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
visit(tools);
|
|
510
|
+
return names;
|
|
511
|
+
}
|
|
512
|
+
function renderCustomToolPrompt(tool, cwd = "") {
|
|
513
|
+
const params = tool.params ? Object.entries(tool.params) : [];
|
|
514
|
+
const replaceCwd = (text) => String(text).replaceAll("${context.cwd}", cwd);
|
|
515
|
+
const paramLines = params.map(([name, description]) => `- ${name}: ${replaceCwd(description)}`).join("\n");
|
|
516
|
+
const usageLines = params.map(([name, description]) => `<${name}>${replaceCwd(description)}</${name}>`).join("\n");
|
|
517
|
+
return `### ${tool.name}
|
|
518
|
+
Description: ${tool.description}
|
|
519
|
+
Parameters:
|
|
520
|
+
${paramLines}
|
|
521
|
+
- task_progress: (optional) A checklist showing task progress after this tool use is completed. The task_progress parameter must be included as a separate parameter inside of the parent tool call, it must be separate from other parameters such as content, arguments, etc. (See 'UPDATING TASK PROGRESS' section for more details)
|
|
522
|
+
Usage:
|
|
523
|
+
<${tool.name}>
|
|
524
|
+
${usageLines}
|
|
525
|
+
<task_progress>Checklist here (optional)</task_progress>
|
|
526
|
+
</${tool.name}>
|
|
527
|
+
`;
|
|
528
|
+
}
|
|
529
|
+
function renderCustomToolsPrompt(tools, cwd = "") {
|
|
530
|
+
return tools.map((tool) => renderCustomToolPrompt(tool, cwd)).join("\n");
|
|
531
|
+
}
|
|
532
|
+
var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
533
|
+
"txt",
|
|
534
|
+
"md",
|
|
535
|
+
"markdown",
|
|
536
|
+
"json",
|
|
537
|
+
"js",
|
|
538
|
+
"mjs",
|
|
539
|
+
"cjs",
|
|
540
|
+
"ts",
|
|
541
|
+
"tsx",
|
|
542
|
+
"jsx",
|
|
543
|
+
"html",
|
|
544
|
+
"htm",
|
|
545
|
+
"css",
|
|
546
|
+
"scss",
|
|
547
|
+
"sass",
|
|
548
|
+
"less",
|
|
549
|
+
"py",
|
|
550
|
+
"java",
|
|
551
|
+
"c",
|
|
552
|
+
"cpp",
|
|
553
|
+
"cc",
|
|
554
|
+
"cxx",
|
|
555
|
+
"h",
|
|
556
|
+
"hpp",
|
|
557
|
+
"cs",
|
|
558
|
+
"go",
|
|
559
|
+
"rs",
|
|
560
|
+
"rb",
|
|
561
|
+
"php",
|
|
562
|
+
"sh",
|
|
563
|
+
"bash",
|
|
564
|
+
"zsh",
|
|
565
|
+
"bat",
|
|
566
|
+
"cmd",
|
|
567
|
+
"ps1",
|
|
568
|
+
"yaml",
|
|
569
|
+
"yml",
|
|
570
|
+
"toml",
|
|
571
|
+
"ini",
|
|
572
|
+
"cfg",
|
|
573
|
+
"conf",
|
|
574
|
+
"xml",
|
|
575
|
+
"svg",
|
|
576
|
+
"csv",
|
|
577
|
+
"log",
|
|
578
|
+
"sql",
|
|
579
|
+
"vue",
|
|
580
|
+
"svelte",
|
|
581
|
+
"astro",
|
|
582
|
+
"graphql",
|
|
583
|
+
"gql",
|
|
584
|
+
"prisma",
|
|
585
|
+
"env",
|
|
586
|
+
"gitignore",
|
|
587
|
+
"dockerfile",
|
|
588
|
+
"makefile",
|
|
589
|
+
"properties",
|
|
590
|
+
"lock"
|
|
591
|
+
]);
|
|
480
592
|
var AgentState = /* @__PURE__ */ ((AgentState2) => {
|
|
481
593
|
AgentState2["IDLE"] = "idle";
|
|
482
594
|
AgentState2["THINKING"] = "thinking";
|
|
@@ -500,9 +612,19 @@ var ClineAgent = class {
|
|
|
500
612
|
skillDir;
|
|
501
613
|
rulesDir;
|
|
502
614
|
customTools;
|
|
615
|
+
/** 当前可用(已展开集合)的顶层工具列表,传给 PromptManager 渲染 */
|
|
616
|
+
activeCustomTools;
|
|
617
|
+
/** 所有已知工具名(含未激活 children),便于查找定义 */
|
|
618
|
+
customToolsByName;
|
|
503
619
|
customToolNames;
|
|
504
620
|
allowDefaultTools;
|
|
505
621
|
customInstructions;
|
|
622
|
+
/** 已激活的工具集入口名 */
|
|
623
|
+
activatedGroups = /* @__PURE__ */ new Set();
|
|
624
|
+
/** activeCustomTools 变更版本号,用于 Prompt 缓存失效 */
|
|
625
|
+
activeToolsVersion = 0;
|
|
626
|
+
/** 缓存 sysPrompt 时记录的版本号 */
|
|
627
|
+
promptActiveToolsVersion = -1;
|
|
506
628
|
sysPrompt;
|
|
507
629
|
noUseTollSysPrompt;
|
|
508
630
|
// 简单的事件回调系统,供宿主环境注册以监听 Agent 内部事件
|
|
@@ -522,31 +644,38 @@ var ClineAgent = class {
|
|
|
522
644
|
this.allowDefaultTools.push("agent_attempt_completion" /* ATTEMPT */);
|
|
523
645
|
}
|
|
524
646
|
this.customInstructions = options.customInstructions;
|
|
647
|
+
this.customToolsByName = /* @__PURE__ */ new Map();
|
|
648
|
+
this.activeCustomTools = [...this.customTools];
|
|
649
|
+
this.customToolNames = new Set(collectCustomToolNames(this.customTools));
|
|
525
650
|
if (this.customTools.length > 0) {
|
|
526
|
-
const dynamicToolNames = /* @__PURE__ */ new Set();
|
|
527
651
|
const customToolParams = /* @__PURE__ */ new Set();
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
652
|
+
const visit = (tools) => {
|
|
653
|
+
for (const customTool of tools) {
|
|
654
|
+
this.customToolsByName.set(customTool.name, customTool);
|
|
655
|
+
if (customTool.params) {
|
|
656
|
+
for (const key in customTool.params) {
|
|
657
|
+
if (!Object.hasOwn(customTool.params, key)) continue;
|
|
658
|
+
customToolParams.add(key);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (Array.isArray(customTool.children) && customTool.children.length > 0) {
|
|
662
|
+
visit(customTool.children);
|
|
534
663
|
}
|
|
535
664
|
}
|
|
536
|
-
}
|
|
665
|
+
};
|
|
666
|
+
visit(this.customTools);
|
|
537
667
|
const defaultToolNames = Object.values(AgentDefaultTool);
|
|
538
|
-
const overlappingTools = Array.from(
|
|
668
|
+
const overlappingTools = Array.from(this.customToolNames).filter((name) => defaultToolNames.includes(name));
|
|
539
669
|
if (overlappingTools.length > 0) {
|
|
540
670
|
throw new Error(`Custom tools and default tools have overlapping names: ${overlappingTools.join(", ")}`);
|
|
541
671
|
}
|
|
542
|
-
if (
|
|
543
|
-
setDynamicToolUseNames("customUser", Array.from(
|
|
672
|
+
if (this.customToolNames.size > 0) {
|
|
673
|
+
setDynamicToolUseNames("customUser", Array.from(this.customToolNames));
|
|
544
674
|
}
|
|
545
675
|
if (customToolParams.size > 0) {
|
|
546
676
|
this.allToolParamNames = Array.from(/* @__PURE__ */ new Set([...this.allToolParamNames, ...Array.from(customToolParams)]));
|
|
547
677
|
}
|
|
548
678
|
}
|
|
549
|
-
this.customToolNames = new Set(this.customTools.map((t) => t.name));
|
|
550
679
|
this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/skills");
|
|
551
680
|
this.rulesDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/rules");
|
|
552
681
|
}
|
|
@@ -570,10 +699,11 @@ var ClineAgent = class {
|
|
|
570
699
|
shell: this.runtime.env.shell(),
|
|
571
700
|
skills: await this.getSkills(),
|
|
572
701
|
agentRules: await this.getAgentRules(),
|
|
573
|
-
customTools: this.
|
|
702
|
+
customTools: this.activeCustomTools,
|
|
574
703
|
allowDefaultTools: this.allowDefaultTools,
|
|
575
704
|
customInstructions: this.customInstructions
|
|
576
705
|
};
|
|
706
|
+
this.promptActiveToolsVersion = this.activeToolsVersion;
|
|
577
707
|
this.sysPrompt = await this.promptManager.getSystemPrompt(context);
|
|
578
708
|
this.noUseTollSysPrompt = this.promptManager.getNoUseToolInstructions(context);
|
|
579
709
|
return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
|
|
@@ -682,9 +812,9 @@ ${content.trim()}\`\`\``);
|
|
|
682
812
|
* 核心任务循环
|
|
683
813
|
*/
|
|
684
814
|
async loop() {
|
|
685
|
-
const {
|
|
686
|
-
const { customTools, customToolNames } = this;
|
|
815
|
+
const { customToolsByName, customToolNames } = this;
|
|
687
816
|
while (this.state === "thinking" /* THINKING */) {
|
|
817
|
+
const { sysPrompt, noUseTollSysPrompt } = await this.getCurrentPrompt();
|
|
688
818
|
this.loopCount++;
|
|
689
819
|
if (this.loopCount > this.maxLoopCount) {
|
|
690
820
|
await this.memory.appendMessage({
|
|
@@ -729,7 +859,33 @@ ${content.trim()}\`\`\``);
|
|
|
729
859
|
}
|
|
730
860
|
}
|
|
731
861
|
if (customToolNames.has(tool.name)) {
|
|
732
|
-
const customTool =
|
|
862
|
+
const customTool = customToolsByName.get(tool.name);
|
|
863
|
+
if (!customTool) {
|
|
864
|
+
toolResults.push({ tool, result: `Error: Custom tool "${tool.name}" not found.` });
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
if (isCustomToolGroup(customTool)) {
|
|
868
|
+
let groupResult;
|
|
869
|
+
if (customTool.onCall) {
|
|
870
|
+
try {
|
|
871
|
+
groupResult = await customTool.onCall(tool.params);
|
|
872
|
+
} catch (error) {
|
|
873
|
+
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
const childrenPrompt = this.activateCustomToolGroup(customTool);
|
|
878
|
+
const finalPrompt = `# New Available Tools
|
|
879
|
+
|
|
880
|
+
The following are instructions for using the new available tools.
|
|
881
|
+
|
|
882
|
+
${childrenPrompt}`;
|
|
883
|
+
const promptBlock = groupResult !== void 0 ? `${typeof groupResult === "string" ? groupResult : JSON.stringify(groupResult)}
|
|
884
|
+
|
|
885
|
+
${finalPrompt}` : finalPrompt;
|
|
886
|
+
toolResults.push({ tool, result: promptBlock });
|
|
887
|
+
continue;
|
|
888
|
+
}
|
|
733
889
|
if (customTool.onCall) {
|
|
734
890
|
try {
|
|
735
891
|
const res = await customTool.onCall(tool.params);
|
|
@@ -832,15 +988,36 @@ STDERR: ${result.stderr}` });
|
|
|
832
988
|
const path2 = tool.params.path || this.runtime.env.cwd();
|
|
833
989
|
const regexStr = tool.params.regex;
|
|
834
990
|
const filePattern = tool.params.file_pattern;
|
|
991
|
+
const includeNodeModules = tool.params.include_node_modules === "true";
|
|
835
992
|
if (regexStr && path2) {
|
|
836
993
|
try {
|
|
837
994
|
let result;
|
|
838
995
|
if (typeof this.runtime.fs.searchFiles === "function") {
|
|
839
996
|
result = await this.runtime.fs.searchFiles(path2, regexStr, filePattern);
|
|
840
997
|
} else {
|
|
841
|
-
result = await this.searchFiles(path2, regexStr, filePattern);
|
|
998
|
+
result = await this.searchFiles(path2, regexStr, filePattern, includeNodeModules);
|
|
999
|
+
}
|
|
1000
|
+
toolResults.push({ tool, result });
|
|
1001
|
+
} catch (e) {
|
|
1002
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
1003
|
+
}
|
|
1004
|
+
} else {
|
|
1005
|
+
toolResults.push({ tool, result: `Error: miss path or regex params` });
|
|
1006
|
+
}
|
|
1007
|
+
} else if (tool.name === "agent_search_file_content" /* SEARCH_CONTENT */) {
|
|
1008
|
+
const path2 = tool.params.path || this.runtime.env.cwd();
|
|
1009
|
+
const regexStr = tool.params.regex;
|
|
1010
|
+
const filePattern = tool.params.file_pattern;
|
|
1011
|
+
const includeNodeModules = tool.params.include_node_modules === "true";
|
|
1012
|
+
if (regexStr && path2) {
|
|
1013
|
+
try {
|
|
1014
|
+
let result;
|
|
1015
|
+
if (typeof this.runtime.fs.searchFileContent === "function") {
|
|
1016
|
+
result = await this.runtime.fs.searchFileContent(path2, regexStr, filePattern);
|
|
1017
|
+
} else {
|
|
1018
|
+
result = await this.searchFileContent(path2, regexStr, filePattern, includeNodeModules);
|
|
842
1019
|
}
|
|
843
|
-
toolResults.push({ tool, result
|
|
1020
|
+
toolResults.push({ tool, result });
|
|
844
1021
|
} catch (e) {
|
|
845
1022
|
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
846
1023
|
}
|
|
@@ -969,6 +1146,27 @@ ${this.promptManager.getUsedToolResultInstructions()}`;
|
|
|
969
1146
|
}
|
|
970
1147
|
}
|
|
971
1148
|
}
|
|
1149
|
+
/**
|
|
1150
|
+
* 激活自定义工具集:将入口的 children 注册到活跃工具列表并返回渲染后的 prompt。
|
|
1151
|
+
*/
|
|
1152
|
+
activateCustomToolGroup(group) {
|
|
1153
|
+
if (this.activatedGroups.has(group.name)) {
|
|
1154
|
+
return renderCustomToolsPrompt(group.children || [], this.runtime.env.cwd());
|
|
1155
|
+
}
|
|
1156
|
+
this.activatedGroups.add(group.name);
|
|
1157
|
+
this.activeCustomTools = [...this.activeCustomTools, ...group.children || []];
|
|
1158
|
+
this.activeToolsVersion++;
|
|
1159
|
+
return renderCustomToolsPrompt(group.children || [], this.runtime.env.cwd());
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* 检查自上次获取 prompt 后是否有工具集被激活,若有则刷新缓存。
|
|
1163
|
+
*/
|
|
1164
|
+
async getCurrentPrompt() {
|
|
1165
|
+
if (this.promptActiveToolsVersion !== this.activeToolsVersion) {
|
|
1166
|
+
return this.getPrompt(true);
|
|
1167
|
+
}
|
|
1168
|
+
return this.getPrompt();
|
|
1169
|
+
}
|
|
972
1170
|
/**
|
|
973
1171
|
* 简单的 Diff 解析与替换辅助方法
|
|
974
1172
|
*/
|
|
@@ -1015,13 +1213,80 @@ ${searchBlock.substring(0, 100)}...`);
|
|
|
1015
1213
|
async getHistory() {
|
|
1016
1214
|
return this.memory.getHistory();
|
|
1017
1215
|
}
|
|
1018
|
-
|
|
1216
|
+
/**
|
|
1217
|
+
* 判断文件是否为可进行内容搜索的文本类文件
|
|
1218
|
+
*/
|
|
1219
|
+
isTextFile(name) {
|
|
1220
|
+
const ext = name.includes(".") ? String(name.split(".").pop()).toLowerCase() : "";
|
|
1221
|
+
if (!ext) {
|
|
1222
|
+
return true;
|
|
1223
|
+
}
|
|
1224
|
+
return TEXT_FILE_EXTENSIONS.has(ext);
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* 按文件名/目录名搜索,层级优先(BFS):
|
|
1228
|
+
* 每一层先匹配完当前层级的所有条目,再进入更深的子目录。
|
|
1229
|
+
*/
|
|
1230
|
+
async searchFiles(dirpath, regex, filePattern, includeNodeModules = false) {
|
|
1019
1231
|
const matches = [];
|
|
1020
|
-
const
|
|
1021
|
-
const
|
|
1232
|
+
const MAX_RESULTS = 100;
|
|
1233
|
+
const MAX_DEPTH = 8;
|
|
1234
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set([".git", "dist", ".agent", ".turbopack"]);
|
|
1235
|
+
const shouldSkipDir = (name) => SKIP_DIRS.has(name) || name === "node_modules" && !includeNodeModules;
|
|
1236
|
+
const nameRe = new RegExp(regex);
|
|
1237
|
+
const globRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
|
|
1238
|
+
const queue = [{ dir: dirpath, depth: 0 }];
|
|
1239
|
+
while (queue.length > 0 && matches.length < MAX_RESULTS) {
|
|
1240
|
+
const { dir, depth } = queue.shift();
|
|
1241
|
+
if (depth > MAX_DEPTH) {
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
let entries;
|
|
1245
|
+
try {
|
|
1246
|
+
entries = await this.runtime.fs.readDir(dir, { recursive: false });
|
|
1247
|
+
} catch {
|
|
1248
|
+
continue;
|
|
1249
|
+
}
|
|
1250
|
+
for (const entry of entries) {
|
|
1251
|
+
if (matches.length >= MAX_RESULTS) {
|
|
1252
|
+
break;
|
|
1253
|
+
}
|
|
1254
|
+
const child = dir === "." ? entry.name : `${dir}/${entry.name}`;
|
|
1255
|
+
if (entry.isDirectory()) {
|
|
1256
|
+
if (!shouldSkipDir(entry.name)) {
|
|
1257
|
+
if (nameRe.test(entry.name)) {
|
|
1258
|
+
matches.push(`${child}/`);
|
|
1259
|
+
}
|
|
1260
|
+
queue.push({ dir: child, depth: depth + 1 });
|
|
1261
|
+
}
|
|
1262
|
+
} else if (entry.isFile()) {
|
|
1263
|
+
if (globRe && !globRe.test(entry.name)) {
|
|
1264
|
+
continue;
|
|
1265
|
+
}
|
|
1266
|
+
if (nameRe.test(entry.name)) {
|
|
1267
|
+
matches.push(child);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
if (matches.length === 0) {
|
|
1273
|
+
return "No files found.";
|
|
1274
|
+
}
|
|
1275
|
+
return matches.join("\n");
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* 按文件内容搜索:正则匹配文件内容,返回匹配文件路径。
|
|
1279
|
+
*/
|
|
1280
|
+
async searchFileContent(dirpath, regex, filePattern, includeNodeModules = false) {
|
|
1281
|
+
const matches = [];
|
|
1282
|
+
const MAX_RESULTS = 100;
|
|
1283
|
+
const MAX_DEPTH = 8;
|
|
1022
1284
|
const SKIP_DIRS = /* @__PURE__ */ new Set([".git", "dist", ".agent", ".turbopack"]);
|
|
1285
|
+
const shouldSkipDir = (name) => SKIP_DIRS.has(name) || name === "node_modules" && !includeNodeModules;
|
|
1286
|
+
const contentRe = new RegExp(regex);
|
|
1287
|
+
const globRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
|
|
1023
1288
|
const walk = async (dir, depth) => {
|
|
1024
|
-
if (depth >
|
|
1289
|
+
if (depth > MAX_DEPTH || matches.length >= MAX_RESULTS) {
|
|
1025
1290
|
return;
|
|
1026
1291
|
}
|
|
1027
1292
|
let entries;
|
|
@@ -1031,21 +1296,24 @@ ${searchBlock.substring(0, 100)}...`);
|
|
|
1031
1296
|
return;
|
|
1032
1297
|
}
|
|
1033
1298
|
for (const entry of entries) {
|
|
1034
|
-
if (matches.length >=
|
|
1299
|
+
if (matches.length >= MAX_RESULTS) {
|
|
1035
1300
|
break;
|
|
1036
1301
|
}
|
|
1037
1302
|
const child = dir === "." ? entry.name : `${dir}/${entry.name}`;
|
|
1038
1303
|
if (entry.isDirectory()) {
|
|
1039
|
-
if (!
|
|
1304
|
+
if (!shouldSkipDir(entry.name)) {
|
|
1040
1305
|
await walk(child, depth + 1);
|
|
1041
1306
|
}
|
|
1042
1307
|
} else if (entry.isFile()) {
|
|
1043
|
-
if (
|
|
1308
|
+
if (!this.isTextFile(entry.name)) {
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
if (globRe && !globRe.test(entry.name)) {
|
|
1044
1312
|
continue;
|
|
1045
1313
|
}
|
|
1046
1314
|
try {
|
|
1047
|
-
const content =
|
|
1048
|
-
if (contentRe.test(content)) {
|
|
1315
|
+
const content = await this.runtime.fs.readFile(child);
|
|
1316
|
+
if (typeof content === "string" && contentRe.test(content)) {
|
|
1049
1317
|
matches.push(child);
|
|
1050
1318
|
}
|
|
1051
1319
|
} catch {
|
|
@@ -1054,6 +1322,9 @@ ${searchBlock.substring(0, 100)}...`);
|
|
|
1054
1322
|
}
|
|
1055
1323
|
};
|
|
1056
1324
|
await walk(dirpath, 0);
|
|
1325
|
+
if (matches.length === 0) {
|
|
1326
|
+
return "No files found with matching content.";
|
|
1327
|
+
}
|
|
1057
1328
|
return matches.join("\n");
|
|
1058
1329
|
}
|
|
1059
1330
|
};
|
|
@@ -1257,10 +1528,11 @@ ${context.customInstructions}
|
|
|
1257
1528
|
if (allowDefaultTools) {
|
|
1258
1529
|
useDefaultTools = defaultTools.filter((tool) => allowDefaultTools.includes(tool.name));
|
|
1259
1530
|
}
|
|
1531
|
+
const renderedCustomTools = renderCustomToolsPrompt(customTools, context.cwd);
|
|
1260
1532
|
return `# Available Tools
|
|
1261
1533
|
You can use the following tools by formatting your output as XML blocks. Only use ONE tool per message, and ALWAYS wait for the user's response with the execution result before proceeding.
|
|
1262
1534
|
|
|
1263
|
-
${[...useDefaultTools
|
|
1535
|
+
${[...useDefaultTools].map((tool) => {
|
|
1264
1536
|
return `### ${tool.name}
|
|
1265
1537
|
Description: ${tool.description}
|
|
1266
1538
|
Parameters:
|
|
@@ -1273,6 +1545,8 @@ ${Object.entries(tool.params).map(([name, description]) => `<${name}>${descripti
|
|
|
1273
1545
|
</${tool.name}>
|
|
1274
1546
|
`;
|
|
1275
1547
|
}).join("\n")}
|
|
1548
|
+
${renderedCustomTools ? `
|
|
1549
|
+
${renderedCustomTools}` : ""}
|
|
1276
1550
|
|
|
1277
1551
|
# Tool Use Examples
|
|
1278
1552
|
${useDefaultTools.filter((item) => Boolean(item.example)).map((item) => item.example).join("\n")}}
|
|
@@ -1639,10 +1913,14 @@ exports.WebApiHandler = WebApiHandler;
|
|
|
1639
1913
|
exports.WebMcpManager = WebMcpManager;
|
|
1640
1914
|
exports.WebMemoryManager = WebMemoryManager;
|
|
1641
1915
|
exports.WebPromptManager = WebPromptManager;
|
|
1916
|
+
exports.collectCustomToolNames = collectCustomToolNames;
|
|
1642
1917
|
exports.createWebAgent = createWebAgent;
|
|
1643
1918
|
exports.defaultTools = defaultTools;
|
|
1644
1919
|
exports.getToolUseNames = getToolUseNames;
|
|
1920
|
+
exports.isCustomToolGroup = isCustomToolGroup;
|
|
1645
1921
|
exports.parseAssistantMessageV2 = parseAssistantMessageV2;
|
|
1922
|
+
exports.renderCustomToolPrompt = renderCustomToolPrompt;
|
|
1923
|
+
exports.renderCustomToolsPrompt = renderCustomToolsPrompt;
|
|
1646
1924
|
exports.setDynamicToolUseNames = setDynamicToolUseNames;
|
|
1647
1925
|
exports.toolParamNames = toolParamNames;
|
|
1648
1926
|
exports.toolUseNames = toolUseNames;
|