@xsai/text 1.0.0-beta.3 → 1.0.0-beta.5

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/dist/index.d.ts CHANGED
@@ -1,8 +1,20 @@
1
- import { M as Message, S as StepResult, L as LanguageModelOptions, a as LanguageModel, T as ToolResultPart, b as ToolExecuteOptions, c as ToolCallPart, d as TextEvent, C as CollectResult } from './language-model-DlNwTTFi.js';
2
- export { A as AssistantMessage, e as AssistantMessageContent, f as CombinedStandardSchema, g as Content, h as ContentEndEvent, i as ContentMap, j as ContentStartEvent, k as ContentType, D as DeveloperMessage, l as DeveloperMessageContent, E as ExecutableTool, F as FilePart, m as FinishReason, I as ImagePart, n as InferSchemaInput, o as InferSchemaOutput, J as JSONSchema7, p as JSONSchema7Definition, q as LanguageModelProviderOptions, r as MessageMap, s as MessageProviderMetadata, t as MessageType, P as PartProviderMetadata, u as ProviderPart, R as RawEvent, v as ReasoningDeltaEvent, w as ReasoningPart, x as ReasoningPartContent, y as RefusalDeltaEvent, z as RefusalPart, B as ResolvedSchema, G as StepEndDoneEvent, H as StepEndEvent, K as StepEndFailEvent, N as StepStartEvent, O as StepStatus, Q as SystemMessage, U as SystemMessageContent, V as TextDeltaEvent, W as TextEventMap, X as TextEventType, Y as TextPart, Z as Tool, _ as ToolCallDeltaEvent, $ as ToolChoice, a0 as ToolOptions, a1 as ToolResultPartContent, a2 as UnresolvedSchema, a3 as Usage, a4 as UserMessage, a5 as UserMessageContent, a6 as collect, a7 as resolveSchema, a8 as tool } from './language-model-DlNwTTFi.js';
1
+ import { S as StepEndDoneEvent, T as ToolCallPart, a as ToolResultPart, U as Usage, b as TextEvent, M as Message, L as LanguageModelOptions, c as LanguageModel, d as ToolExecuteOptions } from './language-model-Dne8NRLD.js';
2
+ export { A as AssistantMessage, e as AssistantMessageContent, f as AudioPart, C as CombinedStandardSchema, g as Content, h as ContentEndEvent, i as ContentMap, j as ContentStartEvent, k as ContentType, D as DeveloperMessage, l as DeveloperMessageContent, E as ExecutableTool, F as FilePart, m as FinishReason, I as ImagePart, n as InferSchemaInput, o as InferSchemaOutput, J as JSONSchema7, p as JSONSchema7Definition, q as LanguageModelProviderOptions, r as MessageMap, s as MessageProviderMetadata, t as MessageType, P as PartProviderMetadata, u as ProviderPart, R as RawEvent, v as ReasoningDeltaEvent, w as ReasoningPart, x as ReasoningPartContent, y as RefusalDeltaEvent, z as RefusalPart, B as ResolvedSchema, G as StepEndEvent, H as StepEndFailEvent, K as StepStartEvent, N as StepStatus, O as SystemMessage, Q as SystemMessageContent, V as TextDeltaEvent, W as TextEventMap, X as TextEventType, Y as TextPart, Z as Tool, _ as ToolCallDeltaEvent, $ as ToolChoice, a0 as ToolOptions, a1 as ToolResultPartContent, a2 as UnresolvedSchema, a3 as UserMessage, a4 as UserMessageContent, a5 as resolveSchema, a6 as tool } from './language-model-Dne8NRLD.js';
3
3
  import { Promisable } from '@xsai/shared';
4
4
  export { HttpError, XSAIError, XSAIErrorCause, XSAIErrorCauseMap, XSAIErrorCode, XSAIErrorOptions } from '@xsai/shared';
5
5
 
