@faapi/faapi 2.0.1 → 3.1.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/index.d.ts CHANGED
@@ -177,6 +177,152 @@ interface ResponseConfig {
177
177
  message: string;
178
178
  }) => unknown;
179
179
  }
180
+ /**
181
+ * model 级配置(Phase 3.5)
182
+ *
183
+ * 挂在 provider 下的单个 model 配置,model 特定字段透传给 LLM API
184
+ * (覆盖 provider 级同名字段)。空对象 `{}` 表示用 provider 级默认。
185
+ *
186
+ * ```ts
187
+ * models: {
188
+ * 'gpt-4o': {}, // 用 provider 级默认
189
+ * 'gpt-4o-mini': { temperature: 0.5 }, // 覆盖 temperature
190
+ * }
191
+ * ```
192
+ */
193
+ interface LlmModelConfig {
194
+ [key: string]: unknown;
195
+ }
196
+ /**
197
+ * LLM provider 配置(Phase 2.4,Phase 3.5 改为嵌套级联结构)
198
+ *
199
+ * 嵌套级联:provider 在外层,model 在 `models` 下挂多个。
200
+ * provider 级字段(`apiKey` / `baseURL`)共享给所有 model;
201
+ * model 级字段在 `models[modelName]` 里覆盖 provider 级同名字段。
202
+ *
203
+ * `config.agent.llms` 的 key 是 provider 名(如 `'openai'` / `'anthropic'`),
204
+ * `config.agent.defaultLlm` 指定默认 provider key(不传时用 `llms` 第一个 key)。
205
+ *
206
+ * 由 Phase 3.2 的 `@faapi/agent` 插件读取,调 `createProvider` 创建实例存 Map。
207
+ *
208
+ * ```ts
209
+ * llms: {
210
+ * openai: {
211
+ * provider: 'openai',
212
+ * apiKey: process.env.OPENAI_API_KEY,
213
+ * baseURL: 'https://api.openai.com/v1',
214
+ * models: { 'gpt-4o': {}, 'gpt-4o-mini': { temperature: 0.5 } },
215
+ * },
216
+ * anthropic: {
217
+ * provider: 'anthropic',
218
+ * apiKey: process.env.ANTHROPIC_API_KEY,
219
+ * models: { 'claude-3-5-sonnet': {} },
220
+ * },
221
+ * }
222
+ * ```
223
+ */
224
+ interface LlmConfig {
225
+ /**
226
+ * LLM 提供方标识(如 'openai' / 'anthropic')
227
+ *
228
+ * Phase 3.2 的 provider 模块按此值选择对应的 LLM 适配器。
229
+ */
230
+ provider: string;
231
+ /**
232
+ * API key(从 `process.env` 读取,避免硬编码)
233
+ *
234
+ * 如 `process.env.OPENAI_API_KEY`。
235
+ */
236
+ apiKey?: string;
237
+ /**
238
+ * API 基础 URL(可选,用于 OpenAI 兼容 API 如 Azure OpenAI / 中转服务)
239
+ *
240
+ * 未设置时用 provider 对应的官方默认值(如 'https://api.openai.com/v1')。
241
+ */
242
+ baseURL?: string;
243
+ /**
244
+ * 该 provider 下挂的 model 列表(key 是 model 名)
245
+ *
246
+ * handler 通过 `agent.run(input, { model: 'gpt-4o' })` 切换 model,
247
+ * 框架按 model 名在所有 provider 的 `models` 里查找定位 provider(详见
248
+ * [agentHandle](../../agent/src/agentHandle.md) 的 Run-level 覆盖优先级表)。
249
+ * model 级字段(如 `temperature`)覆盖 provider 级同名字段。
250
+ */
251
+ models: Record<string, LlmModelConfig>;
252
+ /**
253
+ * 其他透传参数(provider 级,如 temperature / top_p / max_tokens)
254
+ *
255
+ * 这些字段原样传给 LLM API,由 provider 适配器处理。
256
+ * model 级 `models[modelName]` 的同名字段优先。
257
+ */
258
+ [key: string]: unknown;
259
+ }
260
+ /**
261
+ * agent 子系统全局配置(Phase 2.4,Phase 3.5 LLM 配置改为嵌套级联)
262
+ *
263
+ * 提供 agent 子系统的全局默认值,所有字段均可选,未设置时用框架默认值。
264
+ * agent 自身 `config.maxTurns` / `config.model` 优先于全局配置。
265
+ *
266
+ * ```ts
267
+ * import type { FaapiConfig } from '@faapi/faapi';
268
+ * export default {
269
+ * agent: {
270
+ * llms: {
271
+ * openai: {
272
+ * provider: 'openai',
273
+ * apiKey: process.env.OPENAI_API_KEY,
274
+ * models: { 'gpt-4o': {}, 'gpt-4o-mini': { temperature: 0.5 } },
275
+ * },
276
+ * },
277
+ * defaultLlm: 'openai',
278
+ * defaultAgent: 'researcher',
279
+ * maxTurns: 10,
280
+ * maxAgentDepth: 3,
281
+ * },
282
+ * } satisfies FaapiConfig;
283
+ * ```
284
+ *
285
+ * 详见 `src/config/configTypes.md` agent 配置块章节。
286
+ */
287
+ interface AgentConfig {
288
+ /**
289
+ * LLM provider 配置映射(Phase 3.5 改为嵌套级联结构,key 是 provider 名)
290
+ *
291
+ * 值是 [LlmConfig](含 `models`)。plugin setup 时遍历每个 LlmConfig 调
292
+ * `createProvider` 创建实例存 Map,handler 通过 `agent.run(input, { model })`
293
+ * 切换 provider + model(详见 [agentHandle](../../agent/src/agentHandle.md))。
294
+ *
295
+ * 未设置时 Phase 3.x 插件无法调用 LLM,agent 的 `run` 函数仍可手动实现。
296
+ */
297
+ llms?: Record<string, LlmConfig>;
298
+ /**
299
+ * 默认 provider key(Phase 3.5)
300
+ *
301
+ * `agent.run` 不传 `options.model` 时用此 key 对应的 provider 实例。
302
+ * 未设置时用 `llms` 的第一个 key(`Object.keys(llms)[0]`)。
303
+ */
304
+ defaultLlm?: string;
305
+ /**
306
+ * 默认 agent 名,用于 `agent` 参数注入([injectParams](../injection/injectParams.md) Phase 2.3)
307
+ *
308
+ * Phase 2.3 的 `agent` 参数注入暂返回 `undefined`,Phase 3.x 的 @faapi/agent 插件
309
+ * 读取此值从 [agentRegistry](../injection/agentRegistry.md) 查找对应 agent 元数据,
310
+ * 注入 `AgentHandle`(含可调用 `run`)。
311
+ */
312
+ defaultAgent?: string;
313
+ /**
314
+ * 默认最大对话轮数(覆盖 agent 自身 `config.maxTurns`,agent 自身配置优先)
315
+ *
316
+ * Phase 3.3 的 reactLoop 使用此值作为递归深度防护。
317
+ */
318
+ maxTurns?: number;
319
+ /**
320
+ * agent 调用 agent 的最大递归深度(防护无限递归,Phase 3.3 reactLoop 使用)
321
+ *
322
+ * 默认值由 Phase 3.x 的 @faapi/agent 插件定义(如 3)。
323
+ */
324
+ maxAgentDepth?: number;
325
+ }
180
326
  /**
181
327
  * faapi 配置文件类型
182
328
  *
@@ -305,6 +451,37 @@ interface FaapiConfig {
305
451
  * ```
306
452
  */
