@xsai/text 0.0.0-stage → 1.0.0-beta.1
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/LICENSE.md +21 -0
- package/README.md +24 -2
- package/dist/index.d.ts +80 -0
- package/dist/index.js +246 -0
- package/dist/internal.d.ts +58 -0
- package/dist/internal.js +268 -0
- package/dist/language-model-DlNwTTFi.d.ts +545 -0
- package/dist/schema-7PLOBVJ3.js +69 -0
- package/package.json +51 -3
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Moeru AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @xsai/text
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- automd:file src="/docs/snippets/text-responses.md" -->
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
pnpm add @xsai/text @xsai/text-responses
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { generateText } from '@xsai/text'
|
|
11
|
+
import { responses } from '@xsai/text-responses'
|
|
12
|
+
|
|
13
|
+
const model = responses({
|
|
14
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
15
|
+
baseURL: 'https://api.openai.com/v1/',
|
|
16
|
+
model: 'gpt-6-luna',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const { text } = await generateText(model, { input: 'Say hello.' })
|
|
20
|
+
console.log(text)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
<!-- /automd -->
|
|
24
|
+
|
|
25
|
+
Read the [documentation](https://xsai.js.org/getting-started).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
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';
|
|
3
|
+
import { Promisable } from '@xsai/shared';
|
|
4
|
+
export { HttpError, XSAIError, XSAIErrorCause, XSAIErrorCauseMap, XSAIErrorCode, XSAIErrorOptions } from '@xsai/shared';
|
|
5
|
+
|
|
6
|
+
type PrepareStep = (options: PrepareStepOptions) => Promisable<PrepareStepResult | undefined>;
|
|
7
|
+
interface PrepareStepOptions {
|
|
8
|
+
input: readonly Message[];
|
|
9
|
+
signal: AbortSignal;
|
|
10
|
+
stepNumber: number;
|
|
11
|
+
steps: readonly StepResult[];
|
|
12
|
+
}
|
|
13
|
+
interface PrepareStepResult extends Partial<Omit<LanguageModelOptions, 'signal'>> {
|
|
14
|
+
model?: LanguageModel;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type StopCondition = (context: StopContext) => boolean;
|
|
18
|
+
interface StopContext {
|
|
19
|
+
input: readonly Message[];
|
|
20
|
+
step: StepResult;
|
|
21
|
+
steps: readonly StepResult[];
|
|
22
|
+
}
|
|
23
|
+
declare const and: (...conditions: StopCondition[]) => StopCondition;
|
|
24
|
+
declare const or: (...conditions: StopCondition[]) => StopCondition;
|
|
25
|
+
declare const not: (condition: StopCondition) => StopCondition;
|
|
26
|
+
declare const maxSteps: (count: number) => StopCondition;
|
|
27
|
+
declare const hasToolCall: (name?: string) => StopCondition;
|
|
28
|
+
/** @deprecated use `maxSteps` instead. */
|
|
29
|
+
declare const stepCountAtLeast: (count: number) => StopCondition;
|
|
30
|
+
|
|
31
|
+
type PostToolCall = (toolResult: ToolResultPart, options: ToolExecuteOptions) => Promisable<ToolResultPart | void>;
|
|
32
|
+
type PreToolCall = (toolCall: ToolCallPart, options: ToolExecuteOptions) => Promisable<ToolCallPart | ToolResultPart | void>;
|
|
33
|
+
|
|
34
|
+
interface LoopOptions extends LanguageModelOptions {
|
|
35
|
+
postToolCall?: PostToolCall;
|
|
36
|
+
prepareStep?: PrepareStep;
|
|
37
|
+
preToolCall?: PreToolCall;
|
|
38
|
+
/** @default `maxSteps(10)` */
|
|
39
|
+
stopWhen?: StopCondition;
|
|
40
|
+
}
|
|
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>;
|
|
44
|
+
|
|
45
|
+
interface StreamTextHandle {
|
|
46
|
+
result: Promise<CollectResult>;
|
|
47
|
+
stream: ReadableStream<TextEvent>;
|
|
48
|
+
}
|
|
49
|
+
declare const streamText: (model: LanguageModel, options: LoopOptions) => StreamTextHandle;
|
|
50
|
+
|
|
51
|
+
type TextEventListener<E extends Event> = ((this: EventTarget, event: E) => unknown) | {
|
|
52
|
+
handleEvent: (event: E) => unknown;
|
|
53
|
+
};
|
|
54
|
+
type TextEventTargetMap = {
|
|
55
|
+
[K in Exclude<TextEvent['type'], 'raw'>]: CustomEvent<Omit<Extract<TextEvent, {
|
|
56
|
+
type: K;
|
|
57
|
+
}>, 'type'>>;
|
|
58
|
+
} & {
|
|
59
|
+
raw: CustomEvent<unknown>;
|
|
60
|
+
};
|
|
61
|
+
interface TextEventTarget {
|
|
62
|
+
addEventListener: <K extends keyof TextEventTargetMap>(type: K, listener: null | TextEventListener<TextEventTargetMap[K]>, options?: AddEventListenerOptions | boolean) => void;
|
|
63
|
+
dispatchEvent: (event: Event) => boolean;
|
|
64
|
+
removeEventListener: <K extends keyof TextEventTargetMap>(type: K, listener: null | TextEventListener<TextEventTargetMap[K]>, options?: boolean | EventListenerOptions) => void;
|
|
65
|
+
}
|
|
66
|
+
declare const TextEventTarget: {
|
|
67
|
+
new (): TextEventTarget;
|
|
68
|
+
};
|
|
69
|
+
declare const toCustomEvent: <E extends TextEvent>(event: E) => TextEventTargetMap[E["type"]];
|
|
70
|
+
declare const withEventTarget: (events: EventTarget) => TransformStream<TextEvent, TextEvent>;
|
|
71
|
+
|
|
72
|
+
declare module '@xsai/shared' {
|
|
73
|
+
interface XSAIErrorCauseMap {
|
|
74
|
+
'model-error': unknown;
|
|
75
|
+
'protocol-error': unknown;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
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 };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { t as toStepResult, c as collect, a as collectEvent, b as collectResult, r as resolveSchema } from './schema-7PLOBVJ3.js';
|
|
2
|
+
import { XSAIError } from '@xsai/shared';
|
|
3
|
+
export { HttpError, XSAIError } from '@xsai/shared';
|
|
4
|
+
|
|
5
|
+
const and = (...conditions) => (context) => conditions.every((condition) => condition(context));
|
|
6
|
+
const or = (...conditions) => (context) => conditions.some((condition) => condition(context));
|
|
7
|
+
const not = (condition) => (context) => !condition(context);
|
|
8
|
+
const maxSteps = (count) => ({ steps }) => steps.length >= count;
|
|
9
|
+
const hasToolCall = (name) => ({ step }) => step.toolCalls.some((toolCall) => name == null || toolCall.name === name);
|
|
10
|
+
const stepCountAtLeast = maxSteps;
|
|
11
|
+
|
|
12
|
+
const toolError = (call, detail) => ({
|
|
13
|
+
callId: call.callId,
|
|
14
|
+
isError: true,
|
|
15
|
+
output: `Tool "${call.name}" execution failed: ${detail}`,
|
|
16
|
+
type: "tool-result"
|
|
17
|
+
});
|
|
18
|
+
const assertSameCallId = (source, next) => {
|
|
19
|
+
if (source !== next)
|
|
20
|
+
throw new Error(`Tool call hooks must preserve callId "${source}".`);
|
|
21
|
+
};
|
|
22
|
+
const catchToolError = async (call, signal, callback) => {
|
|
23
|
+
try {
|
|
24
|
+
return await callback();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
signal?.throwIfAborted();
|
|
27
|
+
return toolError(call, error instanceof Error ? error.message : String(error));
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const executeTool = async (call, { postToolCall, preToolCall, signal, tools }) => {
|
|
31
|
+
const executeOptions = { signal };
|
|
32
|
+
const preToolCallResult = await catchToolError(call, signal, async () => preToolCall?.(call, executeOptions));
|
|
33
|
+
if (preToolCallResult != null) {
|
|
34
|
+
assertSameCallId(call.callId, preToolCallResult.callId);
|
|
35
|
+
if (preToolCallResult.type === "tool-result")
|
|
36
|
+
return preToolCallResult;
|
|
37
|
+
call = preToolCallResult;
|
|
38
|
+
}
|
|
39
|
+
let shouldPostToolCall = false;
|
|
40
|
+
const toolResult = await catchToolError(call, signal, async () => {
|
|
41
|
+
const tool = tools?.find((candidate) => candidate.name === call.name);
|
|
42
|
+
const executableTool = tool;
|
|
43
|
+
if (executableTool == null || executableTool.execute == null) {
|
|
44
|
+
const available = tools?.map((candidate) => candidate.name).join(", ");
|
|
45
|
+
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.`);
|
|
46
|
+
}
|
|
47
|
+
let toolInput;
|
|
48
|
+
try {
|
|
49
|
+
toolInput = JSON.parse(call.arguments.trim() || "{}");
|
|
50
|
+
} catch {
|
|
51
|
+
return toolError(call, "Failed to parse tool input.");
|
|
52
|
+
}
|
|
53
|
+
let validatedInput = toolInput;
|
|
54
|
+
if (executableTool.inputSchema.validate != null) {
|
|
55
|
+
const validation = await executableTool.inputSchema.validate(toolInput);
|
|
56
|
+
if (validation.issues)
|
|
57
|
+
return toolError(call, `Tool input validation failed for "${call.name}".`);
|
|
58
|
+
validatedInput = validation.value;
|
|
59
|
+
}
|
|
60
|
+
shouldPostToolCall = true;
|
|
61
|
+
return {
|
|
62
|
+
callId: call.callId,
|
|
63
|
+
output: await executableTool.execute(validatedInput, { signal }),
|
|
64
|
+
type: "tool-result"
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
if (!shouldPostToolCall || postToolCall == null)
|
|
68
|
+
return toolResult;
|
|
69
|
+
const postToolCallResult = await catchToolError(call, signal, async () => postToolCall(toolResult, executeOptions));
|
|
70
|
+
if (postToolCallResult == null)
|
|
71
|
+
return toolResult;
|
|
72
|
+
assertSameCallId(toolResult.callId, postToolCallResult.callId);
|
|
73
|
+
return postToolCallResult;
|
|
74
|
+
};
|
|
75
|
+
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
|
+
|
|
77
|
+
const readStep = async function* (stream, signal) {
|
|
78
|
+
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;
|
|
84
|
+
}
|
|
85
|
+
yield event;
|
|
86
|
+
}
|
|
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
|
+
};
|
|
92
|
+
const loop = (model, { postToolCall, prepareStep, preToolCall, stopWhen: stopWhenOption, ...options }) => {
|
|
93
|
+
const stopWhen = stopWhenOption ?? maxSteps(10);
|
|
94
|
+
const input = [...Array.isArray(options.input) ? options.input : [{ content: options.input, role: "user" }]];
|
|
95
|
+
const steps = [];
|
|
96
|
+
const controller = new AbortController();
|
|
97
|
+
const signal = options.signal == null ? controller.signal : AbortSignal.any([options.signal, controller.signal]);
|
|
98
|
+
const generate = async function* () {
|
|
99
|
+
while (true) {
|
|
100
|
+
signal.throwIfAborted();
|
|
101
|
+
const { model: preparedModel = model, ...preparedOptions } = await prepareStep?.({ input, signal, stepNumber: steps.length, steps }) ?? {};
|
|
102
|
+
signal.throwIfAborted();
|
|
103
|
+
const modelOptions = {
|
|
104
|
+
...options,
|
|
105
|
+
...preparedOptions,
|
|
106
|
+
input: preparedOptions?.input ?? input,
|
|
107
|
+
signal
|
|
108
|
+
};
|
|
109
|
+
const stepEnd = yield* readStep(await preparedModel(modelOptions), signal);
|
|
110
|
+
if (stepEnd.status === "failed" || stepEnd.status === "cancelled")
|
|
111
|
+
return;
|
|
112
|
+
const step = toStepResult(stepEnd);
|
|
113
|
+
steps.push(step);
|
|
114
|
+
input.push(step.message);
|
|
115
|
+
const stop = stopWhen({ input, step, steps });
|
|
116
|
+
if (stop || step.toolCalls.length === 0 && step.reason !== "pause_turn")
|
|
117
|
+
return;
|
|
118
|
+
signal.throwIfAborted();
|
|
119
|
+
if (step.toolCalls.length === 0)
|
|
120
|
+
continue;
|
|
121
|
+
const results = await executeTools({
|
|
122
|
+
...modelOptions,
|
|
123
|
+
postToolCall,
|
|
124
|
+
preToolCall,
|
|
125
|
+
reason: step.reason,
|
|
126
|
+
toolCalls: step.toolCalls
|
|
127
|
+
});
|
|
128
|
+
signal.throwIfAborted();
|
|
129
|
+
step.toolResults.push(...results);
|
|
130
|
+
input.push({ content: results, role: "user" });
|
|
131
|
+
for (const [index, content] of results.entries()) {
|
|
132
|
+
yield { contentType: "tool-result", index, type: "content.start" };
|
|
133
|
+
yield { content, index, type: "content.end" };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const source = generate();
|
|
138
|
+
return new ReadableStream({
|
|
139
|
+
cancel: async (reason) => {
|
|
140
|
+
controller.abort(reason);
|
|
141
|
+
await source.return(void 0);
|
|
142
|
+
},
|
|
143
|
+
pull: async (output) => {
|
|
144
|
+
const next = await source.next();
|
|
145
|
+
if (next.done)
|
|
146
|
+
output.close();
|
|
147
|
+
else
|
|
148
|
+
output.enqueue(next.value);
|
|
149
|
+
}
|
|
150
|
+
}, { highWaterMark: 0 });
|
|
151
|
+
};
|
|
152
|
+
|
|
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
|
+
};
|
|
206
|
+
|
|
207
|
+
const TextEventTarget = EventTarget;
|
|
208
|
+
const toCustomEvent = (event) => {
|
|
209
|
+
const { type, ...detail } = event;
|
|
210
|
+
return new CustomEvent(type, {
|
|
211
|
+
detail: event.type === "raw" ? event.detail : detail
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
const withEventTarget = (events) => new TransformStream({
|
|
215
|
+
transform: (event, controller) => {
|
|
216
|
+
events.dispatchEvent(toCustomEvent(event));
|
|
217
|
+
controller.enqueue(event);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const tool = ((options) => {
|
|
222
|
+
const inputSchema = resolveSchema(options.inputSchema);
|
|
223
|
+
const outputSchema = options.outputSchema == null ? void 0 : resolveSchema(options.outputSchema);
|
|
224
|
+
const tool2 = {
|
|
225
|
+
description: options.description,
|
|
226
|
+
inputSchema,
|
|
227
|
+
name: options.name,
|
|
228
|
+
outputSchema
|
|
229
|
+
};
|
|
230
|
+
if (options.execute == null) {
|
|
231
|
+
return tool2;
|
|
232
|
+
} else {
|
|
233
|
+
return {
|
|
234
|
+
...tool2,
|
|
235
|
+
execute: async (input, executeOptions) => {
|
|
236
|
+
const result = await options.execute(input, executeOptions);
|
|
237
|
+
if (outputSchema)
|
|
238
|
+
return JSON.stringify(result);
|
|
239
|
+
else
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
export { TextEventTarget, and, collect, generateText, hasToolCall, loop, maxSteps, not, or, stepCountAtLeast, streamText, toCustomEvent, tool, withEventTarget };
|
|
@@ -0,0 +1,58 @@
|
|
|
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';
|
|
3
|
+
import { XSAIError, EventSourceMessage, SendRequestOptions, HttpOptions } from '@xsai/shared';
|
|
4
|
+
|
|
5
|
+
interface EventBuilder {
|
|
6
|
+
/** Appends text or tool-call identity to a part. */
|
|
7
|
+
delta: (key: PartKey, text: string, extra?: PartDeltaExtra) => void;
|
|
8
|
+
/** Records a non-failed terminal status and closes open parts. */
|
|
9
|
+
done: (status: Exclude<StepStatus, 'failed'>, reason?: FinishReason, message?: AssistantMessage) => void;
|
|
10
|
+
end: (key: PartKey, extra?: PartEndExtra) => void;
|
|
11
|
+
/** Records a provider-declared failure and closes open parts. */
|
|
12
|
+
fail: (error: XSAIError, message?: AssistantMessage) => void;
|
|
13
|
+
/** Emits `step.end` or fails for an incomplete wire stream. */
|
|
14
|
+
flush: () => void;
|
|
15
|
+
meta: (meta: FinishMeta) => void;
|
|
16
|
+
start: (key: PartKey, type: AssistantMessageContent['type'], init?: PartStartInit) => void;
|
|
17
|
+
}
|
|
18
|
+
interface FinishMeta {
|
|
19
|
+
messageId?: string;
|
|
20
|
+
usage?: Usage;
|
|
21
|
+
}
|
|
22
|
+
interface PartDeltaExtra {
|
|
23
|
+
callId?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
}
|
|
26
|
+
interface PartEndExtra {
|
|
27
|
+
/** Authoritative part content, e.g. a Responses `output_item.done` item. */
|
|
28
|
+
content?: AssistantMessageContent;
|
|
29
|
+
/** Attached to reasoning or text parts. */
|
|
30
|
+
providerMetadata?: PartProviderMetadata;
|
|
31
|
+
}
|
|
32
|
+
/** Adapter-assigned identity for a part. */
|
|
33
|
+
type PartKey = number | string;
|
|
34
|
+
interface PartStartInit {
|
|
35
|
+
callId?: string;
|
|
36
|
+
/** Used when the wire never sends a call id, e.g. `call_${index}`. */
|
|
37
|
+
fallbackId?: string;
|
|
38
|
+
/** Wire-level part identity, distinct from the tool call id when both exist. */
|
|
39
|
+
id?: string;
|
|
40
|
+
name?: string;
|
|
41
|
+
source?: string;
|
|
42
|
+
}
|
|
43
|
+
/** @internal */
|
|
44
|
+
declare const eventBuilder: (emit: (event: TextEvent) => void, fail: (error: XSAIError) => void) => EventBuilder;
|
|
45
|
+
/** Parses wire events and enforces stream termination. @internal */
|
|
46
|
+
declare class WireEventStream<W> extends TransformStream<string, TextEvent> {
|
|
47
|
+
constructor(map: (wire: W, builder: EventBuilder) => void, includeRawEvents?: boolean);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
declare class EventSourceDataStream extends TransformStream<EventSourceMessage, string> {
|
|
51
|
+
constructor();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @internal */
|
|
55
|
+
declare const wireRequest: (options: SendRequestOptions, httpOptions: HttpOptions, modelOptions: LanguageModelOptions, eventStream: TransformStream<string, TextEvent>) => Promise<ReadableStream<TextEvent>>;
|
|
56
|
+
|
|
57
|
+
export { EventSourceDataStream, WireEventStream, eventBuilder, wireRequest };
|
|
58
|
+
export type { EventBuilder, FinishMeta, PartDeltaExtra, PartEndExtra, PartKey, PartStartInit };
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
export { a as collectEvent, b as collectResult, r as resolveSchema } from './schema-7PLOBVJ3.js';
|
|
2
|
+
import { XSAIError, sendRequest, EventSourceParserStream } from '@xsai/shared';
|
|
3
|
+
|
|
4
|
+
const emptyContent = (type, init) => {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case "provider":
|
|
7
|
+
return { source: init?.source ?? "", type, value: null };
|
|
8
|
+
case "reasoning":
|
|
9
|
+
return { content: [], type };
|
|
10
|
+
case "refusal":
|
|
11
|
+
return { refusal: "", type };
|
|
12
|
+
case "text":
|
|
13
|
+
return { text: "", type };
|
|
14
|
+
case "tool-call":
|
|
15
|
+
return { arguments: "", callId: "", id: "", name: "", type };
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const acceptIdentity = (current, incoming) => incoming != null && incoming !== "" ? incoming : current;
|
|
19
|
+
const resolveCallId = (state) => {
|
|
20
|
+
if (state.resolvedCallId != null)
|
|
21
|
+
return state.resolvedCallId;
|
|
22
|
+
state.resolvedCallId = acceptIdentity(state.fallbackId, state.callId) ?? `call_${state.index}`;
|
|
23
|
+
return state.resolvedCallId;
|
|
24
|
+
};
|
|
25
|
+
const eventBuilder = (emit, fail) => {
|
|
26
|
+
const parts = [];
|
|
27
|
+
const states = /* @__PURE__ */ new Map();
|
|
28
|
+
let terminalEmitted = false;
|
|
29
|
+
let messageId;
|
|
30
|
+
let terminal;
|
|
31
|
+
let usage;
|
|
32
|
+
const updateReasoning = (state, text) => {
|
|
33
|
+
if (text === "")
|
|
34
|
+
return;
|
|
35
|
+
const part = parts[state.index];
|
|
36
|
+
if (part.type !== "reasoning")
|
|
37
|
+
return;
|
|
38
|
+
const content = part.content;
|
|
39
|
+
const last = content.at(-1);
|
|
40
|
+
parts[state.index] = {
|
|
41
|
+
...part,
|
|
42
|
+
content: last?.type === "text" ? content.with(-1, { text: last.text + text, type: "text" }) : [...content, { text, type: "text" }]
|
|
43
|
+
};
|
|
44
|
+
emit({ delta: text, index: state.index, type: "reasoning.delta" });
|
|
45
|
+
};
|
|
46
|
+
const updateRefusal = (state, text) => {
|
|
47
|
+
if (text === "")
|
|
48
|
+
return;
|
|
49
|
+
const part = parts[state.index];
|
|
50
|
+
if (part.type !== "refusal")
|
|
51
|
+
return;
|
|
52
|
+
parts[state.index] = { ...part, refusal: part.refusal + text };
|
|
53
|
+
emit({ delta: text, index: state.index, type: "refusal.delta" });
|
|
54
|
+
};
|
|
55
|
+
const updateText = (state, text) => {
|
|
56
|
+
if (text === "")
|
|
57
|
+
return;
|
|
58
|
+
const part = parts[state.index];
|
|
59
|
+
if (part.type !== "text")
|
|
60
|
+
return;
|
|
61
|
+
parts[state.index] = { ...part, text: part.text + text };
|
|
62
|
+
emit({ delta: text, index: state.index, type: "text.delta" });
|
|
63
|
+
};
|
|
64
|
+
const updateToolCall = (state, text, extra) => {
|
|
65
|
+
state.callId = acceptIdentity(state.callId, extra?.callId);
|
|
66
|
+
state.name = acceptIdentity(state.name, extra?.name);
|
|
67
|
+
if (text === "")
|
|
68
|
+
return;
|
|
69
|
+
const id = resolveCallId(state);
|
|
70
|
+
const part = parts[state.index];
|
|
71
|
+
if (part.type !== "tool-call")
|
|
72
|
+
return;
|
|
73
|
+
parts[state.index] = {
|
|
74
|
+
...part,
|
|
75
|
+
arguments: part.arguments + text,
|
|
76
|
+
callId: id,
|
|
77
|
+
id,
|
|
78
|
+
name: state.name ?? part.name
|
|
79
|
+
};
|
|
80
|
+
const event = {
|
|
81
|
+
callId: id,
|
|
82
|
+
delta: text,
|
|
83
|
+
index: state.index,
|
|
84
|
+
name: state.name,
|
|
85
|
+
type: "tool-call.delta"
|
|
86
|
+
};
|
|
87
|
+
emit(event);
|
|
88
|
+
};
|
|
89
|
+
const delta = (key, text, extra) => {
|
|
90
|
+
const state = states.get(key);
|
|
91
|
+
if (state === void 0 || state.closed || terminal !== void 0)
|
|
92
|
+
return;
|
|
93
|
+
switch (parts[state.index].type) {
|
|
94
|
+
case "provider":
|
|
95
|
+
break;
|
|
96
|
+
case "reasoning":
|
|
97
|
+
updateReasoning(state, text);
|
|
98
|
+
break;
|
|
99
|
+
case "refusal":
|
|
100
|
+
updateRefusal(state, text);
|
|
101
|
+
break;
|
|
102
|
+
case "text":
|
|
103
|
+
updateText(state, text);
|
|
104
|
+
break;
|
|
105
|
+
case "tool-call":
|
|
106
|
+
updateToolCall(state, text, extra);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const end = (key, extra) => {
|
|
111
|
+
const state = states.get(key);
|
|
112
|
+
if (state === void 0 || state.closed)
|
|
113
|
+
return;
|
|
114
|
+
state.closed = true;
|
|
115
|
+
const accumulated = parts[state.index];
|
|
116
|
+
const callId = resolveCallId(state);
|
|
117
|
+
const built = accumulated.type === "tool-call" ? {
|
|
118
|
+
...accumulated,
|
|
119
|
+
callId,
|
|
120
|
+
id: state.id ?? callId,
|
|
121
|
+
name: state.name ?? ""
|
|
122
|
+
} : accumulated.type === "reasoning" ? {
|
|
123
|
+
...accumulated,
|
|
124
|
+
content: accumulated.content.length === 0 ? [{ text: "", type: "text" }] : accumulated.content,
|
|
125
|
+
id: state.id
|
|
126
|
+
} : accumulated;
|
|
127
|
+
const authoritative = extra?.content ?? built;
|
|
128
|
+
const content = extra?.providerMetadata != null && (authoritative.type === "reasoning" || authoritative.type === "text") ? { ...authoritative, providerMetadata: extra.providerMetadata } : authoritative;
|
|
129
|
+
parts[state.index] = content;
|
|
130
|
+
emit({ content, index: state.index, type: "content.end" });
|
|
131
|
+
};
|
|
132
|
+
const emitTerminal = () => {
|
|
133
|
+
if (terminalEmitted || terminal === void 0)
|
|
134
|
+
return;
|
|
135
|
+
terminalEmitted = true;
|
|
136
|
+
const message = terminal.message ?? {
|
|
137
|
+
content: parts,
|
|
138
|
+
role: "assistant"
|
|
139
|
+
};
|
|
140
|
+
const common = {
|
|
141
|
+
message: message.id == null && messageId != null ? { ...message, id: messageId } : message,
|
|
142
|
+
type: "step.end",
|
|
143
|
+
usage
|
|
144
|
+
};
|
|
145
|
+
if (terminal.status === "failed") {
|
|
146
|
+
emit({ ...common, error: terminal.error, status: terminal.status });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
emit({
|
|
150
|
+
...common,
|
|
151
|
+
reason: terminal.reason,
|
|
152
|
+
status: terminal.status
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
return {
|
|
156
|
+
delta,
|
|
157
|
+
done: (status, reason, message) => {
|
|
158
|
+
if (terminal !== void 0)
|
|
159
|
+
return;
|
|
160
|
+
const messageContent = message?.content ?? parts;
|
|
161
|
+
const hasToolCall = typeof messageContent !== "string" && messageContent.some((part) => part.type === "tool-call");
|
|
162
|
+
const reconciledReason = status === "completed" && (reason == null || reason === "stop") && hasToolCall ? "tool-calls" : reason;
|
|
163
|
+
terminal = { message, reason: reconciledReason, status };
|
|
164
|
+
for (const key of states.keys())
|
|
165
|
+
end(key);
|
|
166
|
+
},
|
|
167
|
+
end,
|
|
168
|
+
fail: (error, message) => {
|
|
169
|
+
if (terminal !== void 0)
|
|
170
|
+
return;
|
|
171
|
+
terminal = { error, message, status: "failed" };
|
|
172
|
+
for (const key of states.keys())
|
|
173
|
+
end(key);
|
|
174
|
+
emitTerminal();
|
|
175
|
+
},
|
|
176
|
+
flush: () => {
|
|
177
|
+
if (terminalEmitted)
|
|
178
|
+
return;
|
|
179
|
+
if (terminal === void 0) {
|
|
180
|
+
terminalEmitted = true;
|
|
181
|
+
fail(new XSAIError("truncated-stream", "wire stream ended without a terminal signal"));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
emitTerminal();
|
|
185
|
+
},
|
|
186
|
+
meta: (meta) => {
|
|
187
|
+
if (meta.messageId != null)
|
|
188
|
+
messageId = meta.messageId;
|
|
189
|
+
if (meta.usage != null)
|
|
190
|
+
usage = meta.usage;
|
|
191
|
+
},
|
|
192
|
+
start: (key, type, init) => {
|
|
193
|
+
if (states.has(key) || terminal !== void 0)
|
|
194
|
+
return;
|
|
195
|
+
const index = states.size;
|
|
196
|
+
const state = {
|
|
197
|
+
callId: init?.callId,
|
|
198
|
+
closed: false,
|
|
199
|
+
fallbackId: init?.fallbackId,
|
|
200
|
+
id: init?.id,
|
|
201
|
+
index,
|
|
202
|
+
name: init?.name
|
|
203
|
+
};
|
|
204
|
+
states.set(key, state);
|
|
205
|
+
parts.push(emptyContent(type, init));
|
|
206
|
+
emit({ contentType: type, index, type: "content.start" });
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
class WireEventStream extends TransformStream {
|
|
211
|
+
constructor(map, includeRawEvents = false) {
|
|
212
|
+
let builder;
|
|
213
|
+
super({
|
|
214
|
+
flush: () => {
|
|
215
|
+
builder.flush();
|
|
216
|
+
},
|
|
217
|
+
start: (controller) => {
|
|
218
|
+
builder = eventBuilder(
|
|
219
|
+
(event) => {
|
|
220
|
+
controller.enqueue(event);
|
|
221
|
+
if (event.type === "step.end" && event.status === "failed")
|
|
222
|
+
controller.terminate();
|
|
223
|
+
},
|
|
224
|
+
(error) => controller.error(error)
|
|
225
|
+
);
|
|
226
|
+
controller.enqueue({ type: "step.start" });
|
|
227
|
+
},
|
|
228
|
+
transform: (data, controller) => {
|
|
229
|
+
let wire;
|
|
230
|
+
try {
|
|
231
|
+
wire = JSON.parse(data);
|
|
232
|
+
} catch (cause) {
|
|
233
|
+
controller.error(new XSAIError("invalid-response", "malformed event data", { cause }));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
if (includeRawEvents)
|
|
238
|
+
controller.enqueue({ detail: wire, type: "raw" });
|
|
239
|
+
map(wire, builder);
|
|
240
|
+
} catch (cause) {
|
|
241
|
+
controller.error(new XSAIError("protocol-error", "failed to normalize wire event", { cause }));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const DONE = "[DONE]";
|
|
249
|
+
class EventSourceDataStream extends TransformStream {
|
|
250
|
+
constructor() {
|
|
251
|
+
super({
|
|
252
|
+
transform: ({ data }, controller) => {
|
|
253
|
+
if (data === DONE) {
|
|
254
|
+
controller.terminate();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
controller.enqueue(data);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const wireRequest = async (options, httpOptions, modelOptions, eventStream) => sendRequest({
|
|
264
|
+
...options,
|
|
265
|
+
signal: modelOptions.signal
|
|
266
|
+
}, httpOptions).then((res) => res.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream()).pipeThrough(new EventSourceDataStream()).pipeThrough(eventStream));
|
|
267
|
+
|
|
268
|
+
export { EventSourceDataStream, WireEventStream, wireRequest };
|
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
import { XSAIError, Promisable } from '@xsai/shared';
|
|
2
|
+
|
|
3
|
+
interface MessageProviderMetadata {
|
|
4
|
+
}
|
|
5
|
+
interface PartProviderMetadata {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type Content = ContentMap[ContentType];
|
|
9
|
+
interface ContentMap {
|
|
10
|
+
'file': FilePart;
|
|
11
|
+
'image': ImagePart;
|
|
12
|
+
'provider': ProviderPart;
|
|
13
|
+
'reasoning': ReasoningPart;
|
|
14
|
+
'refusal': RefusalPart;
|
|
15
|
+
'text': TextPart;
|
|
16
|
+
'tool-call': ToolCallPart;
|
|
17
|
+
'tool-result': ToolResultPart;
|
|
18
|
+
}
|
|
19
|
+
type ContentType = keyof ContentMap;
|
|
20
|
+
interface FilePart {
|
|
21
|
+
data: string | URL;
|
|
22
|
+
type: 'file';
|
|
23
|
+
}
|
|
24
|
+
interface ImagePart {
|
|
25
|
+
data: string | URL;
|
|
26
|
+
detail?: 'auto' | 'high' | 'low';
|
|
27
|
+
type: 'image';
|
|
28
|
+
}
|
|
29
|
+
interface ProviderPart {
|
|
30
|
+
source: string;
|
|
31
|
+
type: 'provider';
|
|
32
|
+
value: unknown;
|
|
33
|
+
}
|
|
34
|
+
interface ReasoningPart {
|
|
35
|
+
content: ReasoningPartContent[];
|
|
36
|
+
id?: string;
|
|
37
|
+
providerMetadata?: PartProviderMetadata;
|
|
38
|
+
type: 'reasoning';
|
|
39
|
+
}
|
|
40
|
+
interface ReasoningPartContent {
|
|
41
|
+
text: string;
|
|
42
|
+
type: 'encrypted' | 'redacted' | 'summary' | 'text';
|
|
43
|
+
}
|
|
44
|
+
interface RefusalPart {
|
|
45
|
+
refusal: string;
|
|
46
|
+
type: 'refusal';
|
|
47
|
+
}
|
|
48
|
+
interface TextPart {
|
|
49
|
+
providerMetadata?: PartProviderMetadata;
|
|
50
|
+
text: string;
|
|
51
|
+
type: 'text';
|
|
52
|
+
}
|
|
53
|
+
interface ToolCallPart {
|
|
54
|
+
arguments: string;
|
|
55
|
+
callId: string;
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
type: 'tool-call';
|
|
59
|
+
}
|
|
60
|
+
interface ToolResultPart {
|
|
61
|
+
callId: string;
|
|
62
|
+
isError?: boolean;
|
|
63
|
+
output: string | ToolResultPartContent[];
|
|
64
|
+
type: 'tool-result';
|
|
65
|
+
}
|
|
66
|
+
type ToolResultPartContent = ImagePart | TextPart;
|
|
67
|
+
|
|
68
|
+
type FinishReason = 'content-filter' | 'length' | 'refusal' | 'stop' | 'tool-calls' | (string & {});
|
|
69
|
+
|
|
70
|
+
interface AssistantMessage {
|
|
71
|
+
content: readonly AssistantMessageContent[] | string;
|
|
72
|
+
id?: string;
|
|
73
|
+
providerMetadata?: MessageProviderMetadata;
|
|
74
|
+
role: 'assistant';
|
|
75
|
+
}
|
|
76
|
+
type AssistantMessageContent = ProviderPart | ReasoningPart | RefusalPart | TextPart | ToolCallPart;
|
|
77
|
+
interface DeveloperMessage {
|
|
78
|
+
content: readonly DeveloperMessageContent[] | string;
|
|
79
|
+
role: 'developer';
|
|
80
|
+
}
|
|
81
|
+
type DeveloperMessageContent = TextPart;
|
|
82
|
+
type Message = MessageMap[MessageType];
|
|
83
|
+
interface MessageMap {
|
|
84
|
+
assistant: AssistantMessage;
|
|
85
|
+
developer: DeveloperMessage;
|
|
86
|
+
system: SystemMessage;
|
|
87
|
+
user: UserMessage;
|
|
88
|
+
}
|
|
89
|
+
type MessageType = keyof MessageMap;
|
|
90
|
+
interface SystemMessage {
|
|
91
|
+
content: readonly SystemMessageContent[] | string;
|
|
92
|
+
role: 'system';
|
|
93
|
+
}
|
|
94
|
+
type SystemMessageContent = TextPart;
|
|
95
|
+
interface UserMessage {
|
|
96
|
+
content: readonly UserMessageContent[] | string;
|
|
97
|
+
role: 'user';
|
|
98
|
+
}
|
|
99
|
+
type UserMessageContent = FilePart | ImagePart | TextPart | ToolResultPart;
|
|
100
|
+
|
|
101
|
+
interface Usage {
|
|
102
|
+
cacheCreationInputTokens?: number;
|
|
103
|
+
cacheReadInputTokens?: number;
|
|
104
|
+
inputTokens: number;
|
|
105
|
+
outputTokens: number;
|
|
106
|
+
reasoningTokens?: number;
|
|
107
|
+
totalTokens: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface ContentEndEvent {
|
|
111
|
+
content: AssistantMessageContent | ToolResultPart;
|
|
112
|
+
index: number;
|
|
113
|
+
type: 'content.end';
|
|
114
|
+
}
|
|
115
|
+
interface ContentStartEvent {
|
|
116
|
+
contentType: AssistantMessageContent['type'] | ToolResultPart['type'];
|
|
117
|
+
index: number;
|
|
118
|
+
type: 'content.start';
|
|
119
|
+
}
|
|
120
|
+
interface RawEvent {
|
|
121
|
+
detail: unknown;
|
|
122
|
+
type: 'raw';
|
|
123
|
+
}
|
|
124
|
+
interface ReasoningDeltaEvent {
|
|
125
|
+
delta: string;
|
|
126
|
+
index: number;
|
|
127
|
+
type: 'reasoning.delta';
|
|
128
|
+
}
|
|
129
|
+
interface RefusalDeltaEvent {
|
|
130
|
+
delta: string;
|
|
131
|
+
index: number;
|
|
132
|
+
type: 'refusal.delta';
|
|
133
|
+
}
|
|
134
|
+
/** @internal */
|
|
135
|
+
interface StepEndDoneEvent {
|
|
136
|
+
error?: never;
|
|
137
|
+
message: AssistantMessage;
|
|
138
|
+
reason?: FinishReason;
|
|
139
|
+
status: Exclude<StepStatus, 'failed'>;
|
|
140
|
+
type: 'step.end';
|
|
141
|
+
usage?: Usage;
|
|
142
|
+
}
|
|
143
|
+
type StepEndEvent = StepEndDoneEvent | StepEndFailEvent;
|
|
144
|
+
/** @internal */
|
|
145
|
+
interface StepEndFailEvent {
|
|
146
|
+
error: XSAIError;
|
|
147
|
+
message: AssistantMessage;
|
|
148
|
+
reason?: never;
|
|
149
|
+
status: 'failed';
|
|
150
|
+
type: 'step.end';
|
|
151
|
+
usage?: Usage;
|
|
152
|
+
}
|
|
153
|
+
interface StepStartEvent {
|
|
154
|
+
type: 'step.start';
|
|
155
|
+
}
|
|
156
|
+
type StepStatus = 'cancelled' | 'completed' | 'failed' | 'incomplete';
|
|
157
|
+
interface TextDeltaEvent {
|
|
158
|
+
delta: string;
|
|
159
|
+
index: number;
|
|
160
|
+
type: 'text.delta';
|
|
161
|
+
}
|
|
162
|
+
type TextEvent = TextEventMap[TextEventType];
|
|
163
|
+
interface TextEventMap {
|
|
164
|
+
'content.end': ContentEndEvent;
|
|
165
|
+
'content.start': ContentStartEvent;
|
|
166
|
+
'raw': RawEvent;
|
|
167
|
+
'reasoning.delta': ReasoningDeltaEvent;
|
|
168
|
+
'refusal.delta': RefusalDeltaEvent;
|
|
169
|
+
'step.end': StepEndEvent;
|
|
170
|
+
'step.start': StepStartEvent;
|
|
171
|
+
'text.delta': TextDeltaEvent;
|
|
172
|
+
'tool-call.delta': ToolCallDeltaEvent;
|
|
173
|
+
}
|
|
174
|
+
type TextEventType = keyof TextEventMap;
|
|
175
|
+
interface ToolCallDeltaEvent {
|
|
176
|
+
callId: string;
|
|
177
|
+
delta: string;
|
|
178
|
+
index: number;
|
|
179
|
+
name?: string;
|
|
180
|
+
type: 'tool-call.delta';
|
|
181
|
+
}
|
|
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
|
+
/** The Standard Typed interface. This is a base type extended by other specs. */
|
|
200
|
+
interface StandardTypedV1<Input = unknown, Output = Input> {
|
|
201
|
+
/** The Standard properties. */
|
|
202
|
+
readonly "~standard": StandardTypedV1.Props<Input, Output>;
|
|
203
|
+
}
|
|
204
|
+
declare namespace StandardTypedV1 {
|
|
205
|
+
/** The Standard Typed properties interface. */
|
|
206
|
+
interface Props<Input = unknown, Output = Input> {
|
|
207
|
+
/** The version number of the standard. */
|
|
208
|
+
readonly version: 1;
|
|
209
|
+
/** The vendor name of the schema library. */
|
|
210
|
+
readonly vendor: string;
|
|
211
|
+
/** Inferred types associated with the schema. */
|
|
212
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
213
|
+
}
|
|
214
|
+
/** The Standard Typed types interface. */
|
|
215
|
+
interface Types<Input = unknown, Output = Input> {
|
|
216
|
+
/** The input type of the schema. */
|
|
217
|
+
readonly input: Input;
|
|
218
|
+
/** The output type of the schema. */
|
|
219
|
+
readonly output: Output;
|
|
220
|
+
}
|
|
221
|
+
/** Infers the input type of a Standard Typed. */
|
|
222
|
+
type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
223
|
+
/** Infers the output type of a Standard Typed. */
|
|
224
|
+
type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
225
|
+
}
|
|
226
|
+
/** The Standard Schema interface. */
|
|
227
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
228
|
+
/** The Standard Schema properties. */
|
|
229
|
+
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
|
230
|
+
}
|
|
231
|
+
declare namespace StandardSchemaV1 {
|
|
232
|
+
/** The Standard Schema properties interface. */
|
|
233
|
+
interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
|
234
|
+
/** Validates unknown input values. */
|
|
235
|
+
readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
|
|
236
|
+
}
|
|
237
|
+
/** The result interface of the validate function. */
|
|
238
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
239
|
+
/** The result interface if validation succeeds. */
|
|
240
|
+
interface SuccessResult<Output> {
|
|
241
|
+
/** The typed output value. */
|
|
242
|
+
readonly value: Output;
|
|
243
|
+
/** A falsy value for `issues` indicates success. */
|
|
244
|
+
readonly issues?: undefined;
|
|
245
|
+
}
|
|
246
|
+
interface Options {
|
|
247
|
+
/** Explicit support for additional vendor-specific parameters, if needed. */
|
|
248
|
+
readonly libraryOptions?: Record<string, unknown> | undefined;
|
|
249
|
+
}
|
|
250
|
+
/** The result interface if validation fails. */
|
|
251
|
+
interface FailureResult {
|
|
252
|
+
/** The issues of failed validation. */
|
|
253
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
254
|
+
}
|
|
255
|
+
/** The issue interface of the failure output. */
|
|
256
|
+
interface Issue {
|
|
257
|
+
/** The error message of the issue. */
|
|
258
|
+
readonly message: string;
|
|
259
|
+
/** The path of the issue, if any. */
|
|
260
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
261
|
+
}
|
|
262
|
+
/** The path segment interface of the issue. */
|
|
263
|
+
interface PathSegment {
|
|
264
|
+
/** The key representing a path segment. */
|
|
265
|
+
readonly key: PropertyKey;
|
|
266
|
+
}
|
|
267
|
+
/** The Standard types interface. */
|
|
268
|
+
interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {
|
|
269
|
+
}
|
|
270
|
+
/** Infers the input type of a Standard. */
|
|
271
|
+
type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
|
272
|
+
/** Infers the output type of a Standard. */
|
|
273
|
+
type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
|
274
|
+
}
|
|
275
|
+
/** The Standard JSON Schema interface. */
|
|
276
|
+
interface StandardJSONSchemaV1<Input = unknown, Output = Input> {
|
|
277
|
+
/** The Standard JSON Schema properties. */
|
|
278
|
+
readonly "~standard": StandardJSONSchemaV1.Props<Input, Output>;
|
|
279
|
+
}
|
|
280
|
+
declare namespace StandardJSONSchemaV1 {
|
|
281
|
+
/** The Standard JSON Schema properties interface. */
|
|
282
|
+
interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
|
283
|
+
/** Methods for generating the input/output JSON Schema. */
|
|
284
|
+
readonly jsonSchema: StandardJSONSchemaV1.Converter;
|
|
285
|
+
}
|
|
286
|
+
/** The Standard JSON Schema converter interface. */
|
|
287
|
+
interface Converter {
|
|
288
|
+
/** Converts the input type to JSON Schema. May throw if conversion is not supported. */
|
|
289
|
+
readonly input: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
|
|
290
|
+
/** Converts the output type to JSON Schema. May throw if conversion is not supported. */
|
|
291
|
+
readonly output: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* The target version of the generated JSON Schema.
|
|
295
|
+
*
|
|
296
|
+
* It is *strongly recommended* that implementers support `"draft-2020-12"` and `"draft-07"`, as they are both in wide use. All other targets can be implemented on a best-effort basis. Libraries should throw if they don't support a specified target.
|
|
297
|
+
*
|
|
298
|
+
* The `"openapi-3.0"` target is intended as a standardized specifier for OpenAPI 3.0 which is a superset of JSON Schema `"draft-04"`.
|
|
299
|
+
*/
|
|
300
|
+
type Target = "draft-2020-12" | "draft-07" | "openapi-3.0" | ({} & string);
|
|
301
|
+
/** The options for the input/output methods. */
|
|
302
|
+
interface Options {
|
|
303
|
+
/** Specifies the target version of the generated JSON Schema. Support for all versions is on a best-effort basis. If a given version is not supported, the library should throw. */
|
|
304
|
+
readonly target: Target;
|
|
305
|
+
/** Explicit support for additional vendor-specific parameters, if needed. */
|
|
306
|
+
readonly libraryOptions?: Record<string, unknown> | undefined;
|
|
307
|
+
}
|
|
308
|
+
/** The Standard types interface. */
|
|
309
|
+
interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {
|
|
310
|
+
}
|
|
311
|
+
/** Infers the input type of a Standard. */
|
|
312
|
+
type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
|
313
|
+
/** Infers the output type of a Standard. */
|
|
314
|
+
type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ==================================================================================================
|
|
318
|
+
// JSON Schema Draft 07
|
|
319
|
+
// ==================================================================================================
|
|
320
|
+
// https://tools.ietf.org/html/draft-handrews-json-schema-validation-01
|
|
321
|
+
// --------------------------------------------------------------------------------------------------
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Primitive type
|
|
325
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
|
|
326
|
+
*/
|
|
327
|
+
type JSONSchema7TypeName =
|
|
328
|
+
| "string" //
|
|
329
|
+
| "number"
|
|
330
|
+
| "integer"
|
|
331
|
+
| "boolean"
|
|
332
|
+
| "object"
|
|
333
|
+
| "array"
|
|
334
|
+
| "null";
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Primitive type
|
|
338
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
|
|
339
|
+
*/
|
|
340
|
+
type JSONSchema7Type =
|
|
341
|
+
| string //
|
|
342
|
+
| number
|
|
343
|
+
| boolean
|
|
344
|
+
| JSONSchema7Object
|
|
345
|
+
| JSONSchema7Array
|
|
346
|
+
| null;
|
|
347
|
+
|
|
348
|
+
// Workaround for infinite type recursion
|
|
349
|
+
interface JSONSchema7Object {
|
|
350
|
+
[key: string]: JSONSchema7Type;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Workaround for infinite type recursion
|
|
354
|
+
// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
|
|
355
|
+
interface JSONSchema7Array extends Array<JSONSchema7Type> {}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Meta schema
|
|
359
|
+
*
|
|
360
|
+
* Recommended values:
|
|
361
|
+
* - 'http://json-schema.org/schema#'
|
|
362
|
+
* - 'http://json-schema.org/hyper-schema#'
|
|
363
|
+
* - 'http://json-schema.org/draft-07/schema#'
|
|
364
|
+
* - 'http://json-schema.org/draft-07/hyper-schema#'
|
|
365
|
+
*
|
|
366
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
|
|
367
|
+
*/
|
|
368
|
+
type JSONSchema7Version = string;
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* JSON Schema v7
|
|
372
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01
|
|
373
|
+
*/
|
|
374
|
+
type JSONSchema7Definition = JSONSchema7 | boolean;
|
|
375
|
+
interface JSONSchema7 {
|
|
376
|
+
$id?: string | undefined;
|
|
377
|
+
$ref?: string | undefined;
|
|
378
|
+
$schema?: JSONSchema7Version | undefined;
|
|
379
|
+
$comment?: string | undefined;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-8.2.4
|
|
383
|
+
* @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#appendix-A
|
|
384
|
+
*/
|
|
385
|
+
$defs?: {
|
|
386
|
+
[key: string]: JSONSchema7Definition;
|
|
387
|
+
} | undefined;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1
|
|
391
|
+
*/
|
|
392
|
+
type?: JSONSchema7TypeName | JSONSchema7TypeName[] | undefined;
|
|
393
|
+
enum?: JSONSchema7Type[] | undefined;
|
|
394
|
+
const?: JSONSchema7Type | undefined;
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.2
|
|
398
|
+
*/
|
|
399
|
+
multipleOf?: number | undefined;
|
|
400
|
+
maximum?: number | undefined;
|
|
401
|
+
exclusiveMaximum?: number | undefined;
|
|
402
|
+
minimum?: number | undefined;
|
|
403
|
+
exclusiveMinimum?: number | undefined;
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.3
|
|
407
|
+
*/
|
|
408
|
+
maxLength?: number | undefined;
|
|
409
|
+
minLength?: number | undefined;
|
|
410
|
+
pattern?: string | undefined;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4
|
|
414
|
+
*/
|
|
415
|
+
items?: JSONSchema7Definition | JSONSchema7Definition[] | undefined;
|
|
416
|
+
additionalItems?: JSONSchema7Definition | undefined;
|
|
417
|
+
maxItems?: number | undefined;
|
|
418
|
+
minItems?: number | undefined;
|
|
419
|
+
uniqueItems?: boolean | undefined;
|
|
420
|
+
contains?: JSONSchema7Definition | undefined;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.5
|
|
424
|
+
*/
|
|
425
|
+
maxProperties?: number | undefined;
|
|
426
|
+
minProperties?: number | undefined;
|
|
427
|
+
required?: string[] | undefined;
|
|
428
|
+
properties?: {
|
|
429
|
+
[key: string]: JSONSchema7Definition;
|
|
430
|
+
} | undefined;
|
|
431
|
+
patternProperties?: {
|
|
432
|
+
[key: string]: JSONSchema7Definition;
|
|
433
|
+
} | undefined;
|
|
434
|
+
additionalProperties?: JSONSchema7Definition | undefined;
|
|
435
|
+
dependencies?: {
|
|
436
|
+
[key: string]: JSONSchema7Definition | string[];
|
|
437
|
+
} | undefined;
|
|
438
|
+
propertyNames?: JSONSchema7Definition | undefined;
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.6
|
|
442
|
+
*/
|
|
443
|
+
if?: JSONSchema7Definition | undefined;
|
|
444
|
+
then?: JSONSchema7Definition | undefined;
|
|
445
|
+
else?: JSONSchema7Definition | undefined;
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.7
|
|
449
|
+
*/
|
|
450
|
+
allOf?: JSONSchema7Definition[] | undefined;
|
|
451
|
+
anyOf?: JSONSchema7Definition[] | undefined;
|
|
452
|
+
oneOf?: JSONSchema7Definition[] | undefined;
|
|
453
|
+
not?: JSONSchema7Definition | undefined;
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-7
|
|
457
|
+
*/
|
|
458
|
+
format?: string | undefined;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-8
|
|
462
|
+
*/
|
|
463
|
+
contentMediaType?: string | undefined;
|
|
464
|
+
contentEncoding?: string | undefined;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9
|
|
468
|
+
*/
|
|
469
|
+
definitions?: {
|
|
470
|
+
[key: string]: JSONSchema7Definition;
|
|
471
|
+
} | undefined;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-10
|
|
475
|
+
*/
|
|
476
|
+
title?: string | undefined;
|
|
477
|
+
description?: string | undefined;
|
|
478
|
+
default?: JSONSchema7Type | undefined;
|
|
479
|
+
readOnly?: boolean | undefined;
|
|
480
|
+
writeOnly?: boolean | undefined;
|
|
481
|
+
examples?: JSONSchema7Type | undefined;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
interface CombinedStandardSchema<Input = unknown, Output = Input> {
|
|
485
|
+
readonly '~standard': Partial<StandardSchemaV1.Props<Input, Output>> & StandardJSONSchemaV1.Props<Input, Output>;
|
|
486
|
+
}
|
|
487
|
+
type InferSchemaInput<Schema extends UnresolvedSchema> = Schema extends StandardTypedV1 ? StandardSchemaV1.InferInput<Schema> : unknown;
|
|
488
|
+
type InferSchemaOutput<Schema extends UnresolvedSchema> = Schema extends StandardTypedV1 ? StandardSchemaV1.InferOutput<Schema> : unknown;
|
|
489
|
+
interface ResolvedSchema<Input = unknown, Output = Input> {
|
|
490
|
+
schema: JSONSchema7;
|
|
491
|
+
validate?: StandardSchemaV1.Props<Input, Output>['validate'];
|
|
492
|
+
}
|
|
493
|
+
type UnresolvedSchema<Input = unknown, Output = Input> = CombinedStandardSchema<Input, Output> | JSONSchema7;
|
|
494
|
+
declare const resolveSchema: <Input = unknown, Output = Input>(schema: UnresolvedSchema<Input, Output>) => ResolvedSchema<Input, Output>;
|
|
495
|
+
|
|
496
|
+
interface ExecutableTool extends Tool {
|
|
497
|
+
execute: (input: unknown, options?: ToolExecuteOptions) => Promisable<string | ToolResultPartContent[]>;
|
|
498
|
+
}
|
|
499
|
+
interface Tool {
|
|
500
|
+
description?: string;
|
|
501
|
+
inputSchema: ResolvedSchema;
|
|
502
|
+
name: string;
|
|
503
|
+
outputSchema?: ResolvedSchema;
|
|
504
|
+
}
|
|
505
|
+
interface ToolExecuteOptions {
|
|
506
|
+
signal?: AbortSignal;
|
|
507
|
+
}
|
|
508
|
+
interface ToolOptions<TInput extends UnresolvedSchema, TOutput extends undefined | UnresolvedSchema = undefined> {
|
|
509
|
+
description?: string;
|
|
510
|
+
execute?: (input: InferSchemaOutput<TInput>, options?: ToolExecuteOptions) => TOutput extends UnresolvedSchema ? Promisable<InferSchemaInput<TOutput>> : Promisable<string | ToolResultPartContent[]>;
|
|
511
|
+
inputSchema: TInput;
|
|
512
|
+
name: string;
|
|
513
|
+
outputSchema?: TOutput;
|
|
514
|
+
}
|
|
515
|
+
interface ToolFactory {
|
|
516
|
+
<TInput extends UnresolvedSchema, TOutput extends undefined | UnresolvedSchema = undefined>(options: Required<Pick<ToolOptions<TInput, TOutput>, 'execute'>> & ToolOptions<TInput, TOutput>): ExecutableTool;
|
|
517
|
+
<TInput extends UnresolvedSchema, TOutput extends undefined | UnresolvedSchema = undefined>(options: ToolOptions<TInput, TOutput>): Tool;
|
|
518
|
+
}
|
|
519
|
+
declare const tool: ToolFactory;
|
|
520
|
+
|
|
521
|
+
type LanguageModel = (options: LanguageModelOptions) => Promisable<ReadableStream<TextEvent>>;
|
|
522
|
+
interface LanguageModelOptions {
|
|
523
|
+
includeRawEvents?: boolean;
|
|
524
|
+
input: Message[] | string;
|
|
525
|
+
instructions?: string;
|
|
526
|
+
maxOutputTokens?: number;
|
|
527
|
+
/** Strict structured-output schema. */
|
|
528
|
+
outputFormat?: UnresolvedSchema;
|
|
529
|
+
providerOptions?: LanguageModelProviderOptions;
|
|
530
|
+
/** Qualitative reasoning effort; provider-specific knobs stay in `providerOptions`. */
|
|
531
|
+
reasoningEffort?: 'high' | 'low' | 'max' | 'medium' | 'none' | 'xhigh' | (string & {});
|
|
532
|
+
signal?: AbortSignal;
|
|
533
|
+
temperature?: number;
|
|
534
|
+
toolChoice?: ToolChoice;
|
|
535
|
+
tools?: Tool[];
|
|
536
|
+
topP?: number;
|
|
537
|
+
}
|
|
538
|
+
interface LanguageModelProviderOptions {
|
|
539
|
+
}
|
|
540
|
+
type ToolChoice = 'auto' | 'none' | 'required' | {
|
|
541
|
+
name: string;
|
|
542
|
+
};
|
|
543
|
+
|
|
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 };
|
|
@@ -0,0 +1,69 @@
|
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsai/text",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0-beta.1",
|
|
5
|
+
"description": "extra-small AI SDK: provider-agnostic text generation, streaming and tool calling.",
|
|
6
|
+
"author": "Moeru AI",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://xsai.js.org",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/moeru-ai/xsai.git",
|
|
12
|
+
"directory": "packages/text"
|
|
13
|
+
},
|
|
14
|
+
"bugs": "https://github.com/moeru-ai/xsai/issues",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"xsai",
|
|
17
|
+
"ai",
|
|
18
|
+
"openai",
|
|
19
|
+
"text",
|
|
20
|
+
"generate-text",
|
|
21
|
+
"stream-text",
|
|
22
|
+
"tool-calling",
|
|
23
|
+
"agent"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json",
|
|
32
|
+
"./internal": {
|
|
33
|
+
"types": "./dist/internal.d.ts",
|
|
34
|
+
"default": "./dist/internal.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@xsai/shared": "1.0.0-beta.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@standard-schema/spec": "1.1.0",
|
|
45
|
+
"@types/json-schema": "^7.0.15"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "pkgroll --clean-dist",
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"test:watch": "vitest"
|
|
51
|
+
},
|
|
52
|
+
"main": "./dist/index.js",
|
|
53
|
+
"types": "./dist/index.d.ts"
|
|
6
54
|
}
|