@codehz/ai 0.1.1 → 0.1.3
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/.oxlintrc.json +1 -16
- package/AGENTS.md +37 -0
- package/README.md +42 -16
- package/dist/index.d.mts +178 -101
- package/dist/index.mjs +442 -202
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/src/adapters/chat-completions.ts +2 -25
- package/src/adapters/index.ts +1 -0
- package/src/adapters/messages.ts +1 -2
- package/src/adapters/mock.ts +162 -13
- package/src/adapters/ollama.ts +2 -15
- package/src/adapters/responses.ts +1 -2
- package/src/helpers/adapter-auxiliary.ts +1 -7
- package/src/helpers/adapter-base.ts +4 -5
- package/src/types/adapter.ts +1 -82
- package/src/types/index.ts +0 -4
package/.oxlintrc.json
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"import/no-duplicates": "error",
|
|
12
12
|
"import/named": "error",
|
|
13
13
|
"import/namespace": "error",
|
|
14
|
+
"no-await-in-loop": "off",
|
|
14
15
|
"typescript/no-non-null-assertion": "warn",
|
|
15
16
|
"unicorn/no-null": "off",
|
|
16
17
|
"unicorn/no-array-for-each": "off",
|
|
@@ -24,22 +25,6 @@
|
|
|
24
25
|
"typescript/no-non-null-assertion": "off",
|
|
25
26
|
"unicorn/no-array-reverse": "off"
|
|
26
27
|
}
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"files": ["examples/**/*.ts"],
|
|
30
|
-
"rules": {
|
|
31
|
-
"no-await-in-loop": "off"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"files": [
|
|
36
|
-
"src/adapters/chat-completions.ts",
|
|
37
|
-
"src/adapters/messages.ts",
|
|
38
|
-
"src/adapters/responses.ts"
|
|
39
|
-
],
|
|
40
|
-
"rules": {
|
|
41
|
-
"no-await-in-loop": "off"
|
|
42
|
-
}
|
|
43
28
|
}
|
|
44
29
|
],
|
|
45
30
|
"env": {
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Repository Guidelines
|
|
2
|
+
|
|
3
|
+
## Project Structure & Module Organization
|
|
4
|
+
|
|
5
|
+
`src/` contains the library source. Keep canonical request/response logic in `src/core/`, provider integrations in `src/adapters/`, reusable stream utilities in `src/helpers/`, and shared types in `src/types/`. The public entrypoint is `src/index.ts`.
|
|
6
|
+
|
|
7
|
+
`tests/` holds Bun test suites plus shared fixtures such as `tests/fixtures.ts`. `examples/` contains runnable usage samples like `examples/basic.ts` and `examples/tool-loop.ts`. `dist/` is generated output from the packaging build and should not be edited by hand.
|
|
8
|
+
|
|
9
|
+
## Build, Test, and Development Commands
|
|
10
|
+
|
|
11
|
+
- `bun install` installs dependencies.
|
|
12
|
+
- `bun run typecheck` runs strict TypeScript validation without emitting files.
|
|
13
|
+
- `bun run lint` checks the codebase with `oxlint`; use `bun run lint:fix` for safe autofixes.
|
|
14
|
+
- `bun run format` applies `oxfmt`; `bun run format:check` verifies formatting in CI style.
|
|
15
|
+
- `bun test` runs the full Bun test suite.
|
|
16
|
+
- `bun run example:basic`, `bun run example:multi-turn`, and `bun run example:tool-loop` execute sample integrations.
|
|
17
|
+
- `bun run prepack` builds the package with `tsdown` into `dist/`.
|
|
18
|
+
|
|
19
|
+
## Coding Style & Naming Conventions
|
|
20
|
+
|
|
21
|
+
This repository uses TypeScript ESM with 2-space indentation, semicolons, double quotes, trailing commas, and LF line endings. `oxfmt` enforces formatting, and `oxlint` enforces import correctness and general safety rules.
|
|
22
|
+
|
|
23
|
+
Follow existing naming patterns: kebab-case filenames such as `chat-completions.ts`, PascalCase for exported classes and types, and camelCase for functions, variables, and helpers. Add public exports through the existing index files instead of reaching into deep paths from consumers.
|
|
24
|
+
|
|
25
|
+
## Testing Guidelines
|
|
26
|
+
|
|
27
|
+
Tests use `bun:test` and live in `tests/*.test.ts`. Name suites after the unit or scenario under test, for example `responses-adapter.test.ts` or `scenarios.test.ts`. Favor behavior-focused `describe`/`it` blocks and cover event ordering, replay round-trips, warnings, and adapter-specific edge cases. Use `MockAdapter` and shared fixtures when validating streaming behavior.
|
|
28
|
+
|
|
29
|
+
## Commit & Pull Request Guidelines
|
|
30
|
+
|
|
31
|
+
Recent history follows conventional prefixes such as `feat(mock): ...`, `refactor(types): ...`, `docs: ...`, `build: ...`, and `chore: ...`. Keep scopes aligned with the subsystem you changed.
|
|
32
|
+
|
|
33
|
+
Pull requests should summarize behavior changes, list verification commands run locally, and link the relevant issue when applicable. Include example output or event traces when changing stream semantics or adapter behavior.
|
|
34
|
+
|
|
35
|
+
## Configuration & Secrets
|
|
36
|
+
|
|
37
|
+
Use environment variables for provider credentials, such as `OPENAI_API_KEY`. Do not hardcode secrets in source, examples, or tests.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nano-ai
|
|
2
2
|
|
|
3
|
-
统一流式 AI
|
|
3
|
+
统一流式 AI 客户端,提供一套 canonical API,对接真实模型后端与面向测试的脚本化 `MockAdapter`(`responses` / `messages` / `chat.completions` / `ollama` / `mock`)。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -109,24 +109,24 @@ console.log(response.replay); // 续接材料
|
|
|
109
109
|
|
|
110
110
|
## 后端 Adapter
|
|
111
111
|
|
|
112
|
-
| Adapter | 类 |
|
|
113
|
-
| ----------------------- | ------------------------ |
|
|
114
|
-
| OpenAI Responses API | `ResponsesAdapter` |
|
|
115
|
-
| Anthropic Messages API | `MessagesAdapter` |
|
|
116
|
-
| OpenAI Chat Completions | `ChatCompletionsAdapter` |
|
|
117
|
-
| Ollama Chat API | `OllamaAdapter` |
|
|
118
|
-
| Scripted Test Backend | `MockAdapter` |
|
|
112
|
+
| Adapter | 类 | 说明 |
|
|
113
|
+
| ----------------------- | ------------------------ | ------------------------ |
|
|
114
|
+
| OpenAI Responses API | `ResponsesAdapter` | OpenAI Responses 端点 |
|
|
115
|
+
| Anthropic Messages API | `MessagesAdapter` | Anthropic Messages 端点 |
|
|
116
|
+
| OpenAI Chat Completions | `ChatCompletionsAdapter` | Chat Completions 端点 |
|
|
117
|
+
| Ollama Chat API | `OllamaAdapter` | 本地或自托管 Ollama |
|
|
118
|
+
| Scripted Test Backend | `MockAdapter` | 脚本化测试夹具 |
|
|
119
119
|
|
|
120
120
|
```ts
|
|
121
121
|
import { ResponsesAdapter, MessagesAdapter, ChatCompletionsAdapter, OllamaAdapter, MockAdapter } from "nano-ai";
|
|
122
122
|
|
|
123
|
-
// OpenAI Responses API
|
|
123
|
+
// OpenAI Responses API
|
|
124
124
|
const responses = new ResponsesAdapter({ apiKey: "sk-..." });
|
|
125
125
|
|
|
126
126
|
// Anthropic Messages API
|
|
127
127
|
const messages = new MessagesAdapter({ apiKey: "sk-ant-..." });
|
|
128
128
|
|
|
129
|
-
// OpenAI Chat Completions
|
|
129
|
+
// OpenAI Chat Completions
|
|
130
130
|
const chat = new ChatCompletionsAdapter({ apiKey: "sk-..." });
|
|
131
131
|
|
|
132
132
|
// Ollama
|
|
@@ -134,6 +134,10 @@ const ollama = new OllamaAdapter({ baseUrl: "http://localhost:11434" });
|
|
|
134
134
|
|
|
135
135
|
// 面向测试的脚本化 mock backend
|
|
136
136
|
const mock = new MockAdapter({
|
|
137
|
+
stream: {
|
|
138
|
+
charsPerSecond: 24,
|
|
139
|
+
chunkSize: 1,
|
|
140
|
+
},
|
|
137
141
|
turns: [
|
|
138
142
|
{
|
|
139
143
|
steps: [
|
|
@@ -150,17 +154,37 @@ const mock = new MockAdapter({
|
|
|
150
154
|
});
|
|
151
155
|
```
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
公开 adapter 接口只暴露稳定的标识与流式来源:
|
|
154
158
|
|
|
155
159
|
```ts
|
|
156
|
-
adapter.
|
|
157
|
-
adapter.
|
|
158
|
-
adapter.capabilities.replayFidelity; // "high" | "medium" | "low"
|
|
160
|
+
adapter.kind; // "responses" | "messages" | "chat-completions" | ...
|
|
161
|
+
adapter.nativeStreaming; // 是否为 provider 原生流,而不是本地模拟分片
|
|
159
162
|
```
|
|
160
163
|
|
|
164
|
+
像 reasoning、tool call、`replay` 材料这类响应特征,应直接从本次事件流、warning 和 `replay` 内容判断。
|
|
165
|
+
|
|
161
166
|
## Mock 后端
|
|
162
167
|
|
|
163
|
-
`MockAdapter`
|
|
168
|
+
`MockAdapter` 是一个面向测试的脚本化 adapter,用来验证长流程工具调用、`replay` 续接和异常路径。
|
|
169
|
+
|
|
170
|
+
如果你要调试前端逐字渲染效果,可以给 `MockAdapter` 打开分片流:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
const mock = new MockAdapter({
|
|
174
|
+
stream: {
|
|
175
|
+
charsPerSecond: 20, // 每秒约 20 个字符
|
|
176
|
+
chunkSize: 1, // 默认 1,即逐字输出
|
|
177
|
+
initialDelayMs: 150, // 可选:首字前停顿
|
|
178
|
+
},
|
|
179
|
+
turns: [
|
|
180
|
+
{
|
|
181
|
+
steps: [{ type: "message", content: "Streaming preview for the frontend." }],
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
默认会发出单个完整 `message.delta`。只有显式配置 `stream` 时,`message` / `reasoning` / `tool_call` 参数才会被拆成多个 delta。单个 step 也可用 `stream: false` 关闭全局流速配置。
|
|
164
188
|
|
|
165
189
|
核心思路是按 turn 写脚本:
|
|
166
190
|
|
|
@@ -317,9 +341,11 @@ const { usage, billing, auxiliary, warnings } = collector.build();
|
|
|
317
341
|
|
|
318
342
|
## 开发命令
|
|
319
343
|
|
|
344
|
+
`examples/` 下的三个示例默认都基于 `MockAdapter`,可直接运行,无需配置真实模型或 API key。
|
|
345
|
+
|
|
320
346
|
```bash
|
|
321
347
|
bun run typecheck # TypeScript 类型检查
|
|
322
|
-
bun run test #
|
|
348
|
+
bun run test # 运行全部测试
|
|
323
349
|
bun run example:basic
|
|
324
350
|
bun run example:multi-turn
|
|
325
351
|
bun run example:tool-loop
|
package/dist/index.d.mts
CHANGED
|
@@ -117,7 +117,7 @@ type AuxiliaryInfo = {
|
|
|
117
117
|
type BackendTrace = {
|
|
118
118
|
requestId?: string;
|
|
119
119
|
rawResponseId?: string;
|
|
120
|
-
adapter: "chat-completions" | "messages" | "responses" | "ollama";
|
|
120
|
+
adapter: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
|
|
121
121
|
isSyntheticStream: boolean;
|
|
122
122
|
metadataSources?: string[];
|
|
123
123
|
warnings?: string[];
|
|
@@ -143,7 +143,7 @@ type StreamEventBase = {
|
|
|
143
143
|
sequence: number;
|
|
144
144
|
timestamp: string;
|
|
145
145
|
backend: {
|
|
146
|
-
kind: "chat-completions" | "messages" | "responses" | "ollama";
|
|
146
|
+
kind: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
|
|
147
147
|
isSynthetic: boolean;
|
|
148
148
|
};
|
|
149
149
|
};
|
|
@@ -228,71 +228,9 @@ type NormalizedRequest = AIRequest & {
|
|
|
228
228
|
model: string;
|
|
229
229
|
requestId: string;
|
|
230
230
|
};
|
|
231
|
-
type AdapterCapabilities = {
|
|
232
|
-
nativeStreaming: boolean;
|
|
233
|
-
messageStreaming: boolean;
|
|
234
|
-
reasoningStreaming: boolean;
|
|
235
|
-
toolCallStreaming: boolean;
|
|
236
|
-
hiddenReasoningReplay: "full" | "partial" | "none";
|
|
237
|
-
replayFidelity: "high" | "medium" | "low";
|
|
238
|
-
tools: boolean;
|
|
239
|
-
usage: "full" | "partial" | "none";
|
|
240
|
-
billing: "direct" | "lookup" | "derived" | "none";
|
|
241
|
-
providerMetadata: boolean;
|
|
242
|
-
};
|
|
243
|
-
declare const CAPABILITY_MATRIX: {
|
|
244
|
-
readonly responses: {
|
|
245
|
-
readonly nativeStreaming: true;
|
|
246
|
-
readonly messageStreaming: true;
|
|
247
|
-
readonly reasoningStreaming: true;
|
|
248
|
-
readonly toolCallStreaming: true;
|
|
249
|
-
readonly hiddenReasoningReplay: "full";
|
|
250
|
-
readonly replayFidelity: "high";
|
|
251
|
-
readonly tools: true;
|
|
252
|
-
readonly usage: "full";
|
|
253
|
-
readonly billing: "lookup";
|
|
254
|
-
readonly providerMetadata: true;
|
|
255
|
-
};
|
|
256
|
-
readonly messages: {
|
|
257
|
-
readonly nativeStreaming: true;
|
|
258
|
-
readonly messageStreaming: true;
|
|
259
|
-
readonly reasoningStreaming: false;
|
|
260
|
-
readonly toolCallStreaming: true;
|
|
261
|
-
readonly hiddenReasoningReplay: "partial";
|
|
262
|
-
readonly replayFidelity: "medium";
|
|
263
|
-
readonly tools: true;
|
|
264
|
-
readonly usage: "full";
|
|
265
|
-
readonly billing: "lookup";
|
|
266
|
-
readonly providerMetadata: true;
|
|
267
|
-
};
|
|
268
|
-
readonly "chat.completions": {
|
|
269
|
-
readonly nativeStreaming: true;
|
|
270
|
-
readonly messageStreaming: true;
|
|
271
|
-
readonly reasoningStreaming: false;
|
|
272
|
-
readonly toolCallStreaming: false;
|
|
273
|
-
readonly hiddenReasoningReplay: "none";
|
|
274
|
-
readonly replayFidelity: "low";
|
|
275
|
-
readonly tools: true;
|
|
276
|
-
readonly usage: "full";
|
|
277
|
-
readonly billing: "derived";
|
|
278
|
-
readonly providerMetadata: false;
|
|
279
|
-
};
|
|
280
|
-
readonly ollama: {
|
|
281
|
-
readonly nativeStreaming: true;
|
|
282
|
-
readonly messageStreaming: true;
|
|
283
|
-
readonly reasoningStreaming: false;
|
|
284
|
-
readonly toolCallStreaming: false;
|
|
285
|
-
readonly hiddenReasoningReplay: "none";
|
|
286
|
-
readonly replayFidelity: "low";
|
|
287
|
-
readonly tools: true;
|
|
288
|
-
readonly usage: "partial";
|
|
289
|
-
readonly billing: "none";
|
|
290
|
-
readonly providerMetadata: false;
|
|
291
|
-
};
|
|
292
|
-
};
|
|
293
231
|
interface BackendAdapter {
|
|
294
|
-
readonly kind: "chat-completions" | "messages" | "responses" | "ollama";
|
|
295
|
-
readonly
|
|
232
|
+
readonly kind: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
|
|
233
|
+
readonly nativeStreaming: boolean;
|
|
296
234
|
stream(request: NormalizedRequest): AsyncIterable<AIStreamEvent>;
|
|
297
235
|
}
|
|
298
236
|
type CreateAIClientOptions = {
|
|
@@ -389,7 +327,7 @@ declare const WarningCode: {
|
|
|
389
327
|
//#endregion
|
|
390
328
|
//#region src/core/event-factory.d.ts
|
|
391
329
|
type EventFactoryBackend = {
|
|
392
|
-
kind: "chat-completions" | "messages" | "responses" | "ollama";
|
|
330
|
+
kind: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
|
|
393
331
|
isSynthetic: boolean;
|
|
394
332
|
};
|
|
395
333
|
type EventFactoryState = {
|
|
@@ -499,7 +437,6 @@ type BillingPostprocessHook = (context: {
|
|
|
499
437
|
usage?: Usage;
|
|
500
438
|
billing?: BillingInfo;
|
|
501
439
|
auxiliary?: AuxiliaryInfo;
|
|
502
|
-
capabilities: AdapterCapabilities;
|
|
503
440
|
}) => MaybePromise<Partial<BillingInfo> | undefined>;
|
|
504
441
|
type AuxiliaryFinalizeOptions = {
|
|
505
442
|
lookup?: () => Promise<LookupResult>;
|
|
@@ -517,10 +454,9 @@ type AuxiliaryFinalizeResult = {
|
|
|
517
454
|
};
|
|
518
455
|
declare class AdapterAuxiliaryState {
|
|
519
456
|
private readonly request;
|
|
520
|
-
private readonly capabilities;
|
|
521
457
|
private readonly collector;
|
|
522
458
|
private readonly metadataSources;
|
|
523
|
-
constructor(request: NormalizedRequest
|
|
459
|
+
constructor(request: NormalizedRequest);
|
|
524
460
|
recordUsage(usage: Partial<Usage>, source: UsageSource, raw?: unknown): void;
|
|
525
461
|
recordBilling(billing: Partial<BillingInfo>, source: BillingSource, raw?: unknown): void;
|
|
526
462
|
recordProviderMetadata(source: string, metadata: Record<string, unknown> | undefined): void;
|
|
@@ -553,8 +489,8 @@ type StreamResult = {
|
|
|
553
489
|
rawResponseId?: string;
|
|
554
490
|
};
|
|
555
491
|
declare abstract class AdapterBase implements BackendAdapter {
|
|
556
|
-
abstract readonly kind: "chat-completions" | "messages" | "responses" | "ollama";
|
|
557
|
-
abstract readonly
|
|
492
|
+
abstract readonly kind: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
|
|
493
|
+
abstract readonly nativeStreaming: boolean;
|
|
558
494
|
/**
|
|
559
495
|
* stream 模板方法:
|
|
560
496
|
* 1. 创建事件工厂,发射 response.started
|
|
@@ -647,18 +583,7 @@ type ResponsesTool = {
|
|
|
647
583
|
};
|
|
648
584
|
declare class ResponsesAdapter extends AdapterBase {
|
|
649
585
|
readonly kind: "responses";
|
|
650
|
-
readonly
|
|
651
|
-
readonly nativeStreaming: true;
|
|
652
|
-
readonly messageStreaming: true;
|
|
653
|
-
readonly reasoningStreaming: true;
|
|
654
|
-
readonly toolCallStreaming: true;
|
|
655
|
-
readonly hiddenReasoningReplay: "full";
|
|
656
|
-
readonly replayFidelity: "high";
|
|
657
|
-
readonly tools: true;
|
|
658
|
-
readonly usage: "full";
|
|
659
|
-
readonly billing: "lookup";
|
|
660
|
-
readonly providerMetadata: true;
|
|
661
|
-
};
|
|
586
|
+
readonly nativeStreaming = true;
|
|
662
587
|
private apiKey;
|
|
663
588
|
private baseUrl;
|
|
664
589
|
private fetchFn;
|
|
@@ -726,18 +651,7 @@ type MessagesAPITool = {
|
|
|
726
651
|
};
|
|
727
652
|
declare class MessagesAdapter extends AdapterBase {
|
|
728
653
|
readonly kind: "messages";
|
|
729
|
-
readonly
|
|
730
|
-
readonly nativeStreaming: true;
|
|
731
|
-
readonly messageStreaming: true;
|
|
732
|
-
readonly reasoningStreaming: false;
|
|
733
|
-
readonly toolCallStreaming: true;
|
|
734
|
-
readonly hiddenReasoningReplay: "partial";
|
|
735
|
-
readonly replayFidelity: "medium";
|
|
736
|
-
readonly tools: true;
|
|
737
|
-
readonly usage: "full";
|
|
738
|
-
readonly billing: "lookup";
|
|
739
|
-
readonly providerMetadata: true;
|
|
740
|
-
};
|
|
654
|
+
readonly nativeStreaming = true;
|
|
741
655
|
private apiKey;
|
|
742
656
|
private apiVersion;
|
|
743
657
|
private baseUrl;
|
|
@@ -796,11 +710,10 @@ type ChatTool = {
|
|
|
796
710
|
};
|
|
797
711
|
declare class ChatCompletionsAdapter extends AdapterBase {
|
|
798
712
|
readonly kind: "chat-completions";
|
|
799
|
-
readonly
|
|
713
|
+
readonly nativeStreaming = true;
|
|
800
714
|
private apiKey;
|
|
801
715
|
private baseUrl;
|
|
802
716
|
private fetchFn;
|
|
803
|
-
private markReasoningCompatibility;
|
|
804
717
|
constructor(options: ChatCompletionsAdapterOptions);
|
|
805
718
|
protected buildRequest(request: NormalizedRequest): ChatRequest;
|
|
806
719
|
protected runStream(providerRequest: ChatRequest, factory: EventFactory, request: NormalizedRequest): AsyncIterable<AIStreamEvent>;
|
|
@@ -845,7 +758,7 @@ type OllamaTool = {
|
|
|
845
758
|
};
|
|
846
759
|
declare class OllamaAdapter extends AdapterBase {
|
|
847
760
|
readonly kind: "ollama";
|
|
848
|
-
readonly
|
|
761
|
+
readonly nativeStreaming = true;
|
|
849
762
|
private baseUrl;
|
|
850
763
|
private apiKey;
|
|
851
764
|
private fetchFn;
|
|
@@ -854,6 +767,170 @@ declare class OllamaAdapter extends AdapterBase {
|
|
|
854
767
|
protected runStream(providerRequest: OllamaChatRequest, factory: EventFactory, request: NormalizedRequest): AsyncIterable<AIStreamEvent>;
|
|
855
768
|
}
|
|
856
769
|
//#endregion
|
|
770
|
+
//#region src/adapters/mock.d.ts
|
|
771
|
+
type MockInputExpectation = {
|
|
772
|
+
type: InputItem["type"];
|
|
773
|
+
id?: string;
|
|
774
|
+
role?: MessageItem["role"];
|
|
775
|
+
name?: string;
|
|
776
|
+
toolName?: string;
|
|
777
|
+
callId?: string;
|
|
778
|
+
outcome?: ToolResultItem["outcome"];
|
|
779
|
+
visibility?: Extract<InputItem, {
|
|
780
|
+
type: "reasoning";
|
|
781
|
+
}>["visibility"];
|
|
782
|
+
source?: Extract<InputItem, {
|
|
783
|
+
type: "opaque";
|
|
784
|
+
}>["source"];
|
|
785
|
+
purpose?: Extract<InputItem, {
|
|
786
|
+
type: "opaque";
|
|
787
|
+
}>["purpose"];
|
|
788
|
+
textIncludes?: string;
|
|
789
|
+
};
|
|
790
|
+
type MockRequestExpectation = {
|
|
791
|
+
minItems?: number;
|
|
792
|
+
maxItems?: number;
|
|
793
|
+
ordered?: boolean;
|
|
794
|
+
requireReplayFromPreviousTurn?: boolean;
|
|
795
|
+
requireToolResultsForPendingCalls?: boolean;
|
|
796
|
+
tools?: "ignore" | "present" | "absent";
|
|
797
|
+
toolChoice?: "ignore" | "present" | "absent";
|
|
798
|
+
items?: MockInputExpectation[];
|
|
799
|
+
};
|
|
800
|
+
type MockTurnContext = {
|
|
801
|
+
turnIndex: number;
|
|
802
|
+
previousReplay: ReplayItem[];
|
|
803
|
+
pendingToolCalls: readonly ToolCallItem[];
|
|
804
|
+
history: readonly MockTurnRecord[];
|
|
805
|
+
};
|
|
806
|
+
type MockTurnValidator = (request: NormalizedRequest, context: MockTurnContext) => void | Promise<void>;
|
|
807
|
+
type MockWarningStep = {
|
|
808
|
+
type: "warning";
|
|
809
|
+
message: string;
|
|
810
|
+
code?: string;
|
|
811
|
+
};
|
|
812
|
+
type MockAuxiliaryStep = {
|
|
813
|
+
type: "auxiliary";
|
|
814
|
+
usage?: Usage;
|
|
815
|
+
billing?: BillingInfo;
|
|
816
|
+
auxiliary?: Partial<AuxiliaryInfo>;
|
|
817
|
+
};
|
|
818
|
+
type MockTextStreamOptions = {
|
|
819
|
+
/**
|
|
820
|
+
* 每秒吐出的字符数。未设置时仍会按 chunk 拆分,但不会额外等待。
|
|
821
|
+
*/
|
|
822
|
+
charsPerSecond?: number;
|
|
823
|
+
/**
|
|
824
|
+
* 每个 delta 最多包含多少个字符,默认 1。
|
|
825
|
+
*/
|
|
826
|
+
chunkSize?: number;
|
|
827
|
+
/**
|
|
828
|
+
* 首个 delta 发出前的延迟。
|
|
829
|
+
*/
|
|
830
|
+
initialDelayMs?: number;
|
|
831
|
+
};
|
|
832
|
+
type MockMessageStep = {
|
|
833
|
+
type: "message";
|
|
834
|
+
id?: string;
|
|
835
|
+
content: string | ContentBlock[];
|
|
836
|
+
stream?: MockTextStreamOptions | false;
|
|
837
|
+
};
|
|
838
|
+
type MockReasoningStep = {
|
|
839
|
+
type: "reasoning";
|
|
840
|
+
id?: string;
|
|
841
|
+
visibility?: Extract<OutputItem, {
|
|
842
|
+
type: "reasoning";
|
|
843
|
+
}>["visibility"];
|
|
844
|
+
content: string | ContentBlock[];
|
|
845
|
+
stream?: MockTextStreamOptions | false;
|
|
846
|
+
};
|
|
847
|
+
type MockToolCallStep = {
|
|
848
|
+
type: "tool_call";
|
|
849
|
+
id: string;
|
|
850
|
+
name: string;
|
|
851
|
+
argumentsText: string;
|
|
852
|
+
argumentsJson?: unknown;
|
|
853
|
+
streamArguments?: boolean;
|
|
854
|
+
stream?: MockTextStreamOptions | false;
|
|
855
|
+
};
|
|
856
|
+
type MockOutputStep = {
|
|
857
|
+
type: "output";
|
|
858
|
+
item: Extract<OutputItem, {
|
|
859
|
+
type: "message" | "reasoning" | "tool_call";
|
|
860
|
+
}>;
|
|
861
|
+
stream?: MockTextStreamOptions | false;
|
|
862
|
+
};
|
|
863
|
+
type MockCompleteStep = {
|
|
864
|
+
type: "complete";
|
|
865
|
+
stopReason?: StopReason;
|
|
866
|
+
replay?: ReplayItem[];
|
|
867
|
+
usage?: Usage;
|
|
868
|
+
billing?: BillingInfo;
|
|
869
|
+
auxiliary?: Partial<AuxiliaryInfo>;
|
|
870
|
+
providerMetadata?: Record<string, unknown>;
|
|
871
|
+
rawResponseId?: string;
|
|
872
|
+
warnings?: string[];
|
|
873
|
+
};
|
|
874
|
+
type MockErrorStep = {
|
|
875
|
+
type: "error";
|
|
876
|
+
message: string;
|
|
877
|
+
code?: string;
|
|
878
|
+
stopReason?: StopReason;
|
|
879
|
+
providerMetadata?: Record<string, unknown>;
|
|
880
|
+
};
|
|
881
|
+
type MockInterruptStep = {
|
|
882
|
+
type: "interrupt";
|
|
883
|
+
};
|
|
884
|
+
type MockThrowStep = {
|
|
885
|
+
type: "throw";
|
|
886
|
+
error: string | Error;
|
|
887
|
+
};
|
|
888
|
+
type MockStep = MockWarningStep | MockAuxiliaryStep | MockMessageStep | MockReasoningStep | MockToolCallStep | MockOutputStep | MockCompleteStep | MockErrorStep | MockInterruptStep | MockThrowStep;
|
|
889
|
+
type MockTurn = {
|
|
890
|
+
name?: string;
|
|
891
|
+
expect?: MockRequestExpectation | MockTurnValidator;
|
|
892
|
+
steps: MockStep[];
|
|
893
|
+
};
|
|
894
|
+
type MockAdapterOptions = {
|
|
895
|
+
turns: MockTurn[];
|
|
896
|
+
onExhausted?: "throw" | "repeat-last" | "complete-empty";
|
|
897
|
+
providerMetadata?: Record<string, unknown>;
|
|
898
|
+
stream?: MockTextStreamOptions;
|
|
899
|
+
};
|
|
900
|
+
type MockTurnRecord = {
|
|
901
|
+
turnIndex: number;
|
|
902
|
+
turnName?: string;
|
|
903
|
+
requestId: string;
|
|
904
|
+
replay: ReplayItem[];
|
|
905
|
+
toolCalls: ToolCallItem[];
|
|
906
|
+
};
|
|
907
|
+
type MockProviderRequest = {
|
|
908
|
+
request: NormalizedRequest;
|
|
909
|
+
turn: MockTurn;
|
|
910
|
+
turnIndex: number;
|
|
911
|
+
turnName?: string;
|
|
912
|
+
remainingPendingToolCalls: ToolCallItem[];
|
|
913
|
+
};
|
|
914
|
+
declare class MockAdapter extends AdapterBase {
|
|
915
|
+
readonly kind: "mock";
|
|
916
|
+
readonly nativeStreaming = false;
|
|
917
|
+
private readonly turns;
|
|
918
|
+
private readonly onExhausted;
|
|
919
|
+
private readonly providerMetadata?;
|
|
920
|
+
private readonly defaultStream?;
|
|
921
|
+
private cursor;
|
|
922
|
+
private previousReplay;
|
|
923
|
+
private pendingToolCalls;
|
|
924
|
+
private history;
|
|
925
|
+
private activeStream;
|
|
926
|
+
constructor(options: MockAdapterOptions);
|
|
927
|
+
protected buildRequest(request: NormalizedRequest): Promise<MockProviderRequest>;
|
|
928
|
+
protected runStream(providerRequest: unknown, factory: EventFactory, request: NormalizedRequest): AsyncIterable<AIStreamEvent>;
|
|
929
|
+
private finalizeTurn;
|
|
930
|
+
private resolveTurn;
|
|
931
|
+
private buildTurnContext;
|
|
932
|
+
}
|
|
933
|
+
//#endregion
|
|
857
934
|
//#region src/helpers/mapping.d.ts
|
|
858
935
|
declare function mapStopReason(providerReason: string): StopReason;
|
|
859
936
|
declare function mapReasoningVisibility(hasThinking: boolean, hasRedacted: boolean): ReasoningItem["visibility"];
|
|
@@ -945,7 +1022,7 @@ type SyntheticStreamOptions = {
|
|
|
945
1022
|
model: string;
|
|
946
1023
|
responseId: string;
|
|
947
1024
|
backend: {
|
|
948
|
-
kind: "chat-completions" | "messages" | "responses";
|
|
1025
|
+
kind: "chat-completions" | "messages" | "responses" | "mock";
|
|
949
1026
|
};
|
|
950
1027
|
output: OutputItem[];
|
|
951
1028
|
replay?: ReplayItem[];
|
|
@@ -974,5 +1051,5 @@ type SyntheticStreamOptions = {
|
|
|
974
1051
|
*/
|
|
975
1052
|
declare function syntheticStream(options: SyntheticStreamOptions): AsyncIterable<AIStreamEvent>;
|
|
976
1053
|
//#endregion
|
|
977
|
-
export { type AIClient, AIError, AIMappingError, AIProviderError, type AIRequest, AIRequestError, type AIResponse, AIStreamError, type AIStreamEvent, AdapterAuxiliaryState, AdapterBase,
|
|
1054
|
+
export { type AIClient, AIError, AIMappingError, AIProviderError, type AIRequest, AIRequestError, type AIResponse, AIStreamError, type AIStreamEvent, AdapterAuxiliaryState, AdapterBase, AuxiliaryCollector, type AuxiliaryFinalizeOptions, type AuxiliaryFinalizeResult, type AuxiliaryInfo, type BackendAdapter, type BackendTrace, type BillingInfo, type BillingPostprocessHook, type BillingSource, ChatCompletionsAdapter, type ChatCompletionsAdapterOptions, type ContentBlock, type CreateAIClientOptions, type EventFactory, type EventFactoryBackend, type EventFactoryState, type FetchFn, type IncludeSettings, type InputItem, type LookupResult, type MessageCompletedEvent, type MessageDeltaEvent, type MessageItem, type MessageStartedEvent, MessagesAdapter, type MessagesAdapterOptions, MockAdapter, type MockAdapterOptions, type MockAuxiliaryStep, type MockCompleteStep, type MockErrorStep, type MockInputExpectation, type MockInterruptStep, type MockMessageStep, type MockOutputStep, type MockReasoningStep, type MockRequestExpectation, type MockStep, type MockTextStreamOptions, type MockThrowStep, type MockToolCallStep, type MockTurn, type MockTurnContext, type MockTurnValidator, type MockWarningStep, type NormalizeOptions, type NormalizedRequest, OllamaAdapter, type OllamaAdapterOptions, type OpaqueItem, type OutputItem, type ReasoningCompletedEvent, type ReasoningDeltaEvent, type ReasoningItem, type ReasoningStartedEvent, type ReplayItem, type ResponseAuxiliaryEvent, type ResponseCompletedEvent, type ResponseStartedEvent, type ResponseWarningEvent, ResponsesAdapter, type ResponsesAdapterOptions, type SSEEvent, type StopReason, type StreamEventBase, type StreamResult, type SyntheticStreamOptions, type ToolCallCompletedEvent, type ToolCallDeltaEvent, type ToolCallItem, type ToolCallStartedEvent, type ToolChoice, type ToolDefinition, type ToolResultItem, type Usage, type UsageSource, type ValidationIssue, WarningCode, aggregateEvents, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createEventFactory, emitMalformedStreamWarning, extractText, imageBlock, instructionsToText, jsonBlock, mapReasoningVisibility, mapStopReason, messageItem, metadataSourceList, normalizeRequest, opaqueBlock, opaqueItem, parseSSEEvents, reasoningItem, replayFromOutput, syntheticStream, textBlock, toolCallItem, toolResultItem, validateRequest };
|
|
978
1055
|
//# sourceMappingURL=index.d.mts.map
|