@faapi/faapi 6.27.0 → 6.29.0

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/cli/index.js CHANGED
@@ -985,6 +985,25 @@ var init_sortRoutes = __esm({
985
985
  }
986
986
  });
987
987
 
988
+ // src/injection/subAgentToolName.ts
989
+ function subAgentToolName(agentName) {
990
+ const toolName = SUB_AGENT_TOOL_PREFIX + agentName;
991
+ if (!LLM_TOOL_NAME_PATTERN.test(toolName)) {
992
+ throw new Error(
993
+ `Sub-agent tool name "${toolName}" (from agent name "${agentName}") violates the LLM tool name pattern ${LLM_TOOL_NAME_PATTERN} \u2014 rename the agent (allowed: a-z A-Z 0-9 '-' '_'; file-based agent directory segments allow a-z A-Z 0-9 '-' only, '_' is the nesting separator)`
994
+ );
995
+ }
996
+ return toolName;
997
+ }
998
+ var LLM_TOOL_NAME_PATTERN, SUB_AGENT_TOOL_PREFIX;
999
+ var init_subAgentToolName = __esm({
1000
+ "src/injection/subAgentToolName.ts"() {
1001
+ "use strict";
1002
+ LLM_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
1003
+ SUB_AGENT_TOOL_PREFIX = "agent-";
1004
+ }
1005
+ });
1006
+
988
1007
  // src/tools/scanTools.ts
989
1008
  import fg2 from "fast-glob";
990
1009
  import path9 from "path";
@@ -1005,7 +1024,15 @@ function extractNamespaceFromRelPath(relPath) {
1005
1024
  const lastSlash = relPath.lastIndexOf("/");
1006
1025
  const dirPath = lastSlash === -1 ? "" : relPath.slice(0, lastSlash);
1007
1026
  if (!dirPath) return "";
1008
- return dirPath.split("/").join(".");
1027
+ const segments = dirPath.split("/");
1028
+ for (const segment of segments) {
1029
+ if (!TOOL_DIR_SEGMENT_PATTERN.test(segment)) {
1030
+ throw new Error(
1031
+ `Invalid tool directory segment "${segment}" in "tools/${relPath}": tool directory names allow a-z A-Z 0-9 '-' only ('_' is reserved as the nesting separator, '.' is not allowed \u2014 tool names are sent to LLMs as function.name) \u2014 rename the directory`
1032
+ );
1033
+ }
1034
+ }
1035
+ return segments.join("_");
1009
1036
  }