6
+ interface StepResult extends Omit<StepEndDoneEvent, 'error' | 'type'> {
7
+ text: string;
8
+ toolCalls: ToolCallPart[];
9
+ toolResults: ToolResultPart[];
10
+ }
11
+
12
+ interface CollectResult extends StepResult {
13
+ steps: readonly StepResult[];
14
+ totalUsage?: Usage;
15
+ }
16
+ declare const collect: (stream: ReadableStream<TextEvent>) => Promise<CollectResult>;
17
+
6
18
  type PrepareStep = (options: PrepareStepOptions) => Promisable<PrepareStepResult | undefined>;
7
19
  interface PrepareStepOptions {
8
20
  input: readonly Message[];
@@ -31,22 +43,16 @@ declare const stepCountAtLeast: (count: number) => StopCondition;
31
43
  type PostToolCall = (toolResult: ToolResultPart, options: ToolExecuteOptions) => Promisable<ToolResultPart | void>;
32
44
  type PreToolCall = (toolCall: ToolCallPart, options: ToolExecuteOptions) => Promisable<ToolCallPart | ToolResultPart | void>;
33
45
 
34
- interface LoopOptions extends LanguageModelOptions {
46
+ interface StreamTextOptions extends LanguageModelOptions {
35
47
  postToolCall?: PostToolCall;
36
48
  prepareStep?: PrepareStep;
37
49
  preToolCall?: PreToolCall;
38
50
  /** @default `maxSteps(10)` */
39
51
  stopWhen?: StopCondition;
40
52
  }
41
- declare const loop: (model: LanguageModel, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhenOption, ...options }: LoopOptions) => ReadableStream<TextEvent>;
42
-
43
- declare const generateText: (model: LanguageModel, options: LoopOptions) => Promise<CollectResult>;
53
+ declare const streamText: (model: LanguageModel, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhenOption, ...options }: StreamTextOptions) => ReadableStream<TextEvent>;
44
54
 
45
- interface StreamTextHandle {
46
- result: Promise<CollectResult>;
47
- stream: ReadableStream<TextEvent>;
48
- }
49
- declare const streamText: (model: LanguageModel, options: LoopOptions) => StreamTextHandle;
55
+ declare const generateText: (model: LanguageModel, options: StreamTextOptions) => Promise<CollectResult>;
50
56
 
51
57
  type TextEventListener<E extends Event> = ((this: EventTarget, event: E) => unknown) | {
52
58
  handleEvent: (event: E) => unknown;
@@ -76,5 +82,5 @@ declare module '@xsai/shared' {
76
82
  }
77
83
  }
78
84
 
79
- export { CollectResult, LanguageModel, LanguageModelOptions, Message, StepResult, TextEvent, TextEventTarget, ToolCallPart, ToolExecuteOptions, ToolResultPart, and, generateText, hasToolCall, loop, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, withEventTarget };
80
- export type { LoopOptions, PostToolCall, PreToolCall, PrepareStep, PrepareStepOptions, PrepareStepResult, StopCondition, StopContext, StreamTextHandle };
85
+ export { LanguageModel, LanguageModelOptions, Message, StepEndDoneEvent, TextEvent, TextEventTarget, ToolCallPart, ToolExecuteOptions, ToolResultPart, Usage, and, collect, generateText, hasToolCall, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, withEventTarget };
86
+ export type { CollectResult, PostToolCall, PreToolCall, PrepareStep, PrepareStepOptions, PrepareStepResult, StepResult, StopCondition, StopContext, StreamTextOptions };
package/dist/index.js CHANGED
@@ -1,6 +1,67 @@
1
- import { t as toStepResult, c as collect, a as collectEvent, b as collectResult, r as resolveSchema } from './schema-7PLOBVJ3.js';
2
1
  import { XSAIError } from '@xsai/shared';
3
2
  export { HttpError, XSAIError } from '@xsai/shared';
