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

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,5 +1,5 @@
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';
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-CAPBb-ti.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 formatIssues, a6 as resolveSchema, a7 as tool } from './language-model-CAPBb-ti.js';
3
3
  import { Promisable } from '@xsai/shared';
4
4
  export { HttpError, XSAIError, XSAIErrorCause, XSAIErrorCauseMap, XSAIErrorCode, XSAIErrorOptions } from '@xsai/shared';
5
5
 
@@ -40,8 +40,13 @@ declare const hasToolCall: (name?: string) => StopCondition;
40
40
  /** @deprecated use `maxSteps` instead. */
41
41
  declare const stepCountAtLeast: (count: number) => StopCondition;
42
42
 
43
+ interface ExecuteToolOptions extends Pick<LanguageModelOptions, 'signal' | 'tools'> {
44
+ postToolCall?: PostToolCall;
45
+ preToolCall?: PreToolCall;
46
+ }
43
47
  type PostToolCall = (toolResult: ToolResultPart, options: ToolExecuteOptions) => Promisable<ToolResultPart | void>;
44
48
  type PreToolCall = (toolCall: ToolCallPart, options: ToolExecuteOptions) => Promisable<ToolCallPart | ToolResultPart | void>;
49
+ declare const executeTool: (call: ToolCallPart, { postToolCall, preToolCall, signal, tools }: ExecuteToolOptions) => Promise<ToolResultPart>;
45
50
 
46
51
  interface StreamTextOptions extends LanguageModelOptions {
47
52
  postToolCall?: PostToolCall;
@@ -82,5 +87,5 @@ declare module '@xsai/shared' {
82
87
  }
83
88
  }
84
89
 
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 };
90
+ export { LanguageModel, LanguageModelOptions, Message, StepEndDoneEvent, TextEvent, TextEventTarget, ToolCallPart, ToolExecuteOptions, ToolResultPart, Usage, and, collect, executeTool, generateText, hasToolCall, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, withEventTarget };
91
+ export type { CollectResult, ExecuteToolOptions, PostToolCall, PreToolCall, PrepareStep, PrepareStepOptions, PrepareStepResult, StepResult, StopCondition, StopContext, StreamTextOptions };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { XSAIError } from '@xsai/shared';
2
2
  export { HttpError, XSAIError } from '@xsai/shared';
3
- import { r as resolveSchema } from './schema-Bny4Y6lV.js';
3
+ import { f as formatIssues, r as readStep, a as resolveSchema } from './read-step-DXGjtk1d.js';
4
4
 
5
5
  const getText = (message) => typeof message.content === "string" ? message.content : message.content.filter((part) => part.type === "text").map((part) => part.text).join("");
6
6
  const getToolCalls = (message) => typeof message.content === "string" ? [] : message.content.filter((part) => part.type === "tool-call");
@@ -80,7 +80,7 @@ const assertSameCallId = (source, next) => {
80
80
  if (source !== next)
81
81
  throw new Error(`Tool call hooks must preserve callId "${source}".`);
82
82
  };
