@amical/aiagent-sdk 0.1.10 → 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.
@@ -484,6 +484,44 @@ var toolParamNames = [
484
484
  "start_line",
485
485
  "end_line"
486
486
  ];
487
+
488
+ // src/shared/custom-tools.ts
489
+ function isCustomToolGroup(tool) {
490
+ return Array.isArray(tool.children) && tool.children.length > 0;
491
+ }
492
+ function collectCustomToolNames(tools) {
493
+ const names = [];
494
+ const visit = (list) => {
495
+ for (const tool of list) {
496
+ names.push(tool.name);
497
+ if (Array.isArray(tool.children) && tool.children.length > 0) {
498
+ visit(tool.children);
499
+ }
500
+ }
501
+ };
502
+ visit(tools);
503
+ return names;
504
+ }
505
+ function renderCustomToolPrompt(tool, cwd = "") {
506
+ const params = tool.params ? Object.entries(tool.params) : [];
507
+ const replaceCwd = (text) => String(text).replaceAll("${context.cwd}", cwd);
508
+ const paramLines = params.map(([name, description]) => `- ${name}: ${replaceCwd(description)}`).join("\n");
509
+ const usageLines = params.map(([name, description]) => `<${name}>${replaceCwd(description)}</${name}>`).join("\n");
510
+ return `### ${tool.name}
511
+ Description: ${tool.description}
512
+ Parameters:
513
+ ${paramLines}
514
+ - 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)
515
+ Usage:
516
+ <${tool.name}>
517
+ ${usageLines}
518
+ <task_progress>Checklist here (optional)</task_progress>
519
+ </${tool.name}>
520
+ `;
521
+ }
522
+ function renderCustomToolsPrompt(tools, cwd = "") {
523
+ return tools.map((tool) => renderCustomToolPrompt(tool, cwd)).join("\n");
524
+ }
487
525
  var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
488
526
  "txt",
489
527
  "md",