3
+ import { r as resolveSchema } from './schema-Bny4Y6lV.js';
4
+
5
+ const getText = (message) => typeof message.content === "string" ? message.content : message.content.filter((part) => part.type === "text").map((part) => part.text).join("");
6
+ const getToolCalls = (message) => typeof message.content === "string" ? [] : message.content.filter((part) => part.type === "tool-call");
7
+ const toStepResult = (event) => {
8
+ const { type: _type, ...result } = event;
9
+ return {
10
+ ...result,
11
+ text: getText(event.message),
12
+ toolCalls: getToolCalls(event.message),
13
+ toolResults: []
14
+ };
15
+ };
16
+
17
+ const totalUsage = (steps) => {
18
+ const usages = steps.flatMap((step) => step.usage == null ? [] : [step.usage]);
19
+ if (usages.length === 0)
20
+ return void 0;
21
+ const sum = (key) => {
22
+ const values = usages.map((usage) => usage[key]).filter((value) => value != null);
23
+ return values.length === 0 ? void 0 : values.reduce((total, value) => total + value, 0);
24
+ };
25
+ return {
26
+ cacheCreationInputTokens: sum("cacheCreationInputTokens"),
27
+ cacheReadInputTokens: sum("cacheReadInputTokens"),
28
+ inputTokens: sum("inputTokens") ?? 0,
29
+ outputTokens: sum("outputTokens") ?? 0,
30
+ reasoningTokens: sum("reasoningTokens"),
31
+ totalTokens: sum("totalTokens") ?? 0
32
+ };
33
+ };
34
+ const collect = async (stream) => {
35
+ const steps = [];
36
+ let failedError;
37
+ for await (const event of stream) {
38
+ if (failedError != null)
39
+ continue;
40
+ if (event.type === "step.end") {
41
+ if (event.status === "failed")
42
+ failedError = event.error;
43
+ else
44
+ steps.push(toStepResult(event));
45
+ continue;
46
+ }
47
+ if (event.type !== "content.end" || event.content.type !== "tool-result")
48
+ continue;
49
+ const step = steps.at(-1);
50
+ if (step == null)
51
+ throw new XSAIError("protocol-error", "tool result arrived before a step.end event");
52
+ step.toolResults.push(event.content);
53
+ }
54
+ if (failedError != null)
55
+ throw failedError;
56
+ const finalStep = steps.at(-1);
57
+ if (finalStep == null)
58
+ throw new XSAIError("truncated-stream", "model stream ended without a step.end event");
59
+ return {
60
+ ...finalStep,
61
+ steps,
62
+ totalUsage: totalUsage(steps)
63
+ };
64
+ };
4
65
 
5
66
  const and = (...conditions) => (context) => conditions.every((condition) => condition(context));
6
67
  const or = (...conditions) => (context) => conditions.some((condition) => condition(context));
@@ -28,7 +89,7 @@ const catchToolError = async (call, signal, callback) => {
28
89
  }
29
90
  };
30
91
  const executeTool = async (call, { postToolCall, preToolCall, signal, tools }) => {
31
- const executeOptions = { signal };
92
+ const executeOptions = { callId: call.callId, signal };
32
93
  const preToolCallResult = await catchToolError(call, signal, async () => preToolCall?.(call, executeOptions));
33
94
  if (preToolCallResult != null) {
34
95
  assertSameCallId(call.callId, preToolCallResult.callId);
@@ -60,7 +121,7 @@ const executeTool = async (call, { postToolCall, preToolCall, signal, tools }) =
60
121
  shouldPostToolCall = true;
61
122
  return {
62
123
  callId: call.callId,
63
- output: await executableTool.execute(validatedInput, { signal }),
124
+ output: await executableTool.execute(validatedInput, executeOptions),
64
125
  type: "tool-result"
65
126
  };
66
127
  });
@@ -75,21 +136,38 @@ const executeTool = async (call, { postToolCall, preToolCall, signal, tools }) =
75
136
  const executeTools = async ({ reason, toolCalls, ...options }) => reason === "length" ? toolCalls.map((call) => toolError(call, "The response reached the output token limit before the tool call was complete.")) : Promise.all(toolCalls.map(async (call) => executeTool(call, options)));
76
137
 