83
- const catchToolError = async (call, signal, callback) => {
83
+ const attempt = async (call, signal, callback) => {
84
84
  try {
85
85
  return await callback();
86
86
  } catch (error) {
@@ -88,85 +88,48 @@ const catchToolError = async (call, signal, callback) => {
88
88
  return toolError(call, error instanceof Error ? error.message : String(error));
89
89
  }
90
90
  };
91
+ const parseInput = (args) => {
92
+ try {
93
+ return JSON.parse(args.trim() || "{}");
94
+ } catch {
95
+ throw new Error("Failed to parse tool input.");
96
+ }
97
+ };
98
+ const runTool = async (call, tools, options) => {
99
+ const tool = tools?.find((candidate) => candidate.name === call.name);
100
+ if (tool == null) {
101
+ const available = tools?.map((candidate) => candidate.name).join(", ");
102
+ throw new Error(`Model tried to call unavailable tool "${call.name}", ${available == null || available === "" ? "No tools are available" : `Available tools: ${available}`}.`);
103
+ }
104
+ if (tool.execute == null)
105
+ throw new Error(`Tool "${call.name}" is not executable.`);
106
+ let input = parseInput(call.arguments);
107
+ if (tool.inputSchema.validate != null) {
108
+ const validation = await tool.inputSchema.validate(input);
109
+ if (validation.issues)
110
+ throw new Error(`Tool input validation failed for "${call.name}": ${formatIssues(validation.issues)}`);
111
+ input = validation.value;
112
+ }
113
+ return { callId: call.callId, output: await tool.execute(input, options), type: "tool-result" };
114
+ };
91
115
  const executeTool = async (call, { postToolCall, preToolCall, signal, tools }) => {
92
- const executeOptions = { signal };
93
- const preToolCallResult = await catchToolError(call, signal, async () => preToolCall?.(call, executeOptions));
94
- if (preToolCallResult != null) {
95
- assertSameCallId(call.callId, preToolCallResult.callId);
96
- if (preToolCallResult.type === "tool-result")
97
- return preToolCallResult;
98
- call = preToolCallResult;
116
+ const options = { callId: call.callId, signal };
117
+ const prepared = await attempt(call, signal, async () => preToolCall?.(call, options));
118
+ if (prepared != null) {
119
+ assertSameCallId(call.callId, prepared.callId);
120
+ if (prepared.type === "tool-result")
121
+ return prepared;
122
+ call = prepared;
99
123
  }
100
- let shouldPostToolCall = false;
101
- const toolResult = await catchToolError(call, signal, async () => {
102
- const tool = tools?.find((candidate) => candidate.name === call.name);
103
- const executableTool = tool;
104
- if (executableTool == null || executableTool.execute == null) {
105
- const available = tools?.map((candidate) => candidate.name).join(", ");
106
- return toolError(call, tool == null ? `Model tried to call unavailable tool "${call.name}", ${available == null || available === "" ? "No tools are available" : `Available tools: ${available}`}.` : `Tool "${call.name}" is not executable.`);
107
- }
108
- let toolInput;
109
- try {
110
- toolInput = JSON.parse(call.arguments.trim() || "{}");
111
- } catch {
112
- return toolError(call, "Failed to parse tool input.");
113
- }
114
- let validatedInput = toolInput;
115
- if (executableTool.inputSchema.validate != null) {
116
- const validation = await executableTool.inputSchema.validate(toolInput);
117
- if (validation.issues)
118
- return toolError(call, `Tool input validation failed for "${call.name}".`);
119
- validatedInput = validation.value;
120
- }
121
- shouldPostToolCall = true;
122
- return {
123
- callId: call.callId,
124
- output: await executableTool.execute(validatedInput, { signal }),
125
- type: "tool-result"
126
- };
127
- });
128
- if (!shouldPostToolCall || postToolCall == null)
129
- return toolResult;
130
- const postToolCallResult = await catchToolError(call, signal, async () => postToolCall(toolResult, executeOptions));
131
- if (postToolCallResult == null)
132
- return toolResult;
133
- assertSameCallId(toolResult.callId, postToolCallResult.callId);
134
- return postToolCallResult;
124
+ const result = await attempt(call, signal, async () => runTool(call, tools, options));
125
+ const posted = await attempt(call, signal, async () => postToolCall?.(result, options));
126
+ if (posted == null)
127
+ return result;
128
+ assertSameCallId(result.callId, posted.callId);
129
+ return posted;
135
130
  };
136
131
  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)));