@@ -567,9 +605,19 @@ var ClineAgent = class {
567
605
  skillDir;
568
606
  rulesDir;
569
607
  customTools;
608
+ /** 当前可用(已展开集合)的顶层工具列表,传给 PromptManager 渲染 */
609
+ activeCustomTools;
610
+ /** 所有已知工具名(含未激活 children),便于查找定义 */
611
+ customToolsByName;
570
612
  customToolNames;
571
613
  allowDefaultTools;
572
614
  customInstructions;
615
+ /** 已激活的工具集入口名 */
616
+ activatedGroups = /* @__PURE__ */ new Set();
617
+ /** activeCustomTools 变更版本号,用于 Prompt 缓存失效 */
618
+ activeToolsVersion = 0;
619
+ /** 缓存 sysPrompt 时记录的版本号 */
620
+ promptActiveToolsVersion = -1;
573
621
  sysPrompt;
574
622
  noUseTollSysPrompt;
575
623
  // 简单的事件回调系统,供宿主环境注册以监听 Agent 内部事件
@@ -589,31 +637,38 @@ var ClineAgent = class {
589
637
  this.allowDefaultTools.push("agent_attempt_completion" /* ATTEMPT */);
590
638
  }
591
639
  this.customInstructions = options.customInstructions;
640
+ this.customToolsByName = /* @__PURE__ */ new Map();
641
+ this.activeCustomTools = [...this.customTools];
642
+ this.customToolNames = new Set(collectCustomToolNames(this.customTools));
592
643
  if (this.customTools.length > 0) {
593
- const dynamicToolNames = /* @__PURE__ */ new Set();
594
644
  const customToolParams = /* @__PURE__ */ new Set();
595
- for (const customTool of this.customTools) {
596
- dynamicToolNames.add(customTool.name);
597
- if (customTool.params) {
598
- for (const key in customTool.params) {
599
- if (!Object.hasOwn(customTool.params, key)) continue;
600
- customToolParams.add(key);
645
+ const visit = (tools) => {
646
+ for (const customTool of tools) {
647
+ this.customToolsByName.set(customTool.name, customTool);
648
+ if (customTool.params) {
649
+ for (const key in customTool.params) {
650
+ if (!Object.hasOwn(customTool.params, key)) continue;
651
+ customToolParams.add(key);
652
+ }
653
+ }
654
+ if (Array.isArray(customTool.children) && customTool.children.length > 0) {
655
+ visit(customTool.children);
601
656
  }
602
657
  }
603
- }
658
+ };
659
+ visit(this.customTools);
604
660
  const defaultToolNames = Object.values(AgentDefaultTool);
605
- const overlappingTools = Array.from(dynamicToolNames).filter((name) => defaultToolNames.includes(name));
661
+ const overlappingTools = Array.from(this.customToolNames).filter((name) => defaultToolNames.includes(name));
606
662
  if (overlappingTools.length > 0) {
607
663
  throw new Error(`Custom tools and default tools have overlapping names: ${overlappingTools.join(", ")}`);
608
664
  }
609
- if (dynamicToolNames.size > 0) {
610
- setDynamicToolUseNames("customUser", Array.from(dynamicToolNames));
665
+ if (this.customToolNames.size > 0) {
666
+ setDynamicToolUseNames("customUser", Array.from(this.customToolNames));
611
667
  }
612
668
  if (customToolParams.size > 0) {
613
669
  this.allToolParamNames = Array.from(/* @__PURE__ */ new Set([...this.allToolParamNames, ...Array.from(customToolParams)]));
614
670
  }
615
671
  }
616
- this.customToolNames = new Set(this.customTools.map((t) => t.name));
617
672
  this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/skills");
618
673
  this.rulesDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/rules");
619
674
  }
@@ -637,10 +692,11 @@ var ClineAgent = class {
637
692
  shell: this.runtime.env.shell(),
638
693
  skills: await this.getSkills(),
639
694
  agentRules: await this.getAgentRules(),
640
- customTools: this.customTools,
695
+ customTools: this.activeCustomTools,
641
696
  allowDefaultTools: this.allowDefaultTools,
642
697
  customInstructions: this.customInstructions
643
698
  };
699
+ this.promptActiveToolsVersion = this.activeToolsVersion;
644
700
  this.sysPrompt = await this.promptManager.getSystemPrompt(context);
645
701
  this.noUseTollSysPrompt = this.promptManager.getNoUseToolInstructions(context);
646
702
  return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
@@ -749,9 +805,9 @@ ${content.trim()}\`\`\``);
749
805
  * 核心任务循环
750
806
  */
751
807
  async loop() {
752
- const { sysPrompt, noUseTollSysPrompt } = await this.getPrompt(true);
753
- const { customTools, customToolNames } = this;
808
+ const { customToolsByName, customToolNames } = this;
754
809
  while (this.state === "thinking" /* THINKING */) {
810
+ const { sysPrompt, noUseTollSysPrompt } = await this.getCurrentPrompt();
755
811
  this.loopCount++;
756
812
  if (this.loopCount > this.maxLoopCount) {
757
813
  await this.memory.appendMessage({
@@ -796,7 +852,33 @@ ${content.trim()}\`\`\``);
796
852
  }
797
853
  }
798
854
  if (customToolNames.has(tool.name)) {
799
- const customTool = customTools.find((t) => t.name === tool.name);
855
+ const customTool = customToolsByName.get(tool.name);
856
+ if (!customTool) {
857
+ toolResults.push({ tool, result: `Error: Custom tool "${tool.name}" not found.` });
858
+ continue;
859
+ }
860
+ if (isCustomToolGroup(customTool)) {
861
+ let groupResult;
862
+ if (customTool.onCall) {
863
+ try {
864
+ groupResult = await customTool.onCall(tool.params);
865
+ } catch (error) {
866
+ toolResults.push({ tool, result: `Error: ${error.message}` });
867
+ continue;
868
+ }
869
+ }
870
+ const childrenPrompt = this.activateCustomToolGroup(customTool);
871
+ const finalPrompt = `# New Available Tools
872
+
873
+ The following are instructions for using the new available tools.
874
+
875
+ ${childrenPrompt}`;
876
+ const promptBlock = groupResult !== void 0 ? `${typeof groupResult === "string" ? groupResult : JSON.stringify(groupResult)}
877
+
878
+ ${finalPrompt}` : finalPrompt;
879
+ toolResults.push({ tool, result: promptBlock });
880
+ continue;
881
+ }
800
882
  if (customTool.onCall) {
801
883
  try {
802
884
  const res = await customTool.onCall(tool.params);
@@ -1057,6 +1139,27 @@ ${this.promptManager.getUsedToolResultInstructions()}`;
1057
1139
  }
1058
1140
  }
1059
1141
  }
1142
+ /**
1143
+ * 激活自定义工具集:将入口的 children 注册到活跃工具列表并返回渲染后的 prompt。
1144
+ */
1145
+ activateCustomToolGroup(group) {
1146
+ if (this.activatedGroups.has(group.name)) {
1147
+ return renderCustomToolsPrompt(group.children || [], this.runtime.env.cwd());
1148
+ }
1149
+ this.activatedGroups.add(group.name);
1150
+ this.activeCustomTools = [...this.activeCustomTools, ...group.children || []];
1151
+ this.activeToolsVersion++;
1152
+ return renderCustomToolsPrompt(group.children || [], this.runtime.env.cwd());
1153
+ }
1154
+ /**
1155
+ * 检查自上次获取 prompt 后是否有工具集被激活,若有则刷新缓存。
1156
+ */
1157
+ async getCurrentPrompt() {
1158
+ if (this.promptActiveToolsVersion !== this.activeToolsVersion) {
1159
+ return this.getPrompt(true);
1160
+ }
1161
+ return this.getPrompt();
1162
+ }
1060
1163
  /**
1061
1164
  * 简单的 Diff 解析与替换辅助方法
1062
1165
  */
@@ -1418,10 +1521,11 @@ ${context.customInstructions}
1418
1521
  if (allowDefaultTools) {
1419
1522
  useDefaultTools = defaultTools.filter((tool) => allowDefaultTools.includes(tool.name));
1420
1523
  }
1524
+ const renderedCustomTools = renderCustomToolsPrompt(customTools, context.cwd);
1421
1525
  return `# Available Tools
1422
1526
  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.
1423
1527
 
1424
- ${[...useDefaultTools, ...customTools].map((tool) => {
1528
+ ${[...useDefaultTools].map((tool) => {
1425
1529
  return `### ${tool.name}
1426
1530
  Description: ${tool.description}
1427
1531
  Parameters:
@@ -1434,6 +1538,8 @@ ${Object.entries(tool.params).map(([name, description]) => `<${name}>${descripti
1434
1538
  </${tool.name}>
1435
1539
  `;
1436
1540
  }).join("\n")}
1541
+ ${renderedCustomTools ? `
1542
+ ${renderedCustomTools}` : ""}
1437
1543
 
1438
1544
  # Tool Use Examples
1439
1545
  ${useDefaultTools.filter((item) => Boolean(item.example)).map((item) => item.example).join("\n")}}
@@ -1789,6 +1895,6 @@ function createWebAgent(options) {
1789
1895
  return agent;
1790
1896
  }
1791
1897
 
1792
- export { AgentDefaultTool, AgentState, ClineAgent, DefaultWebRuntime, READ_ONLY_TOOLS, TOOL_RESULT_BLOCK, VERSION, WebApiHandler, WebMcpManager, WebMemoryManager, WebPromptManager, createWebAgent, defaultTools, getToolUseNames, parseAssistantMessageV2, setDynamicToolUseNames, toolParamNames, toolUseNames };
1898
+ export { AgentDefaultTool, AgentState, ClineAgent, DefaultWebRuntime, READ_ONLY_TOOLS, TOOL_RESULT_BLOCK, VERSION, WebApiHandler, WebMcpManager, WebMemoryManager, WebPromptManager, collectCustomToolNames, createWebAgent, defaultTools, getToolUseNames, isCustomToolGroup, parseAssistantMessageV2, renderCustomToolPrompt, renderCustomToolsPrompt, setDynamicToolUseNames, toolParamNames, toolUseNames };
1793
1899
  //# sourceMappingURL=webRuntime.mjs.map
1794
1900
  //# sourceMappingURL=webRuntime.mjs.map