@faapi/faapi 6.4.1 → 6.5.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.
@@ -1,3 +1,133 @@
1
+ /**
2
+ * Tool 的 LLM 可见核心字段
3
+ *
4
+ * 描述"tool 是什么"——LLM 真正需要消费的字段(发往 LLM 的 tool 定义只含
5
+ * `name` / `description` / input schema),**不含**代码本体加载细节
6
+ * (`filePath` / `functionName` / `inputTypeName`)。
7
+ *
8
+ * 与 [AgentCore](./extractAgentMetadata.md) 对称——LLM-facing 字段与代码加载
9
+ * 细节分离,便于未来扩展(如 DB-driven tool 只实现 `ToolCore` 即可)。
10
+ *
11
+ * `toolRegistry` 查询入口 / `@faapi/agent` 子包的 `buildToolDefinitions`
12
+ * 都消费 `ToolCore` 字段组装 LLM tool 列表。
13
+ */
14
+ interface ToolCore {
15
+ /** tool 名(`@tool` JSDoc 覆盖值 或 路径推导值) */
16
+ name: string;
17
+ /** JSDoc 描述(tool 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
18
+ description?: string;
19
+ }
20
+ /**
21
+ * Tool 完整元数据(文件型 tool)
22
+ *
23
+ * 继承 [ToolCore](./extractToolMetadata.md) 的 LLM 字段,额外扩展**代码本体加载细节**:
24
+ * - `filePath` — `loadToolModule` 加载 `handler.js` 产物定位函数用
25
+ * - `functionName` — 源码导出函数名(不受 `@tool` 覆盖影响,AST 定位 + 运行时 resolveExport 用)
26
+ * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md)
27
+ * 生成 zod schema;运行时 `resolveToolSchema` 据此定位 `zod.js`)
28
+ *
29
+ * 由 [extractToolMetadata](./extractToolMetadata.md) 产出,合并路径推导字段
30
+ * (来自 [scanTools](../tools/scanTools.md) 的 `ToolManifest`)与 AST 提取字段
31
+ * (JSDoc 描述、`@tool` 覆盖名、第一个参数 interface 名)。
32
+ *
33
+ * 字段来源:
34
+ * - `name` — `@tool` JSDoc 覆盖值,或 `pathMeta.name`(路径推导)
35
+ * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
36
+ * - `filePath` / `functionName` — 由 `pathMeta` 透传
37
+ * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md) 生成 zod schema)
38
+ */
39
+ interface ToolMetadata extends ToolCore {
40
+ /** 第一个参数的 interface/type 名(用于生成 zod schema),
41
+ * 无参数/参数无类型标注/参数为内联类型字面量时为 `undefined` */
42
+ inputTypeName?: string;
43
+ /** 源码相对路径(从 `pathMeta` 透传) */
44
+ filePath: string;
45
+ /** 源码中的导出函数名(从 `pathMeta` 透传,AST 定位用,不受 `@tool` 覆盖影响) */
46
+ functionName: string;
47
+ }
48
+ /**
49
+ * 路径推导的 tool 元数据(由 [scanTools](../tools/scanTools.ts) 计算)
50
+ *
51
+ * 透传到 [ToolMetadata](./extractToolMetadata.ts) 输出,与 AST 提取字段合并。
52
+ */
53
+ interface ToolPathMeta {
54
+ /** 路径推导的 tool 名(如 `weather.getWeather`) */
55
+ name: string;
56
+ /** 源码相对路径(如 `src/tools/weather/handler.ts`) */
57
+ filePath: string;
58
+ }
59
+
60
+ /**
61
+ * Agent 的 LLM 可见核心字段
62
+ *
63
+ * 描述"agent 是什么"——LLM 真正需要消费的字段,**不含**代码本体加载细节
64
+ * (filePath / hasRun)。文件型 agent 与 DB-driven skill 都实现此接口。
65
+ *
66
+ * - 文件型 agent:由 [AgentMetadata](./extractAgentMetadata.md) 继承扩展,
67
+ * 额外含 `filePath` / `hasRun`(代码本体加载用)
68
+ * - DB-driven skill:业务方 plugin 从 DB 字段映射到本接口即可,无需填占位值
69
+ * (skill 无源文件,不走 `loadAgentModule`,自然不读 filePath / hasRun)
70
+ *
71
+ * `@faapi/agent` 子包的 `Agent` 类、`agentRegistry` 查询入口、`asTool` 包装
72
+ * 都消费 `AgentCore`,实现"agent 与 skill 走同一运行时链路"。
73
+ */
74
+ interface AgentCore {
75
+ /** agent 名(`@agent` JSDoc 覆盖值 或 目录推导值) */
76
+ name: string;
77
+ /** JSDoc 描述(agent 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
78
+ description?: string;
79
+ /** 系统提示词(config 块字面量提取);文件型 agent 必填(构建期校验),DB skill 由业务方自治 */
80
+ systemPrompt?: string;
81
+ /** agent 显式声明可用的 tool 引用列表(config 块字面量提取),未声明时为 `undefined`;声明了但含无法静态求值的元素在构建期抛错 */
82
+ tools?: string[];
83
+ /** 可调用的其他 agent 名列表(config 块字面量提取),未声明时为 `undefined`;声明了但含无法静态求值的元素在构建期抛错 */
84
+ agents?: string[];
85
+ /** LLM 模型名(config 块字面量提取),未声明时为 `undefined`;声明了但非字面量在构建期抛错 */
86
+ model?: string;
87
+ /** 最大对话轮数(config 块字面量提取),未声明时为 `undefined`;声明了但非数字字面量在构建期抛错 */
88
+ maxTurns?: number;
89
+ }
90
+ /**
91
+ * Agent 完整元数据(文件型 agent)
92
+ *
93
+ * 继承 [AgentCore](./extractAgentMetadata.md) 的 LLM 字段,额外扩展**代码本体加载细节**:
94
+ * - `filePath` — `loadAgentModule` 加载 `handler.js` 产物提取 `run` 函数用
95
+ * - `hasRun` — 是否导出 `run` 函数(`Agent.executeSubAgent` 据此决定走自定义 run
96
+ * 还是默认 reactLoop)
97
+ *
98
+ * DB-driven skill 不实现此接口(无源文件,无需加载),只实现 `AgentCore`。
99
+ *
100
+ * 由 [extractAgentMetadata](./extractAgentMetadata.md) 产出,合并路径推导字段
101
+ * (来自 [scanAgents](../agents/scanAgents.md) 的 `AgentManifest`)与 AST 提取字段
102
+ * (JSDoc 描述、`@agent` 覆盖名、config 块字段)。
103
+ *
104
+ * 字段来源:
105
+ * - `name` — `@agent` JSDoc 覆盖值,或 `pathMeta.name`(目录推导)
106
+ * - `filePath` / `hasRun` — 由 `pathMeta` 透传
107
+ * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
108
+ * - `systemPrompt` / `tools` / `agents` / `model` / `maxTurns` — config 块字面量提取
109
+ */
110
+ interface AgentMetadata extends AgentCore {
111
+ /** 源码相对路径(从 `pathMeta` 透传),`loadAgentModule` 据此加载 `handler.js` 提取 `run` */
112
+ filePath: string;
113
+ /** 是否导出 `run` 函数(从 `pathMeta` 透传),`Agent.executeSubAgent` 据此选择自定义 run / 默认 reactLoop */
114
+ hasRun: boolean;
115
+ }
116
+ /**
117
+ * 路径推导的 agent 元数据(由 [scanAgents](../agents/scanAgents.ts) 计算)
118
+ *
119
+ * 透传到 [AgentMetadata](./extractAgentMetadata.ts) 输出,与 AST 提取字段合并。
120
+ * 与 [ToolPathMeta](./extractToolMetadata.md) 对称。
121
+ */
122
+ interface AgentPathMeta {
123
+ /** 目录推导的 agent 名(如 `researcher`) */
124
+ name: string;
125
+ /** 源码相对路径(如 `src/agents/researcher/handler.ts`) */
126
+ filePath: string;
127
+ /** 是否导出 `run` 函数(scanAgents 正则检测) */
128
+ hasRun: boolean;
129
+ }
130
+
1
131
  /**
2
132
  * app 实例级任务注册表(与 tool/agent/skill registry 同构,方案 A 实例化)
3
133
  *
@@ -138,6 +268,11 @@ interface TaskWorkerOptions {
138
268
  };
139
269
  /** 单次执行超时(毫秒) */
140
270
  timeoutMs: number;
271
+ /**
272
+ * 注册表快照(纯数据,postMessage 结构化克隆传入,worker 内重建只读视图注入
273
+ * taskCtx.registries)——语义层从 `TaskRegistriesView` 生成,缺省为空视图
274
+ */
275
+ registries?: TaskRegistriesSnapshot;
141
276
  /** 外部取消信号(驱动停机超时 abort)——abort 同样触发两段式取消 */
142
277
  externalSignal?: AbortSignal;
143
278
  /** 宽限期覆盖(默认 KILL_GRACE_MS)——测试注入短值用,业务不配置 */
@@ -145,6 +280,112 @@ interface TaskWorkerOptions {
145
280
  }
146
281
  declare function runTaskInWorker(options: TaskWorkerOptions): Promise<unknown>;
147
282
 
283
+ /**
284
+ * app 级注册表(方案 A:注册表实例化)
285
+ *
286
+ * 每个应用实例(`createAppBase`)持有一套独立的注册表,随 app 创建、随
287
+ * `app.close()` 销毁——多 app 同进程(测试 / 嵌入 / 多租户)互不串台。
288
+ * 此前注册表是模块级全局单例 + hydrate 整体替换语义,后创建的 app 会覆盖
289
+ * 先创建的 app 的清单,任一 app close 会清空全部(详见各模块 .md)。
290
+ *
291
+ * 原四个模块(toolRegistry / agentRegistry / skillRegistry / agentHandle)
292
+ * 保留同名全局函数作为**默认实例的便捷访问器**(供编程式直调 / 单元测试 /
293
+ * 无 app 上下文的场景),内部全部路由到本模块的 `defaultRegistries`。
294
+ * 框架自身链路(hydrate / 请求注入 / `@faapi/agent` 插件 / lifecycle 钩子)
295
+ * 一律走 app 实例,不再读写全局默认实例。
296
+ */
297
+ interface ToolRegistry {
298
+ /** 全量替换(tool 清单来自编译期产物,reload 时整体重新生成) */
299
+ hydrate(tools: ToolMetadata[]): void;
300
+ /** 按全名查找(如 `weather.getWeather`) */
301
+ get(name: string): ToolMetadata | undefined;
302
+ /** 所有已注册 tool(副本) */
303
+ list(): ToolMetadata[];
304
+ clear(): void;
305
+ }
306
+ /** agent 包装为 tool 的描述符(reactLoop 据此识别 sub-agent 递归) */
307
+ interface AgentToolDescriptor {
308
+ kind: 'agent';
309
+ name: string;
310
+ agentName: string;
311
+ description?: string;
312
+ metadata: AgentCore;
313
+ }
314
+ interface AgentRegistry {
315
+ /** 全量替换(与 hydrateToolRegistry 同构) */
316
+ hydrate(agents: AgentMetadata[]): void;
317
+ /** LLM 可见元数据(AgentCore) */
318
+ getAgent(name: string): AgentCore | undefined;
319
+ /** 完整元数据(含 filePath / hasRun,供加载 handler.js 执行 run) */
320
+ getAgentEntry(name: string): AgentMetadata | undefined;
321
+ /** 所有已注册 agent 的 LLM 可见元数据(副本) */
322
+ listAgents(): AgentCore[];
323
+ /** 包装为 tool 描述符 */
324
+ asTool(name: string): AgentToolDescriptor | undefined;
325
+ /**
326
+ * 解析 agent 显式声明的 tool 集合。
327
+ * 跨注册表依赖:经由构造时绑定的 tool 注册表查找(同属一套 AppRegistries,
328
+ * 由 createAppBase 在同一启动阶段水合)
329
+ */
330
+ resolveAgentTools(name: string): ToolMetadata[];
331
+ /** 解析 agent 可调用的子 agent 集合 */
332
+ resolveSubAgents(name: string): AgentCore[];
333
+ clear(): void;
334
+ }
335
+ interface SkillRegistry {
336
+ /** 全量替换(DB change stream 场景也可用 upsert 增量) */
337
+ hydrate(skills: AgentCore[]): void;
338
+ /** 增量注册 / 覆盖(业务方监听 DB 单条变更) */
339
+ upsert(skill: AgentCore): void;
340
+ remove(name: string): void;
341
+ get(name: string): AgentCore | undefined;
342
+ list(): AgentCore[];
343
+ clear(): void;
344
+ }
345
+ /** agent handle 工厂函数(由 `@faapi/agent` 插件注册) */
346
+ type AgentHandleFactory = (ctx: FaapiContext) => unknown;
347
+ interface AgentHandleStore {
348
+ /** 注册工厂(null 清理);二次注册覆盖 */
349
+ register(factory: AgentHandleFactory | null): void;
350
+ /** 工厂已注册时返回 AgentHandle 实例,未注册返回 undefined */
351
+ get(ctx: FaapiContext): unknown;
352
+ clear(): void;
353
+ }
354
+ /** task 客户端工厂函数(由 createAppBase 注册,返回 TaskClient 门面) */
355
+ type TaskHandleFactory = (ctx: FaapiContext) => unknown;
356
+ interface TaskHandleStore {
357
+ /** 注册工厂(null 清理);二次注册覆盖 */
358
+ register(factory: TaskHandleFactory | null): void;
359
+ /** 工厂已注册时返回 TaskClient,未注册返回 undefined */
360
+ get(ctx: FaapiContext): unknown;
361
+ clear(): void;
362
+ }
363
+ /** 一个 app 实例持有的全套注册表 */
364
+ interface AppRegistries {
365
+ tool: ToolRegistry;
366
+ agent: AgentRegistry;
367
+ skill: SkillRegistry;
368
+ task: TaskRegistry;
369
+ agentHandle: AgentHandleStore;
370
+ taskHandle: TaskHandleStore;
371
+ }
372
+ /**
373
+ * 任务侧注册表只读视图(AppRegistries 的查询投影)
374
+ *
375
+ * 注入任务执行上下文(`TaskContext.registries`)——任务执行侧不在 handler 请求链路上
376
+ * (拿不到 `FaapiContext.registries`),`getApp()` 在隔离 worker 线程内也不可用
377
+ * (globalThis 独立)。刻意不暴露 `hydrate`/`clear` 写接口:任务不是注册表的所有者。
378
+ */
379
+ interface TaskRegistriesView {
380
+ agent: Pick<AgentRegistry, 'getAgent' | 'getAgentEntry' | 'listAgents' | 'asTool' | 'resolveAgentTools' | 'resolveSubAgents'>;
381
+ tool: Pick<ToolRegistry, 'get' | 'list'>;
382
+ skill: Pick<SkillRegistry, 'get' | 'list'>;
383
+ }
384
+ /** 从 AppRegistries 构造任务侧只读视图(活引用——进程内执行路径直接使用) */
385
+ declare function createTaskRegistriesView(registries: AppRegistries): TaskRegistriesView;
386
+ /** 创建一套 app 级注册表(`createAppBase` 每次调用创建独立实例) */
387
+ declare function createAppRegistries(): AppRegistries;
388
+
148
389
  /**
149
390
  * 任务元信息(业务方在 task.ts 中 `export const task = {...}` 声明)
150
391
  *
@@ -214,6 +455,18 @@ interface TaskJob {
214
455
  /** 计划执行时间戳(重试/延迟任务与 createdAt 不同) */
215
456
  runAt?: number;
216
457
  }