307
453
  plugins?: PluginDeclaration[];
454
+ /**
455
+ * agent 子系统全局配置(Phase 2.4)
456
+ *
457
+ * 提供 agent 子系统的全局默认值:LLM 提供方、默认 agent、
458
+ * 最大对话轮数、agent 调用 agent 的最大递归深度。
459
+ *
460
+ * agent 自身 `config.maxTurns` / `config.model` 优先于全局配置。
461
+ * tool 引用列表只在每个 agent 自身的 `config.tools` 里声明(无全局共享 defaultTools)。
462
+ *
463
+ * ```ts
464
+ * import type { FaapiConfig } from '@faapi/faapi';
465
+ * export default {
466
+ * agent: {
467
+ * llms: {
468
+ * openai: {
469
+ * provider: 'openai',
470
+ * apiKey: process.env.OPENAI_API_KEY,
471
+ * models: { 'gpt-4o': {} },
472
+ * },
473
+ * },
474
+ * defaultLlm: 'openai',
475
+ * defaultAgent: 'researcher',
476
+ * maxTurns: 10,
477
+ * maxAgentDepth: 3,
478
+ * },
479
+ * } satisfies FaapiConfig;
480
+ * ```
481
+ *
482
+ * 详见 `src/config/configTypes.md` agent 配置块章节。
483
+ */
484
+ agent?: AgentConfig;
308
485
  /**
309
486
  * 扩展 ctx:在每次请求创建上下文后调用,可挂载自定义方法(如 ctx.xml、ctx.stream)
310
487
  *
@@ -654,6 +831,439 @@ declare function collectRouteSchemaSources(routes: RouteManifest, rootDir?: stri
654
831
  mergedAllTypes: Map<string, HandlerTypeInfo>;
655
832
  };
656
833
 
834
+ /**
835
+ * Agent 的 LLM 可见核心字段
836
+ *
837
+ * 描述"agent 是什么"——LLM 真正需要消费的字段,**不含**代码本体加载细节
838
+ * (filePath / hasRun)。文件型 agent 与 DB-driven skill 都实现此接口。
839
+ *
840
+ * - 文件型 agent:由 [AgentMetadata](./extractAgentMetadata.md) 继承扩展,
841
+ * 额外含 `filePath` / `hasRun`(代码本体加载用)
842
+ * - DB-driven skill:业务方 plugin 从 DB 字段映射到本接口即可,无需填占位值
843
+ * (skill 无源文件,不走 `loadAgentModule`,自然不读 filePath / hasRun)
844
+ *
845
+ * `@faapi/agent` 子包的 `Agent` 类、`agentRegistry` 查询入口、`asTool` 包装
846
+ * 都消费 `AgentCore`,实现"agent 与 skill 走同一运行时链路"。
847
+ */
848
+ interface AgentCore {
849
+ /** agent 名(`@agent` JSDoc 覆盖值 或 目录推导值) */
850
+ name: string;
851
+ /** JSDoc 描述(agent 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
852
+ description?: string;
853
+ /** 系统提示词(config 块字面量提取),无/非字面量时为 `undefined` */
854
+ systemPrompt?: string;
855
+ /** agent 显式声明可用的 tool 引用列表(config 块字面量提取),无/含非字面量元素时为 `undefined` */
856
+ tools?: string[];
857
+ /** 可调用的其他 agent 名列表(config 块字面量提取),无/含非字面量元素时为 `undefined` */
858
+ agents?: string[];
859
+ /** LLM 模型名(config 块字面量提取),无/非字面量时为 `undefined` */
860
+ model?: string;
861
+ /** 最大对话轮数(config 块字面量提取),无/非字面量时为 `undefined` */
862
+ maxTurns?: number;
863
+ }
864
+ /**
865
+ * Agent 完整元数据(文件型 agent)
866
+ *
867
+ * 继承 [AgentCore](./extractAgentMetadata.md) 的 LLM 字段,额外扩展**代码本体加载细节**:
868
+ * - `filePath` — `loadAgentModule` 加载 `handler.js` 产物提取 `run` 函数用
869
+ * - `hasRun` — 是否导出 `run` 函数(`Agent.executeSubAgent` 据此决定走自定义 run
870
+ * 还是默认 reactLoop)
871
+ *
872
+ * DB-driven skill 不实现此接口(无源文件,无需加载),只实现 `AgentCore`。
873
+ *
874
+ * 由 [extractAgentMetadata](./extractAgentMetadata.md) 产出,合并路径推导字段
875
+ * (来自 [scanAgents](../agents/scanAgents.md) 的 `AgentManifest`)与 AST 提取字段
876
+ * (JSDoc 描述、`@agent` 覆盖名、config 块字段)。
877
+ *
878
+ * 字段来源:
879
+ * - `name` — `@agent` JSDoc 覆盖值,或 `pathMeta.name`(目录推导)
880
+ * - `filePath` / `hasRun` — 由 `pathMeta` 透传
881
+ * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
882
+ * - `systemPrompt` / `tools` / `agents` / `model` / `maxTurns` — config 块字面量提取
883
+ */
884
+ interface AgentMetadata extends AgentCore {
885
+ /** 源码相对路径(从 `pathMeta` 透传),`loadAgentModule` 据此加载 `handler.js` 提取 `run` */
886
+ filePath: string;
887
+ /** 是否导出 `run` 函数(从 `pathMeta` 透传),`Agent.executeSubAgent` 据此选择自定义 run / 默认 reactLoop */
888
+ hasRun: boolean;
889
+ }
890
+ /**
891
+ * 路径推导的 agent 元数据(由 [scanAgents](../agents/scanAgents.ts) 计算)
892
+ *
893
+ * 透传到 [AgentMetadata](./extractAgentMetadata.ts) 输出,与 AST 提取字段合并。
894
+ * 与 [ToolPathMeta](./extractToolMetadata.md) 对称。
895
+ */
896
+ interface AgentPathMeta {
897
+ /** 目录推导的 agent 名(如 `researcher`) */
898
+ name: string;
899
+ /** 源码相对路径(如 `src/agents/researcher/handler.ts`) */
900
+ filePath: string;
901
+ /** 是否导出 `run` 函数(scanAgents 正则检测) */
902
+ hasRun: boolean;
903
+ }
904
+
905
+ /**
906
+ * Tool 的 LLM 可见核心字段
907
+ *
908
+ * 描述"tool 是什么"——LLM 真正需要消费的字段(发往 LLM 的 tool 定义只含
909
+ * `name` / `description` / input schema),**不含**代码本体加载细节
910
+ * (`filePath` / `functionName` / `inputTypeName`)。
911
+ *
912
+ * 与 [AgentCore](./extractAgentMetadata.md) 对称——LLM-facing 字段与代码加载
913
+ * 细节分离,便于未来扩展(如 DB-driven tool 只实现 `ToolCore` 即可)。
914
+ *
915
+ * `toolRegistry` 查询入口 / `@faapi/agent` 子包的 `buildToolDefinitions`
916
+ * 都消费 `ToolCore` 字段组装 LLM tool 列表。
917
+ */
918
+ interface ToolCore {
919
+ /** tool 名(`@tool` JSDoc 覆盖值 或 路径推导值) */
920
+ name: string;
921
+ /** JSDoc 描述(tool 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
922
+ description?: string;
923
+ }
924
+ /**
925
+ * Tool 完整元数据(文件型 tool)
926
+ *
927
+ * 继承 [ToolCore](./extractToolMetadata.md) 的 LLM 字段,额外扩展**代码本体加载细节**:
928
+ * - `filePath` — `loadToolModule` 加载 `handler.js` 产物定位函数用
929
+ * - `functionName` — 源码导出函数名(不受 `@tool` 覆盖影响,AST 定位 + 运行时 resolveExport 用)
930
+ * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md)
931
+ * 生成 zod schema;运行时 `resolveToolSchema` 据此定位 `zod.js`)
932
+ *
933
+ * 由 [extractToolMetadata](./extractToolMetadata.md) 产出,合并路径推导字段
934
+ * (来自 [scanTools](../tools/scanTools.md) 的 `ToolManifest`)与 AST 提取字段
935
+ * (JSDoc 描述、`@tool` 覆盖名、第一个参数 interface 名)。
936
+ *
937
+ * 字段来源:
938
+ * - `name` — `@tool` JSDoc 覆盖值,或 `pathMeta.name`(路径推导)
939
+ * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
940
+ * - `filePath` / `functionName` — 由 `pathMeta` 透传
941
+ * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md) 生成 zod schema)
942
+ */
943
+ interface ToolMetadata extends ToolCore {
944
+ /** 第一个参数的 interface/type 名(用于生成 zod schema),
945
+ * 无参数/参数无类型标注/参数为内联类型字面量时为 `undefined` */
946
+ inputTypeName?: string;
947
+ /** 源码相对路径(从 `pathMeta` 透传) */
948
+ filePath: string;
949
+ /** 源码中的导出函数名(从 `pathMeta` 透传,AST 定位用,不受 `@tool` 覆盖影响) */
950
+ functionName: string;
951
+ }
952
+ /**
953
+ * 路径推导的 tool 元数据(由 [scanTools](../tools/scanTools.ts) 计算)
954
+ *
955
+ * 透传到 [ToolMetadata](./extractToolMetadata.ts) 输出,与 AST 提取字段合并。
956
+ */
957
+ interface ToolPathMeta {
958
+ /** 路径推导的 tool 名(如 `weather.getWeather`) */
959
+ name: string;
960
+ /** 源码相对路径(如 `src/tools/weather/handler.ts`) */
961
+ filePath: string;
962
+ }
963
+
964
+ /**
965
+ * 按名查找单个 agent 的 LLM 可见元数据
966
+ *
967
+ * 返回 [AgentCore](../ast/extractAgentMetadata.md) 字段(name / description /
968
+ * systemPrompt / tools / agents / model / maxTurns),**不含** `filePath` / `hasRun`。
969
+ *
970
+ * skill fallback:先查 [skillRegistry](./skillRegistry.ts) 的 `getSkill`,
971
+ * 命中返回 skill 元数据(运行时业务方动态注册的 DB-driven skill);
972
+ * 未命中查文件 registry。
973
+ *
974
+ * 用于 LLM-facing 场景(`agents` 参数注入、`asTool` 描述、
975
+ * `resolveAgentTools` / `resolveSubAgents` 解析)。
976
+ * 加载 handler.js 执行 `run` 函数请用 [getAgentEntry](#getAgentEntry)。
977
+ *
978
+ * @param name agent 名(如 `researcher`,含 `@agent` 覆盖值)
979
+ * @returns `AgentCore` 或 `undefined`(未注册)
980
+ */
981
+ declare function getAgent(name: string): AgentCore | undefined;
982
+ /**
983
+ * 按名查找单个 agent 的完整元数据(含代码加载细节)
984
+ *
985
+ * 返回 [AgentMetadata](../ast/extractAgentMetadata.md) —— 继承 AgentCore
986
+ * 额外含 `filePath` / `hasRun`,供 `@faapi/agent` 子包 `loadAgentModule`
987
+ * 加载 handler.js 执行自定义 `run` 函数。
988
+ *
989
+ * **不 fallback 到 skillRegistry**——DB skill 无源文件,不走 `loadAgentModule`。
990
+ * 调用方需先判断 `entry?.hasRun` 再决定是否加载 handler.js。
991
+ *
992
+ * @param name agent 名
993
+ * @returns `AgentMetadata` 或 `undefined`(未注册 / DB skill 无文件)
994
+ */
995
+ declare function getAgentEntry(name: string): AgentMetadata | undefined;
996
+ /**
997
+ * agent 包装为 tool 的描述符
998
+ *
999
+ * 与 [ToolMetadata](../ast/extractToolMetadata.md) 平行结构,供 reactLoop 把
1000
+ * agent 当作 tool 发给 LLM。reactLoop 按 `kind` 字段路由执行:
1001
+ * - `'tool'` → `loadToolModule` 加载 handler 函数
1002
+ * - `'agent'` → `loadAgentModule` 加载 agent handler + 递归 reactLoop
1003
+ *
1004
+ * `name` 加 `agent.` 前缀避免与常规 tool 冲突,reactLoop 据此识别 sub-agent 递归。
1005
+ * 不含 input schema——agent `run` 函数参数为开放式(任意 JSON),无类型约束。
1006
+ *
1007
+ * `metadata` 为 [AgentCore](../ast/extractAgentMetadata.md) 类型——reactLoop 只消费
1008
+ * LLM-facing 字段(systemPrompt / model / maxTurns);加载 handler.js 执行 `run`
1009
+ * 函数由 `@faapi/agent` 子包通过 [getAgentEntry](#getAgentEntry) 单独获取。
1010
+ */
1011
+ interface AgentToolDescriptor {
1012
+ /** 标识此 tool 实际是 agent(reactLoop 据此走 sub-agent 递归) */
1013
+ kind: 'agent';
1014
+ /** tool 名(默认 `agent.<agentName>`,避免与常规 tool 冲突) */
1015
+ name: string;
1016
+ /** agent 名(不含前缀,用于按名查找 agent 元数据) */
1017
+ agentName: string;
1018
+ /** 描述(对 LLM 可见,来自 `agent.description`),无 JSDoc 描述时为 `undefined` */
1019
+ description?: string;
1020
+ /** agent LLM 可见元数据引用(reactLoop 取 `systemPrompt` / `model` / `maxTurns`) */
1021
+ metadata: AgentCore;
1022
+ }
1023
+ /**
1024
+ * 解析 agent 可用 tool 集合
1025
+ *
1026
+ * 只返回 agent 显式声明的 tool(agent config 块的 `tools` 字段)。
1027
+ * `resolveAgentTools` 只关心 agent 自身显式声明的部分,职责单一。
1028
+ * sub-agent 的合并由 `@faapi/agent` 的 `Agent.buildToolDefinitions` 在更上层完成(按 `name` 去重)。
1029
+ *
1030
+ * agent 必须显式声明用哪些 tool,显式优于隐式。
1031
+ *
1032
+ * skill fallback:通过 [getAgent](#getAgent) 自动发现 DB-driven skill,
1033
+ * skill 的 `tools` 字段同样会被解析。DB skill 引用的 tool 必须在 toolRegistry
1034
+ * 注册(文件型 tool 或未来 DB-driven tool)。
1035
+ *
1036
+ * `tools` 中未在 toolRegistry 找到的 tool 名静默跳过(tool 可选可用,不强制存在)。
1037
+ *
1038
+ * 跨注册表依赖 [toolRegistry](./toolRegistry.ts) 的 `getTool`,
1039
+ * 两个注册表由 `createAppBase` 在同一启动阶段水合。
1040
+ *
1041
+ * @param name agent 名
1042
+ * @returns `ToolMetadata[]`(agent 未注册返回空数组)
1043
+ */
1044
+ declare function resolveAgentTools(name: string): ToolMetadata[];
1045
+ /**
1046
+ * 解析 agent 可调用的子 agent 集合
1047
+ *
1048
+ * 读 `agent.agents` 字段([extractAgentMetadata](../ast/extractAgentMetadata.md)
1049
+ * 提取的 `config.agents` 字面量列表),按名查找已注册 agent。
1050
+ *
1051
+ * skill fallback:通过 [getAgent](#getAgent) 自动发现 DB-driven skill。
1052
+ * 父 agent 可以在 `agents` 列表里引用 DB skill 名,递归调用走相同链路。
1053
+ *
1054
+ * 返回 `AgentCore[]`(LLM-facing 字段,供 `@faapi/agent` 子包包装为
1055
+ * `AgentToolDescriptor` 发给 LLM)。加载 sub-agent handler.js 执行 `run` 函数
1056
+ * 由 `@faapi/agent` 子包通过 [getAgentEntry](#getAgentEntry) 单独获取。
1057
+ *
1058
+ * reactLoop 组装 LLM tool 列表:
1059
+ * ```ts
1060
+ * const tools = [
1061
+ * ...resolveAgentTools(name), // 常规 tool
1062
+ * ...resolveSubAgents(name).map((a) => asTool(a.name)!), // agent-as-tool
1063
+ * ];
1064
+ * ```
1065
+ *
1066
+ * @param name agent 名
1067
+ * @returns `AgentCore[]`(`agents` 未设置 / agent 未注册返回空数组)
1068
+ */
1069
+ declare function resolveSubAgents(name: string): AgentCore[];
1070
+
1071
+ /**
1072
+ * 加载后的 agent 模块
1073
+ *
1074
+ * 与 [ToolModule](./loadToolModule.md) 对称——agent 的代码本体只有可选的 `run` 函数
1075
+ * (自定义 agent 运行逻辑,替代默认 reactLoop)。
1076
+ *
1077
+ * > `config` 字段已移除——`AgentMetadata` 已含 AST 提取的字面量字段
1078
+ * > (systemPrompt / tools / agents / model / maxTurns),`AgentModule.config`
1079
+ * > 原本用于运行时拿到完整 config 对象(含动态字段),但 `executeSubAgent`
1080
+ * > 拿到 `mod.config` 后从不读取(run 函数在自己模块内直接引用 config 变量),
1081
+ * > 属于死链路,故移除。
1082
+ *
1083
+ * `AgentMetadata`(从 `faapi-agents.js` 水合)已含字面量字段,本模块仅用于
1084
+ * 在运行时拿到 `run` 函数引用。
1085
+ */
1086
+ interface AgentModule {
1087
+ /**
1088
+ * 自定义 agent 运行函数(可选)
1089
+ *
1090
+ * `hasRun` 为 true 时一定为 function;为 false 时为 `undefined`。
1091
+ * 调用方式由 `@faapi/agent` 子包的 Agent 类定义(Phase 3.x)。
1092
+ */
1093
+ run: ((...args: unknown[]) => unknown) | undefined;
1094
+ }
1095
+ /**
1096
+ * 动态 import agent handler 文件并提取 `run` 导出
1097
+ *
1098
+ * Dev 按需编译模式(Vite 风格):先 `ensureCompiled` 确保产物存在再 import,
1099
+ * 避免 import 不存在的文件污染 Vite SSR 内部状态(详见 [loadRouteModule](./loadRouteModule.md))。
1100
+ * Prod 模式:产物在 build 阶段已固化,直接 import,失败即报错。
1101
+ *
1102
+ * 与 [loadToolModule](./loadToolModule.md) 的差异:
1103
+ * - tool 按 `functionName` 提取单个函数(校验为 function)
1104
+ * - agent 只提取 `run`(函数,可选)——config 块字段已在 AST 阶段提取为字面量,
1105
+ * 运行时无需再加载 config 对象
1106
+ *
1107
+ * 错误传递:
1108
+ * - 编译失败 → 抛 "Failed to compile agent module"
1109
+ * - import 失败 → 抛 "Failed to load agent module"
1110
+ *
1111
+ * @param filePath agent handler 文件的绝对路径(产物形式,如 `dist/agents/researcher/handler.js`)
1112
+ * @param hasRun 是否应提取 run 导出(来自 `AgentMetadata.hasRun`)
1113
+ * @param rootDir 项目根目录(按需编译模式用,可选)
1114
+ */
1115
+ declare function loadAgentModule(filePath: string, hasRun: boolean, rootDir?: string): Promise<AgentModule>;
1116
+
1117
+ /**
1118
+ * 加载后的 tool 模块
1119
+ *
1120
+ * 与 `RouteModule` 对称——`functionName` 替代 `method`(tool 没有HTTP方法维度)。
1121
+ * `handler` 是从模块解析出的 tool 函数,可直接调用。
1122
+ */
1123
+ interface ToolModule {
1124
+ /** tool 函数(已校验为 function 类型) */
1125
+ handler: (...args: unknown[]) => unknown;
1126
+ /** 源码导出名(如 `getWeather`,用于日志/调试,与 `method` 对应) */
1127
+ functionName: string;
1128
+ }
1129
+ /**
1130
+ * 动态 import tool handler 文件并提取指定函数名的导出
1131
+ *
1132
+ * Dev 按需编译模式(Vite 风格):先 `ensureCompiled` 确保产物存在再 import,
1133
+ * 避免 import 不存在的文件污染 Vite SSR 内部状态(详见 [loadRouteModule](./loadRouteModule.md))。
1134
+ * Prod 模式:产物在 build 阶段已固化,直接 import,失败即报错。
1135
+ *
1136
+ * 错误传递:
1137
+ * - 编译失败 → 抛 "Failed to compile tool module"
1138
+ * - import 失败 → 抛 "Failed to load tool module"
1139
+ * - 导出不是函数 → 抛 "does not export a valid function"
1140
+ *
1141
+ * @param filePath tool handler 文件的绝对路径(产物形式,如 `dist/tools/weather/handler.js`)
1142
+ * @param functionName 源码导出函数名(如 `getWeather`,由 `ToolManifest.functionName` 提供)
1143
+ * @param rootDir 项目根目录(按需编译模式用,可选)
1144
+ */
1145
+ declare function loadToolModule(filePath: string, functionName: string, rootDir?: string): Promise<ToolModule>;
1146
+
1147
+ /**
1148
+ * 加载后的 tool schema 模块
1149
+ *
1150
+ * 与 [ToolModule](./loadToolModule.md) 对称——`schema` 替代 `handler`。
1151
+ *
1152
+ * `schema` 是 `unknown` 类型——faapi 核心不依赖 zod(zod 是 peerDep),
1153
+ * `zod.js` 由业务方安装的 zod 创建,`@faapi/agent` 负责断言为 zod schema 后
1154
+ * 调 `z.toJSONSchema` / `safeParse`。
1155
+ */
1156
+ interface ToolSchemaModule {
1157
+ /** zod schema 对象(由业务方安装的 zod 创建) */
1158
+ schema: unknown;
1159
+ /** schema 导出名(如 `WeatherInputSchema`,用于日志/调试) */
1160
+ schemaName: string;
1161
+ }
1162
+ /**
1163
+ * 动态加载 tool 的 zod.js schema 模块
1164
+ *
1165
+ * 与 [loadToolModule](./loadToolModule.md) 对称——一个加载 handler.js(tool 函数),
1166
+ * 一个加载 zod.js(tool schema)。
1167
+ *
1168
+ * 行为:
1169
+ * - `tool.inputTypeName` 为 `undefined` → 返回 `undefined`(无 schema,用自由 schema)
1170
+ * - zod.js 文件不存在 → 返回 `undefined`(schema 可选,缺失用自由 schema)
1171
+ * - import 失败 / 导出名不匹配 → 返回 `undefined`
1172
+ *
1173
+ * 与 route schema 不同(route schema 缺失抛 `InternalError`),tool schema 是可选的——
1174
+ * `@faapi/agent` 的 `resolveToolSchema` 未提供时用自由 schema `{ type: 'object' }`,
1175
+ * LLM 自由传参,handler 内部自行处理参数合法性。
1176
+ *
1177
+ * @param tool tool 元数据(含 `filePath` + `inputTypeName`)
1178
+ * @param rootDir 项目根目录(用于计算 zod.js 绝对路径,`tool.filePath` 是相对路径时拼接)
1179
+ */
1180
+ declare function loadToolSchema(tool: ToolMetadata, rootDir?: string): Promise<ToolSchemaModule | undefined>;
1181
+
1182
+ /**
1183
+ * 按全名查找单个 tool
1184
+ *
1185
+ * @param tool 全名(如 `weather.getWeather`)
1186
+ * @returns `ToolMetadata` 或 `undefined`(未注册)
1187
+ */
1188
+ declare function getTool(name: string): ToolMetadata | undefined;
1189
+
1190
+ /**
1191
+ * 水合 skill 注册表(全量替换)
1192
+ *
1193
+ * 业务方 plugin `lifecycle.onReady` 启动期调用:全量查 DB → 转 `AgentCore[]`
1194
+ * → 调本函数灌入。与 `hydrateAgentRegistry` 同构,全量替换而非增量。
1195
+ *
1196
+ * 运行时增量更新场景(DB change stream)用 [upsertSkill](#upsertSkill) /
1197
+ * [removeSkill](#removeSkill),不走本函数。
1198
+ *
1199
+ * @param skills 从 DB / 外部源加载并转好的 `AgentCore[]`
1200
+ */
1201
+ declare function hydrateSkillRegistry(skills: AgentCore[]): void;
1202
+ /**
1203
+ * 单条增改 skill(运行时增量)
1204
+ *
1205
+ * 监听 DB change stream 的 `insert` / `update` 事件时调用。
1206
+ * `Map.set` 原子操作,并发安全(多请求同时 upsert 最后一次 wins)。
1207
+ *
1208
+ * 同名 skill 覆盖(更新),不重复累积。
1209
+ *
1210
+ * @param core skill 的 LLM 可见元数据
1211
+ */
1212
+ declare function upsertSkill(core: AgentCore): void;
1213
+ /**
1214
+ * 单条删除 skill(运行时增量)
1215
+ *
1216
+ * 监听 DB change stream 的 `delete` 事件时调用。
1217
+ * 幂等:删除不存在的 name 静默无操作,不抛错。
1218
+ *
1219
+ * @param name skill 名
1220
+ */
1221
+ declare function removeSkill(name: string): void;
1222
+ /**
1223
+ * 按名查单个 skill
1224
+ *
1225
+ * @param name skill 名
1226
+ * @returns `AgentCore` 或 `undefined`(未注册)
1227
+ */
1228
+ declare function getSkill(name: string): AgentCore | undefined;
1229
+ /**
1230
+ * 返回所有已注册 skill
1231
+ *
1232
+ * 返回副本,调用方修改不影响内部状态(与 `listAgents` / `listTools` 同构)。
1233
+ */
1234
+ declare function listSkills(): AgentCore[];
1235
+
1236
+ /**
1237
+ * agent handle 工厂注册表(单例)
1238
+ *
1239
+ * 让 `@faapi/agent` 插件在启动时注册「请求级 agent handle 工厂」,
1240
+ * [injectParams](./injectParams.md) 在 `agent` 参数注入时调工厂拿到 `AgentHandle` 实例。
1241
+ *
1242
+ * 解耦设计:faapi 核心不依赖 `@faapi/agent`——核心只提供注册 / 查询点,
1243
+ * 工厂返回 `unknown`,具体类型由 `@faapi/agent` 的 `AgentHandle` 接口定义。
1244
+ *
1245
+ * 详见 [agentHandle.md](./agentHandle.md)。
1246
+ */
1247
+ /** agent handle 工厂函数(由 `@faapi/agent` 插件注册) */
1248
+ type AgentHandleFactory = (ctx: FaapiContext) => unknown;
1249
+ /**
1250
+ * 注册 agent handle 工厂
1251
+ *
1252
+ * 由 `@faapi/agent` 插件在 `setup()` 时调用,传入创建 `AgentHandle` 的工厂函数。
1253
+ * 二次注册覆盖第一次(与 `hydrateAgentRegistry` 全量替换同构)。
1254
+ *
1255
+ * 传入 `null` 等效于 [clearAgentHandleFactory](#clearAgentHandleFactory)。
1256
+ *
1257
+ * @param factory 工厂函数或 `null`(清理)
1258
+ */
1259
+ declare function registerAgentHandleFactory(factory: AgentHandleFactory | null): void;
1260
+ /**
1261
+ * 清空工厂注册(app close / 测试清理时调用)
1262
+ *
1263
+ * 与 `clearAgentRegistry` / `clearToolRegistry` 对称,避免测试间状态泄漏。
1264
+ */
1265
+ declare function clearAgentHandleFactory(): void;
1266
+
657
1267
  /**
658
1268
  * 加载 faapi 配置文件
659
1269
  *
@@ -699,7 +1309,8 @@ declare const ROUTE_NOT_FOUND = "ROUTE_NOT_FOUND";
699
1309
  declare const METHOD_NOT_ALLOWED = "METHOD_NOT_ALLOWED";
700
1310
  declare const INTERNAL_ERROR = "INTERNAL_ERROR";
701
1311
  declare const MODULE_LOAD_ERROR = "MODULE_LOAD_ERROR";
702
- type ErrorCode = typeof VALIDATION_ERROR | typeof ROUTE_NOT_FOUND | typeof METHOD_NOT_ALLOWED | typeof INTERNAL_ERROR | typeof MODULE_LOAD_ERROR;
1312
+ declare const PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE";
1313
+ type ErrorCode = typeof VALIDATION_ERROR | typeof ROUTE_NOT_FOUND | typeof METHOD_NOT_ALLOWED | typeof INTERNAL_ERROR | typeof MODULE_LOAD_ERROR | typeof PAYLOAD_TOO_LARGE;
703
1314
 
704
1315
  declare class FaapiError extends Error {
705
1316
  readonly code: ErrorCode;
@@ -822,10 +1433,14 @@ interface AppBase {
822
1433
  inject(options?: InjectOptions): Promise<InjectResponse>;
823
1434
  }
824
1435
 
825
- /** dev 应用接口(AppBase + reloadRoutes 热替换) */
1436
+ /** dev 应用接口(AppBase + reloadRoutes/reloadTools/reloadAgents 热替换) */
826
1437
  interface DevApp extends AppBase {
827
1438
  /** 重新水合路由清单 + 清 schema 缓存 + 更新 server 路由引用(dev 热替换用) */
828
1439
  reloadRoutes(): Promise<void>;
1440
+ /** 重新扫描 tools + 重生成 faapi-tools.js + 清缓存(dev 热替换用) */
1441
+ reloadTools(): Promise<void>;
1442
+ /** 重新扫描 agents + 重生成 faapi-agents.js + 清缓存(dev 热替换用) */
1443
+ reloadAgents(): Promise<void>;
829
1444
  }
830
1445
  /**
831
1446
  * dev 模式应用启动 API
@@ -872,4 +1487,4 @@ type ProdApp = AppBase;
872
1487
  */
873
1488
  declare function createProdApp(options?: CreateAppOptions): Promise<ProdApp>;
874
1489
 
875
- export { type ProdApp as App, CorsOptions, type CreateAppOptions, type DevApp, type FaapiConfig, FaapiContext, FaapiError, FaapiMiddleware, type FaapiPlugin, type HandlerTypeInfo, HelmetOptions, type InjectOptions, type InjectResponse, InjectorMap, InternalError, type LifecycleContext, type LifecycleHooks, LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type ResponseConfig, RouteManifest, RouteNotFoundError, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, type TypeConstraint, type UpgradeHandler, ValidationError, type ValidationErrorCode, type ValidationIssue, type WsContext, type WsEventHandlers, type WsHandler, type WsSocket, collectRouteSchemaSources, createProdApp as createApp, createDevApp, createProdApp, createProgram, extractTypeInfo, getApp, getInputTypeForMethod, invalidateProgramCache, loadConfig, loadEnv, resolveTypeNode };
1490
+ export { type AgentConfig, type AgentCore, type AgentHandleFactory, type AgentMetadata, type AgentModule, type AgentPathMeta, type AgentToolDescriptor, type ProdApp as App, CorsOptions, type CreateAppOptions, type DevApp, type FaapiConfig, FaapiContext, FaapiError, FaapiMiddleware, type FaapiPlugin, type HandlerTypeInfo, HelmetOptions, type InjectOptions, type InjectResponse, InjectorMap, InternalError, type LifecycleContext, type LifecycleHooks, type LlmConfig, type LlmModelConfig, LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type ResponseConfig, RouteManifest, RouteNotFoundError, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, type ToolCore, type ToolMetadata, type ToolModule, type ToolPathMeta, type ToolSchemaModule, type TypeConstraint, type UpgradeHandler, ValidationError, type ValidationErrorCode, type ValidationIssue, type WsContext, type WsEventHandlers, type WsHandler, type WsSocket, clearAgentHandleFactory, collectRouteSchemaSources, createProdApp as createApp, createDevApp, createProdApp, createProgram, extractTypeInfo, getAgent, getAgentEntry, getApp, getInputTypeForMethod, getSkill, getTool, hydrateSkillRegistry, invalidateProgramCache, listSkills, loadAgentModule, loadConfig, loadEnv, loadToolModule, loadToolSchema, registerAgentHandleFactory, removeSkill, resolveAgentTools, resolveSubAgents, resolveTypeNode, upsertSkill };