@faapi/faapi 3.0.0 → 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
@@ -178,13 +178,48 @@ interface ResponseConfig {
178
178
  }) => unknown;
179
179
  }
180
180
  /**
181
- * LLM 提供方配置(Phase 2.4
181
+ * model 级配置(Phase 3.5
182
182
  *
183
- * 定义如何连接 LLM 服务(OpenAI 兼容 API),由 Phase 3.2 的 `@faapi/agent` 插件读取。
184
- * 支持 `provider` 标识 + OpenAI 兼容字段(apiKey / model / baseURL),
185
- * 额外字段透传给 LLM API(如 temperature / max_tokens)。
183
+ * 挂在 provider 下的单个 model 配置,model 特定字段透传给 LLM API
184
+ * (覆盖 provider 级同名字段)。空对象 `{}` 表示用 provider 级默认。
186
185
  *
187
- * `model` 是默认模型,agent 自身 `config.model` 可覆盖。
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
+ * ```
188
223
  */
189
224
  interface LlmConfig {
190
225
  /**
@@ -199,10 +234,6 @@ interface LlmConfig {
199
234
  * 如 `process.env.OPENAI_API_KEY`。
200
235
  */
201
236
  apiKey?: string;
202
- /**
203
- * 默认模型(如 'gpt-4o'),agent 自身 `config.model` 优先
204
- */
205
- model?: string;
206
237
  /**
207
238
  * API 基础 URL(可选,用于 OpenAI 兼容 API 如 Azure OpenAI / 中转服务)
208
239
  *
@@ -210,14 +241,24 @@ interface LlmConfig {
210
241
  */
211
242
  baseURL?: string;
212
243
  /**
213
- * 其他透传参数(如 temperature / max_tokens / top_p)
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)
214
254
  *
215
255
  * 这些字段原样传给 LLM API,由 provider 适配器处理。
256
+ * model 级 `models[modelName]` 的同名字段优先。
216
257
  */
217
258
  [key: string]: unknown;
218
259
  }
219
260
  /**
220
- * agent 子系统全局配置(Phase 2.4
261
+ * agent 子系统全局配置(Phase 2.4,Phase 3.5 LLM 配置改为嵌套级联)
221
262
  *
222
263
  * 提供 agent 子系统的全局默认值,所有字段均可选,未设置时用框架默认值。
223
264
  * agent 自身 `config.maxTurns` / `config.model` 优先于全局配置。
@@ -226,11 +267,17 @@ interface LlmConfig {
226
267
  * import type { FaapiConfig } from '@faapi/faapi';
227
268
  * export default {
228
269
  * agent: {
229
- * llm: { provider: 'openai', apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o' },
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',
230
278
  * defaultAgent: 'researcher',
231
279
  * maxTurns: 10,
232
280
  * maxAgentDepth: 3,
233
- * defaultTools: ['weather.getWeather'],
234
281
  * },
235
282
  * } satisfies FaapiConfig;
236
283
  * ```
@@ -239,11 +286,22 @@ interface LlmConfig {
239
286
  */
