@codehz/ai 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # nano-ai
1
+ # @codehz/ai
2
2
 
3
- 统一流式 AI 客户端,提供一套 canonical API,对接真实模型后端与面向测试的回调驱动 `MockAdapter`(`responses` / `messages` / `chat.completions` / `ollama` / `mock`)。
3
+ 统一流式 AI 客户端,提供一套 canonical API,对接真实模型后端与面向测试的回调驱动 `MockAdapter`(`responses` / `messages` / `chat-completions` / `ollama` / `mock`)。
4
4
 
5
5
  ## 安装
6
6
 
7
7
  ```bash
8
- bun add nano-ai
8
+ bun add @codehz/ai
9
9
  ```
10
10
 
11
11
  依赖:Bun(内置 `fetch`、`crypto`),无需额外运行时依赖。
@@ -13,7 +13,7 @@ bun add nano-ai
13
13
  ## 快速开始
14
14
 
15
15
  ```ts
16
- import { createAIClient, ResponsesAdapter } from "nano-ai";
16
+ import { createAIClient, ResponsesAdapter } from "@codehz/ai";
17
17
 
18
18
  const client = createAIClient({
19
19
  adapter: new ResponsesAdapter({ apiKey: process.env.OPENAI_API_KEY! }),
@@ -69,22 +69,22 @@ response.started → (item.started → item.delta* → item.completed)* → resp
69
69
 
70
70
  事件类型:
71
71
 
72
- | 事件 | 含义 |
73
- | ------------------------------------- | ------------------------------- |
74
- | `response.started` | 响应开始 |
75
- | `message.{started,delta,completed}` | 消息输出 |
76
- | `reasoning.{started,delta,completed}` | 思维链 |
77
- | `tool_call.{started,delta,completed}` | 工具调用 |
78
- | `response.warning` | 非致命警告 |
79
- | `response.auxiliary` | usage / billing 辅助信息 |
80
- | `response.completed` | 响应结束,内含完整 `AIResponse` |
72
+ | 事件 | 含义 |
73
+ | ------------------------------------- | ------------------------------------------- |
74
+ | `response.started` | 响应开始 |
75
+ | `message.{started,delta,completed}` | 消息输出 |
76
+ | `reasoning.{started,delta,completed}` | 思维链 |
77
+ | `tool_call.{started,delta,completed}` | 工具调用 |
78
+ | `response.warning` | 非致命警告 |
79
+ | `response.auxiliary` | usage / billing 辅助信息 |
80
+ | `response.completed` | 响应结束,携带 replay、终止原因及最终元数据 |
81
81
 
82
82
  ### 统一终结结果
83
83
 
84
84
  流结束后可通过 `collectStream()` 聚合为 `AIResponse`:
85
85
 
86
86
  ```ts
87
- import { collectStream } from "nano-ai";
87
+ import { collectStream } from "@codehz/ai";
88
88
 
89
89
  const response = await collectStream(client.stream({ input }));
90
90
  console.log(response.text); // 全部文本
@@ -95,17 +95,18 @@ console.log(response.replay); // 续接材料
95
95
 
96
96
  `AIResponse` 包含:
97
97
 
98
- | 字段 | 类型 | 说明 |
99
- | ------------ | ---------------- | ------------------------ |
100
- | `output` | `OutputItem[]` | 当前轮输出 |
101
- | `replay` | `ReplayItem[]` | 续接材料(下次请求带回) |
102
- | `text` | `string` | 全部文本拼接 |
103
- | `toolCalls` | `ToolCallItem[]` | 工具调用 |
104
- | `stopReason` | `StopReason` | 终止原因 |
105
- | `usage` | `Usage` | token 统计 |
106
- | `billing` | `BillingInfo` | 计费信息 |
107
- | `warnings` | `string[]` | 非致命警告 |
108
- | `backend` | `BackendTrace` | 调用链路元数据 |
98
+ | 字段 | 类型 | 说明 |
99
+ | ------------ | ---------------- | ------------------------- |
100
+ | `output` | `OutputItem[]` | 当前轮输出 |
101
+ | `replay` | `ReplayItem[]` | 续接材料(下次请求带回) |
102
+ | `text` | `string` | 全部文本拼接 |
103
+ | `toolCalls` | `ToolCallItem[]` | 工具调用 |
104
+ | `stopReason` | `StopReason?` | 终止原因(可选) |
105
+ | `usage` | `Usage?` | token 统计(可选) |
106
+ | `billing` | `BillingInfo?` | 计费信息(可选) |
107
+ | `auxiliary` | `AuxiliaryInfo?` | Provider 辅助信息(可选) |
108
+ | `warnings` | `string[]?` | 非致命警告(可选) |
109
+ | `backend` | `BackendTrace` | 调用链路元数据 |
109
110
 
