@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.
@@ -17,6 +17,7 @@ var AgentDefaultTool = /* @__PURE__ */ ((AgentDefaultTool2) => {
17
17
  AgentDefaultTool2["FILE_DELETE"] = "agent_delete_file";
18
18
  AgentDefaultTool2["DIR_DELETE"] = "agent_delete_directory";
19
19
  AgentDefaultTool2["SEARCH"] = "agent_search_files";
20
+ AgentDefaultTool2["SEARCH_CONTENT"] = "agent_search_file_content";
20
21
  AgentDefaultTool2["LIST_FILES"] = "agent_list_files";
21
22
  AgentDefaultTool2["LIST_CODE_DEF"] = "agent_list_code_definition_names";
22
23
  AgentDefaultTool2["BROWSER"] = "agent_browser_action";
@@ -190,11 +191,22 @@ return (
190
191
  },
191
192
  {
192
193
  name: "agent_search_files" /* SEARCH */,
193
- description: "Search for files in a directory that match a regex pattern or glob pattern.",
194
+ 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.",
194
195
  params: {
195
196
  path: "(required) The absolute or relative directory path to search.",
196
- regex: "(required) The regex pattern to match files against.",
197
- file_pattern: "(optional) glob pattern like *.ts."
197
+ regex: "(required) The regex pattern to match file or directory names against.",
198
+ file_pattern: "(optional) glob pattern like *.ts.",
199
+ include_node_modules: "(optional) set to true to include node_modules in the search. Defaults to false, so node_modules is skipped."
200
+ }
201
+ },
202
+ {
203
+ name: "agent_search_file_content" /* SEARCH_CONTENT */,
204
+ 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.",
205
+ params: {
206
+ path: "(required) The absolute or relative directory path to search.",
207
+ regex: "(required) The regex pattern to match file content against.",
208
+ file_pattern: "(optional) glob pattern like *.ts to limit which files are searched.",
209
+ include_node_modules: "(optional) set to true to include node_modules in the search. Defaults to false, so node_modules is skipped."
198
210
  }
199
211
  },
200
212
  {
@@ -263,6 +275,7 @@ var READ_ONLY_TOOLS = [
263
275
  "agent_list_files" /* LIST_FILES */,
264
276
  "agent_read_file" /* FILE_READ */,
265
277
  "agent_search_files" /* SEARCH */,
278
+ "agent_search_file_content" /* SEARCH_CONTENT */,
266
279
  "agent_list_code_definition_names" /* LIST_CODE_DEF */,
267
280
  "agent_browser_action" /* BROWSER */,
268
281
  "agent_ask_followup_question" /* ASK */,
@@ -432,6 +445,7 @@ var toolParamNames = [
432
445
  "diff",
433
446
  "regex",
434
447
  "file_pattern",
448
+ "include_node_modules",
435
449
  "recursive",
436
450
  "action",
437
451
  "url",
@@ -470,6 +484,104 @@ var toolParamNames = [
470
484
  "start_line",
471
485
  "end_line"
472
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
+ }
525
+ var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
526
+ "txt",
527
+ "md",
528
+ "markdown",
529
+ "json",
530
+ "js",
531
+ "mjs",
532
+ "cjs",
533
+ "ts",
534
+ "tsx",
535
+ "jsx",
536
+ "html",
537
+ "htm",
538
+ "css",
539
+ "scss",
540
+ "sass",
541
+ "less",
542
+ "py",
543
+ "java",
544
+ "c",
545
+ "cpp",
546
+ "cc",
547
+ "cxx",
548
+ "h",
549
+ "hpp",
550
+ "cs",
551
+ "go",
552
+ "rs",
553
+ "rb",
554
+ "php",
555
+ "sh",
556
+ "bash",
557
+ "zsh",
558
+ "bat",
559
+ "cmd",
560
+ "ps1",
561
+ "yaml",
562
+ "yml",
563
+ "toml",
564
+ "ini",
565
+ "cfg",
566
+ "conf",
567
+ "xml",
568
+ "svg",
569
+ "csv",
570
+ "log",
571
+ "sql",
572
+ "vue",
573
+ "svelte",
574
+ "astro",
575
+ "graphql",
576
+ "gql",
577
+ "prisma",
578
+ "env",
579
+ "gitignore",
580
+ "dockerfile",
581
+ "makefile",
582
+ "properties",
583
+ "lock"
584
+ ]);
473
585
  var AgentState = /* @__PURE__ */ ((AgentState2) => {
474
586
  AgentState2["IDLE"] = "idle";
475
587
  AgentState2["THINKING"] = "thinking";
@@ -493,9 +605,19 @@ var ClineAgent = class {
493
605
  skillDir;
494
606
  rulesDir;
495
607
  customTools;
608
+ /** 当前可用(已展开集合)的顶层工具列表,传给 PromptManager 渲染 */
609
+ activeCustomTools;
610
+ /** 所有已知工具名(含未激活 children),便于查找定义 */
611
+ customToolsByName;
496
612
  customToolNames;
497
613
  allowDefaultTools;
498
614
  customInstructions;
615
+ /** 已激活的工具集入口名 */
616
+ activatedGroups = /* @__PURE__ */ new Set();
617
+ /** activeCustomTools 变更版本号,用于 Prompt 缓存失效 */
618
+ activeToolsVersion = 0;
619
+ /** 缓存 sysPrompt 时记录的版本号 */
620
+ promptActiveToolsVersion = -1;
499
621
  sysPrompt;
500
622
  noUseTollSysPrompt;
501
623
  // 简单的事件回调系统,供宿主环境注册以监听 Agent 内部事件
@@ -515,31 +637,38 @@ var ClineAgent = class {
515
637
  this.allowDefaultTools.push("agent_attempt_completion" /* ATTEMPT */);
516
638
  }
517
639
  this.customInstructions = options.customInstructions;
640
+ this.customToolsByName = /* @__PURE__ */ new Map();
641
+ this.activeCustomTools = [...this.customTools];
642
+ this.customToolNames = new Set(collectCustomToolNames(this.customTools));
518
643
  if (this.customTools.length > 0) {
519
- const dynamicToolNames = /* @__PURE__ */ new Set();
520
644
  const customToolParams = /* @__PURE__ */ new Set();
521
- for (const customTool of this.customTools) {
522
- dynamicToolNames.add(customTool.name);
523
- if (customTool.params) {
524
- for (const key in customTool.params) {
525
- if (!Object.hasOwn(customTool.params, key)) continue;
526
- 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);
527
656
  }
528
657
  }
529
- }
658
+ };
659
+ visit(this.customTools);
530
660
  const defaultToolNames = Object.values(AgentDefaultTool);
531
- const overlappingTools = Array.from(dynamicToolNames).filter((name) => defaultToolNames.includes(name));
661
+ const overlappingTools = Array.from(this.customToolNames).filter((name) => defaultToolNames.includes(name));
532
662
  if (overlappingTools.length > 0) {
533
663
  throw new Error(`Custom tools and default tools have overlapping names: ${overlappingTools.join(", ")}`);
534
664
  }
535
- if (dynamicToolNames.size > 0) {
536
- setDynamicToolUseNames("customUser", Array.from(dynamicToolNames));
665
+ if (this.customToolNames.size > 0) {
666
+ setDynamicToolUseNames("customUser", Array.from(this.customToolNames));
537
667
  }
538
668
  if (customToolParams.size > 0) {
539
669
  this.allToolParamNames = Array.from(/* @__PURE__ */ new Set([...this.allToolParamNames, ...Array.from(customToolParams)]));
540
670
  }
541
671
  }
542
- this.customToolNames = new Set(this.customTools.map((t) => t.name));
543
672
  this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/skills");
544
673
  this.rulesDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/rules");
545
674
  }
@@ -563,10 +692,11 @@ var ClineAgent = class {
563
692
  shell: this.runtime.env.shell(),
564
693
  skills: await this.getSkills(),
565
694
  agentRules: await this.getAgentRules(),
566
- customTools: this.customTools,
695
+ customTools: this.activeCustomTools,
567
696
  allowDefaultTools: this.allowDefaultTools,
568
697
  customInstructions: this.customInstructions
569
698
  };
699
+ this.promptActiveToolsVersion = this.activeToolsVersion;
570
700
  this.sysPrompt = await this.promptManager.getSystemPrompt(context);
571
701
  this.noUseTollSysPrompt = this.promptManager.getNoUseToolInstructions(context);
572
702
  return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
@@ -675,9 +805,9 @@ ${content.trim()}\`\`\``);
675
805
  * 核心任务循环
676
806
  */
677
807
  async loop() {
678
- const { sysPrompt, noUseTollSysPrompt } = await this.getPrompt(true);
679
- const { customTools, customToolNames } = this;
808
+ const { customToolsByName, customToolNames } = this;
680
809
  while (this.state === "thinking" /* THINKING */) {
810
+ const { sysPrompt, noUseTollSysPrompt } = await this.getCurrentPrompt();
681
811
  this.loopCount++;
682
812
  if (this.loopCount > this.maxLoopCount) {
683
813
  await this.memory.appendMessage({
@@ -722,7 +852,33 @@ ${content.trim()}\`\`\``);
722
852
  }
723
853
  }
724
854
  if (customToolNames.has(tool.name)) {
725
- 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
+ }
726
882
  if (customTool.onCall) {
727
883
  try {
728
884
  const res = await customTool.onCall(tool.params);
@@ -825,15 +981,36 @@ STDERR: ${result.stderr}` });
825
981
  const path2 = tool.params.path || this.runtime.env.cwd();
826
982
  const regexStr = tool.params.regex;
827
983
  const filePattern = tool.params.file_pattern;
984
+ const includeNodeModules = tool.params.include_node_modules === "true";
828
985
  if (regexStr && path2) {
829
986
  try {
830
987
  let result;
831
988
  if (typeof this.runtime.fs.searchFiles === "function") {
832
989
  result = await this.runtime.fs.searchFiles(path2, regexStr, filePattern);
833
990
  } else {
834
- result = await this.searchFiles(path2, regexStr, filePattern);
991
+ result = await this.searchFiles(path2, regexStr, filePattern, includeNodeModules);
992
+ }
993
+ toolResults.push({ tool, result });
994
+ } catch (e) {
995
+ toolResults.push({ tool, result: `Error: ${e.message}` });
996
+ }
997
+ } else {
998
+ toolResults.push({ tool, result: `Error: miss path or regex params` });
999
+ }
1000
+ } else if (tool.name === "agent_search_file_content" /* SEARCH_CONTENT */) {
1001
+ const path2 = tool.params.path || this.runtime.env.cwd();
1002
+ const regexStr = tool.params.regex;
1003
+ const filePattern = tool.params.file_pattern;
1004
+ const includeNodeModules = tool.params.include_node_modules === "true";
1005
+ if (regexStr && path2) {
1006
+ try {
1007
+ let result;
1008
+ if (typeof this.runtime.fs.searchFileContent === "function") {
1009
+ result = await this.runtime.fs.searchFileContent(path2, regexStr, filePattern);
1010
+ } else {
1011
+ result = await this.searchFileContent(path2, regexStr, filePattern, includeNodeModules);
835
1012
  }
836
- toolResults.push({ tool, result: `${result}` });
1013
+ toolResults.push({ tool, result });
837
1014
  } catch (e) {
838
1015
  toolResults.push({ tool, result: `Error: ${e.message}` });
839
1016
  }
@@ -962,6 +1139,27 @@ ${this.promptManager.getUsedToolResultInstructions()}`;
962
1139
  }
963
1140
  }
964
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
+ }
965
1163
  /**
966
1164
  * 简单的 Diff 解析与替换辅助方法
967
1165
  */
@@ -1008,13 +1206,80 @@ ${searchBlock.substring(0, 100)}...`);
1008
1206
  async getHistory() {
1009
1207
  return this.memory.getHistory();
1010
1208
  }
1011
- async searchFiles(dirpath, regex, filePattern) {
1209
+ /**
1210
+ * 判断文件是否为可进行内容搜索的文本类文件
1211
+ */
1212
+ isTextFile(name) {
1213
+ const ext = name.includes(".") ? String(name.split(".").pop()).toLowerCase() : "";
1214
+ if (!ext) {
1215
+ return true;
1216
+ }
1217
+ return TEXT_FILE_EXTENSIONS.has(ext);
1218
+ }
1219
+ /**
1220
+ * 按文件名/目录名搜索,层级优先(BFS):
1221
+ * 每一层先匹配完当前层级的所有条目,再进入更深的子目录。
1222
+ */
1223
+ async searchFiles(dirpath, regex, filePattern, includeNodeModules = false) {
1012
1224
  const matches = [];
1013
- const contentRe = new RegExp(regex);
1014
- const nameRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
1225
+ const MAX_RESULTS = 100;
1226
+ const MAX_DEPTH = 8;
1227
+ const SKIP_DIRS = /* @__PURE__ */ new Set([".git", "dist", ".agent", ".turbopack"]);
1228
+ const shouldSkipDir = (name) => SKIP_DIRS.has(name) || name === "node_modules" && !includeNodeModules;
1229
+ const nameRe = new RegExp(regex);
1230
+ const globRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
1231
+ const queue = [{ dir: dirpath, depth: 0 }];
1232
+ while (queue.length > 0 && matches.length < MAX_RESULTS) {
1233
+ const { dir, depth } = queue.shift();
1234
+ if (depth > MAX_DEPTH) {
1235
+ continue;
1236
+ }
1237
+ let entries;
1238
+ try {
1239
+ entries = await this.runtime.fs.readDir(dir, { recursive: false });
1240
+ } catch {
1241
+ continue;
1242
+ }
1243
+ for (const entry of entries) {
1244
+ if (matches.length >= MAX_RESULTS) {
1245
+ break;
1246
+ }
1247
+ const child = dir === "." ? entry.name : `${dir}/${entry.name}`;
1248
+ if (entry.isDirectory()) {
1249
+ if (!shouldSkipDir(entry.name)) {
1250
+ if (nameRe.test(entry.name)) {
1251
+ matches.push(`${child}/`);
1252
+ }
1253
+ queue.push({ dir: child, depth: depth + 1 });
1254
+ }
1255
+ } else if (entry.isFile()) {
1256
+ if (globRe && !globRe.test(entry.name)) {
1257
+ continue;
1258
+ }
1259
+ if (nameRe.test(entry.name)) {
1260
+ matches.push(child);
1261
+ }
1262
+ }
1263
+ }
1264
+ }
1265
+ if (matches.length === 0) {
1266
+ return "No files found.";
1267
+ }
1268
+ return matches.join("\n");
1269
+ }
1270
+ /**
1271
+ * 按文件内容搜索:正则匹配文件内容,返回匹配文件路径。
1272
+ */
1273
+ async searchFileContent(dirpath, regex, filePattern, includeNodeModules = false) {
1274
+ const matches = [];
1275
+ const MAX_RESULTS = 100;
1276
+ const MAX_DEPTH = 8;
1015
1277
  const SKIP_DIRS = /* @__PURE__ */ new Set([".git", "dist", ".agent", ".turbopack"]);
1278
+ const shouldSkipDir = (name) => SKIP_DIRS.has(name) || name === "node_modules" && !includeNodeModules;
1279
+ const contentRe = new RegExp(regex);
1280
+ const globRe = filePattern ? new RegExp(filePattern.replace(/\./g, "\\.").replace(/\*/g, ".*")) : null;
1016
1281
  const walk = async (dir, depth) => {
1017
- if (depth > 8 || matches.length >= 100) {
1282
+ if (depth > MAX_DEPTH || matches.length >= MAX_RESULTS) {
1018
1283
  return;
1019
1284
  }
1020
1285
  let entries;
@@ -1024,21 +1289,24 @@ ${searchBlock.substring(0, 100)}...`);
1024
1289
  return;
1025
1290
  }
1026
1291
  for (const entry of entries) {
1027
- if (matches.length >= 100) {
1292
+ if (matches.length >= MAX_RESULTS) {
1028
1293
  break;
1029
1294
  }
1030
1295
  const child = dir === "." ? entry.name : `${dir}/${entry.name}`;
1031
1296
  if (entry.isDirectory()) {
1032
- if (!SKIP_DIRS.has(entry.name)) {
1297
+ if (!shouldSkipDir(entry.name)) {
1033
1298
  await walk(child, depth + 1);
1034
1299
  }
1035
1300
  } else if (entry.isFile()) {
1036
- if (nameRe && !nameRe.test(entry.name)) {
1301
+ if (!this.isTextFile(entry.name)) {
1302
+ continue;
1303
+ }
1304
+ if (globRe && !globRe.test(entry.name)) {
1037
1305
  continue;
1038
1306
  }
1039
1307
  try {
1040
- const content = (await this.runtime.fs.readFile(child, "utf8")).toString();
1041
- if (contentRe.test(content)) {
1308
+ const content = await this.runtime.fs.readFile(child);
1309
+ if (typeof content === "string" && contentRe.test(content)) {
1042
1310
  matches.push(child);
1043
1311
  }
1044
1312
  } catch {
@@ -1047,6 +1315,9 @@ ${searchBlock.substring(0, 100)}...`);
1047
1315
  }
1048
1316
  };
1049
1317
  await walk(dirpath, 0);
1318
+ if (matches.length === 0) {
1319
+ return "No files found with matching content.";
1320
+ }
1050
1321
  return matches.join("\n");
1051
1322
  }
1052
1323
  };
@@ -1250,10 +1521,11 @@ ${context.customInstructions}
1250
1521
  if (allowDefaultTools) {
1251
1522
  useDefaultTools = defaultTools.filter((tool) => allowDefaultTools.includes(tool.name));
1252
1523
  }
1524
+ const renderedCustomTools = renderCustomToolsPrompt(customTools, context.cwd);
1253
1525
  return `# Available Tools
1254
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.
1255
1527
 
1256
- ${[...useDefaultTools, ...customTools].map((tool) => {
1528
+ ${[...useDefaultTools].map((tool) => {
1257
1529
  return `### ${tool.name}
1258
1530
  Description: ${tool.description}
1259
1531
  Parameters:
@@ -1266,6 +1538,8 @@ ${Object.entries(tool.params).map(([name, description]) => `<${name}>${descripti
1266
1538
  </${tool.name}>
1267
1539
  `;
1268
1540
  }).join("\n")}
1541
+ ${renderedCustomTools ? `
1542
+ ${renderedCustomTools}` : ""}
1269
1543
 
1270
1544
  # Tool Use Examples
1271
1545
  ${useDefaultTools.filter((item) => Boolean(item.example)).map((item) => item.example).join("\n")}}
@@ -1621,6 +1895,6 @@ function createWebAgent(options) {
1621
1895
  return agent;
1622
1896
  }
1623
1897
 
1624
- 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 };
1625
1899
  //# sourceMappingURL=webRuntime.mjs.map
1626
1900
  //# sourceMappingURL=webRuntime.mjs.map