1010
1037
  function filePathToToolNamespace(filePath) {
1011
1038
  const normalized = filePath.replace(/\\/g, "/");
@@ -1016,7 +1043,13 @@ function filePathToToolNamespace(filePath) {
1016
1043
  return "";
1017
1044
  }
1018
1045
  function buildToolName(namespace, functionName) {
1019
- return namespace ? `${namespace}.${functionName}` : functionName;
1046
+ const name = namespace ? `${namespace}_${functionName}` : functionName;
1047
+ if (!LLM_TOOL_NAME_PATTERN.test(name)) {
1048
+ throw new Error(
1049
+ `Tool name "${name}" (function "${functionName}"${namespace ? ` in namespace "${namespace}"` : ""}) violates the LLM tool name pattern ${LLM_TOOL_NAME_PATTERN} \u2014 rename the function or use a @tool JSDoc override (allowed: a-z A-Z 0-9 '-' '_')`
1050
+ );
1051
+ }
1052
+ return name;
1020
1053
  }
1021
1054
  async function scanTools(rootDir, patterns) {
1022
1055
  const files = await fg2(patterns, {
@@ -1054,16 +1087,18 @@ async function scanTools(rootDir, patterns) {
1054
1087
  }
1055
1088
  return tools;
1056
1089
  }
1057
- var TOOL_PATTERNS, TOOL_EXPORT_RE, RESERVED_EXPORTS;
1090
+ var TOOL_PATTERNS, TOOL_EXPORT_RE, RESERVED_EXPORTS, TOOL_DIR_SEGMENT_PATTERN;
1058
1091
  var init_scanTools = __esm({
1059
1092
  "src/tools/scanTools.ts"() {
1060
1093
  "use strict";
1094
+ init_subAgentToolName();
1061
1095
  TOOL_PATTERNS = ["src/tools/**/*.ts"];
1062
1096
  TOOL_EXPORT_RE = new RegExp(
1063
1097
  String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
1064
1098
  "g"
1065
1099
  );
1066
1100
  RESERVED_EXPORTS = /* @__PURE__ */ new Set(["default", "config", "run"]);
1101
+ TOOL_DIR_SEGMENT_PATTERN = /^[a-zA-Z0-9-]+$/;
1067
1102
  }
1068
1103
  });
1069
1104
 
@@ -2898,6 +2933,14 @@ function extractToolMetadata(program, filePath, functionName, pathMeta) {
2898
2933
  const jsDoc = getJSDocFromNode(jsDocOwner);
2899
2934
  const description = extractDescription(jsDoc);
2900
2935
  const toolNameOverride = extractJSDocTagValue(jsDoc, "tool");
2936
+ if (toolNameOverride !== void 0 && !LLM_TOOL_NAME_PATTERN.test(toolNameOverride)) {
2937
+ throw SchemaExtractionError.at(
2938
+ jsDocOwner,
2939
+ "@tool",
2940
+ `\u8986\u76D6\u540D "${toolNameOverride}" \u542B\u975E\u6CD5\u5B57\u7B26\u2014\u2014\u987B\u6EE1\u8DB3 ${LLM_TOOL_NAME_PATTERN}\uFF08tool \u540D\u76F4\u63A5\u4F5C\u4E3A LLM function.name\uFF0C\u5F3A\u6821\u9A8C\u4E0A\u6E38\u5BF9\u975E\u6CD5\u5B57\u7B26\u6574\u5355 400\uFF09`,
2941
+ sourceFile
2942
+ );
2943
+ }
2901
2944
  const inputTypeName = getFirstParamTypeName(fn, sourceFile);
2902
2945
  return {
2903
2946
  name: toolNameOverride ?? pathMeta.name,
@@ -2939,6 +2982,8 @@ var init_extractToolMetadata = __esm({
2939
2982
  "src/ast/extractToolMetadata.ts"() {
2940
2983
  "use strict";
2941
2984
  init_jsDocMetadata();
2985
+ init_subAgentToolName();
2986
+ init_resolveTypeNode();
2942
2987
  }
2943
2988
  });
2944
2989
 
@@ -3090,7 +3135,15 @@ function extractAgentNameFromPath(filePath) {
3090
3135
  `Not an agent path: "${filePath}". Expected pattern: src/agents/<name>/handler.ts`
3091
3136
  );
3092
3137
  }
3093
- return match[1].replace(/\//g, ".");
3138
+ const segments = match[1].split("/");
3139
+ for (const segment of segments) {
3140
+ if (!AGENT_DIR_SEGMENT_PATTERN.test(segment)) {
3141
+ throw new Error(
3142
+ `Invalid agent directory segment "${segment}" in "${filePath}": agent directory names allow a-z A-Z 0-9 '-' only ('_' is reserved as the nesting separator, '.' is not allowed \u2014 agent names become LLM tool names "agent-<name>") \u2014 rename the directory`
3143
+ );
3144
+ }
3145
+ }
3146
+ return segments.join("_");
3094
3147
  }
3095
3148
  async function scanAgents(rootDir, patterns) {
3096
3149
  const files = await fg3(patterns, {
@@ -3121,11 +3174,12 @@ async function scanAgents(rootDir, patterns) {
3121
3174
  }
3122
3175
  return agents;
3123
3176
  }
3124
- var DEFAULT_AGENT_PATTERNS;
3177
+ var DEFAULT_AGENT_PATTERNS, AGENT_DIR_SEGMENT_PATTERN;
3125
3178
  var init_scanAgents = __esm({
3126
3179
  "src/agents/scanAgents.ts"() {
3127
3180
  "use strict";
3128
3181
  DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
3182
+ AGENT_DIR_SEGMENT_PATTERN = /^[a-zA-Z0-9-]+$/;
3129
3183
  }
3130
3184
  });
3131
3185
 
@@ -3164,6 +3218,14 @@ function extractAgentMetadata(program, filePath, pathMeta) {
3164
3218
  const jsDoc = getJSDocFromNode(configFound.jsDocOwner);
3165
3219
  const description = extractDescription(jsDoc);
3166
3220
  const agentNameOverride = extractJSDocTagValue(jsDoc, "agent");
3221
+ if (agentNameOverride !== void 0 && !LLM_TOOL_NAME_PATTERN.test(agentNameOverride)) {
3222
+ throw SchemaExtractionError.at(
3223
+ configFound.jsDocOwner,
3224
+ "@agent",
3225
+ `\u8986\u76D6\u540D "${agentNameOverride}" \u542B\u975E\u6CD5\u5B57\u7B26\u2014\u2014\u987B\u6EE1\u8DB3 ${LLM_TOOL_NAME_PATTERN}\uFF08\u8986\u76D6\u540D\u6210\u4E3A LLM \u5DE5\u5177\u540D "agent-<\u8986\u76D6\u540D>"\uFF0C\u5F3A\u6821\u9A8C\u4E0A\u6E38\u5BF9\u975E\u6CD5\u5B57\u7B26\u6574\u5355 400\uFF09`,
3226
+ sourceFile
3227
+ );
3228
+ }
3167
3229
  const { systemPrompt, systemPromptFile, tools, agents, model, maxTurns, inputDescription } = extractConfigFields(objectLiteral, sourceFile);
3168
3230
  return {
3169
3231
  name: agentNameOverride ?? pathMeta.name,
@@ -3385,6 +3447,7 @@ var init_extractAgentMetadata = __esm({
3385
3447
  "use strict";
3386
3448
  init_jsDocMetadata();
3387
3449
  init_resolveTypeNode();
3450
+ init_subAgentToolName();
3388
3451
  }
3389
3452
  });
3390
3453
 
@@ -7550,7 +7613,7 @@ function createAgentRegistry(tool) {
7550
7613
  if (!agent) return void 0;
7551
7614
  return {
7552
7615
  kind: "agent",
7553
- name: `agent.${agent.name}`,
7616
+ name: subAgentToolName(agent.name),
7554
7617
  agentName: agent.name,
7555
7618
  description: agent.description,
7556
7619
  metadata: agent
@@ -7688,6 +7751,7 @@ var init_registries = __esm({
7688
7751
  "src/injection/registries.ts"() {
7689
7752
  "use strict";
7690
7753
  init_taskRegistry();
7754
+ init_subAgentToolName();
7691
7755
  defaultRegistries = createAppRegistries();
7692
7756
  }
7693
7757
  });
@@ -10288,7 +10352,6 @@ async function createAppBase(options) {
10288
10352
  wsRoutes,
10289
10353
  rootDir,
10290
10354
  dist,
10291
- resourcesDir,
10292
10355
  tasks: taskQueue,
10293
10356
  async listen(listenPort) {
10294
10357
  const envPort = process.env.PORT ? Number(process.env.PORT) : void 0;