@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
|
@@ -22,6 +22,7 @@ var AgentDefaultTool = /* @__PURE__ */ ((AgentDefaultTool2) => {
|
|
|
22
22
|
AgentDefaultTool2["FILE_DELETE"] = "agent_delete_file";
|
|
23
23
|
AgentDefaultTool2["DIR_DELETE"] = "agent_delete_directory";
|
|
24
24
|
AgentDefaultTool2["SEARCH"] = "agent_search_files";
|
|
25
|
+
AgentDefaultTool2["SEARCH_CONTENT"] = "agent_search_file_content";
|
|
25
26
|
AgentDefaultTool2["LIST_FILES"] = "agent_list_files";
|
|
26
27
|
AgentDefaultTool2["LIST_CODE_DEF"] = "agent_list_code_definition_names";
|
|
27
28
|
AgentDefaultTool2["BROWSER"] = "agent_browser_action";
|
|
@@ -195,11 +196,22 @@ return (
|
|
|
195
196
|
},
|
|
196
197
|
{
|
|
197
198
|
name: "agent_search_files" /* SEARCH */,
|
|
198
|
-
description: "Search for files in a directory
|
|
199
|
+
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.",
|
|
199
200
|
params: {
|
|
200
201
|
path: "(required) The absolute or relative directory path to search.",
|
|
201
|
-
regex: "(required) The regex pattern to match
|
|
202
|
-
file_pattern: "(optional) glob pattern like *.ts."
|
|
202
|
+
regex: "(required) The regex pattern to match file or directory names against.",
|
|
203
|
+
file_pattern: "(optional) glob pattern like *.ts.",
|
|
204
|
+
include_node_modules: "(optional) set to true to include node_modules in the search. Defaults to false, so node_modules is skipped."
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "agent_search_file_content" /* SEARCH_CONTENT */,
|
|
209
|
+
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.",
|
|
210
|
+
params: {
|
|
211
|
+
path: "(required) The absolute or relative directory path to search.",
|
|
212
|
+
regex: "(required) The regex pattern to match file content against.",
|
|
213
|
+
file_pattern: "(optional) glob pattern like *.ts to limit which files are searched.",
|
|
214
|
+
include_node_modules: "(optional) set to true to include node_modules in the search. Defaults to false, so node_modules is skipped."
|
|
203
215
|
}
|
|
204
216
|
},
|
|
205
217
|
{
|
|
@@ -268,6 +280,7 @@ var READ_ONLY_TOOLS = [
|
|
|
268
280
|
"agent_list_files" /* LIST_FILES */,
|
|
269
281
|
"agent_read_file" /* FILE_READ */,
|
|
270
282
|
"agent_search_files" /* SEARCH */,
|
|
283
|
+
"agent_search_file_content" /* SEARCH_CONTENT */,
|
|
271
284
|
"agent_list_code_definition_names" /* LIST_CODE_DEF */,
|
|
272
285
|
"agent_browser_action" /* BROWSER */,
|
|
273
286
|
"agent_ask_followup_question" /* ASK */,
|
|
@@ -437,6 +450,7 @@ var toolParamNames = [
|
|
|
437
450
|
"diff",
|
|
438
451
|
"regex",
|
|
439
452
|
"file_pattern",
|
|
453
|
+
"include_node_modules",
|
|
440
454
|
"recursive",
|
|
441
455
|
"action",
|
|
442
456
|
"url",
|
|
@@ -475,6 +489,104 @@ var toolParamNames = [
|
|
|
475
489
|
"start_line",
|
|
476
490
|
"end_line"
|
|
477
491
|
];
|
|
492
|
+
|
|
493
|
+
// src/shared/custom-tools.ts
|
|
494
|
+
function isCustomToolGroup(tool) {
|
|
495
|
+
return Array.isArray(tool.children) && tool.children.length > 0;
|
|
496
|
+
}
|
|
497
|
+
function collectCustomToolNames(tools) {
|
|
498
|
+
const names = [];
|
|
499
|
+
const visit = (list) => {
|
|
500
|
+
for (const tool of list) {
|
|
501
|
+
names.push(tool.name);
|
|
502
|
+
if (Array.isArray(tool.children) && tool.children.length > 0) {
|
|
503
|
+
visit(tool.children);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
visit(tools);
|
|
508
|
+
return names;
|
|
509
|
+
}
|
|
510
|
+
function renderCustomToolPrompt(tool, cwd = "") {
|
|
511
|
+
const params = tool.params ? Object.entries(tool.params) : [];
|
|
512
|
+
const replaceCwd = (text) => String(text).replaceAll("${context.cwd}", cwd);
|
|
513
|
+
const paramLines = params.map(([name, description]) => `- ${name}: ${replaceCwd(description)}`).join("\n");
|
|
514
|
+
const usageLines = params.map(([name, description]) => `<${name}>${replaceCwd(description)}</${name}>`).join("\n");
|
|
515
|
+
return `### ${tool.name}
|
|
516
|
+
Description: ${tool.description}
|
|
517
|
+
Parameters:
|
|
518
|
+
${paramLines}
|
|
519
|
+
- 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)
|
|
520
|
+
Usage:
|
|
521
|
+
<${tool.name}>
|
|
522
|
+
${usageLines}
|
|
523
|
+
<task_progress>Checklist here (optional)</task_progress>
|
|
524
|
+
</${tool.name}>
|
|
525
|
+
`;
|
|
526
|
+
}
|
|
527
|
+
function renderCustomToolsPrompt(tools, cwd = "") {
|
|
528
|
+
return tools.map((tool) => renderCustomToolPrompt(tool, cwd)).join("\n");
|
|
529
|
+
}
|
|
530
|
+
var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
531
|
+
"txt",
|
|
532
|
+
"md",
|
|
533
|
+
"markdown",
|
|
534
|
+
"json",
|
|
535
|
+
"js",
|
|
536
|
+
"mjs",
|
|
537
|
+
"cjs",
|
|
538
|
+
"ts",
|
|
539
|
+
"tsx",
|
|
540
|
+
"jsx",
|
|
541
|
+
"html",
|
|
542
|
+
"htm",
|
|
543
|
+
"css",
|
|
544
|
+
"scss",
|
|
545
|
+
"sass",
|
|
546
|
+
"less",
|
|
547
|
+
"py",
|
|
548
|
+
"java",
|
|
549
|
+
"c",
|
|
550
|
+
"cpp",
|
|
551
|
+
"cc",
|
|
552
|
+
"cxx",
|
|
553
|
+
"h",
|
|
554
|
+
"hpp",
|
|
555
|
+
"cs",
|
|
556
|
+
"go",
|
|
557
|
+
"rs",
|
|
558
|
+
"rb",
|
|
559
|
+
"php",
|
|
560
|
+
"sh",
|
|
561
|
+
"bash",
|
|
562
|
+
"zsh",
|
|
563
|
+
"bat",
|
|
564
|
+
"cmd",
|
|
565
|
+
"ps1",
|
|
566
|
+
"yaml",
|
|
567
|
+
"yml",
|
|
568
|
+
"toml",
|
|
569
|
+
"ini",
|
|
570
|
+
"cfg",
|
|
571
|
+
"conf",
|
|
572
|
+
"xml",
|
|
573
|
+
"svg",
|
|
574
|
+
"csv",
|
|
575
|
+
"log",
|
|
576
|
+
"sql",
|
|
577
|
+
"vue",
|
|
578
|
+
"svelte",
|
|
579
|
+
"astro",
|
|
580
|
+
"graphql",
|
|
581
|
+
"gql",
|
|
582
|
+
"prisma",
|
|
583
|
+
"env",
|
|
584
|
+
"gitignore",
|
|
585
|
+
"dockerfile",
|
|
586
|
+
"makefile",
|
|
587
|
+
"properties",
|
|
588
|
+
"lock"
|
|
589
|
+
]);
|
|
478
590
|
var AgentState = /* @__PURE__ */ ((AgentState2) => {
|
|
479
591
|
AgentState2["IDLE"] = "idle";
|
|
480
592
|
AgentState2["THINKING"] = "thinking";
|
|
@@ -498,9 +610,19 @@ var ClineAgent = class {
|
|
|
498
610
|
skillDir;
|
|
499
611
|
rulesDir;
|
|
500
612
|
customTools;
|
|
613
|
+
/** 当前可用(已展开集合)的顶层工具列表,传给 PromptManager 渲染 */
|
|
614
|
+
activeCustomTools;
|
|
615
|
+
/** 所有已知工具名(含未激活 children),便于查找定义 */
|
|
616
|
+
customToolsByName;
|
|
501
617
|
customToolNames;
|
|
502
618
|
allowDefaultTools;
|
|
503
619
|
customInstructions;
|
|
620
|
+
/** 已激活的工具集入口名 */
|
|
621
|
+
activatedGroups = /* @__PURE__ */ new Set();
|
|
622
|
+
/** activeCustomTools 变更版本号,用于 Prompt 缓存失效 */
|
|
623
|
+
activeToolsVersion = 0;
|
|
624
|
+
/** 缓存 sysPrompt 时记录的版本号 */
|
|
625
|
+
promptActiveToolsVersion = -1;
|
|
504
626
|
sysPrompt;
|
|
505
627
|
noUseTollSysPrompt;
|
|
506
628
|
// 简单的事件回调系统,供宿主环境注册以监听 Agent 内部事件
|
|
@@ -520,31 +642,38 @@ var ClineAgent = class {
|
|
|
520
642
|
this.allowDefaultTools.push("agent_attempt_completion" /* ATTEMPT */);
|
|
521
643
|
}
|
|
522
644
|
this.customInstructions = options.customInstructions;
|
|
645
|
+
this.customToolsByName = /* @__PURE__ */ new Map();
|
|
646
|
+
this.activeCustomTools = [...this.customTools];
|
|
647
|
+
this.customToolNames = new Set(collectCustomToolNames(this.customTools));
|
|
523
648
|
if (this.customTools.length > 0) {
|
|
524
|
-
const dynamicToolNames = /* @__PURE__ */ new Set();
|
|
525
649
|
const customToolParams = /* @__PURE__ */ new Set();
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
650
|
+
const visit = (tools) => {
|
|
651
|
+
for (const customTool of tools) {
|
|
652
|
+
this.customToolsByName.set(customTool.name, customTool);
|
|
653
|
+
if (customTool.params) {
|
|
654
|
+
for (const key in customTool.params) {
|
|
655
|
+
if (!Object.hasOwn(customTool.params, key)) continue;
|
|
656
|
+
customToolParams.add(key);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
if (Array.isArray(customTool.children) && customTool.children.length > 0) {
|
|
660
|
+
visit(customTool.children);
|
|
532
661
|
}
|
|
533
662
|
}
|
|
534
|
-
}
|
|
663
|
+
};
|
|
664
|
+
visit(this.customTools);
|
|
535
665
|
const defaultToolNames = Object.values(AgentDefaultTool);
|
|
536
|
-
const overlappingTools = Array.from(
|
|
666
|
+
const overlappingTools = Array.from(this.customToolNames).filter((name) => defaultToolNames.includes(name));
|
|
537
667
|
if (overlappingTools.length > 0) {
|
|
538
668
|
throw new Error(`Custom tools and default tools have overlapping names: ${overlappingTools.join(", ")}`);
|
|
539
669
|
}
|
|
540
|
-
if (
|
|
541
|
-
setDynamicToolUseNames("customUser", Array.from(
|
|
670
|
+
if (this.customToolNames.size > 0) {
|
|
671
|
+
setDynamicToolUseNames("customUser", Array.from(this.customToolNames));
|
|
542
672
|
}
|
|
543
673
|
if (customToolParams.size > 0) {
|
|
544
674
|
this.allToolParamNames = Array.from(/* @__PURE__ */ new Set([...this.allToolParamNames, ...Array.from(customToolParams)]));
|
|
545
675
|
}
|
|
546
676
|
}
|
|
547
|
-
this.customToolNames = new Set(this.customTools.map((t) => t.name));
|
|
548
677
|
this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/skills");
|
|
549
678
|
this.rulesDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/rules");
|
|
550
679
|
}
|
|
@@ -568,10 +697,11 @@ var ClineAgent = class {
|
|
|
568
697
|
shell: this.runtime.env.shell(),
|
|
569
698
|
skills: await this.getSkills(),
|
|
570
699
|
agentRules: await this.getAgentRules(),
|
|
571
|
-
customTools: this.
|
|
700
|
+
customTools: this.activeCustomTools,
|
|
572
701
|
allowDefaultTools: this.allowDefaultTools,
|
|
573
702
|
customInstructions: this.customInstructions
|
|
574
703
|
};
|
|
704
|
+
this.promptActiveToolsVersion = this.activeToolsVersion;
|
|
575
705
|
this.sysPrompt = await this.promptManager.getSystemPrompt(context);
|
|
576
706
|
this.noUseTollSysPrompt = this.promptManager.getNoUseToolInstructions(context);
|
|
577
707
|
return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
|
|
@@ -680,9 +810,9 @@ ${content.trim()}\`\`\``);
|
|
|
680
810
|
* 核心任务循环
|
|
681
811
|
*/
|
|
682
812
|
async loop() {
|
|
683
|
-
const {
|
|
684
|
-
const { customTools, customToolNames } = this;
|
|
813
|
+
const { customToolsByName, customToolNames } = this;
|
|
685
814
|
while (this.state === "thinking" /* THINKING */) {
|
|
815
|
+
const { sysPrompt, noUseTollSysPrompt } = await this.getCurrentPrompt();
|
|
686
816
|
this.loopCount++;
|
|
687
817
|
if (this.loopCount > this.maxLoopCount) {
|
|
688
818
|
await this.memory.appendMessage({
|
|
@@ -727,7 +857,33 @@ ${content.trim()}\`\`\``);
|
|
|
727
857
|
}
|
|
728
858
|
}
|
|
729
859
|
if (customToolNames.has(tool.name)) {
|
|
730
|
-
const customTool =
|
|
860
|
+
const customTool = customToolsByName.get(tool.name);
|
|
861
|
+
if (!customTool) {
|
|
862
|
+
toolResults.push({ tool, result: `Error: Custom tool "${tool.name}" not found.` });
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
if (isCustomToolGroup(customTool)) {
|
|
866
|
+
let groupResult;
|
|
867
|
+
if (customTool.onCall) {
|
|
868
|
+
try {
|
|
869
|
+
groupResult = await customTool.onCall(tool.params);
|
|
870
|
+
} catch (error) {
|
|
871
|
+
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
const childrenPrompt = this.activateCustomToolGroup(customTool);
|
|
876
|
+
const finalPrompt = `# New Available Tools
|
|
877
|
+
|
|
878
|
+
The following are instructions for using the new available tools.
|
|
879
|
+
|
|
880
|
+
${childrenPrompt}`;
|
|
881
|
+
const promptBlock = groupResult !== void 0 ? `${typeof groupResult === "string" ? groupResult : JSON.stringify(groupResult)}
|
|
882
|
+
|
|
883
|
+
${finalPrompt}` : finalPrompt;
|
|
884
|
+
toolResults.push({ tool, result: promptBlock });
|
|
885
|
+
continue;
|
|
886
|
+
}
|
|
731
887
|
if (customTool.onCall) {
|
|
732
888
|
try {
|
|
733
889
|
const res = await customTool.onCall(tool.params);
|
|
@@ -830,15 +986,36 @@ STDERR: ${result.stderr}` });
|
|
|
830
986
|
const path3 = tool.params.path || this.runtime.env.cwd();
|
|
831
987
|
const regexStr = tool.params.regex;
|
|
832
988
|
const filePattern = tool.params.file_pattern;
|
|
989
|
+
const includeNodeModules = tool.params.include_node_modules === "true";
|
|
833
990
|
if (regexStr && path3) {
|
|
834
991
|
try {
|
|
835
992
|
let result;
|
|
836
993
|
if (typeof this.runtime.fs.searchFiles === "function") {
|
|
837
994
|
result = await this.runtime.fs.searchFiles(path3, regexStr, filePattern);
|
|
838
995
|
} else {
|
|
839
|
-
result = await this.searchFiles(path3, regexStr, filePattern);
|
|
996
|
+
result = await this.searchFiles(path3, regexStr, filePattern, includeNodeModules);
|
|
997
|
+
}
|
|
998
|
+
toolResults.push({ tool, result });
|
|
999
|
+
} catch (e) {
|
|
1000
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
1001
|
+
}
|
|
1002
|
+
} else {
|
|
1003
|
+
toolResults.push({ tool, result: `Error: miss path or regex params` });
|
|
1004
|
+
}
|
|
1005
|
+
} else if (tool.name === "agent_search_file_content" /* SEARCH_CONTENT */) {
|
|
1006
|
+
const path3 = tool.params.path || this.runtime.env.cwd();
|
|
1007
|
+
const regexStr = tool.params.regex;
|
|
1008
|
+
const filePattern = tool.params.file_pattern;
|
|
1009
|
+
const includeNodeModules = tool.params.include_node_modules === "true";
|
|
1010
|
+
if (regexStr && path3) {
|
|
1011
|
+
try {
|
|
1012
|
+
let result;
|
|
1013
|
+
if (typeof this.runtime.fs.searchFileContent === "function") {
|
|
1014
|
+
result = await this.runtime.fs.searchFileContent(path3, regexStr, filePattern);
|
|
1015
|
+
} else {
|
|
1016
|
+
result = await this.searchFileContent(path3, regexStr, filePattern, includeNodeModules);
|
|
840
1017
|
}
|
|
841
|
-
toolResults.push({ tool, result
|
|
1018
|
+
toolResults.push({ tool, result });
|
|
842
1019
|
} catch (e) {
|
|
843
1020
|
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
844
1021
|
}
|
|
@@ -967,6 +1144,27 @@ ${this.promptManager.getUsedToolResultInstructions()}`;
|
|
|
967
1144
|
}
|
|
968
1145
|
}
|
|
969
1146
|
}
|
|
1147
|
+
/**
|
|
1148
|
+
* 激活自定义工具集:将入口的 children 注册到活跃工具列表并返回渲染后的 prompt。
|
|
1149
|
+
*/
|
|
1150
|
+
activateCustomToolGroup(group) {
|
|
1151
|
+
if (this.activatedGroups.has(group.name)) {
|
|
1152
|
+
return renderCustomToolsPrompt(group.children || [], this.runtime.env.cwd());
|
|
1153
|
+
}
|
|
1154
|
+
this.activatedGroups.add(group.name);
|
|
1155
|
+
this.activeCustomTools = [...this.activeCustomTools, ...group.children || []];
|
|
1156
|
+
this.activeToolsVersion++;
|
|
1157
|
+
return renderCustomToolsPrompt(group.children || [], this.runtime.env.cwd());
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* 检查自上次获取 prompt 后是否有工具集被激活,若有则刷新缓存。
|
|
1161
|
+
*/
|
|
1162
|
+
async getCurrentPrompt() {
|
|
1163
|
+
if (this.promptActiveToolsVersion !== this.activeToolsVersion) {
|
|
1164
|
+
return this.getPrompt(true);
|
|
1165
|
+
}
|
|
1166
|
+
return this.getPrompt();
|
|
1167
|
+
}
|
|
970
1168
|
/**
|
|
971
1169
|
* 简单的 Diff 解析与替换辅助方法
|
|
972
1170
|
*/
|
|
@@ -1013,13 +1211,80 @@ ${searchBlock.substring(0, 100)}...`);
|
|
|
1013
1211
|
async getHistory() {
|
|
1014
1212
|
return this.memory.getHistory();
|
|
1015
1213
|
}
|
|
1016
|
-
|
|
1214
|
+
/**
|
|
1215
|
+
* 判断文件是否为可进行内容搜索的文本类文件
|
|
1216
|
+
*/
|
|
1217
|
+
isTextFile(name) {
|
|
1218
|
+
const ext = name.includes(".") ? String(name.split(".").pop()).toLowerCase() : "";
|
|
1219
|
+
if (!ext) {
|
|
1220
|
+
return true;
|
|
1221
|
+
}
|
|
1222
|
+
return TEXT_FILE_EXTENSIONS.has(ext);
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* 按文件名/目录名搜索,层级优先(BFS):
|
|
1226
|
+
* 每一层先匹配完当前层级的所有条目,再进入更深的子目录。
|
|
1227
|
+
*/
|
|
1228
|
+
async searchFiles(dirpath, regex, filePattern, includeNodeModules = false) {
|
|
1017
1229
|
const matches = [];
|
|
1018
|
-
const
|
|
1019
|
-
const
|
|
1230
|
+
const MAX_RESULTS = 100;
|
|
1231
|
+
const MAX_DEPTH = 8;
|
|
1232
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set([".git", "dist", ".agent", ".turbopack"]);
|
|
1233
|
+
const shouldSkipDir = (name) => SKIP_DIRS.has(name) || name === "node_modules" && !includeNodeModules;
|
|
1234
|
+
const nameRe = new RegExp(regex);
|
|
1235
|
+
const globRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
|
|
1236
|
+
const queue = [{ dir: dirpath, depth: 0 }];
|
|
1237
|
+
while (queue.length > 0 && matches.length < MAX_RESULTS) {
|
|
1238
|
+
const { dir, depth } = queue.shift();
|
|
1239
|
+
if (depth > MAX_DEPTH) {
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
let entries;
|
|
1243
|
+
try {
|
|
1244
|
+
entries = await this.runtime.fs.readDir(dir, { recursive: false });
|
|
1245
|
+
} catch {
|
|
1246
|
+
continue;
|
|
1247
|
+
}
|
|
1248
|
+
for (const entry of entries) {
|
|
1249
|
+
if (matches.length >= MAX_RESULTS) {
|
|
1250
|
+
break;
|
|
1251
|
+
}
|
|
1252
|
+
const child = dir === "." ? entry.name : `${dir}/${entry.name}`;
|
|
1253
|
+
if (entry.isDirectory()) {
|
|
1254
|
+
if (!shouldSkipDir(entry.name)) {
|
|
1255
|
+
if (nameRe.test(entry.name)) {
|
|
1256
|
+
matches.push(`${child}/`);
|
|
1257
|
+
}
|
|
1258
|
+
queue.push({ dir: child, depth: depth + 1 });
|
|
1259
|
+
}
|
|
1260
|
+
} else if (entry.isFile()) {
|
|
1261
|
+
if (globRe && !globRe.test(entry.name)) {
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
if (nameRe.test(entry.name)) {
|
|
1265
|
+
matches.push(child);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (matches.length === 0) {
|
|
1271
|
+
return "No files found.";
|
|
1272
|
+
}
|
|
1273
|
+
return matches.join("\n");
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* 按文件内容搜索:正则匹配文件内容,返回匹配文件路径。
|
|
1277
|
+
*/
|
|
1278
|
+
async searchFileContent(dirpath, regex, filePattern, includeNodeModules = false) {
|
|
1279
|
+
const matches = [];
|
|
1280
|
+
const MAX_RESULTS = 100;
|
|
1281
|
+
const MAX_DEPTH = 8;
|
|
1020
1282
|
const SKIP_DIRS = /* @__PURE__ */ new Set([".git", "dist", ".agent", ".turbopack"]);
|
|
1283
|
+
const shouldSkipDir = (name) => SKIP_DIRS.has(name) || name === "node_modules" && !includeNodeModules;
|
|
1284
|
+
const contentRe = new RegExp(regex);
|
|
1285
|
+
const globRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
|
|
1021
1286
|
const walk = async (dir, depth) => {
|
|
1022
|
-
if (depth >
|
|
1287
|
+
if (depth > MAX_DEPTH || matches.length >= MAX_RESULTS) {
|
|
1023
1288
|
return;
|
|
1024
1289
|
}
|
|
1025
1290
|
let entries;
|
|
@@ -1029,21 +1294,24 @@ ${searchBlock.substring(0, 100)}...`);
|
|
|
1029
1294
|
return;
|
|
1030
1295
|
}
|
|
1031
1296
|
for (const entry of entries) {
|
|
1032
|
-
if (matches.length >=
|
|
1297
|
+
if (matches.length >= MAX_RESULTS) {
|
|
1033
1298
|
break;
|
|
1034
1299
|
}
|
|
1035
1300
|
const child = dir === "." ? entry.name : `${dir}/${entry.name}`;
|
|
1036
1301
|
if (entry.isDirectory()) {
|
|
1037
|
-
if (!
|
|
1302
|
+
if (!shouldSkipDir(entry.name)) {
|
|
1038
1303
|
await walk(child, depth + 1);
|
|
1039
1304
|
}
|
|
1040
1305
|
} else if (entry.isFile()) {
|
|
1041
|
-
if (
|
|
1306
|
+
if (!this.isTextFile(entry.name)) {
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
if (globRe && !globRe.test(entry.name)) {
|
|
1042
1310
|
continue;
|
|
1043
1311
|
}
|
|
1044
1312
|
try {
|
|
1045
|
-
const content =
|
|
1046
|
-
if (contentRe.test(content)) {
|
|
1313
|
+
const content = await this.runtime.fs.readFile(child);
|
|
1314
|
+
if (typeof content === "string" && contentRe.test(content)) {
|
|
1047
1315
|
matches.push(child);
|
|
1048
1316
|
}
|
|
1049
1317
|
} catch {
|
|
@@ -1052,6 +1320,9 @@ ${searchBlock.substring(0, 100)}...`);
|
|
|
1052
1320
|
}
|
|
1053
1321
|
};
|
|
1054
1322
|
await walk(dirpath, 0);
|
|
1323
|
+
if (matches.length === 0) {
|
|
1324
|
+
return "No files found with matching content.";
|
|
1325
|
+
}
|
|
1055
1326
|
return matches.join("\n");
|
|
1056
1327
|
}
|
|
1057
1328
|
};
|
|
@@ -1255,10 +1526,11 @@ ${context.customInstructions}
|
|
|
1255
1526
|
if (allowDefaultTools) {
|
|
1256
1527
|
useDefaultTools = defaultTools.filter((tool) => allowDefaultTools.includes(tool.name));
|
|
1257
1528
|
}
|
|
1529
|
+
const renderedCustomTools = renderCustomToolsPrompt(customTools, context.cwd);
|
|
1258
1530
|
return `# Available Tools
|
|
1259
1531
|
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.
|
|
1260
1532
|
|
|
1261
|
-
${[...useDefaultTools
|
|
1533
|
+
${[...useDefaultTools].map((tool) => {
|
|
1262
1534
|
return `### ${tool.name}
|
|
1263
1535
|
Description: ${tool.description}
|
|
1264
1536
|
Parameters:
|
|
@@ -1271,6 +1543,8 @@ ${Object.entries(tool.params).map(([name, description]) => `<${name}>${descripti
|
|
|
1271
1543
|
</${tool.name}>
|
|
1272
1544
|
`;
|
|
1273
1545
|
}).join("\n")}
|
|
1546
|
+
${renderedCustomTools ? `
|
|
1547
|
+
${renderedCustomTools}` : ""}
|
|
1274
1548
|
|
|
1275
1549
|
# Tool Use Examples
|
|
1276
1550
|
${useDefaultTools.filter((item) => Boolean(item.example)).map((item) => item.example).join("\n")}}
|
|
@@ -1707,6 +1981,6 @@ function createNodeAgent(options) {
|
|
|
1707
1981
|
return agent;
|
|
1708
1982
|
}
|
|
1709
1983
|
|
|
1710
|
-
export { AgentDefaultTool, AgentState, ClineAgent, DefaultNodeRuntime, NodeApiHandler, NodeMcpManager, NodeMemoryManager, NodePromptManager, READ_ONLY_TOOLS, TOOL_RESULT_BLOCK, VERSION, createNodeAgent, defaultTools, getToolUseNames, parseAssistantMessageV2, setDynamicToolUseNames, toolParamNames, toolUseNames };
|
|
1984
|
+
export { AgentDefaultTool, AgentState, ClineAgent, DefaultNodeRuntime, NodeApiHandler, NodeMcpManager, NodeMemoryManager, NodePromptManager, READ_ONLY_TOOLS, TOOL_RESULT_BLOCK, VERSION, collectCustomToolNames, createNodeAgent, defaultTools, getToolUseNames, isCustomToolGroup, parseAssistantMessageV2, renderCustomToolPrompt, renderCustomToolsPrompt, setDynamicToolUseNames, toolParamNames, toolUseNames };
|
|
1711
1985
|
//# sourceMappingURL=nodeRuntime.mjs.map
|
|
1712
1986
|
//# sourceMappingURL=nodeRuntime.mjs.map
|