240
287
  interface AgentConfig {
241
288
  /**
242
- * LLM 提供方配置(Phase 3.2 @faapi/agent 插件使用)
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))。
243
294
  *
244
295
  * 未设置时 Phase 3.x 插件无法调用 LLM,agent 的 `run` 函数仍可手动实现。
245
296
  */
246
- llm?: LlmConfig;
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;
247
305
  /**
248
306
  * 默认 agent 名,用于 `agent` 参数注入([injectParams](../injection/injectParams.md) Phase 2.3)
249
307
  *
@@ -252,13 +310,6 @@ interface AgentConfig {
252
310
  * 注入 `AgentHandle`(含可调用 `run`)。
253
311
  */
254
312
  defaultAgent?: string;
255
- /**
256
- * 默认 tool 列表,所有 agent 都可用(无需在每个 agent 的 `tools` 重复声明)
257
- *
258
- * 与 agent 自身 `tools` 合并(都加入可用 tool 集合,去重)。
259
- * 由 `@faapi/agent` 插件在 setup 时合并到 agent 的 tool 引用列表。
260
- */
261
- defaultTools?: string[];
262
313
  /**
263
314
  * 默认最大对话轮数(覆盖 agent 自身 `config.maxTurns`,agent 自身配置优先)
264
315
  *
@@ -403,19 +454,25 @@ interface FaapiConfig {
403
454
  /**
404
455
  * agent 子系统全局配置(Phase 2.4)
405
456
  *
406
- * 提供 agent 子系统的全局默认值:LLM 提供方、默认 agent、默认共享 tool
457
+ * 提供 agent 子系统的全局默认值:LLM 提供方、默认 agent、
407
458
  * 最大对话轮数、agent 调用 agent 的最大递归深度。
408
459
  *
409
460
  * agent 自身 `config.maxTurns` / `config.model` 优先于全局配置。
410
- * `defaultTools` agent 自身 `tools` 合并(去重)。
461
+ * tool 引用列表只在每个 agent 自身的 `config.tools` 里声明(无全局共享 defaultTools)。
411
462
  *
412
463
  * ```ts
413
464
  * import type { FaapiConfig } from '@faapi/faapi';
414
465
  * export default {
415
466
  * agent: {
416
- * llm: { provider: 'openai', apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o' },
467
+ * llms: {
468
+ * openai: {
469
+ * provider: 'openai',
470
+ * apiKey: process.env.OPENAI_API_KEY,
471
+ * models: { 'gpt-4o': {} },
472
+ * },
473
+ * },
474
+ * defaultLlm: 'openai',
417
475
  * defaultAgent: 'researcher',
418
- * defaultTools: ['weather.getWeather'],
419
476
  * maxTurns: 10,
420
477
  * maxAgentDepth: 3,
421
478
  * },
@@ -775,47 +832,65 @@ declare function collectRouteSchemaSources(routes: RouteManifest, rootDir?: stri
775
832
  };
776
833
 
777
834
  /**
778
- * Agent 完整元数据
835
+ * Agent 的 LLM 可见核心字段
779
836
  *
780
- * [extractAgentMetadata](./extractAgentMetadata.md) 产出,合并路径推导字段
781
- * (来自 [scanAgents](../agents/scanAgents.md) `AgentManifest`)AST 提取字段
782
- * (JSDoc 描述、`@agent` 覆盖名、config 块字段)。
837
+ * 描述"agent 是什么"——LLM 真正需要消费的字段,**不含**代码本体加载细节
838
+ * (filePath / hasRun)。文件型 agentDB-driven skill 都实现此接口。
783
839
  *
784
- * [ToolMetadata](./extractToolMetadata.md) 对称——一个从函数导出提取 JSDoc + 参数类型,
785
- * 一个从 config 导出提取 JSDoc + 配置块。
840
+ * - 文件型 agent:由 [AgentMetadata](./extractAgentMetadata.md) 继承扩展,
841
+ * 额外含 `filePath` / `hasRun`(代码本体加载用)
842
+ * - DB-driven skill:业务方 plugin 从 DB 字段映射到本接口即可,无需填占位值
843
+ * (skill 无源文件,不走 `loadAgentModule`,自然不读 filePath / hasRun)
786
844
  *
787
- * 字段来源:
788
- * - `name` — `@agent` JSDoc 覆盖值,或 `pathMeta.name`(目录推导)
789
- * - `filePath` / `hasConfig` / `hasRun` — 由 `pathMeta` 透传
790
- * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
791
- * - `systemPrompt` / `tools` / `agents` / `model` / `maxTurns` — config 块字面量提取
845
+ * `@faapi/agent` 子包的 `Agent` 类、`agentRegistry` 查询入口、`asTool` 包装
846
+ * 都消费 `AgentCore`,实现"agent skill 走同一运行时链路"。
792
847
  */
793
- interface AgentMetadata {
848
+ interface AgentCore {
794
849
  /** agent 名(`@agent` JSDoc 覆盖值 或 目录推导值) */
795
850
  name: string;
796
- /** JSDoc 描述(agent 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
851
+ /** JSDoc 描述(agent 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
797
852
  description?: string;
798
- /** 源码相对路径( `pathMeta` 透传) */
799
- filePath: string;
800
- /** 是否导出 config 块(从 `pathMeta` 透传) */
801
- hasConfig: boolean;
802
- /** 是否导出 run 函数(从 `pathMeta` 透传) */
803
- hasRun: boolean;
804
- /** 系统提示词(config 块字面量提取),无/非字面量时为 `undefined` */
853
+ /** 系统提示词(config 块字面量提取),无/非字面量时为 `undefined` */
805
854
  systemPrompt?: string;
806
- /** agent 显式声明可用的 tool 引用列表(config 块字面量提取),无/含非字面量元素时为 `undefined` */
855
+ /** agent 显式声明可用的 tool 引用列表(config 块字面量提取),无/含非字面量元素时为 `undefined` */
807
856
  tools?: string[];
808
- /** 可调用的其他 agent 名列表(config 块字面量提取),无/含非字面量元素时为 `undefined` */
857
+ /** 可调用的其他 agent 名列表(config 块字面量提取),无/含非字面量元素时为 `undefined` */
809
858
  agents?: string[];
810
- /** LLM 模型名(config 块字面量提取),无/非字面量时为 `undefined` */
859
+ /** LLM 模型名(config 块字面量提取),无/非字面量时为 `undefined` */
811
860
  model?: string;
812
- /** 最大对话轮数(config 块字面量提取),无/非字面量时为 `undefined` */
861
+ /** 最大对话轮数(config 块字面量提取),无/非字面量时为 `undefined` */
813
862
  maxTurns?: number;
814
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
+ }
815
890
  /**
816
891
  * 路径推导的 agent 元数据(由 [scanAgents](../agents/scanAgents.ts) 计算)
817
892
  *
818
- * 透传到 [AgentMetadata](./extractAgentMetadata.ts) 输出,与 AST 提取字段合并。
893
+ * 透传到 [AgentMetadata](./extractAgentMetadata.ts) 输出,与 AST 提取字段合并。
819
894
  * 与 [ToolPathMeta](./extractToolMetadata.md) 对称。
820
895
  */
821
896
  interface AgentPathMeta {
@@ -823,14 +898,37 @@ interface AgentPathMeta {
823
898
  name: string;
824
899
  /** 源码相对路径(如 `src/agents/researcher/handler.ts`) */
825
900
  filePath: string;
826
- /** 是否导出 config (scanAgents 正则检测) */
827
- hasConfig: boolean;
828
- /** 是否导出 run 函数(scanAgents 正则检测) */
901
+ /** 是否导出 `run` 函数(scanAgents 正则检测) */
829
902
  hasRun: boolean;
830
903
  }
831
904
 
832
905
  /**
833
- * Tool 完整元数据
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`)
834
932
  *
835
933
  * 由 [extractToolMetadata](./extractToolMetadata.md) 产出,合并路径推导字段
836
934
  * (来自 [scanTools](../tools/scanTools.md) 的 `ToolManifest`)与 AST 提取字段
@@ -838,15 +936,11 @@ interface AgentPathMeta {
838
936
  *
839
937
  * 字段来源:
840
938
  * - `name` — `@tool` JSDoc 覆盖值,或 `pathMeta.name`(路径推导)
841
- * - `filePath` / `functionName` — 由 `pathMeta` 透传
842
939
  * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
940
+ * - `filePath` / `functionName` — 由 `pathMeta` 透传
843
941
  * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md) 生成 zod schema)
844
942
  */
845
- interface ToolMetadata {
846
- /** tool 名(`@tool` JSDoc 覆盖值 或 路径推导值) */
847
- name: string;
848
- /** JSDoc 描述(tool 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
849
- description?: string;
943
+ interface ToolMetadata extends ToolCore {
850
944
  /** 第一个参数的 interface/type 名(用于生成 zod schema),
851
945
  * 无参数/参数无类型标注/参数为内联类型字面量时为 `undefined` */
852
946
  inputTypeName?: string;
@@ -868,12 +962,37 @@ interface ToolPathMeta {
868
962
  }
869
963
 
870
964
  /**
871
- * 按名查找单个 agent
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)。
872
977
  *
873
978
  * @param name agent 名(如 `researcher`,含 `@agent` 覆盖值)
874
- * @returns `AgentMetadata` 或 `undefined`(未注册)
979
+ * @returns `AgentCore` 或 `undefined`(未注册)
875
980
  */
876
- declare function getAgent(name: string): AgentMetadata | undefined;
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;
877
996
  /**
878
997
  * agent 包装为 tool 的描述符
879
998
  *
@@ -884,6 +1003,10 @@ declare function getAgent(name: string): AgentMetadata | undefined;
884
1003
  *
885
1004
  * `name` 加 `agent.` 前缀避免与常规 tool 冲突,reactLoop 据此识别 sub-agent 递归。
886
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) 单独获取。
887
1010
  */
888
1011
  interface AgentToolDescriptor {
889
1012
  /** 标识此 tool 实际是 agent(reactLoop 据此走 sub-agent 递归) */
@@ -894,19 +1017,22 @@ interface AgentToolDescriptor {
894
1017
  agentName: string;
895
1018
  /** 描述(对 LLM 可见,来自 `agent.description`),无 JSDoc 描述时为 `undefined` */
896
1019
  description?: string;
897
- /** agent 元数据引用(reactLoop 取 `systemPrompt` / `model` / `maxTurns` / `filePath` 等) */
898
- metadata: AgentMetadata;
1020
+ /** agent LLM 可见元数据引用(reactLoop 取 `systemPrompt` / `model` / `maxTurns`) */
1021
+ metadata: AgentCore;
899
1022
  }
900
1023
  /**
901
1024
  * 解析 agent 可用 tool 集合
902
1025
  *
903
1026
  * 只返回 agent 显式声明的 tool(agent config 块的 `tools` 字段)。
904
- * 不在此处合并全局 `defaultTools`——`defaultTools` 的合并由 `@faapi/agent` 的
905
- * `Agent.buildToolDefinitions` 在更上层完成(与 sub-agent 一起按 `name` 去重)。
906
1027
  * `resolveAgentTools` 只关心 agent 自身显式声明的部分,职责单一。
1028
+ * sub-agent 的合并由 `@faapi/agent` 的 `Agent.buildToolDefinitions` 在更上层完成(按 `name` 去重)。
907
1029
  *
908
1030
  * agent 必须显式声明用哪些 tool,显式优于隐式。
909
1031
  *
1032
+ * skill fallback:通过 [getAgent](#getAgent) 自动发现 DB-driven skill,
1033
+ * skill 的 `tools` 字段同样会被解析。DB skill 引用的 tool 必须在 toolRegistry
1034
+ * 注册(文件型 tool 或未来 DB-driven tool)。
1035
+ *
910
1036
  * `tools` 中未在 toolRegistry 找到的 tool 名静默跳过(tool 可选可用,不强制存在)。
911
1037
  *
912
1038
  * 跨注册表依赖 [toolRegistry](./toolRegistry.ts) 的 `getTool`,
@@ -922,6 +1048,13 @@ declare function resolveAgentTools(name: string): ToolMetadata[];
922
1048
  * 读 `agent.agents` 字段([extractAgentMetadata](../ast/extractAgentMetadata.md)
923
1049
  * 提取的 `config.agents` 字面量列表),按名查找已注册 agent。
924
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
+ *
925
1058
  * reactLoop 组装 LLM tool 列表:
926
1059
  * ```ts
927
1060
  * const tools = [
@@ -931,34 +1064,26 @@ declare function resolveAgentTools(name: string): ToolMetadata[];
931
1064
  * ```
932
1065
  *
933
1066
  * @param name agent 名
934
- * @returns `AgentMetadata[]`(`agents` 未设置 / agent 未注册返回空数组)
1067
+ * @returns `AgentCore[]`(`agents` 未设置 / agent 未注册返回空数组)
935
1068
  */
936
- declare function resolveSubAgents(name: string): AgentMetadata[];
1069
+ declare function resolveSubAgents(name: string): AgentCore[];
937
1070
 
938
1071
  /**
939
1072
  * 加载后的 agent 模块
940
1073
  *
941
- * 与 [ToolModule](./loadToolModule.md) 对称——agent 不像 tool 只有一个 handler 函数,
942
- * 它导出 `config` 块(对象,含运行时可能动态求值的字段)和可选的 `run` 函数。
1074
+ * 与 [ToolModule](./loadToolModule.md) 对称——agent 的代码本体只有可选的 `run` 函数
1075
+ * (自定义 agent 运行逻辑,替代默认 reactLoop)。
943
1076
  *
944
- * - `config`:agent 配置对象(含 systemPrompt / tools / agents / model / maxTurns 等,
945
- * 以及任何非字面量字段——AST 阶段仅提取字面量,动态值需运行时加载)
946
- * - `run`:自定义 agent 运行逻辑(可选,替代默认 reactLoop)
1077
+ * > `config` 字段已移除——`AgentMetadata` 已含 AST 提取的字面量字段
1078
+ * > (systemPrompt / tools / agents / model / maxTurns),`AgentModule.config`
1079
+ * > 原本用于运行时拿到完整 config 对象(含动态字段),但 `executeSubAgent`
1080
+ * > 拿到 `mod.config` 后从不读取(run 函数在自己模块内直接引用 config 变量),
1081
+ * > 属于死链路,故移除。
947
1082
  *
948
- * `AgentMetadata`(从 `faapi-agents.js` 水合)已含字面量字段,`loadAgentModule`
949
- * 用于在运行时拿到完整 config 对象(含动态字段)和 run 函数引用。
1083
+ * `AgentMetadata`(从 `faapi-agents.js` 水合)已含字面量字段,本模块仅用于
1084
+ * 在运行时拿到 `run` 函数引用。
950
1085
  */
951
1086
  interface AgentModule {
952
- /**
953
- * agent 配置对象(含运行时字段)
954
- *
955
- * `hasConfig` 为 true 时一定存在;为 false 时为 `undefined`。
956
- * 可能是对象字面量(`export const config = {...}`)或函数返回值(`export function config() { return {...} }`)。
957
- *
958
- * 函数形式:本模块调用 `config()` 拿到返回值(无参调用,与 AST 阶段的字面量提取不同——
959
- * 运行时可拿到动态求值结果)。
960
- */
961
- config: Record<string, unknown> | undefined;
962
1087
  /**
963
1088
  * 自定义 agent 运行函数(可选)
964
1089
  *
@@ -968,7 +1093,7 @@ interface AgentModule {
968
1093
  run: ((...args: unknown[]) => unknown) | undefined;
969
1094
  }
970
1095
  /**
971
- * 动态 import agent handler 文件并提取 `config` 和 `run` 导出
1096
+ * 动态 import agent handler 文件并提取 `run` 导出
972
1097
  *
973
1098
  * Dev 按需编译模式(Vite 风格):先 `ensureCompiled` 确保产物存在再 import,
974
1099
  * 避免 import 不存在的文件污染 Vite SSR 内部状态(详见 [loadRouteModule](./loadRouteModule.md))。
@@ -976,20 +1101,18 @@ interface AgentModule {
976
1101
  *
977
1102
  * 与 [loadToolModule](./loadToolModule.md) 的差异:
978
1103
  * - tool 按 `functionName` 提取单个函数(校验为 function)
979
- * - agent 提取 `config`(对象或函数返回对象)和 `run`(函数,可选)
980
- * - agent 的 config 可能为函数形式(`export function config() { return {...} }`),
981
- * 本模块自动调用拿到返回值(与 AST 阶段仅提字面量不同——运行时拿动态值)
1104
+ * - agent 只提取 `run`(函数,可选)——config 块字段已在 AST 阶段提取为字面量,
1105
+ * 运行时无需再加载 config 对象
982
1106
  *
983
1107
  * 错误传递:
984
1108
  * - 编译失败 → 抛 "Failed to compile agent module"
985
1109
  * - import 失败 → 抛 "Failed to load agent module"
986
1110
  *
987
1111
  * @param filePath agent handler 文件的绝对路径(产物形式,如 `dist/agents/researcher/handler.js`)
988
- * @param hasConfig 是否应提取 config 导出(来自 `AgentMetadata.hasConfig`)
989
1112
  * @param hasRun 是否应提取 run 导出(来自 `AgentMetadata.hasRun`)
990
1113
  * @param rootDir 项目根目录(按需编译模式用,可选)
991
1114
  */
992
- declare function loadAgentModule(filePath: string, hasConfig: boolean, hasRun: boolean, rootDir?: string): Promise<AgentModule>;
1115
+ declare function loadAgentModule(filePath: string, hasRun: boolean, rootDir?: string): Promise<AgentModule>;
993
1116
 
994
1117
  /**
995
1118
  * 加载后的 tool 模块
@@ -1064,6 +1187,52 @@ declare function loadToolSchema(tool: ToolMetadata, rootDir?: string): Promise<T
1064
1187
  */
1065
1188
  declare function getTool(name: string): ToolMetadata | undefined;
1066
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
+
1067
1236
  /**
1068
1237
  * agent handle 工厂注册表(单例)
1069
1238
  *
@@ -1140,7 +1309,8 @@ declare const ROUTE_NOT_FOUND = "ROUTE_NOT_FOUND";
1140
1309
  declare const METHOD_NOT_ALLOWED = "METHOD_NOT_ALLOWED";
1141
1310
  declare const INTERNAL_ERROR = "INTERNAL_ERROR";
1142
1311
  declare const MODULE_LOAD_ERROR = "MODULE_LOAD_ERROR";
1143
- 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;
1144
1314
 
1145
1315
  declare class FaapiError extends Error {
1146
1316
  readonly code: ErrorCode;
@@ -1317,4 +1487,4 @@ type ProdApp = AppBase;
1317
1487
  */
1318
1488
  declare function createProdApp(options?: CreateAppOptions): Promise<ProdApp>;
1319
1489
 
1320
- export { type AgentConfig, 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, LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type ResponseConfig, RouteManifest, RouteNotFoundError, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, 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, getApp, getInputTypeForMethod, getTool, invalidateProgramCache, loadAgentModule, loadConfig, loadEnv, loadToolModule, loadToolSchema, registerAgentHandleFactory, resolveAgentTools, resolveSubAgents, 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 };