137
132
 
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
- };
146
- let stepEnd;
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;
161
- }
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());
168
- }
169
- };
170
133
  const streamText = (model, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhenOption, ...options }) => {
171
134
  const stopWhen = stopWhenOption ?? maxSteps(10);
172
135
  const input = [...Array.isArray(options.input) ? options.input : [{ content: options.input, role: "user" }]];
@@ -263,7 +226,7 @@ const tool = ((options) => {
263
226
  if (outputSchema?.validate != null) {
264
227
  const validation = await outputSchema.validate(result);
265
228
  if (validation.issues)
266
- throw new Error(`Tool output validation failed for "${options.name}".`);
229
+ throw new Error(`Tool output validation failed for "${options.name}": ${formatIssues(validation.issues)}`);
267
230
  result = validation.value;
268
231
  }
269
232
  if (outputSchema)
@@ -275,4 +238,4 @@ const tool = ((options) => {
275
238
  }
276
239
  });
277
240
 
278
- export { TextEventTarget, and, collect, generateText, hasToolCall, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, tool, withEventTarget };
241
+ export { TextEventTarget, and, collect, executeTool, generateText, hasToolCall, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, tool, withEventTarget };
@@ -1,5 +1,5 @@
1
- import { StepStatus, FinishReason, AssistantMessage, AssistantMessageContent, PartProviderMetadata, Usage, TextEvent, LanguageModelOptions } from './index.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';
1
+ import { StepStatus, FinishReason, AssistantMessage, AssistantMessageContent, PartProviderMetadata, Usage, TextEvent, StepEndEvent, LanguageModelOptions } from './index.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 formatIssues, a6 as resolveSchema } from './language-model-CAPBb-ti.js';
3
3
  import { XSAIError, EventSourceMessage, SendRequestOptions, HttpOptions } from '@xsai/shared';
4
4
 
5
5
  interface EventBuilder {
@@ -17,6 +17,7 @@ interface EventBuilder {
17
17
  }
18
18
  interface FinishMeta {
19
19
  messageId?: string;
20
+ model?: string;
20
21
  usage?: Usage;
21
22
  }
22
23
  interface PartDeltaExtra {
@@ -51,8 +52,24 @@ declare class EventSourceDataStream extends TransformStream<EventSourceMessage,
51
52
  constructor();
52
53
  }
53
54
 
55
+ /**
56
+ * Reads a model stream until it ends or `signal` aborts. Unlike `for await` on the stream itself,
57
+ * an abort ends a pending read even if the model ignores its signal, and the model sees the reason.
58
+ * Not covered by semver.
59
+ *
60
+ * @internal
61
+ */
62
+ declare const readEvents: (stream: ReadableStream<TextEvent>, signal: AbortSignal) => AsyncGenerator<TextEvent, void>;
63
+ /**
64
+ * Reads one model step and checks that it has exactly one `step.end`.
65
+ * Not covered by semver.
66
+ *
67
+ * @internal
68
+ */
69
+ declare const readStep: (stream: ReadableStream<TextEvent>, signal: AbortSignal) => AsyncGenerator<TextEvent, StepEndEvent>;
70
+
54
71
  /** @internal */
55
72
  declare const wireRequest: (options: SendRequestOptions, httpOptions: HttpOptions, modelOptions: LanguageModelOptions, eventStream: TransformStream<string, TextEvent>) => Promise<ReadableStream<TextEvent>>;
56
73
 
57
- export { EventSourceDataStream, WireEventStream, eventBuilder, wireRequest };
74
+ export { EventSourceDataStream, WireEventStream, eventBuilder, readEvents, readStep, wireRequest };
58
75
  export type { EventBuilder, FinishMeta, PartDeltaExtra, PartEndExtra, PartKey, PartStartInit };
package/dist/internal.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { XSAIError, sendRequest, EventSourceParserStream } from '@xsai/shared';
2
- export { r as resolveSchema } from './schema-Bny4Y6lV.js';
2
+ export { f as formatIssues, b as readEvents, r as readStep, a as resolveSchema } from './read-step-DXGjtk1d.js';
3
3
 
4
4
  const emptyContent = (type, init) => {
5
5
  switch (type) {
@@ -28,6 +28,7 @@ const eventBuilder = (emit, fail) => {
28
28
  let terminalEmitted = false;
29
29
  let messageId;
30
30
  let terminal;
31
+ let model;
31
32
  let usage;
32
33
  const updateReasoning = (state, text) => {
33
34
  if (text === "")
@@ -139,6 +140,7 @@ const eventBuilder = (emit, fail) => {
139
140
  };
140
141
  const common = {
141
142
  message: message.id == null && messageId != null ? { ...message, id: messageId } : message,
143
+ model,
142
144
  type: "step.end",
143
145
  usage
144
146
  };
@@ -186,6 +188,8 @@ const eventBuilder = (emit, fail) => {
186
188
  meta: (meta) => {
187
189
  if (meta.messageId != null)
188
190
  messageId = meta.messageId;
191
+ if (meta.model != null)
192
+ model = meta.model;
189
193
  if (meta.usage != null)
190
194
  usage = meta.usage;
191
195
  },
@@ -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;
@@ -76,6 +82,7 @@ interface AssistantMessage {
76
82
  type AssistantMessageContent = ProviderPart | ReasoningPart | RefusalPart | TextPart | ToolCallPart;
77
83
  interface DeveloperMessage {
78
84
  content: readonly DeveloperMessageContent[] | string;
85
+ providerMetadata?: MessageProviderMetadata;
79
86
  role: 'developer';
80
87
  }
81
88
  type DeveloperMessageContent = TextPart;
@@ -89,6 +96,7 @@ interface MessageMap {
89
96
  type MessageType = keyof MessageMap;
90
97
  interface SystemMessage {
91
98
  content: readonly SystemMessageContent[] | string;
99
+ providerMetadata?: MessageProviderMetadata;
92
100
  role: 'system';
93
101
  }
94
102
  type SystemMessageContent = TextPart;
@@ -96,7 +104,7 @@ interface UserMessage {
96
104
  content: readonly UserMessageContent[] | string;
97
105
  role: 'user';
98
106
  }
99
- type UserMessageContent = FilePart | ImagePart | TextPart | ToolResultPart;
107
+ type UserMessageContent = AudioPart | FilePart | ImagePart | TextPart | ToolResultPart;
100
108
 
101
109
  interface Usage {
102
110
  cacheCreationInputTokens?: number;
@@ -135,6 +143,8 @@ interface RefusalDeltaEvent {
135
143
  interface StepEndDoneEvent {
136
144
  error?: never;
137
145
  message: AssistantMessage;
146
+ /** The model that the provider says answered, if it says. */
147
+ model?: string;
138
148
  reason?: FinishReason;
139
149
  status: Exclude<StepStatus, 'failed'>;
140
150
  type: 'step.end';
@@ -145,6 +155,8 @@ type StepEndEvent = StepEndDoneEvent | StepEndFailEvent;
145
155
  interface StepEndFailEvent {
146
156
  error: XSAIError;
147
157
  message: AssistantMessage;
158
+ /** The model that the provider says answered, if it says. */
159
+ model?: string;
148
160
  reason?: never;
149
161
  status: 'failed';
150
162
  type: 'step.end';
@@ -475,6 +487,7 @@ interface ResolvedSchema<Input = unknown, Output = Input> {
475
487
  validate?: StandardSchemaV1.Props<Input, Output>['validate'];
476
488
  }
477
489
  type UnresolvedSchema<Input = unknown, Output = Input> = CombinedStandardSchema<Input, Output> | JSONSchema7;
490
+ declare const formatIssues: (issues: readonly StandardSchemaV1.Issue[]) => string;
478
491
  declare const resolveSchema: <Input = unknown, Output = Input>(schema: UnresolvedSchema<Input, Output>) => ResolvedSchema<Input, Output>;
479
492
 
480
493
  interface ExecutableTool extends Tool {
@@ -487,6 +500,7 @@ interface Tool {
487
500
  outputSchema?: ResolvedSchema;
488
501
  }
489
502
  interface ToolExecuteOptions {
503
+ callId: string;
490
504
  signal?: AbortSignal;
491
505
  }
492
506
  interface ToolOptions<TInput extends UnresolvedSchema, TOutput extends undefined | UnresolvedSchema = undefined> {
@@ -525,5 +539,5 @@ type ToolChoice = 'auto' | 'none' | 'required' | {
525
539
  name: string;
526
540
  };
527
541
 
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 };
542
+ export { formatIssues as a5, resolveSchema as a6, tool as a7 };
543
+ 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,50 @@
1
+ import { XSAIError } from '@xsai/shared';
2
+
3
+ const formatIssues = (issues) => issues.map(({ message, path }) => {
4
+ const location = path?.map((segment) => String(typeof segment === "object" ? segment.key : segment)).join(".");
5
+ return location == null || location === "" ? message : `${location}: ${message}`;
6
+ }).join("; ");
7
+ const resolveSchema = (schema) => "~standard" in schema ? {
8
+ schema: schema["~standard"].jsonSchema.input({ target: "draft-07" }),
9
+ validate: schema["~standard"].validate
10
+ } : { schema };
11
+
12
+ const readEvents = async function* (stream, signal) {
13
+ const reader = stream.getReader();
14
+ let cancellation;
15
+ const abort = () => {
16
+ cancellation = reader.cancel(signal.reason);
17
+ void cancellation.catch(() => {
18
+ });
19
+ };
20
+ signal.addEventListener("abort", abort, { once: true });
21
+ try {
22
+ signal.throwIfAborted();
23
+ while (true) {
24
+ const { done, value } = await reader.read();
25
+ signal.throwIfAborted();
26
+ if (done)
27
+ return;
28
+ yield value;
29
+ }
30
+ } finally {
31
+ signal.removeEventListener("abort", abort);
32
+ await (cancellation ?? reader.cancel(signal.reason)).finally(() => reader.releaseLock());
33
+ }
34
+ };
35
+ const readStep = async function* (stream, signal) {
36
+ let stepEnd;
37
+ for await (const event of readEvents(stream, signal)) {
38
+ if (event.type === "step.end") {
39
+ if (stepEnd != null)
40
+ throw new XSAIError("protocol-error", "model stream produced more than one step.end event");
41
+ stepEnd = event;
42
+ }
43
+ yield event;
44
+ }
45
+ if (stepEnd == null)
46
+ throw new XSAIError("truncated-stream", "model stream ended without a step.end event");
47
+ return stepEnd;
48
+ };
49
+
50
+ export { resolveSchema as a, readEvents as b, formatIssues as f, readStep 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.4",
4
+ "version": "1.0.0-beta.6",
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.4"
44
+ "@xsai/shared": "1.0.0-beta.6"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@standard-schema/spec": "1.1.0",
@@ -1,6 +0,0 @@
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 };