@xsai/stream-text 0.4.0-beta.2 → 0.4.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -1
- package/dist/index.js +25 -23
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { WithUnknown } from '@xsai/shared';
|
|
1
2
|
import { CompletionToolCall, CompletionToolResult, FinishReason, Usage, ChatOptions, CompletionStep, Message } from '@xsai/shared-chat';
|
|
2
3
|
|
|
3
4
|
type StreamTextEvent = (CompletionToolCall & {
|
|
@@ -51,8 +52,9 @@ interface StreamTextResult {
|
|
|
51
52
|
messages: Promise<Message[]>;
|
|
52
53
|
steps: Promise<CompletionStep[]>;
|
|
53
54
|
textStream: ReadableStream<string>;
|
|
55
|
+
totalUsage: Promise<undefined | Usage>;
|
|
54
56
|
usage: Promise<undefined | Usage>;
|
|
55
57
|
}
|
|
56
|
-
declare const streamText: (options: StreamTextOptions) =>
|
|
58
|
+
declare const streamText: (options: WithUnknown<StreamTextOptions>) => StreamTextResult;
|
|
57
59
|
|
|
58
60
|
export { type StreamTextEvent, type StreamTextOptions, type StreamTextResult, streamText };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
+
import { trampoline, objCamelToSnake } from '@xsai/shared';
|
|
1
2
|
import { chat, executeTool, determineStepType } from '@xsai/shared-chat';
|
|
2
3
|
|
|
3
|
-
const strCamelToSnake = (str) => str.replace(/[A-Z]/g, (s) => `_${s.toLowerCase()}`);
|
|
4
|
-
const objCamelToSnake = (obj) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [strCamelToSnake(k), v]));
|
|
5
|
-
|
|
6
|
-
const trampoline = async (fn) => {
|
|
7
|
-
let result = await fn();
|
|
8
|
-
while (result instanceof Function)
|
|
9
|
-
result = await result();
|
|
10
|
-
return result;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
4
|
class DelayedPromise {
|
|
14
5
|
get promise() {
|
|
15
6
|
if (this._promise == null) {
|
|
@@ -82,14 +73,16 @@ const transformChunk = () => {
|
|
|
82
73
|
});
|
|
83
74
|
};
|
|
84
75
|
|
|
85
|
-
const streamText =
|
|
76
|
+
const streamText = (options) => {
|
|
86
77
|
const steps = [];
|
|
87
78
|
const messages = structuredClone(options.messages);
|
|
88
79
|
const maxSteps = options.maxSteps ?? 1;
|
|
89
80
|
let usage;
|
|
81
|
+
let totalUsage;
|
|
90
82
|
const resultSteps = new DelayedPromise();
|
|
91
83
|
const resultMessages = new DelayedPromise();
|
|
92
84
|
const resultUsage = new DelayedPromise();
|
|
85
|
+
const resultTotalUsage = new DelayedPromise();
|
|
93
86
|
let eventCtrl;
|
|
94
87
|
let textCtrl;
|
|
95
88
|
const eventStream = new ReadableStream({ start: (controller) => eventCtrl = controller });
|
|
@@ -102,16 +95,21 @@ const streamText = async (options) => {
|
|
|
102
95
|
steps.push(step);
|
|
103
96
|
void options.onStepFinish?.(step);
|
|
104
97
|
};
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
98
|
+
const doStream = async () => {
|
|
99
|
+
const { body: stream } = await chat({
|
|
100
|
+
...options,
|
|
101
|
+
maxSteps: void 0,
|
|
102
|
+
messages,
|
|
103
|
+
stream: true,
|
|
104
|
+
streamOptions: options.streamOptions != null ? objCamelToSnake(options.streamOptions) : void 0
|
|
105
|
+
});
|
|
113
106
|
const pushUsage = (u) => {
|
|
114
107
|
usage = u;
|
|
108
|
+
totalUsage = totalUsage ? {
|
|
109
|
+
completion_tokens: totalUsage.completion_tokens + u.completion_tokens,
|
|
110
|
+
prompt_tokens: totalUsage.prompt_tokens + u.prompt_tokens,
|
|
111
|
+
total_tokens: totalUsage.total_tokens + u.total_tokens
|
|
112
|
+
} : { ...u };
|
|
115
113
|
};
|
|
116
114
|
let text = "";
|
|
117
115
|
const pushText = (content) => {
|
|
@@ -122,7 +120,7 @@ const streamText = async (options) => {
|
|
|
122
120
|
const toolCalls = [];
|
|
123
121
|
const toolResults = [];
|
|
124
122
|
let finishReason = "other";
|
|
125
|
-
await
|
|
123
|
+
await stream.pipeThrough(transformChunk()).pipeTo(new WritableStream({
|
|
126
124
|
abort: (reason) => {
|
|
127
125
|
eventCtrl?.error(reason);
|
|
128
126
|
textCtrl?.error(reason);
|
|
@@ -166,6 +164,8 @@ const streamText = async (options) => {
|
|
|
166
164
|
messages.push({ content: text, role: "assistant", tool_calls });
|
|
167
165
|
if (tool_calls.length !== 0) {
|
|
168
166
|
for (const toolCall of tool_calls) {
|
|
167
|
+
if (toolCall == null)
|
|
168
|
+
continue;
|
|
169
169
|
const { completionToolCall, completionToolResult, message } = await executeTool({
|
|
170
170
|
abortSignal: options.abortSignal,
|
|
171
171
|
messages,
|
|
@@ -194,12 +194,11 @@ const streamText = async (options) => {
|
|
|
194
194
|
usage
|
|
195
195
|
});
|
|
196
196
|
if (toolCalls.length !== 0 && steps.length < maxSteps)
|
|
197
|
-
return async () =>
|
|
197
|
+
return async () => doStream();
|
|
198
198
|
};
|
|
199
|
-
const stream = await startStream();
|
|
200
199
|
void (async () => {
|
|
201
200
|
try {
|
|
202
|
-
await trampoline(async () =>
|
|
201
|
+
await trampoline(async () => doStream());
|
|
203
202
|
eventCtrl?.close();
|
|
204
203
|
textCtrl?.close();
|
|
205
204
|
} catch (err) {
|
|
@@ -208,10 +207,12 @@ const streamText = async (options) => {
|
|
|
208
207
|
resultSteps.reject(err);
|
|
209
208
|
resultMessages.reject(err);
|
|
210
209
|
resultUsage.reject(err);
|
|
210
|
+
resultTotalUsage.reject(err);
|
|
211
211
|
} finally {
|
|
212
212
|
resultSteps.resolve(steps);
|
|
213
213
|
resultMessages.resolve(messages);
|
|
214
214
|
resultUsage.resolve(usage);
|
|
215
|
+
resultTotalUsage.resolve(totalUsage);
|
|
215
216
|
void options.onFinish?.(steps.at(-1));
|
|
216
217
|
}
|
|
217
218
|
})();
|
|
@@ -220,6 +221,7 @@ const streamText = async (options) => {
|
|
|
220
221
|
messages: resultMessages.promise,
|
|
221
222
|
steps: resultSteps.promise,
|
|
222
223
|
textStream,
|
|
224
|
+
totalUsage: resultTotalUsage.promise,
|
|
223
225
|
usage: resultUsage.promise
|
|
224
226
|
};
|
|
225
227
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsai/stream-text",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.0-beta.
|
|
4
|
+
"version": "0.4.0-beta.4",
|
|
5
5
|
"description": "extra-small AI SDK.",
|
|
6
6
|
"author": "Moeru AI",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@xsai/shared
|
|
32
|
+
"@xsai/shared": "~0.4.0-beta.4",
|
|
33
|
+
"@xsai/shared-chat": "~0.4.0-beta.4"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"valibot": "^1.0.0",
|
|
36
|
-
"@xsai/
|
|
37
|
-
"@xsai/tool": "~0.4.0-beta.2"
|
|
37
|
+
"@xsai/tool": "~0.4.0-beta.4"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "pkgroll",
|