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