@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 +9 -4
- package/dist/index.js +41 -78
- package/dist/internal.d.ts +20 -3
- package/dist/internal.js +5 -1
- package/dist/{language-model-rSwDu2og.d.ts → language-model-CAPBb-ti.d.ts} +17 -3
- package/dist/read-step-DXGjtk1d.js +50 -0
- package/package.json +2 -2
- package/dist/schema-Bny4Y6lV.js +0 -6
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-
|
|
2
|
-
export { A as AssistantMessage, e as AssistantMessageContent, C as CombinedStandardSchema,
|
|
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 './
|
|
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
|
|
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
|
|
93
|
-
const
|
|
94
|
-
if (
|
|
95
|
-
assertSameCallId(call.callId,
|
|
96
|
-
if (
|
|
97
|
-
return
|
|
98
|
-
call =
|
|
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
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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 };
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StepStatus, FinishReason, AssistantMessage, AssistantMessageContent, PartProviderMetadata, Usage, TextEvent, LanguageModelOptions } from './index.js';
|
|
2
|
-
export { C as CombinedStandardSchema,
|
|
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 './
|
|
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
|
|
529
|
-
export type {
|
|
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
|
+
"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.
|
|
44
|
+
"@xsai/shared": "1.0.0-beta.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@standard-schema/spec": "1.1.0",
|