77
138
  const readStep = async function* (stream, signal) {
139
+ const reader = stream.getReader();
140
+ let cancellation;
141
+ const abort = () => {
142
+ cancellation = reader.cancel(signal.reason);
143
+ void cancellation.catch(() => {
144
+ });
145
+ };
78
146
  let stepEnd;
79
- for await (const event of stream.pipeThrough(new TransformStream(), { signal })) {
80
- if (event.type === "step.end") {
81
- if (stepEnd != null)
82
- throw new XSAIError("protocol-error", "model stream produced more than one step.end event");
83
- stepEnd = event;
147
+ signal.addEventListener("abort", abort, { once: true });
148
+ try {
149
+ signal.throwIfAborted();
150
+ while (true) {
151
+ const { done, value: event } = await reader.read();
152
+ signal.throwIfAborted();
153
+ if (done)
154
+ break;
155
+ if (event.type === "step.end") {
156
+ if (stepEnd != null)
157
+ throw new XSAIError("protocol-error", "model stream produced more than one step.end event");
158
+ stepEnd = event;
159
+ }
160
+ yield event;
84
161
  }
85
- yield event;
162
+ if (stepEnd == null)
163
+ throw new XSAIError("truncated-stream", "model stream ended without a step.end event");
164
+ return stepEnd;
165
+ } finally {
166
+ signal.removeEventListener("abort", abort);
167
+ await (cancellation ?? reader.cancel(signal.reason)).finally(() => reader.releaseLock());
86
168
  }
87
- signal.throwIfAborted();
88
- if (stepEnd == null)
89
- throw new XSAIError("truncated-stream", "model stream ended without a step.end event");
90
- return stepEnd;
91
169
  };
92
- const loop = (model, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhenOption, ...options }) => {
170
+ const streamText = (model, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhenOption, ...options }) => {
93
171
  const stopWhen = stopWhenOption ?? maxSteps(10);
94
172
  const input = [...Array.isArray(options.input) ? options.input : [{ content: options.input, role: "user" }]];
95
173
  const steps = [];
@@ -150,59 +228,7 @@ const loop = (model, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhe
150
228
  }, { highWaterMark: 0 });
151
229
  };
152
230
 
153
- const generateText = async (model, options) => collect(loop(model, options));
154
-
155
- const streamText = (model, options) => {
156
- const result = Promise.withResolvers();
157
- void result.promise.catch(() => {
158
- });
159
- const steps = [];
160
- let sourceReader;
161
- let cancelled = false;
162
- const stream = new ReadableStream({
163
- cancel: async (reason) => {
164
- cancelled = true;
165
- result.reject(reason === void 0 ? new DOMException("The operation was aborted.", "AbortError") : reason);
166
- await sourceReader?.cancel(reason);
167
- },
168
- start: (controller) => {
169
- const reader = loop(model, options).getReader();
170
- sourceReader = reader;
171
- void (async () => {
172
- let failedError;
173
- try {
174
- while (true) {
175
- const { done, value } = await reader.read();
176
- if (done)
177
- break;
178
- if (cancelled)
179
- return;
180
- failedError ??= collectEvent(steps, value);
181
- controller.enqueue(value);
182
- }
183
- if (cancelled)
184
- return;
185
- if (failedError != null) {
186
- result.reject(failedError);
187
- controller.close();
188
- return;
189
- }
190
- result.resolve(collectResult(steps));
191
- controller.close();
192
- } catch (error) {
193
- if (cancelled)
194
- return;
195
- result.reject(error);
196
- controller.error(error);
197
- } finally {
198
- sourceReader = void 0;
199
- reader.releaseLock();
200
- }
201
- })();
202
- }
203
- });
204
- return { result: result.promise, stream };
205
- };
231
+ const generateText = async (model, options) => collect(streamText(model, options));
206
232
 
207
233
  const TextEventTarget = EventTarget;
