@faapi/agent 0.0.0-canary.0 → 3.0.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.
@@ -0,0 +1,602 @@
1
+ import { LlmConfig, AgentMetadata, ToolMetadata, ToolModule, AgentModule, AgentToolDescriptor, FaapiPlugin } from '@faapi/faapi';
2
+
3
+ /**
4
+ * LLM Provider 错误
5
+ *
6
+ * 含 HTTP 状态码(网络错误为 `undefined`)和响应体摘要,
7
+ * 业务方可通过 `instanceof LLMProviderError` 区分 LLM 错误与其他错误。
8
+ */
9
+ declare class LLMProviderError extends Error {
10
+ /** HTTP 状态码(网络错误 / JSON 解析错误为 undefined) */
11
+ readonly status?: number;
12
+ /** 响应体摘要(前 500 字符,便于诊断) */
13
+ readonly body?: string;
14
+ constructor(message: string, options?: {
15
+ status?: number;
16
+ body?: string;
17
+ cause?: unknown;
18
+ });
19
+ }
20
+ /**
21
+ * 创建 OpenAI 兼容 LLMProvider
22
+ *
23
+ * @param config LLM 提供方配置(apiKey / model / baseURL / 透传字段)
24
+ * @returns LLMProvider 实例(含 complete + stream 方法)
25
+ */
26
+ declare function createOpenAIProvider(config: LlmConfig): LLMProvider;
27
+
28
+ /**
29
+ * LLM Provider 抽象层
30
+ *
31
+ * 统一 `complete` / `stream` 接口,屏蔽 OpenAI / Anthropic 等 LLM 服务差异。
32
+ * [reactLoop](./reactLoop.md) 与 [Agent 类](./agent.md) 通过此接口调用 LLM,
33
+ * 与具体 provider 解耦。
34
+ *
35
+ * 详见 [provider.md](./provider.md)。
36
+ */
37
+ /**
38
+ * 对话消息
39
+ *
40
+ * 四种 role 与 OpenAI chat completions 一致:
41
+ * - `system` —— 系统提示词(agent 的 systemPrompt)
42
+ * - `user` —— 用户输入
43
+ * - `assistant` —— LLM 回复(可能含 toolCalls)
44
+ * - `tool` —— tool 执行结果(需带 toolCallId 标识对应哪个 tool_call)
45
+ */
46
+ interface LLMMessage {
47
+ role: 'system' | 'user' | 'assistant' | 'tool';
48
+ /** 消息内容(assistant 角色 + tool_calls 时可能为空字符串) */
49
+ content: string;
50
+ /** role='tool' 时:对应的 tool_call ID(用于 LLM 关联 tool 结果) */
51
+ toolCallId?: string;
52
+ /** role='assistant' 时:LLM 请求的 tool 调用(reactLoop 据此执行 tool) */
53
+ toolCalls?: LLMToolCall[];
54
+ }
55
+ /**
56
+ * LLM 请求的 tool 调用
57
+ *
58
+ * 由 LLM 在 assistant 消息中返回。`arguments` 已 JSON.parse,
59
+ * reactLoop 直接传给 tool 函数。
60
+ */
61
+ interface LLMToolCall {
62
+ /** tool call ID(provider 分配,用于匹配 tool 结果) */
63
+ id: string;
64
+ /** tool 名(匹配 LLMToolDefinition.name) */
65
+ name: string;
66
+ /** tool 参数(已 JSON.parse 的对象) */
67
+ arguments: Record<string, unknown>;
68
+ }
69
+ /**
70
+ * Tool 定义
71
+ *
72
+ * 由 [reactLoop](./reactLoop.md) 从 [toolRegistry](../../faapi/src/injection/toolRegistry.md)
73
+ * + [agentRegistry.resolveSubAgents](../../faapi/src/injection/agentRegistry.md) 组装:
74
+ * - 常规 tool:`input` 来自 AST 提取的 zod schema(JSON Schema 形式)
75
+ * - agent-as-tool:`input` 为自由 schema(agent 参数开放)
76
+ */
77
+ interface LLMToolDefinition {
78
+ /** tool 名(如 `weather.getWeather` 或 `agent.researcher`) */
79
+ name: string;
80
+ /** tool 描述(对 LLM 可见,引导 LLM 选择调用) */
81
+ description?: string;
82
+ /** JSON Schema 对象(描述 tool 参数结构) */
83
+ input: Record<string, unknown>;
84
+ }
85
+ /**
86
+ * complete / stream 的入参
87
+ *
88
+ * `model` / `temperature` / `maxTokens` 优先级高于 [LlmConfig](../../faapi/src/config/configTypes.md)
89
+ * (agent 自身 `config.model` 覆盖全局默认)。
90
+ */
91
+ interface LLMCompleteRequest {
92
+ /** 对话消息(含历史 + 当前轮) */
93
+ messages: LLMMessage[];
94
+ /** 可用 tool 列表(未提供时 LLM 不会发起 tool_call) */
95
+ tools?: LLMToolDefinition[];
96
+ /** 覆盖 LlmConfig.model(agent 自身配置优先) */
97
+ model?: string;
98
+ /** 采样温度(0~2) */
99
+ temperature?: number;
100
+ /** 最大生成 token 数 */
101
+ maxTokens?: number;
102
+ }
103
+ /**
104
+ * LLM 响应的停止原因
105
+ *
106
+ * - `stop` —— LLM 主动结束(自然结束 / 遇到 stop 序列)
107
+ * - `tool_calls` —— LLM 请求调用 tool(reactLoop 据此进入下一轮)
108
+ * - `length` —— 达到 max_tokens 上限
109
+ * - `content_filter` —— 内容过滤触发
110
+ * - `other` —— 其他原因(未识别的 finish_reason)
111
+ */
112
+ type LLMStopReason = 'stop' | 'tool_calls' | 'length' | 'content_filter' | 'other';
113
+ /**
114
+ * complete 的返回
115
+ *
116
+ * `message.toolCalls` 不为空时 stopReason 应为 `'tool_calls'`。
117
+ */
118
+ interface LLMResponse {
119
+ /** assistant 消息(含 content + 可选 toolCalls) */
120
+ message: LLMMessage;
121
+ /** 停止原因(reactLoop 据此判断是否进入下一轮) */
122
+ stopReason: LLMStopReason;
123
+ /** token 用量(部分 provider 不返回) */
124
+ usage?: LLMUsage;
125
+ }
126
+ /**
127
+ * Token 用量
128
+ */
129
+ interface LLMUsage {
130
+ promptTokens: number;
131
+ completionTokens: number;
132
+ totalTokens: number;
133
+ }
134
+ /**
135
+ * stream 的单个 chunk
136
+ *
137
+ * - 内容流:`deltaContent` 为增量 token
138
+ * - tool 调用:累积完成后在最终 chunk 一并 emit `toolCalls`
139
+ * - 结束:最终 chunk 含 `finishReason` + 可选 `usage`
140
+ */
141
+ interface LLMStreamChunk {
142
+ /** 增量内容(streaming token) */
143
+ deltaContent?: string;
144
+ /** 累积完成的 tool 调用(在最终 chunk 出现) */
145
+ toolCalls?: LLMToolCall[];
146
+ /** 结束原因(只在最终 chunk 出现) */
147
+ finishReason?: LLMStopReason;
148
+ /** token 用量(部分 provider 在最终 chunk 提供) */
149
+ usage?: LLMUsage;
150
+ }
151
+ /**
152
+ * LLM Provider 抽象接口
153
+ *
154
+ * 实现方:
155
+ * - [createOpenAIProvider](./providers/openai.md) —— OpenAI 兼容 API
156
+ *
157
+ * 消费方:
158
+ * - [reactLoop](./reactLoop.md) Phase 3.3 —— 调 complete / stream 执行 ReAct 循环
159
+ * - [Agent 类](./agent.md) Phase 3.4 —— 构造时持有 provider 实例
160
+ */
161
+ interface LLMProvider {
162
+ /** 非流式:阻塞到 LLM 返回完整响应 */
163
+ complete(request: LLMCompleteRequest): Promise<LLMResponse>;
164
+ /** 流式:异步迭代 chunk(增量 token + tool call + 结束) */
165
+ stream(request: LLMCompleteRequest): AsyncIterable<LLMStreamChunk>;
166
+ }
167
+
168
+ /**
169
+ * 按 `config.provider` 路由到对应的 LLM 适配器
170
+ *
171
+ * Phase 3.2 仅支持 `'openai'`,其他值抛错不静默降级(参考 AGENTS.md §6.3)。
172
+ *
173
+ * @param config LLM 提供方配置(来自 faapi.config.ts 的 `agent.llm`)
174
+ * @returns LLMProvider 实例
175
+ * @throws {Error} 当 `config.provider` 不是已支持的值
176
+ */
177
+ declare function createProvider(config: LlmConfig): LLMProvider;
178
+
179
+ /**
180
+ * ReAct(Reasoning + Acting)循环引擎
181
+ *
182
+ * 反复调 LLM、执行 tool、把结果回传 LLM,直到 LLM 给出最终回答或达到 `maxTurns` 上限。
183
+ *
184
+ * 详见 [reactLoop.md](./reactLoop.md)。
185
+ */
186
+ /**
187
+ * Tool 执行函数
188
+ *
189
+ * 由 [Agent 类](./agent.md)提供——reactLoop 不关心 tool 如何被找到和执行。
190
+ * Agent 类的 `executeTool` 实现:
191
+ * - 常规 tool → `loadToolModule` 加载 handler 并调用
192
+ * - agent-as-tool(`agent.` 前缀)→ 递归调子 agent 的 reactLoop(含 `maxAgentDepth` 防护)
193
+ *
194
+ * 返回值可以是任意类型——非 string 会被 JSON.stringify 后回传 LLM。
195
+ */
196
+ type ToolExecutor = (name: string, args: Record<string, unknown>) => Promise<unknown>;
197
+ /**
198
+ * reactLoop 配置
199
+ *
200
+ * 由 [Agent 类](./agent.md)组装并传入。
201
+ */
202
+ interface ReactLoopConfig {
203
+ /** LLM provider 实例(由 [createProvider](./provider.md) 创建) */
204
+ provider: LLMProvider;
205
+ /** 系统提示词(来自 agent metadata 的 `systemPrompt`) */
206
+ systemPrompt?: string;
207
+ /** 可用 tool 列表(由 `resolveAgentTools` + `resolveSubAgents().map(asTool)` 组装) */
208
+ tools?: LLMToolDefinition[];
209
+ /** tool 执行函数(由 Agent 类提供,路由到常规 tool 或子 agent) */
210
+ executeTool: ToolExecutor;
211
+ /** 最大对话轮数(默认 10,来自 [AgentConfig](../../faapi/src/config/configTypes.md).maxTurns) */
212
+ maxTurns?: number;
213
+ /** 覆盖 LLM 模型名(来自 agent metadata 的 `model`) */
214
+ model?: string;
215
+ /** 采样温度 */
216
+ temperature?: number;
217
+ /** 最大生成 token 数 */
218
+ maxTokens?: number;
219
+ }
220
+ /**
221
+ * 非流式循环结果
222
+ */
223
+ interface ReactLoopResult {
224
+ /** 最终 assistant 消息内容 */
225
+ content: string;
226
+ /** 完整对话历史(system + user + assistant + tool 消息) */
227
+ messages: LLMMessage[];
228
+ /** 使用的轮数(含最终轮) */
229
+ turns: number;
230
+ /** 最终轮的停止原因 */
231
+ stopReason: LLMStopReason;
232
+ /** 累计 token 用量(多轮累加,provider 不返回时为 `undefined`) */
233
+ usage?: LLMUsage;
234
+ }
235
+ /**
236
+ * 流式循环的单个 chunk
237
+ *
238
+ * 每个 chunk 至多含一个字段:
239
+ * - `deltaContent` — LLM 增量 token(多次 yield)
240
+ * - `toolCall` — tool 开始执行
241
+ * - `toolResult` — tool 执行完成
242
+ * - `done` — 循环结束(只 yield 一次)
243
+ */
244
+ interface ReactLoopStreamChunk {
245
+ /** LLM 增量 token */
246
+ deltaContent?: string;
247
+ /** tool 开始执行(LLM 请求调用 tool) */
248
+ toolCall?: {
249
+ name: string;
250
+ arguments: Record<string, unknown>;
251
+ };
252
+ /** tool 执行完成(含结果) */
253
+ toolResult?: {
254
+ name: string;
255
+ result: string;
256
+ };
257
+ /** 循环结束 */
258
+ done?: {
259
+ content: string;
260
+ turns: number;
261
+ stopReason: LLMStopReason;
262
+ usage?: LLMUsage;
263
+ };
264
+ }
265
+ /**
266
+ * reactLoop 系统级错误
267
+ *
268
+ * 目前仅用于 `maxTurns` 超限。tool 执行错误不抛此类型——它们被 catch 后回传 LLM。
269
+ */
270
+ declare class ReactLoopError extends Error {
271
+ /** 配置的 maxTurns 值 */
272
+ readonly maxTurns: number;
273
+ constructor(message: string, maxTurns: number);
274
+ }
275
+ /**
276
+ * 执行 ReAct 循环(非流式)
277
+ *
278
+ * 反复调 `provider.complete()` → 执行 tool → 回传结果,直到 LLM 返回 `stop`(或其他非 `tool_calls` 原因)或超出 `maxTurns`。
279
+ *
280
+ * @param input 用户输入
281
+ * @param config 循环配置
282
+ * @returns 最终结果(content + messages + turns + stopReason + usage)
283
+ * @throws {ReactLoopError} 超出 maxTurns
284
+ * @throws {Error} provider.complete 抛错时立即传播
285
+ */
286
+ declare function reactLoop(input: string, config: ReactLoopConfig): Promise<ReactLoopResult>;
287
+ /**
288
+ * 执行 ReAct 循环(流式)
289
+ *
290
+ * 使用 `provider.stream()` 异步迭代 chunks,yield `deltaContent` + `toolCall` + `toolResult` + `done`。
291
+ *
292
+ * @param input 用户输入
293
+ * @param config 循环配置
294
+ * @yields {ReactLoopStreamChunk} 流式 chunk
295
+ * @throws {ReactLoopError} 超出 maxTurns
296
+ * @throws {Error} provider.stream 抛错时立即传播
297
+ */
298
+ declare function reactLoopStream(input: string, config: ReactLoopConfig): AsyncIterable<ReactLoopStreamChunk>;
299
+
300
+ /**
301
+ * 全局 agent 配置覆盖
302
+ *
303
+ * 来自 faapi.config.ts 的 `agent` 块,提供全局默认值。
304
+ * agent 自身 `config.maxTurns` / `config.model` 优先于全局配置。
305
+ */
306
+ interface AgentRuntimeConfig {
307
+ /** 默认最大对话轮数(agent 自身 maxTurns 优先) */
308
+ maxTurns?: number;
309
+ /** agent 调用 agent 的最大递归深度(默认 3) */
310
+ maxAgentDepth?: number;
311
+ /** 默认 tool 列表,所有 agent 都可用 */
312
+ defaultTools?: string[];
313
+ }
314
+ /**
315
+ * tool schema 解析结果
316
+ *
317
+ * 由 Phase 3.5 的注入器实现,提供 JSON Schema(给 LLM)和校验函数(给执行前校验)。
318
+ * - `jsonSchema` —— 发给 LLM 作为 tool 参数描述
319
+ * - `validate` —— 执行前校验 LLM 返回的参数,失败时返回 `{ error }` 回传 LLM 重试
320
+ */
321
+ interface ToolSchemaResolution {
322
+ /** tool 参数的 JSON Schema(发给 LLM) */
323
+ jsonSchema: Record<string, unknown>;
324
+ /** 执行前校验函数(成功返回 coerce 后的 value,失败返回 error) */
325
+ validate: (input: Record<string, unknown>) => {
326
+ ok: true;
327
+ value: Record<string, unknown>;
328
+ } | {
329
+ ok: false;
330
+ error: string;
331
+ };
332
+ }
333
+ /**
334
+ * Agent 运行时依赖(依赖注入)
335
+ *
336
+ * Agent 类**不直接 import** faapi 核心的注册表/加载器,而是通过此接口接收访问器函数。
337
+ * 原因:
338
+ * - **可测试**——测试传 mock 访问器,无需启动真实注册表
339
+ * - **解耦**——Agent 类不依赖核心运行时模块
340
+ * - **phase 边界**——Phase 3.4 实现 Agent 类逻辑,Phase 3.5 注入真实访问器
341
+ *
342
+ * 访问器签名与 faapi 核心对称(见 [agent.md](./agent.md) 依赖注入章节)。
343
+ */
344
+ interface AgentDeps {
345
+ /** LLM provider 实例 */
346
+ provider: LLMProvider;
347
+ /** 当前 agent 名 */
348
+ agentName: string;
349
+ /** 项目根目录(Phase 3.5 接线时用于加载器) */
350
+ rootDir: string;
351
+ /** 全局 agent 配置覆盖 */
352
+ config?: AgentRuntimeConfig;
353
+ /** 查 agent 元数据(对应 agentRegistry.getAgent) */
354
+ getAgent: (name: string) => AgentMetadata | undefined;
355
+ /** 查 tool 元数据(对应 toolRegistry.getTool) */
356
+ getTool: (name: string) => ToolMetadata | undefined;
357
+ /** 解析 agent 可用常规 tool(对应 agentRegistry.resolveAgentTools) */
358
+ resolveAgentTools: (name: string) => ToolMetadata[];
359
+ /** 解析 agent 可调用 sub-agent 列表(对应 agentRegistry.resolveSubAgents) */
360
+ resolveSubAgents: (name: string) => AgentMetadata[];
361
+ /** 动态 import tool handler(对应 loadToolModule) */
362
+ loadToolModule: (filePath: string, functionName: string) => Promise<ToolModule>;
363
+ /** 动态 import agent handler(对应 loadAgentModule) */
364
+ loadAgentModule: (filePath: string, hasConfig: boolean, hasRun: boolean) => Promise<AgentModule>;
365
+ /** tool input 的 schema 解析(Phase 3.5 实现,可选) */
366
+ resolveToolSchema?: (tool: ToolMetadata) => Promise<ToolSchemaResolution | undefined>;
367
+ }
368
+ /**
369
+ * Agent 系统级错误
370
+ *
371
+ * agent 未注册等不可恢复错误时抛出(调用方负责捕获)。
372
+ * sub-agent 递归超限用 {@link AgentRecursionError}。
373
+ */
374
+ declare class AgentError extends Error {
375
+ constructor(message: string);
376
+ }
377
+ /**
378
+ * sub-agent 递归超 `maxAgentDepth` 时抛出
379
+ *
380
+ * 被 [reactLoop](./reactLoop.md) catch 后错误消息回传 LLM,LLM 可据此调整策略。
381
+ */
382
+ declare class AgentRecursionError extends AgentError {
383
+ /** 配置的 maxAgentDepth 值 */
384
+ readonly maxDepth: number;
385
+ /** 当前递归深度(超出 maxDepth) */
386
+ readonly currentDepth: number;
387
+ constructor(maxDepth: number, currentDepth: number);
388
+ }
389
+ /**
390
+ * faapi Agent
391
+ *
392
+ * 组装 [reactLoop](./reactLoop.md) 配置、执行 tool、递归 sub-agent 的运行时入口。
393
+ */
394
+ declare class Agent {
395
+ private readonly deps;
396
+ /** 当前递归深度(根 agent 为 1,sub-agent 递增) */
397
+ private readonly depth;
398
+ /**
399
+ * tool schema 解析缓存(按 tool.name 缓存,含 undefined 结果)
400
+ *
401
+ * `buildToolDefinitions` 组装 LLM tool 列表时解析一次 schema(取 jsonSchema),
402
+ * `executeTool` 执行前校验时复用同一份 schema(取 validate)——
403
+ * 避免每次 tool 执行都重新 `loadToolSchema` + `z.toJSONSchema`。
404
+ *
405
+ * 实例级缓存:sub-agent 各有独立 cache(tool 集合可能不同)。
406
+ */
407
+ private readonly schemaCache;
408
+ /**
409
+ * @param deps 运行时依赖(访问器 + provider + config)
410
+ * @param depth 递归深度(默认 1 = 根 agent;sub-agent 递归时传入 depth+1)
411
+ */
412
+ constructor(deps: AgentDeps, depth?: number);
413
+ /**
414
+ * 非流式执行——组装 config 调 [reactLoop](./reactLoop.md)
415
+ *
416
+ * @param input 用户输入
417
+ * @returns 最终结果(content + messages + turns + stopReason + usage)
418
+ * @throws {AgentError} agent 未注册
419
+ * @throws {ReactLoopError} 超出 maxTurns
420
+ * @throws {Error} provider.complete 抛错时立即传播
421
+ */
422
+ run(input: string): Promise<ReactLoopResult>;
423
+ /**
424
+ * 流式执行——组装 config 调 [reactLoopStream](./reactLoop.md)
425
+ *
426
+ * @param input 用户输入
427
+ * @yields 流式 chunk(deltaContent / toolCall / toolResult / done)
428
+ * @throws {AgentError} agent 未注册
429
+ * @throws {ReactLoopError} 超出 maxTurns
430
+ * @throws {Error} provider.stream 抛错时立即传播
431
+ */
432
+ stream(input: string): AsyncIterable<ReactLoopStreamChunk>;
433
+ /**
434
+ * 把自身包装为 `AgentToolDescriptor` 供 LLM 当 tool 调用
435
+ *
436
+ * 与 [agentRegistry.asTool](../../faapi/src/injection/agentRegistry.md) 同构——
437
+ * Agent 类自带此方法便于在注入器场景直接调用(不必再过注册表)。
438
+ *
439
+ * @returns `AgentToolDescriptor` 或 `undefined`(agent 未注册)
440
+ */
441
+ asTool(): AgentToolDescriptor | undefined;
442
+ /**
443
+ * 查询 tool schema(带缓存)
444
+ *
445
+ * `buildToolDefinitions` 与 `executeTool` 共用此方法——
446
+ * 首次调用触发 `deps.resolveToolSchema`(加载 zod.js + 生成 JSON Schema),
447
+ * 后续命中缓存直接返回(含 `undefined` 结果,用 `has` 区分未解析 vs 解析为空)。
448
+ *
449
+ * `deps.resolveToolSchema` 未提供时直接返回 `undefined`,不写缓存。
450
+ */
451
+ private getToolSchema;
452
+ /**
453
+ * 组装 ReactLoopConfig
454
+ *
455
+ * 1. 查 agent 元数据(未注册抛 AgentError)
456
+ * 2. buildToolDefinitions 组装 tool 列表
457
+ * 3. config 字段优先级:agent 元数据 > 全局 AgentRuntimeConfig
458
+ */
459
+ private buildLoopConfig;
460
+ /**
461
+ * 组装 LLM 可见 tool 列表
462
+ *
463
+ * 合并三个来源(按 `name` 去重,先入者保留):
464
+ * 1. **resolveAgentTools** —— agent 显式声明的 `tools` 引用
465
+ * 2. **全局 defaultTools** —— `config.defaultTools` 中的 tool 名(所有 agent 共享)
466
+ * 3. **sub-agent** —— `resolveSubAgents` 每个包装为 `agent.<name>`
467
+ *
468
+ * 每个常规 tool 的 `input`:
469
+ * - `resolveToolSchema` 提供 → 用其 `jsonSchema`
470
+ * - 未提供 / tool 无 `inputTypeName` → 自由 schema `{ type: 'object' }`
471
+ *
472
+ * sub-agent 的 `input` 始终为 `{ type: 'object' }`(agent 参数开放)。
473
+ */
474
+ private buildToolDefinitions;
475
+ /**
476
+ * tool 执行路由(由 reactLoop 调用)
477
+ *
478
+ * - `agent.` 前缀 → {@link executeSubAgent} 递归
479
+ * - 常规 tool → `loadToolModule` 加载 handler + 可选 input 校验 → 调用
480
+ *
481
+ * **常规 tool 校验失败**:不抛错,返回 `{ error }` 对象——reactLoop stringify 后
482
+ * 作为 tool 结果回传 LLM,LLM 可据此修正参数重试。
483
+ *
484
+ * **tool 未找到 / 加载失败**:抛错,被 reactLoop catch 后同样回传 LLM。
485
+ */
486
+ private executeTool;
487
+ /**
488
+ * sub-agent 递归执行
489
+ *
490
+ * 1. `maxAgentDepth` 防护——超限抛 {@link AgentRecursionError}
491
+ * 2. sub-agent handler 导出 `run` 时调自定义 `mod.run(args)`
492
+ * 3. 无 `run` 时调 `subAgent.run(JSON.stringify(args))` 走默认 reactLoop
493
+ *
494
+ * 自定义 run 接收原始 args 对象;默认 reactLoop 接收 stringify 后的 args
495
+ * 作为 user 消息(agent-as-tool input 为开放式 JSON)。
496
+ */
497
+ private executeSubAgent;
498
+ }
499
+
500
+ /**
501
+ * agent handle——注入到 handler 的 `agent` 参数,提供可调用的 agent 运行入口
502
+ *
503
+ * faapi 核心的 [agentHandle](../../faapi/src/injection/agentHandle.md) 工厂注册机制
504
+ * 让本包的 [plugin](./plugin.md) 在 setup 时注册工厂函数,injectParams 在
505
+ * `agent` 参数注入时调工厂拿到 `AgentHandle` 实例。
506
+ *
507
+ * `Agent` 类满足此接口(结构化类型),plugin 的工厂直接返回 `Agent` 实例,
508
+ * 无需额外包装层。handler 通过 `AgentHandle` 类型获得类型安全:
509
+ *
510
+ * ```ts
511
+ * import type { AgentHandle } from '@faapi/agent';
512
+ *
513
+ * // src/api/chat/handler.ts
514
+ * export function POST(agent: AgentHandle, body: { input: string }) {
515
+ * const result = await agent.run(body.input);
516
+ * return { content: result.content, turns: result.turns };
517
+ * }
518
+ * ```
519
+ *
520
+ * 工厂未注册(`@faapi/agent` 插件未加载或 `config.agent.llm` / `defaultAgent` 未配置)
521
+ * 时注入 `undefined`,handler 需自行处理。
522
+ *
523
+ * 详见 [agentHandle.md](./agentHandle.md)。
524
+ */
525
+ interface AgentHandle {
526
+ /**
527
+ * 非流式执行 agent
528
+ *
529
+ * 组装 ReAct 循环 config(systemPrompt + tools + maxTurns)→ 调
530
+ * [reactLoop](./reactLoop.md) → 返回最终结果。
531
+ *
532
+ * @param input 用户输入文本
533
+ * @returns 循环结果(content + messages + turns + stopReason + usage)
534
+ * @throws {AgentError} agent 未注册
535
+ * @throws {ReactLoopError} 超出 maxTurns
536
+ * @throws {Error} LLM provider 抛错时立即传播
537
+ */
538
+ run(input: string): Promise<ReactLoopResult>;
539
+ /**
540
+ * 流式执行 agent
541
+ *
542
+ * 组装 config → 调 [reactLoopStream](./reactLoop.md) → yield 流式 chunk。
543
+ * 适用于 LLM token 流式输出、tool 调用过程展示等场景。
544
+ *
545
+ * @param input 用户输入文本
546
+ * @yields 流式 chunk(deltaContent / toolCall / toolResult / done)
547
+ * @throws {AgentError} agent 未注册
548
+ * @throws {ReactLoopError} 超出 maxTurns
549
+ * @throws {Error} LLM provider 抛错时立即传播
550
+ */
551
+ stream(input: string): AsyncIterable<ReactLoopStreamChunk>;
552
+ /**
553
+ * 把自身包装为 `AgentToolDescriptor` 供 LLM 当 tool 调用
554
+ *
555
+ * 用于 agent-as-tool 场景:父 agent 把子 agent 包装为 tool,
556
+ * 加入 LLM 可见 tool 列表,LLM 调用时触发 sub-agent 递归执行。
557
+ *
558
+ * @returns `AgentToolDescriptor` 或 `undefined`(agent 未注册)
559
+ */
560
+ asTool(): AgentToolDescriptor | undefined;
561
+ }
562
+
563
+ /**
564
+ * @faapi/agent faapi 插件——注册 agent handle 工厂,让 handler 的 `agent` 参数注入可用的 Agent 实例
565
+ *
566
+ * 在 faapi.config.ts 中声明:
567
+ * ```ts
568
+ * import type { FaapiConfig } from '@faapi/faapi';
569
+ *
570
+ * export default {
571
+ * agent: {
572
+ * llm: { provider: 'openai', apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o' },
573
+ * defaultAgent: 'researcher',
574
+ * maxTurns: 10,
575
+ * },
576
+ * plugins: ['@faapi/agent'],
577
+ * } satisfies FaapiConfig;
578
+ * ```
579
+ *
580
+ * 插件 setup 时:
581
+ * 1. 读 `config.agent.llm` → `createProvider` → LLMProvider 实例(单例)
582
+ * 2. 读 `config.agent.defaultAgent` / `maxTurns` / `maxAgentDepth` / `defaultTools`
583
+ * 3. 从 `@faapi/faapi` import 注册表/加载器访问器(getAgent / getTool / resolveAgentTools /
584
+ * resolveSubAgents / loadAgentModule / loadToolModule)
585
+ * 4. `registerAgentHandleFactory` 注册工厂——每次请求时构造 [Agent](./agent.md) 实例注入到
586
+ * handler 的 `agent` 参数
587
+ *
588
+ * 配置缺失时(`agent.llm` 或 `agent.defaultAgent` 未设置)跳过工厂注册并打印警告,
589
+ * handler 的 `agent` 参数注入 `undefined`。
590
+ *
591
+ * 详见 [plugin.md](./plugin.md)。
592
+ */
593
+
594
+ /**
595
+ * @faapi/agent faapi 插件入口
596
+ *
597
+ * 在 faapi.config.ts 的 `plugins` 字段中声明 `'@faapi/agent'` 即可启用。
598
+ * 插件加载后,handler 的 `agent` 参数可注入可用的 [AgentHandle](./agentHandle.md)。
599
+ */
600
+ declare const agentPlugin: FaapiPlugin;
601
+
602
+ export { Agent, type AgentDeps, AgentError, type AgentHandle, AgentRecursionError, type AgentRuntimeConfig, type LLMCompleteRequest, type LLMMessage, type LLMProvider, LLMProviderError, type LLMResponse, type LLMStopReason, type LLMStreamChunk, type LLMToolCall, type LLMToolDefinition, type LLMUsage, type ReactLoopConfig, ReactLoopError, type ReactLoopResult, type ReactLoopStreamChunk, type ToolExecutor, type ToolSchemaResolution, createOpenAIProvider, createProvider, agentPlugin as default, reactLoop, reactLoopStream };