110
111
  流式 `message.delta` / `reasoning.delta` 保持后端分片粒度;完成态 `output` 中的
111
112
  `message` / `reasoning` 会合并相邻 `text` content blocks(直接拼接且不添加分隔符),
@@ -129,7 +130,7 @@ import {
129
130
  OllamaAdapter,
130
131
  MockAdapter,
131
132
  withMockStreaming,
132
- } from "nano-ai";
133
+ } from "@codehz/ai";
133
134
 
134
135
  // OpenAI Responses API
135
136
  const responses = new ResponsesAdapter({ apiKey: "sk-..." });
@@ -163,20 +164,15 @@ const mock = new MockAdapter({
163
164
  });
164
165
  ```
165
166
 
166
- 公开 adapter 接口暴露稳定标识和各维度能力:
167
+ 公开 adapter 接口暴露稳定标识和流来源:
167
168
 
168
169
  ```ts
169
170
  adapter.kind; // "responses" | "messages" | "chat-completions" | ...
170
- adapter.capabilities.textStreaming; // "native" | "synthetic" | "none"
171
- adapter.capabilities.reasoningStreaming;
172
- adapter.capabilities.toolCallStreaming;
173
- adapter.capabilities.replay; // "canonical" | "opaque" | "none"
174
- adapter.capabilities.usage; // "stream" | "final" | "none"
175
- adapter.capabilities.toolResultOutcomes;
171
+ adapter.isSyntheticStream;
176
172
  ```
177
173
 
178
- `nativeStreaming` 已由 `capabilities` 直接替代。响应级 `backend.isSyntheticStream` 根据
179
- `textStreaming === "synthetic"` 推导;具体响应内容仍应从本次事件流、warning 和 `replay` 判断。
174
+ 响应级 `backend.isSyntheticStream` 使用同一标记;具体响应内容仍应从
175
+ 本次事件流、warning 和 `replay` 判断。
180
176
 
181
177
  ## Mock 后端
182
178
 
@@ -208,7 +204,7 @@ const handler = withMockStreaming(
208
204
  - 可用 `assertMockRequest()` 验证调用方是否把上一轮 `replay` 和当前 `tool_result` 正确带回
209
205
 
210
206
  ```ts
211
- import { assertMockRequest, createAIClient, MockAdapter } from "nano-ai";
207
+ import { assertMockRequest, createAIClient, MockAdapter } from "@codehz/ai";
212
208
 