458
+ /**
459
+ * 隔离执行跨线程传递的注册表快照(纯数据,结构化克隆安全)
460
+ *
461
+ * 注册表对象含函数闭包不可 postMessage;元数据本身是纯数据——语义层从
462
+ * `TaskRegistriesView` 生成快照,worker wrapper 内重建只读视图。
463
+ */
464
+ interface TaskRegistriesSnapshot {
465
+ /** agent 完整元数据(含 filePath/hasRun,非仅 LLM 可见字段) */
466
+ agents: AgentMetadata[];
467
+ tools: ToolMetadata[];
468
+ skills: AgentCore[];
469
+ }
217
470
  /**
218
471
  * 传给任务 run 函数的第二参数
219
472
  */
@@ -227,6 +480,14 @@ interface TaskContext {
227
480
  name: string;
228
481
  attempt: number;
229
482
  };
483
+ /**
484
+ * app 注册表只读视图(agent/tool/skill 元数据查询,不含 hydrate/clear 写接口)
485
+ *
486
+ * 进程内执行为活引用;隔离执行为派发时刻的快照视图(worker 内重建)——
487
+ * 执行中途的 reload/DB skill 变更不影响当次执行。
488
+ * 任务内组装 agent 用 `registries.agent.getAgentEntry(name)`(含 filePath/hasRun)。
489
+ */
490
+ registries: TaskRegistriesView;
230
491
  }
