@xsai/text 1.0.0-beta.3 → 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 +19 -13
- package/dist/index.js +99 -67
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +1 -1
- package/dist/{language-model-DlNwTTFi.d.ts → language-model-rSwDu2og.d.ts} +2 -18
- package/dist/schema-Bny4Y6lV.js +6 -0
- package/package.json +2 -2
- package/dist/schema-7PLOBVJ3.js +0 -69
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as AssistantMessage, e as AssistantMessageContent,
|
|
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
|
|
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
|
|
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
|
-
|
|
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 {
|
|
80
|
-
export type {
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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,
|
|
278
|
+
export { TextEventTarget, and, collect, generateText, hasToolCall, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, tool, withEventTarget };
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StepStatus, FinishReason, AssistantMessage, AssistantMessageContent, PartProviderMetadata, Usage, TextEvent, LanguageModelOptions } from './index.js';
|
|
2
|
-
export {
|
|
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 {
|
|
545
|
-
export type {
|
|
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 };
|
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.
|
|
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.
|
|
44
|
+
"@xsai/shared": "1.0.0-beta.4"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@standard-schema/spec": "1.1.0",
|
package/dist/schema-7PLOBVJ3.js
DELETED
|
@@ -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 };
|