213
209
  const client = createAIClient({
214
210
  adapter: new MockAdapter({
@@ -325,7 +321,7 @@ const r2 = await collectStream(client.stream({ input, tools }));
325
321
  非流式后端可通过 `syntheticStream()` 包装为规范事件流:
326
322
 
327
323
  ```ts
328
- import { syntheticStream } from "nano-ai";
324
+ import { syntheticStream } from "@codehz/ai";
329
325
 
330
326
  const events = syntheticStream({
331
327
  model: "gpt-4o",
@@ -345,7 +341,7 @@ for await (const event of events) {
345
341
  `AuxiliaryCollector` 提供分层 best-effort 采集(流事件 → headers → lookup → derived):
346
342
 
347
343
  ```ts
348
- import { AuxiliaryCollector } from "nano-ai";
344
+ import { AuxiliaryCollector } from "@codehz/ai";
349
345
 
350
346
  const collector = new AuxiliaryCollector();
351
347
  collector.recordUsage({ inputTokens: 10, outputTokens: 5 }, "stream");
package/dist/index.d.mts CHANGED
@@ -42,7 +42,6 @@ type ToolCallItem = {
42
42
  id: string;
43
43
  name: string;
44
44
  argumentsText: string;
45
- argumentsJson?: unknown;
46
45
  };
47
46
  type ToolResultItem = {
48
47
  type: "tool_result";
@@ -88,7 +87,8 @@ type AIRequest = {
88
87
  include?: IncludeSettings;
89
88
  metadata?: Record<string, string>;
90
89
  temperature?: number;
91
- maxOutputTokens?: number;
90
+ maxOutputTokens?: number; /** AbortSignal 用于打断请求。abort 时 fetch 调用会被取消,流迭代器抛出 AbortError。 */
91
+ signal?: AbortSignal;
92
92
  };
93
93
  //#endregion
94
94
  //#region src/types/response.d.ts
@@ -233,24 +233,16 @@ type NormalizedRequest = AIRequest & {
233
233
  model: string;
234
234
  requestId: string;
235
235
  };
236
- type StreamingCapability = "native" | "synthetic" | "none";
237
- type AdapterCapabilities = {
238
- readonly textStreaming: StreamingCapability;
239
- readonly reasoningStreaming: StreamingCapability;
240
- readonly toolCallStreaming: StreamingCapability;
241
- readonly replay: "canonical" | "opaque" | "none";
242
- readonly usage: "stream" | "final" | "none";
243
- readonly toolResultOutcomes: ReadonlyArray<"success" | "error" | "rejected">;
244
- };
245
236
  interface BackendAdapter {
246
237
  readonly kind: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
247
- readonly capabilities: AdapterCapabilities;
238
+ readonly isSyntheticStream: boolean;
248
239
  stream(request: NormalizedRequest): AsyncIterable<AIStreamEvent>;
249
240
  }
250
241
  type CreateAIClientOptions = {
251
242
  adapter: BackendAdapter;
252
243
  model: string;
253
- defaults?: Partial<AIRequest>;
244
+ defaults?: Partial<AIRequest>; /** 全局默认 AbortSignal,当 request.signal 未设置时生效。 */
245
+ signal?: AbortSignal;
254
246
  };
255
247
  interface AIClient {
256
248
  stream(request: AIRequest): AsyncIterable<AIStreamEvent>;
@@ -523,7 +515,7 @@ type StreamResult = {
523
515
  };
524
516
  declare abstract class AdapterBase implements BackendAdapter {
525
517
  abstract readonly kind: "chat-completions" | "messages" | "responses" | "ollama" | "mock";
526
- abstract readonly capabilities: AdapterCapabilities;
518
+ abstract readonly isSyntheticStream: boolean;
527
519
  /**
528
520
  * stream 模板方法:
529
521
  * 1. 创建事件工厂,发射 response.started
@@ -616,7 +608,7 @@ type ResponsesTool = {
616
608
  };
617
609
  declare class ResponsesAdapter extends AdapterBase {
618
610
  readonly kind: "responses";
619
- readonly capabilities: AdapterCapabilities;
611
+ readonly isSyntheticStream = false;
620
612
  private apiKey;
621
613
  private baseUrl;
622
614
  private fetchFn;
@@ -684,7 +676,7 @@ type MessagesAPITool = {
684
676
  };
685
677
  declare class MessagesAdapter extends AdapterBase {
686
678
  readonly kind: "messages";
687
- readonly capabilities: AdapterCapabilities;
679
+ readonly isSyntheticStream = false;
688
680
  private apiKey;
689
681
  private apiVersion;
690
682
  private baseUrl;
@@ -742,7 +734,7 @@ type ChatTool = {
742
734
  };
743
735
  declare class ChatCompletionsAdapter extends AdapterBase {
744
736
  readonly kind: "chat-completions";
745
- readonly capabilities: AdapterCapabilities;
737
+ readonly isSyntheticStream = false;
746
738
  private apiKey;
747
739
  private baseUrl;
748
740
  private fetchFn;
@@ -790,7 +782,7 @@ type OllamaTool = {
790
782
  };
791
783
  declare class OllamaAdapter extends AdapterBase {
792
784
  readonly kind: "ollama";
793
- readonly capabilities: AdapterCapabilities;
785
+ readonly isSyntheticStream = false;
794
786
  private baseUrl;
795
787
  private apiKey;
796
788
  private fetchFn;
@@ -839,7 +831,8 @@ type MockHandlerContext = {
839
831
  turnIndex: number;
840
832
  previousReplay: ReplayItem[];
841
833
  pendingToolCalls: readonly ToolCallItem[];
842
- history: readonly MockHistoryRecord[];
834
+ history: readonly MockHistoryRecord[]; /** 请求的 AbortSignal,handler 可检查 signal.aborted 提前退出。 */
835
+ signal?: AbortSignal;
843
836
  };
844
837
  type MockWarningStep = {
845
838
  type: "warning";
@@ -886,7 +879,6 @@ type MockToolCallStep = {
886
879
  id: string;
887
880
  name: string;
888
881
  argumentsText: string;
889
- argumentsJson?: unknown;
890
882
  streamArguments?: boolean;
891
883
  stream?: MockTextStreamOptions | false;
892
884
  };
@@ -939,14 +931,7 @@ type MockProviderRequest = {
939
931
  declare function assertMockRequest(request: NormalizedRequest, expectation: MockRequestExpectation, context: MockHandlerContext): void;
940
932
  declare class MockAdapter extends AdapterBase {
941
933
  readonly kind: "mock";
942
- readonly capabilities: {
943
- readonly textStreaming: "synthetic";
944
- readonly reasoningStreaming: "synthetic";
945
- readonly toolCallStreaming: "synthetic";
946
- readonly replay: "canonical";
947
- readonly usage: "final";
948
- readonly toolResultOutcomes: readonly ["success", "error", "rejected"];
949
- };
934
+ readonly isSyntheticStream = true;
950
935
  private readonly handler;
951
936
  private readonly providerMetadata?;
952
937
  private cursor;
@@ -979,7 +964,7 @@ declare function opaqueBlock(payload: unknown): ContentBlock & {
979
964
  };
980
965
  declare function messageItem(content: ContentBlock[], overrides?: Partial<Omit<MessageItem, "type" | "content">>): MessageItem;
981
966
  declare function reasoningItem(content: ContentBlock[], visibility?: ReasoningItem["visibility"], id?: string): ReasoningItem;
982
- declare function toolCallItem(id: string, name: string, argumentsText: string, argumentsJson?: unknown): ToolCallItem;
967
+ declare function toolCallItem(id: string, name: string, argumentsText: string): ToolCallItem;
983
968
  declare function toolResultItem(callId: string, toolName: string, outcome: ToolResultItem["outcome"], content: ContentBlock[]): ToolResultItem;
984
969
  declare function opaqueItem(source: OpaqueItem["source"], purpose: OpaqueItem["purpose"], payload: unknown, id?: string): OpaqueItem;
985
970
  /**
@@ -1190,27 +1175,20 @@ declare function splitLines(buffer: string, allowEOF: boolean): StreamSplitResul
1190
1175
  declare function splitSSEFrames(buffer: string, allowEOF: boolean): StreamSplitResult;
1191
1176
  //#endregion
1192
1177
  //#region src/helpers/request-mapper.d.ts
1193
- type ProviderProfile = {
1194
- readonly kind: string;
1195
- readonly instructionsMode: "system_message" | "instructions_field" | "none";
1196
- readonly supportedBlockTypes: ReadonlyArray<ContentBlock["type"]>;
1197
- readonly reasoningBlockTypes: ReadonlyArray<ContentBlock["type"]>;
1198
- readonly capabilities: AdapterCapabilities;
1199
- };
1200
1178
  declare class NormalizedRequestMapper {
1201
- readonly profile: ProviderProfile;
1202
- constructor(profile: ProviderProfile);
1179
+ readonly kind: string;
1180
+ constructor(kind: string);
1203
1181
  mapInstructions(instructions: string | InstructionBlock[]): string;
1204
1182
  ensureTextBlocks(blocks: ContentBlock[], field: string): ContentBlock[];
1205
1183
  ensureReasoningBlocks(blocks: ContentBlock[], field: string): Array<Extract<ContentBlock, {
1206
1184
  type: "text";
1207
1185
  }>>;
1208
- assertToolResultOutcome(outcome: ToolResultItem["outcome"]): void;
1186
+ parseToolArguments(item: ToolCallItem): Record<string, unknown>;
1209
1187
  rollbackTrailingAssistantMessages<T extends {
1210
1188
  role: string;
1211
1189
  }>(messages: T[]): void;
1212
1190
  private ensureBlocks;
1213
1191
  }
1214
1192
  //#endregion
1215
- export { type AIClient, AIError, AIMappingError, AIProviderError, type AIRequest, AIRequestError, type AIResponse, AIStreamError, type AIStreamEvent, AdapterAuxiliaryState, AdapterBase, type AdapterCapabilities, 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, IncrementalStreamParser, type InputItem, type InstructionBlock, type JsonContentBlock, type LookupResult, MAX_OPAQUE_JSON_DEPTH, MAX_OPAQUE_PAYLOAD_BYTES, type MessageCompletedEvent, type MessageDeltaEvent, type MessageItem, type MessageStartedEvent, MessagesAdapter, type MessagesAdapterOptions, MockAdapter, type MockAdapterOptions, type MockAuxiliaryStep, type MockCompleteStep, type MockErrorStep, type MockHandler, type MockHandlerContext, type MockHistoryRecord, type MockInputExpectation, type MockInterruptStep, type MockMessageStep, type MockOutputStep, type MockReasoningStep, type MockRequestExpectation, type MockStaticHandler, type MockStep, type MockTextStreamOptions, type MockThrowStep, type MockToolCallStep, type MockWarningStep, type NormalizeOptions, type NormalizedRequest, NormalizedRequestMapper, OllamaAdapter, type OllamaAdapterOptions, type OpaqueEnvelopeResult, type OpaqueItem, type OutputItem, PROVIDER_ERROR_MESSAGE_MAX_LEN, PROVIDER_ERROR_RAW_BODY_THRESHOLD, type ProviderProfile, 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 StreamParseResult, type StreamResult, type StreamSplitResult, type StreamingCapability, type SyntheticStreamOptions, type TextContentBlock, type ToolCallCompletedEvent, type ToolCallDeltaEvent, type ToolCallItem, type ToolCallStartedEvent, type ToolChoice, type ToolDefinition, type ToolResultItem, type Usage, type UsageSource, type ValidationIssue, WarningCode, aggregateEvents, assertMockRequest, assertOpaqueReplayEnvelope, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createEventFactory, emitMalformedStreamWarning, extractProviderErrorMessage, extractText, imageBlock, instructionsToText, jsonBlock, mapReasoningVisibility, mapStopReason, measureJsonDepth, messageItem, metadataSourceList, normalizeRequest, opaqueBlock, opaqueItem, parseSSEEvents, providerHttpError, reasoningItem, replayFromOutput, splitLines, splitSSEFrames, syntheticStream, textBlock, toolCallItem, toolResultItem, usageFromAnthropicMessages, usageFromChatCompletions, usageFromOllama, usageFromOpenAIResponses, validateOpaqueReplayEnvelope, validateRequest, withMockStreaming };
1193
+ 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, IncrementalStreamParser, type InputItem, type InstructionBlock, type JsonContentBlock, type LookupResult, MAX_OPAQUE_JSON_DEPTH, MAX_OPAQUE_PAYLOAD_BYTES, type MessageCompletedEvent, type MessageDeltaEvent, type MessageItem, type MessageStartedEvent, MessagesAdapter, type MessagesAdapterOptions, MockAdapter, type MockAdapterOptions, type MockAuxiliaryStep, type MockCompleteStep, type MockErrorStep, type MockHandler, type MockHandlerContext, type MockHistoryRecord, type MockInputExpectation, type MockInterruptStep, type MockMessageStep, type MockOutputStep, type MockReasoningStep, type MockRequestExpectation, type MockStaticHandler, type MockStep, type MockTextStreamOptions, type MockThrowStep, type MockToolCallStep, type MockWarningStep, type NormalizeOptions, type NormalizedRequest, NormalizedRequestMapper, OllamaAdapter, type OllamaAdapterOptions, type OpaqueEnvelopeResult, type OpaqueItem, type OutputItem, PROVIDER_ERROR_MESSAGE_MAX_LEN, PROVIDER_ERROR_RAW_BODY_THRESHOLD, 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 StreamParseResult, type StreamResult, type StreamSplitResult, type SyntheticStreamOptions, type TextContentBlock, type ToolCallCompletedEvent, type ToolCallDeltaEvent, type ToolCallItem, type ToolCallStartedEvent, type ToolChoice, type ToolDefinition, type ToolResultItem, type Usage, type UsageSource, type ValidationIssue, WarningCode, aggregateEvents, assertMockRequest, assertOpaqueReplayEnvelope, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createEventFactory, emitMalformedStreamWarning, extractProviderErrorMessage, extractText, imageBlock, instructionsToText, jsonBlock, mapReasoningVisibility, mapStopReason, measureJsonDepth, messageItem, metadataSourceList, normalizeRequest, opaqueBlock, opaqueItem, parseSSEEvents, providerHttpError, reasoningItem, replayFromOutput, splitLines, splitSSEFrames, syntheticStream, textBlock, toolCallItem, toolResultItem, usageFromAnthropicMessages, usageFromChatCompletions, usageFromOllama, usageFromOpenAIResponses, validateOpaqueReplayEnvelope, validateRequest, withMockStreaming };
1216
1194
  //# sourceMappingURL=index.d.mts.map