208
234
  const toCustomEvent = (event) => {
@@ -233,7 +259,13 @@ const tool = ((options) => {
233
259
  return {
234
260
  ...tool2,
235
261
  execute: async (input, executeOptions) => {
236
- const result = await options.execute(input, executeOptions);
262
+ let result = await options.execute(input, executeOptions);
263
+ if (outputSchema?.validate != null) {
264
+ const validation = await outputSchema.validate(result);
265
+ if (validation.issues)
266
+ throw new Error(`Tool output validation failed for "${options.name}".`);
267
+ result = validation.value;
268
+ }
237
269
  if (outputSchema)
238
270
  return JSON.stringify(result);
239
271
  else
@@ -243,4 +275,4 @@ const tool = ((options) => {
243
275
  }
244
276
  });
245
277
 
246
- export { TextEventTarget, and, collect, generateText, hasToolCall, loop, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, tool, withEventTarget };
278
+ export { TextEventTarget, and, collect, generateText, hasToolCall, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, tool, withEventTarget };
@@ -1,5 +1,5 @@
1
1
  import { StepStatus, FinishReason, AssistantMessage, AssistantMessageContent, PartProviderMetadata, Usage, TextEvent, LanguageModelOptions } from './index.js';
2
- export { f as CombinedStandardSchema, n as InferSchemaInput, o as InferSchemaOutput, J as JSONSchema7, p as JSONSchema7Definition, B as ResolvedSchema, a2 as UnresolvedSchema, a9 as collectEvent, aa as collectResult, a7 as resolveSchema } from './language-model-DlNwTTFi.js';
2
+ export { C as CombinedStandardSchema, n as InferSchemaInput, o as InferSchemaOutput, J as JSONSchema7, p as JSONSchema7Definition, B as ResolvedSchema, a2 as UnresolvedSchema, a5 as resolveSchema } from './language-model-Dne8NRLD.js';
3
3
  import { XSAIError, EventSourceMessage, SendRequestOptions, HttpOptions } from '@xsai/shared';
4
4
 
5
5
  interface EventBuilder {
package/dist/internal.js CHANGED
@@ -1,5 +1,5 @@
1
- export { a as collectEvent, b as collectResult, r as resolveSchema } from './schema-7PLOBVJ3.js';
2
1
  import { XSAIError, sendRequest, EventSourceParserStream } from '@xsai/shared';
2
+ export { r as resolveSchema } from './schema-Bny4Y6lV.js';
3
3
 
4
4
  const emptyContent = (type, init) => {
5
5
  switch (type) {
@@ -5,8 +5,14 @@ interface MessageProviderMetadata {
5
5
  interface PartProviderMetadata {
6
6
  }
7
7
 
8
+ interface AudioPart {
9
+ data: string;
10
+ format: 'mp3' | 'wav';
11
+ type: 'audio';
12
+ }
8
13
  type Content = ContentMap[ContentType];
9
14
  interface ContentMap {
15
+ 'audio': AudioPart;
10
16
  'file': FilePart;
11
17
  'image': ImagePart;
12
18
  'provider': ProviderPart;
@@ -96,7 +102,7 @@ interface UserMessage {
96
102
  content: readonly UserMessageContent[] | string;
97
103
  role: 'user';
98
104
  }
99
- type UserMessageContent = FilePart | ImagePart | TextPart | ToolResultPart;
105
+ type UserMessageContent = AudioPart | FilePart | ImagePart | TextPart | ToolResultPart;
100
106
 
101
107
  interface Usage {
102
108
  cacheCreationInputTokens?: number;
@@ -180,22 +186,6 @@ interface ToolCallDeltaEvent {
180
186
  type: 'tool-call.delta';
181
187
  }
182
188
 
183
- interface StepResult extends Omit<StepEndDoneEvent, 'error' | 'type'> {
184
- text: string;
185
- toolCalls: ToolCallPart[];
186
- toolResults: ToolResultPart[];
187
- }
188
-
189
- interface CollectResult extends StepResult {
190
- steps: readonly StepResult[];
191
- totalUsage?: Usage;
192
- }
193
- /** @internal */
194
- declare const collectEvent: (steps: StepResult[], event: TextEvent) => unknown;
195
- /** @internal */
196
- declare const collectResult: (steps: StepResult[]) => CollectResult;
197
- declare const collect: (stream: ReadableStream<TextEvent>) => Promise<CollectResult>;
198
-
199
189
  /** The Standard Typed interface. This is a base type extended by other specs. */
200
190
  interface StandardTypedV1<Input = unknown, Output = Input> {
201
191
  /** The Standard properties. */
@@ -503,6 +493,7 @@ interface Tool {
503
493
  outputSchema?: ResolvedSchema;
504
494
  }
505
495
  interface ToolExecuteOptions {
496
+ callId: string;
506
497
  signal?: AbortSignal;
507
498
  }
508
499
  interface ToolOptions<TInput extends UnresolvedSchema, TOutput extends undefined | UnresolvedSchema = undefined> {
@@ -541,5 +532,5 @@ type ToolChoice = 'auto' | 'none' | 'required' | {
541
532
  name: string;
542
533
  };
543
534
 
544
- export { collect as a6, resolveSchema as a7, tool as a8, collectEvent as a9, collectResult as aa };
545
- export type { ToolChoice as $, AssistantMessage as A, ResolvedSchema as B, CollectResult as C, DeveloperMessage as D, ExecutableTool as E, FilePart as F, StepEndDoneEvent as G, StepEndEvent as H, ImagePart as I, JSONSchema7 as J, StepEndFailEvent as K, LanguageModelOptions as L, Message as M, StepStartEvent as N, StepStatus as O, PartProviderMetadata as P, SystemMessage as Q, RawEvent as R, StepResult as S, ToolResultPart as T, SystemMessageContent as U, TextDeltaEvent as V, TextEventMap as W, TextEventType as X, TextPart as Y, Tool as Z, ToolCallDeltaEvent as _, LanguageModel as a, ToolOptions as a0, ToolResultPartContent as a1, UnresolvedSchema as a2, Usage as a3, UserMessage as a4, UserMessageContent as a5, ToolExecuteOptions as b, ToolCallPart as c, TextEvent as d, AssistantMessageContent as e, CombinedStandardSchema as f, Content as g, ContentEndEvent as h, ContentMap as i, ContentStartEvent as j, ContentType as k, DeveloperMessageContent as l, FinishReason as m, InferSchemaInput as n, InferSchemaOutput as o, JSONSchema7Definition as p, LanguageModelProviderOptions as q, MessageMap as r, MessageProviderMetadata as s, MessageType as t, ProviderPart as u, ReasoningDeltaEvent as v, ReasoningPart as w, ReasoningPartContent as x, RefusalDeltaEvent as y, RefusalPart as z };
535
+ export { resolveSchema as a5, tool as a6 };
536
+ export type { ToolChoice as $, AssistantMessage as A, ResolvedSchema as B, CombinedStandardSchema as C, DeveloperMessage as D, ExecutableTool as E, FilePart as F, StepEndEvent as G, StepEndFailEvent as H, ImagePart as I, JSONSchema7 as J, StepStartEvent as K, LanguageModelOptions as L, Message as M, StepStatus as N, SystemMessage as O, PartProviderMetadata as P, SystemMessageContent as Q, RawEvent as R, StepEndDoneEvent as S, ToolCallPart as T, Usage as U, TextDeltaEvent as V, TextEventMap as W, TextEventType as X, TextPart as Y, Tool as Z, ToolCallDeltaEvent as _, ToolResultPart as a, ToolOptions as a0, ToolResultPartContent as a1, UnresolvedSchema as a2, UserMessage as a3, UserMessageContent as a4, TextEvent as b, LanguageModel as c, ToolExecuteOptions as d, AssistantMessageContent as e, AudioPart as f, Content as g, ContentEndEvent as h, ContentMap as i, ContentStartEvent as j, ContentType as k, DeveloperMessageContent as l, FinishReason as m, InferSchemaInput as n, InferSchemaOutput as o, JSONSchema7Definition as p, LanguageModelProviderOptions as q, MessageMap as r, MessageProviderMetadata as s, MessageType as t, ProviderPart as u, ReasoningDeltaEvent as v, ReasoningPart as w, ReasoningPartContent as x, RefusalDeltaEvent as y, RefusalPart as z };
@@ -0,0 +1,6 @@
1
+ const resolveSchema = (schema) => "~standard" in schema ? {
2
+ schema: schema["~standard"].jsonSchema.input({ target: "draft-07" }),
3
+ validate: schema["~standard"].validate
4
+ } : { schema };
5
+
6
+ export { resolveSchema as r };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xsai/text",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.3",
4
+ "version": "1.0.0-beta.5",
5
5
  "description": "extra-small AI SDK: provider-agnostic text generation, streaming and tool calling.",
6
6
  "author": "Moeru AI",
7
7
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "node": ">=26"
42
42
  },
43
43
  "dependencies": {
44
- "@xsai/shared": "1.0.0-beta.3"
44
+ "@xsai/shared": "1.0.0-beta.5"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@standard-schema/spec": "1.1.0",
@@ -1,69 +0,0 @@
1
- import { XSAIError } from '@xsai/shared';
2
-
3
- const getText = (message) => typeof message.content === "string" ? message.content : message.content.filter((part) => part.type === "text").map((part) => part.text).join("");
4
- const getToolCalls = (message) => typeof message.content === "string" ? [] : message.content.filter((part) => part.type === "tool-call");
5
- const toStepResult = (event) => {
6
- const { type: _type, ...result } = event;
7
- return {
8
- ...result,
9
- text: getText(event.message),
10
- toolCalls: getToolCalls(event.message),
11
- toolResults: []
12
- };
13
- };
14
-
15
- const totalUsage = (steps) => {
16
- const usages = steps.flatMap((step) => step.usage == null ? [] : [step.usage]);
17
- if (usages.length === 0)
18
- return void 0;
19
- const sum = (key) => {
20
- const values = usages.map((usage) => usage[key]).filter((value) => value != null);
21
- return values.length === 0 ? void 0 : values.reduce((total, value) => total + value, 0);
22
- };
23
- return {
24
- cacheCreationInputTokens: sum("cacheCreationInputTokens"),
25
- cacheReadInputTokens: sum("cacheReadInputTokens"),
26
- inputTokens: sum("inputTokens") ?? 0,
27
- outputTokens: sum("outputTokens") ?? 0,
28
- reasoningTokens: sum("reasoningTokens"),
29
- totalTokens: sum("totalTokens") ?? 0
30
- };
31
- };
32
- const collectEvent = (steps, event) => {
33
- if (event.type === "step.end") {
34
- if (event.status === "failed")
35
- return event.error;
36
- steps.push(toStepResult(event));
37
- } else if (event.type === "content.end" && event.content.type === "tool-result") {
38
- const step = steps.at(-1);
39
- if (step == null)
40
- throw new XSAIError("protocol-error", "tool result arrived before a step.end event");
41
- step.toolResults.push(event.content);
42
- }
43
- };
44
- const collectResult = (steps) => {
45
- const finalStep = steps.at(-1);
46
- if (finalStep == null)
47
- throw new XSAIError("truncated-stream", "model stream ended without a step.end event");
48
- return {
49
- ...finalStep,
50
- steps,
51
- totalUsage: totalUsage(steps)
52
- };
53
- };
54
- const collect = async (stream) => {
55
- const steps = [];
56
- let failedError;
57
- for await (const event of stream)
58
- failedError ??= collectEvent(steps, event);
59
- if (failedError != null)
60
- throw failedError;
61
- return collectResult(steps);
62
- };
63
-
64
- const resolveSchema = (schema) => "~standard" in schema ? {
65
- schema: schema["~standard"].jsonSchema.input({ target: "draft-07" }),
66
- validate: schema["~standard"].validate
67
- } : { schema };
68
-
69
- export { collectEvent as a, collectResult as b, collect as c, resolveSchema as r, toStepResult as t };