231
492
  /**
232
493
  * 任务模块形态(task.ts 编译产物中与执行相关的导出)
@@ -299,6 +560,11 @@ interface TaskQueueDeps {
299
560
  rootDir: string;
300
561
  /** faapi.config.ts 全量配置,透传给 run 的 TaskContext.config */
301
562
  config?: unknown;
563
+ /**
564
+ * app 注册表只读视图(`createTaskRegistriesView`)——注入两条执行路径的
565
+ * TaskContext.registries;缺省为空视图(直接构造队列的测试/嵌入场景)
566
+ */
567
+ registries?: TaskRegistriesView;
302
568
  /**
303
569
  * 队列驱动(必填):`loadTaskDriver` 解析结果(pgboss/bullmq 子包驱动)
304
570
  * 或自定义 TaskDriver 实例;无任务清单时由 createAppBase 传入 idleTaskDriver
@@ -409,228 +675,6 @@ interface SseWriter {
409
675
  readonly response: Response;
410
676
  }
411
677
 
412
- /**
413
- * Tool 的 LLM 可见核心字段
414
- *
415
- * 描述"tool 是什么"——LLM 真正需要消费的字段(发往 LLM 的 tool 定义只含
416
- * `name` / `description` / input schema),**不含**代码本体加载细节
417
- * (`filePath` / `functionName` / `inputTypeName`)。
418
- *
419
- * 与 [AgentCore](./extractAgentMetadata.md) 对称——LLM-facing 字段与代码加载
420
- * 细节分离,便于未来扩展(如 DB-driven tool 只实现 `ToolCore` 即可)。
421
- *
422
- * `toolRegistry` 查询入口 / `@faapi/agent` 子包的 `buildToolDefinitions`
423
- * 都消费 `ToolCore` 字段组装 LLM tool 列表。
424
- */
425
- interface ToolCore {
426
- /** tool 名(`@tool` JSDoc 覆盖值 或 路径推导值) */
427
- name: string;
428
- /** JSDoc 描述(tool 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
429
- description?: string;
430
- }
431
- /**
432
- * Tool 完整元数据(文件型 tool)
433
- *
434
- * 继承 [ToolCore](./extractToolMetadata.md) 的 LLM 字段,额外扩展**代码本体加载细节**:
435
- * - `filePath` — `loadToolModule` 加载 `handler.js` 产物定位函数用
436
- * - `functionName` — 源码导出函数名(不受 `@tool` 覆盖影响,AST 定位 + 运行时 resolveExport 用)
437
- * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md)
438
- * 生成 zod schema;运行时 `resolveToolSchema` 据此定位 `zod.js`)
439
- *
440
- * 由 [extractToolMetadata](./extractToolMetadata.md) 产出,合并路径推导字段
441
- * (来自 [scanTools](../tools/scanTools.md) 的 `ToolManifest`)与 AST 提取字段
442
- * (JSDoc 描述、`@tool` 覆盖名、第一个参数 interface 名)。
443
- *
444
- * 字段来源:
445
- * - `name` — `@tool` JSDoc 覆盖值,或 `pathMeta.name`(路径推导)
446
- * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
447
- * - `filePath` / `functionName` — 由 `pathMeta` 透传
448
- * - `inputTypeName` — 第一个参数的 TypeReference 名(供 [extractTypeInfo](./extractHandlerTypes.md) 生成 zod schema)
449
- */
450
- interface ToolMetadata extends ToolCore {
451
- /** 第一个参数的 interface/type 名(用于生成 zod schema),
452
- * 无参数/参数无类型标注/参数为内联类型字面量时为 `undefined` */
453
- inputTypeName?: string;
454
- /** 源码相对路径(从 `pathMeta` 透传) */
455
- filePath: string;
456
- /** 源码中的导出函数名(从 `pathMeta` 透传,AST 定位用,不受 `@tool` 覆盖影响) */
457
- functionName: string;
458
- }
459
- /**
460
- * 路径推导的 tool 元数据(由 [scanTools](../tools/scanTools.ts) 计算)
461
- *
462
- * 透传到 [ToolMetadata](./extractToolMetadata.ts) 输出,与 AST 提取字段合并。
463
- */
464
- interface ToolPathMeta {
465
- /** 路径推导的 tool 名(如 `weather.getWeather`) */
466
- name: string;
467
- /** 源码相对路径(如 `src/tools/weather/handler.ts`) */
468
- filePath: string;
469
- }
470
-
471
- /**
472
- * Agent 的 LLM 可见核心字段
473
- *
474
- * 描述"agent 是什么"——LLM 真正需要消费的字段,**不含**代码本体加载细节
475
- * (filePath / hasRun)。文件型 agent 与 DB-driven skill 都实现此接口。
476
- *
477
- * - 文件型 agent:由 [AgentMetadata](./extractAgentMetadata.md) 继承扩展,
478
- * 额外含 `filePath` / `hasRun`(代码本体加载用)
479
- * - DB-driven skill:业务方 plugin 从 DB 字段映射到本接口即可,无需填占位值
480
- * (skill 无源文件,不走 `loadAgentModule`,自然不读 filePath / hasRun)
481
- *
482
- * `@faapi/agent` 子包的 `Agent` 类、`agentRegistry` 查询入口、`asTool` 包装
483
- * 都消费 `AgentCore`,实现"agent 与 skill 走同一运行时链路"。
484
- */
485
- interface AgentCore {
486
- /** agent 名(`@agent` JSDoc 覆盖值 或 目录推导值) */
487
- name: string;
488
- /** JSDoc 描述(agent 描述,对 LLM 可见),无 JSDoc 或 JSDoc 无自由文本时为 `undefined` */
489
- description?: string;
490
- /** 系统提示词(config 块字面量提取);文件型 agent 必填(构建期校验),DB skill 由业务方自治 */
491
- systemPrompt?: string;
492
- /** agent 显式声明可用的 tool 引用列表(config 块字面量提取),未声明时为 `undefined`;声明了但含无法静态求值的元素在构建期抛错 */
493
- tools?: string[];
494
- /** 可调用的其他 agent 名列表(config 块字面量提取),未声明时为 `undefined`;声明了但含无法静态求值的元素在构建期抛错 */
495
- agents?: string[];
496
- /** LLM 模型名(config 块字面量提取),未声明时为 `undefined`;声明了但非字面量在构建期抛错 */
497
- model?: string;
498
- /** 最大对话轮数(config 块字面量提取),未声明时为 `undefined`;声明了但非数字字面量在构建期抛错 */
499
- maxTurns?: number;
500
- }
501
- /**
502
- * Agent 完整元数据(文件型 agent)
503
- *
504
- * 继承 [AgentCore](./extractAgentMetadata.md) 的 LLM 字段,额外扩展**代码本体加载细节**:
505
- * - `filePath` — `loadAgentModule` 加载 `handler.js` 产物提取 `run` 函数用
506
- * - `hasRun` — 是否导出 `run` 函数(`Agent.executeSubAgent` 据此决定走自定义 run
507
- * 还是默认 reactLoop)
508
- *
509
- * DB-driven skill 不实现此接口(无源文件,无需加载),只实现 `AgentCore`。
510
- *
511
- * 由 [extractAgentMetadata](./extractAgentMetadata.md) 产出,合并路径推导字段
512
- * (来自 [scanAgents](../agents/scanAgents.md) 的 `AgentManifest`)与 AST 提取字段
513
- * (JSDoc 描述、`@agent` 覆盖名、config 块字段)。
514
- *
515
- * 字段来源:
516
- * - `name` — `@agent` JSDoc 覆盖值,或 `pathMeta.name`(目录推导)
517
- * - `filePath` / `hasRun` — 由 `pathMeta` 透传
518
- * - `description` — JSDoc 注释块自由文本(对 LLM 可见)
519
- * - `systemPrompt` / `tools` / `agents` / `model` / `maxTurns` — config 块字面量提取
520
- */
521
- interface AgentMetadata extends AgentCore {
522
- /** 源码相对路径(从 `pathMeta` 透传),`loadAgentModule` 据此加载 `handler.js` 提取 `run` */
523
- filePath: string;
524
- /** 是否导出 `run` 函数(从 `pathMeta` 透传),`Agent.executeSubAgent` 据此选择自定义 run / 默认 reactLoop */
525
- hasRun: boolean;
526
- }
527
- /**
528
- * 路径推导的 agent 元数据(由 [scanAgents](../agents/scanAgents.ts) 计算)
529
- *
530
- * 透传到 [AgentMetadata](./extractAgentMetadata.ts) 输出,与 AST 提取字段合并。
531
- * 与 [ToolPathMeta](./extractToolMetadata.md) 对称。
532
- */
533
- interface AgentPathMeta {
534
- /** 目录推导的 agent 名(如 `researcher`) */
535
- name: string;
536
- /** 源码相对路径(如 `src/agents/researcher/handler.ts`) */
537
- filePath: string;
538
- /** 是否导出 `run` 函数(scanAgents 正则检测) */
539
- hasRun: boolean;
540
- }
541
-
542
- /**
543
- * app 级注册表(方案 A:注册表实例化)
544
- *
545
- * 每个应用实例(`createAppBase`)持有一套独立的注册表,随 app 创建、随
546
- * `app.close()` 销毁——多 app 同进程(测试 / 嵌入 / 多租户)互不串台。
547
- * 此前注册表是模块级全局单例 + hydrate 整体替换语义,后创建的 app 会覆盖
548
- * 先创建的 app 的清单,任一 app close 会清空全部(详见各模块 .md)。
549
- *
550
- * 原四个模块(toolRegistry / agentRegistry / skillRegistry / agentHandle)
551
- * 保留同名全局函数作为**默认实例的便捷访问器**(供编程式直调 / 单元测试 /
552
- * 无 app 上下文的场景),内部全部路由到本模块的 `defaultRegistries`。
553
- * 框架自身链路(hydrate / 请求注入 / `@faapi/agent` 插件 / lifecycle 钩子)
554
- * 一律走 app 实例,不再读写全局默认实例。
555
- */
556
- interface ToolRegistry {
557
- /** 全量替换(tool 清单来自编译期产物,reload 时整体重新生成) */
558
- hydrate(tools: ToolMetadata[]): void;
559
- /** 按全名查找(如 `weather.getWeather`) */
560
- get(name: string): ToolMetadata | undefined;
561
- /** 所有已注册 tool(副本) */
562
- list(): ToolMetadata[];
563
- clear(): void;
564
- }
565
- /** agent 包装为 tool 的描述符(reactLoop 据此识别 sub-agent 递归) */
566
- interface AgentToolDescriptor {
567
- kind: 'agent';
568
- name: string;
569
- agentName: string;
570
- description?: string;
571
- metadata: AgentCore;
572
- }
573
- interface AgentRegistry {
574
- /** 全量替换(与 hydrateToolRegistry 同构) */
575
- hydrate(agents: AgentMetadata[]): void;
576
- /** LLM 可见元数据(AgentCore) */
577
- getAgent(name: string): AgentCore | undefined;
578
- /** 完整元数据(含 filePath / hasRun,供加载 handler.js 执行 run) */
579
- getAgentEntry(name: string): AgentMetadata | undefined;
580
- /** 所有已注册 agent 的 LLM 可见元数据(副本) */
581
- listAgents(): AgentCore[];
582
- /** 包装为 tool 描述符 */
583
- asTool(name: string): AgentToolDescriptor | undefined;
584
- /**
585
- * 解析 agent 显式声明的 tool 集合。
586
- * 跨注册表依赖:经由构造时绑定的 tool 注册表查找(同属一套 AppRegistries,
587
- * 由 createAppBase 在同一启动阶段水合)
588
- */
589
- resolveAgentTools(name: string): ToolMetadata[];
590
- /** 解析 agent 可调用的子 agent 集合 */
591
- resolveSubAgents(name: string): AgentCore[];
592
- clear(): void;
593
- }
594
- interface SkillRegistry {
595
- /** 全量替换(DB change stream 场景也可用 upsert 增量) */
596
- hydrate(skills: AgentCore[]): void;
597
- /** 增量注册 / 覆盖(业务方监听 DB 单条变更) */
598
- upsert(skill: AgentCore): void;
599
- remove(name: string): void;
600
- get(name: string): AgentCore | undefined;
601
- list(): AgentCore[];
602
- clear(): void;
603
- }
604
- /** agent handle 工厂函数(由 `@faapi/agent` 插件注册) */
605
- type AgentHandleFactory = (ctx: FaapiContext) => unknown;
606
- interface AgentHandleStore {
607
- /** 注册工厂(null 清理);二次注册覆盖 */
608
- register(factory: AgentHandleFactory | null): void;
609
- /** 工厂已注册时返回 AgentHandle 实例,未注册返回 undefined */
610
- get(ctx: FaapiContext): unknown;
611
- clear(): void;
612
- }
613
- /** task 客户端工厂函数(由 createAppBase 注册,返回 TaskClient 门面) */
614
- type TaskHandleFactory = (ctx: FaapiContext) => unknown;
615
- interface TaskHandleStore {
616
- /** 注册工厂(null 清理);二次注册覆盖 */
617
- register(factory: TaskHandleFactory | null): void;
618
- /** 工厂已注册时返回 TaskClient,未注册返回 undefined */
619
- get(ctx: FaapiContext): unknown;
620
- clear(): void;
621
- }
622
- /** 一个 app 实例持有的全套注册表 */
623
- interface AppRegistries {
624
- tool: ToolRegistry;
625
- agent: AgentRegistry;
626
- skill: SkillRegistry;
627
- task: TaskRegistry;
628
- agentHandle: AgentHandleStore;
629
- taskHandle: TaskHandleStore;
630
- }
631
- /** 创建一套 app 级注册表(`createAppBase` 每次调用创建独立实例) */
632
- declare function createAppRegistries(): AppRegistries;
633
-
634
678
  interface CookieOptions {
635
679
  domain?: string;
636
680
  path?: string;
@@ -1060,4 +1104,4 @@ interface RouteInfo {
1060
1104
  output: RouteOutputSchema | null;
1061
1105
  }
1062
1106
 
1063
- export { type AppRegistries as A, type TaskDriverJob as B, type CorsOptions as C, type TaskDriverProcess as D, type TaskDriverRecord as E, type FaapiContext as F, type TaskFailedInfo as G, type HelmetOptions as H, type InjectorMap as I, type TaskJob as J, type TaskJobStatus as K, type LoggerOptions as L, type TaskMetadata as M, type TaskModule as N, type ToolCore as O, type ToolPathMeta as P, type ToolRegistry as Q, type RouteManifest as R, type SkillRegistry as S, type TaskClient as T, cors as U, createAppRegistries as V, type WsRouteManifest as W, createTaskRegistry as X, helmet as Y, logger as Z, type FaapiMiddleware as a, type TaskFailedHandler as b, type TaskQueueDeps as c, type TaskQueue as d, type TaskDriver as e, type TaskRegistry as f, type TaskManifest as g, type ToolMetadata as h, type AgentCore as i, type AgentMetadata as j, type AgentHandleFactory as k, type AgentHandleStore as l, type AgentPathMeta as m, type AgentRegistry as n, type AgentToolDescriptor as o, type FaapiContextConfig as p, type FaapiTaskMeta as q, type FailOptions as r, type Injector as s, type RouteInfo as t, type RouteInputSchema as u, type RouteOutputSchema as v, type RouteParamSchema as w, type SseEvent as x, type SseWriter as y, type TaskContext as z };
1107
+ export { helmet as $, type AppRegistries as A, type TaskDriverJob as B, type CorsOptions as C, type TaskDriverProcess as D, type TaskDriverRecord as E, type FaapiContext as F, type TaskFailedInfo as G, type HelmetOptions as H, type InjectorMap as I, type TaskJob as J, type TaskJobStatus as K, type LoggerOptions as L, type TaskMetadata as M, type TaskModule as N, type TaskRegistriesSnapshot as O, type TaskRegistriesView as P, type ToolCore as Q, type RouteManifest as R, type SkillRegistry as S, type TaskClient as T, type ToolPathMeta as U, type ToolRegistry as V, type WsRouteManifest as W, cors as X, createAppRegistries as Y, createTaskRegistriesView as Z, createTaskRegistry as _, type FaapiMiddleware as a, logger as a0, type TaskFailedHandler as b, type TaskQueueDeps as c, type TaskQueue as d, type TaskDriver as e, type TaskRegistry as f, type TaskManifest as g, type ToolMetadata as h, type AgentCore as i, type AgentMetadata as j, type AgentHandleFactory as k, type AgentHandleStore as l, type AgentPathMeta as m, type AgentRegistry as n, type AgentToolDescriptor as o, type FaapiContextConfig as p, type FaapiTaskMeta as q, type FailOptions as r, type Injector as s, type RouteInfo as t, type RouteInputSchema as u, type RouteOutputSchema as v, type RouteParamSchema as w, type SseEvent as x, type SseWriter as y, type TaskContext as z };
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FaapiContext, a as FaapiMiddleware, I as InjectorMap, R as RouteManifest, W as WsRouteManifest, C as CorsOptions, H as HelmetOptions, L as LoggerOptions } from './routeTypes-_17rXzal.js';
1
+ import { F as FaapiContext, a as FaapiMiddleware, I as InjectorMap, R as RouteManifest, W as WsRouteManifest, C as CorsOptions, H as HelmetOptions, L as LoggerOptions } from './routeTypes-q9OXB--o.js';
2
2
  import { Server } from 'node:http';
3
3
  import { WebSocket } from 'ws';
4
4