@xsai/text 1.0.0-beta.2 → 1.0.0-beta.4

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-rSwDu2og.js';
2
+ export { A as AssistantMessage, e as AssistantMessageContent, C as CombinedStandardSchema, f as Content, g as ContentEndEvent, h as ContentMap, i as ContentStartEvent, j as ContentType, D as DeveloperMessage, k as DeveloperMessageContent, E as ExecutableTool, F as FilePart, l as FinishReason, I as ImagePart, m as InferSchemaInput, n as InferSchemaOutput, J as JSONSchema7, o as JSONSchema7Definition, p as LanguageModelProviderOptions, q as MessageMap, r as MessageProviderMetadata, s as MessageType, P as PartProviderMetadata, t as ProviderPart, R as RawEvent, u as ReasoningDeltaEvent, v as ReasoningPart, w as ReasoningPartContent, x as RefusalDeltaEvent, y as RefusalPart, z as ResolvedSchema, B as StepEndEvent, G as StepEndFailEvent, H as StepStartEvent, K as StepStatus, N as SystemMessage, O as SystemMessageContent, Q as TextDeltaEvent, V as TextEventMap, W as TextEventType, X as TextPart, Y as Tool, Z as ToolCallDeltaEvent, _ as ToolChoice, $ as ToolOptions, a0 as ToolResultPartContent, a1 as UnresolvedSchema, a2 as UserMessage, a3 as UserMessageContent, a4 as resolveSchema, a5 as tool } from './language-model-rSwDu2og.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));
@@ -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, m as InferSchemaInput, n as InferSchemaOutput, J as JSONSchema7, o as JSONSchema7Definition, z as ResolvedSchema, a1 as UnresolvedSchema, a4 as resolveSchema } from './language-model-rSwDu2og.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) {
@@ -180,22 +180,6 @@ interface ToolCallDeltaEvent {
180
180
  type: 'tool-call.delta';
181
181
  }
182
182
 
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
183
  /** The Standard Typed interface. This is a base type extended by other specs. */
200
184
  interface StandardTypedV1<Input = unknown, Output = Input> {
201
185
  /** The Standard properties. */
@@ -541,5 +525,5 @@ type ToolChoice = 'auto' | 'none' | 'required' | {
541
525
  name: string;
542
526
  };
543
527
 
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 };
528
+ export { resolveSchema as a4, tool as a5 };
529
+ export type { ToolOptions as $, AssistantMessage as A, StepEndEvent as B, CombinedStandardSchema as C, DeveloperMessage as D, ExecutableTool as E, FilePart as F, StepEndFailEvent as G, StepStartEvent as H, ImagePart as I, JSONSchema7 as J, StepStatus as K, LanguageModelOptions as L, Message as M, SystemMessage as N, SystemMessageContent as O, PartProviderMetadata as P, TextDeltaEvent as Q, RawEvent as R, StepEndDoneEvent as S, ToolCallPart as T, Usage as U, TextEventMap as V, TextEventType as W, TextPart as X, Tool as Y, ToolCallDeltaEvent as Z, ToolChoice as _, ToolResultPart as a, ToolResultPartContent as a0, UnresolvedSchema as a1, UserMessage as a2, UserMessageContent as a3, TextEvent as b, LanguageModel as c, ToolExecuteOptions as d, AssistantMessageContent as e, Content as f, ContentEndEvent as g, ContentMap as h, ContentStartEvent as i, ContentType as j, DeveloperMessageContent as k, FinishReason as l, InferSchemaInput as m, InferSchemaOutput as n, JSONSchema7Definition as o, LanguageModelProviderOptions as p, MessageMap as q, MessageProviderMetadata as r, MessageType as s, ProviderPart as t, ReasoningDeltaEvent as u, ReasoningPart as v, ReasoningPartContent as w, RefusalDeltaEvent as x, RefusalPart as y, ResolvedSchema 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.2",
4
+ "version": "1.0.0-beta.4",
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.2"
44
+ "@xsai/shared": "1.0.0-beta.4"
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 };