ai 6.0.268 → 6.0.271
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/CHANGELOG.md +27 -0
- package/dist/index.d.mts +48 -21
- package/dist/index.d.ts +48 -21
- package/dist/index.js +378 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +317 -68
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.mjs +1 -1
- package/dist/test/index.d.mts +4 -1
- package/dist/test/index.d.ts +4 -1
- package/dist/test/index.js +6 -0
- package/dist/test/index.js.map +1 -1
- package/dist/test/index.mjs +6 -0
- package/dist/test/index.mjs.map +1 -1
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +2 -2
- package/docs/07-reference/01-ai-sdk-core/06-embed-many.mdx +6 -2
- package/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx +33 -5
- package/package.json +3 -3
- package/src/agent/create-agent-ui-stream.ts +2 -2
- package/src/embed/embed-many.ts +75 -6
- package/src/generate-text/stream-text.ts +84 -1
- package/src/middleware/wrap-embedding-model.ts +8 -1
- package/src/model/get-embedding-model-max-input-bytes-per-call.ts +15 -0
- package/src/test/mock-embedding-model-v3.ts +9 -0
- package/src/ui/direct-chat-transport.ts +2 -2
- package/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +1 -0
- package/src/ui/validate-ui-messages.ts +136 -55
- package/src/ui-message-stream/create-ui-message-stream.ts +47 -17
- package/src/ui-message-stream/handle-ui-message-stream-finish.ts +58 -15
- package/src/ui-message-stream/index.ts +5 -1
- package/src/ui-message-stream/ui-message-stream-on-finish-callback.ts +7 -0
- package/src/ui-message-stream/ui-message-stream-outcome.ts +12 -0
- package/src/ui-message-stream/ui-message-stream-writer.ts +15 -0
- package/src/util/create-stitchable-stream.ts +35 -3
|
@@ -8,6 +8,7 @@ import type { UIMessage } from '../ui/ui-messages';
|
|
|
8
8
|
import type { ErrorHandler } from '../util/error-handler';
|
|
9
9
|
import type { InferUIMessageChunk, UIMessageChunk } from './ui-message-chunks';
|
|
10
10
|
import type { UIMessageStreamOnFinishCallback } from './ui-message-stream-on-finish-callback';
|
|
11
|
+
import type { UIMessageStreamOutcome } from './ui-message-stream-outcome';
|
|
11
12
|
import type { UIMessageStreamOnStepFinishCallback } from './ui-message-stream-on-step-finish-callback';
|
|
12
13
|
|
|
13
14
|
export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
@@ -17,6 +18,7 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
17
18
|
onFinish,
|
|
18
19
|
onError,
|
|
19
20
|
stream,
|
|
21
|
+
getOutcome,
|
|
20
22
|
}: {
|
|
21
23
|
stream: ReadableStream<InferUIMessageChunk<UI_MESSAGE>>;
|
|
22
24
|
|
|
@@ -39,6 +41,11 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
39
41
|
onStepFinish?: UIMessageStreamOnStepFinishCallback<UI_MESSAGE>;
|
|
40
42
|
|
|
41
43
|
onFinish?: UIMessageStreamOnFinishCallback<UI_MESSAGE>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Returns the operation-level outcome declared by the stream owner.
|
|
47
|
+
*/
|
|
48
|
+
getOutcome?: () => UIMessageStreamOutcome;
|
|
42
49
|
}): ReadableStream<InferUIMessageChunk<UI_MESSAGE>> {
|
|
43
50
|
// last message is only relevant for assistant messages
|
|
44
51
|
let lastMessage: UI_MESSAGE | undefined =
|
|
@@ -51,6 +58,13 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
let isAborted = false;
|
|
61
|
+
let hasProcessingFailure = false;
|
|
62
|
+
let processingError: unknown;
|
|
63
|
+
|
|
64
|
+
const recordProcessingFailure = (error: unknown) => {
|
|
65
|
+
hasProcessingFailure = true;
|
|
66
|
+
processingError = error;
|
|
67
|
+
};
|
|
54
68
|
|
|
55
69
|
const idInjectedStream = stream.pipeThrough(
|
|
56
70
|
new TransformStream<
|
|
@@ -58,21 +72,31 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
58
72
|
InferUIMessageChunk<UI_MESSAGE>
|
|
59
73
|
>({
|
|
60
74
|
transform(chunk, controller) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
75
|
+
try {
|
|
76
|
+
let outputChunk = chunk;
|
|
77
|
+
|
|
78
|
+
// when there is no messageId in the start chunk,
|
|
79
|
+
// but the user checked for persistence,
|
|
80
|
+
// inject the messageId into the chunk
|
|
81
|
+
if (chunk.type === 'start') {
|
|
82
|
+
const startChunk = chunk as UIMessageChunk & { type: 'start' };
|
|
83
|
+
if (startChunk.messageId == null && messageId != null) {
|
|
84
|
+
outputChunk = {
|
|
85
|
+
...startChunk,
|
|
86
|
+
messageId,
|
|
87
|
+
} as InferUIMessageChunk<UI_MESSAGE>;
|
|
88
|
+
}
|
|
68
89
|
}
|
|
69
|
-
}
|
|
70
90
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
91
|
+
if (chunk.type === 'abort') {
|
|
92
|
+
isAborted = true;
|
|
93
|
+
}
|
|
74
94
|
|
|
75
|
-
|
|
95
|
+
controller.enqueue(outputChunk);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
recordProcessingFailure(error);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
76
100
|
},
|
|
77
101
|
}),
|
|
78
102
|
);
|
|
@@ -95,7 +119,12 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
95
119
|
write: (options?: UIMessageStreamWriteOptions) => void;
|
|
96
120
|
}) => Promise<void>,
|
|
97
121
|
) => {
|
|
98
|
-
|
|
122
|
+
try {
|
|
123
|
+
await job({ state, write: () => {} });
|
|
124
|
+
} catch (error) {
|
|
125
|
+
recordProcessingFailure(error);
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
99
128
|
};
|
|
100
129
|
|
|
101
130
|
let finishCalled = false;
|
|
@@ -107,9 +136,17 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
107
136
|
finishCalled = true;
|
|
108
137
|
|
|
109
138
|
const isContinuation = state.message.id === lastMessage?.id;
|
|
139
|
+
const declaredOutcome = getOutcome?.() ?? { status: 'unknown' };
|
|
140
|
+
const outcome: UIMessageStreamOutcome = hasProcessingFailure
|
|
141
|
+
? { status: 'failed', error: processingError }
|
|
142
|
+
: declaredOutcome.status === 'unknown' && isAborted
|
|
143
|
+
? { status: 'aborted' }
|
|
144
|
+
: declaredOutcome;
|
|
145
|
+
|
|
110
146
|
await onFinish({
|
|
111
|
-
isAborted,
|
|
147
|
+
isAborted: isAborted || outcome.status === 'aborted',
|
|
112
148
|
isContinuation,
|
|
149
|
+
outcome,
|
|
113
150
|
responseMessage: state.message as UI_MESSAGE,
|
|
114
151
|
messages: [
|
|
115
152
|
...(isContinuation ? originalMessages.slice(0, -1) : originalMessages),
|
|
@@ -138,7 +175,13 @@ export function handleUIMessageStreamFinish<UI_MESSAGE extends UIMessage>({
|
|
|
138
175
|
] as UI_MESSAGE[],
|
|
139
176
|
});
|
|
140
177
|
} catch (error) {
|
|
141
|
-
|
|
178
|
+
try {
|
|
179
|
+
onError(error);
|
|
180
|
+
} catch (onErrorError) {
|
|
181
|
+
recordProcessingFailure(onErrorError);
|
|
182
|
+
await callOnFinish();
|
|
183
|
+
throw onErrorError;
|
|
184
|
+
}
|
|
142
185
|
}
|
|
143
186
|
};
|
|
144
187
|
|
|
@@ -10,5 +10,9 @@ export {
|
|
|
10
10
|
} from './ui-message-chunks';
|
|
11
11
|
export { UI_MESSAGE_STREAM_HEADERS } from './ui-message-stream-headers';
|
|
12
12
|
export type { UIMessageStreamOnFinishCallback } from './ui-message-stream-on-finish-callback';
|
|
13
|
+
export type { UIMessageStreamOutcome } from './ui-message-stream-outcome';
|
|
13
14
|
export type { UIMessageStreamOnStepFinishCallback } from './ui-message-stream-on-step-finish-callback';
|
|
14
|
-
export type {
|
|
15
|
+
export type {
|
|
16
|
+
UIMessageStreamWriter,
|
|
17
|
+
UIMessageStreamWriterWithOutcome,
|
|
18
|
+
} from './ui-message-stream-writer';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FinishReason } from '../types/language-model';
|
|
2
2
|
import type { UIMessage } from '../ui/ui-messages';
|
|
3
|
+
import type { UIMessageStreamOutcome } from './ui-message-stream-outcome';
|
|
3
4
|
|
|
4
5
|
export type UIMessageStreamOnFinishCallback<UI_MESSAGE extends UIMessage> =
|
|
5
6
|
(event: {
|
|
@@ -19,6 +20,12 @@ export type UIMessageStreamOnFinishCallback<UI_MESSAGE extends UIMessage> =
|
|
|
19
20
|
*/
|
|
20
21
|
isAborted: boolean;
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* The operation-level outcome of the stream. Fatal stream-processing
|
|
25
|
+
* failures override outcomes declared by the stream owner.
|
|
26
|
+
*/
|
|
27
|
+
outcome: UIMessageStreamOutcome;
|
|
28
|
+
|
|
22
29
|
/**
|
|
23
30
|
* The message that was sent to the client as a response
|
|
24
31
|
* (including the original message if it was extended).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The operation-level outcome of a UI message stream.
|
|
3
|
+
*
|
|
4
|
+
* This is separate from model finish reasons and individual stream chunks.
|
|
5
|
+
* Fatal stream-processing failures override outcomes declared by the stream
|
|
6
|
+
* owner.
|
|
7
|
+
*/
|
|
8
|
+
export type UIMessageStreamOutcome =
|
|
9
|
+
| { status: 'completed' }
|
|
10
|
+
| { status: 'failed'; error?: unknown }
|
|
11
|
+
| { status: 'aborted' }
|
|
12
|
+
| { status: 'unknown' };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { UIMessage } from '../ui';
|
|
2
2
|
import type { ErrorHandler } from '../util/error-handler';
|
|
3
3
|
import type { InferUIMessageChunk } from './ui-message-chunks';
|
|
4
|
+
import type { UIMessageStreamOutcome } from './ui-message-stream-outcome';
|
|
4
5
|
|
|
5
6
|
export interface UIMessageStreamWriter<
|
|
6
7
|
UI_MESSAGE extends UIMessage = UIMessage,
|
|
@@ -22,3 +23,17 @@ export interface UIMessageStreamWriter<
|
|
|
22
23
|
*/
|
|
23
24
|
onError: ErrorHandler | undefined;
|
|
24
25
|
}
|
|
26
|
+
|
|
27
|
+
export interface UIMessageStreamWriterWithOutcome<
|
|
28
|
+
UI_MESSAGE extends UIMessage = UIMessage,
|
|
29
|
+
> extends UIMessageStreamWriter<UI_MESSAGE> {
|
|
30
|
+
/**
|
|
31
|
+
* Declares the operation-level outcome of the composed stream.
|
|
32
|
+
*
|
|
33
|
+
* The first outcome declared through this method is retained. Fatal
|
|
34
|
+
* execution, merge, error-handling, or downstream processing failures
|
|
35
|
+
* override declared outcomes. Declaring an outcome does not write a chunk or
|
|
36
|
+
* close the stream.
|
|
37
|
+
*/
|
|
38
|
+
setOutcome(outcome: UIMessageStreamOutcome): void;
|
|
39
|
+
}
|
|
@@ -25,9 +25,14 @@ export function createStitchableStream<T>(): {
|
|
|
25
25
|
}> = [];
|
|
26
26
|
let controller: ReadableStreamDefaultController<T> | null = null;
|
|
27
27
|
let isClosed = false;
|
|
28
|
+
let isCancelled = false;
|
|
28
29
|
let waitForNewStream = createResolvablePromise<void>();
|
|
29
30
|
|
|
30
31
|
const terminate = () => {
|
|
32
|
+
if (isCancelled) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
isClosed = true;
|
|
32
37
|
waitForNewStream.resolve();
|
|
33
38
|
|
|
@@ -40,6 +45,10 @@ export function createStitchableStream<T>(): {
|
|
|
40
45
|
};
|
|
41
46
|
|
|
42
47
|
const processPull = async () => {
|
|
48
|
+
if (isCancelled) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
// Case 1: Outer stream is closed and no more inner streams
|
|
44
53
|
if (isClosed && innerStreams.length === 0) {
|
|
45
54
|
controller?.close();
|
|
@@ -54,8 +63,14 @@ export function createStitchableStream<T>(): {
|
|
|
54
63
|
return processPull();
|
|
55
64
|
}
|
|
56
65
|
|
|
66
|
+
const currentStream = innerStreams[0];
|
|
67
|
+
|
|
57
68
|
try {
|
|
58
|
-
const { value, done } = await
|
|
69
|
+
const { value, done } = await currentStream.reader.read();
|
|
70
|
+
|
|
71
|
+
if (isCancelled) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
59
74
|
|
|
60
75
|
if (done) {
|
|
61
76
|
// Case 3: Current inner stream is done
|
|
@@ -73,8 +88,12 @@ export function createStitchableStream<T>(): {
|
|
|
73
88
|
controller?.enqueue(value);
|
|
74
89
|
}
|
|
75
90
|
} catch (error) {
|
|
91
|
+
if (isCancelled) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
76
95
|
// Case 5: Current inner stream throws an error
|
|
77
|
-
|
|
96
|
+
currentStream.onError?.(error);
|
|
78
97
|
controller?.error(error);
|
|
79
98
|
innerStreams.shift(); // Remove the errored stream
|
|
80
99
|
terminate(); // we have errored, terminate all streams
|
|
@@ -88,12 +107,15 @@ export function createStitchableStream<T>(): {
|
|
|
88
107
|
},
|
|
89
108
|
pull: processPull,
|
|
90
109
|
async cancel() {
|
|
110
|
+
isCancelled = true;
|
|
111
|
+
isClosed = true;
|
|
112
|
+
waitForNewStream.resolve();
|
|
113
|
+
|
|
91
114
|
for (const { reader, onCancel } of innerStreams) {
|
|
92
115
|
onCancel?.();
|
|
93
116
|
await reader.cancel();
|
|
94
117
|
}
|
|
95
118
|
innerStreams = [];
|
|
96
|
-
isClosed = true;
|
|
97
119
|
},
|
|
98
120
|
}),
|
|
99
121
|
addStream: (
|
|
@@ -103,6 +125,12 @@ export function createStitchableStream<T>(): {
|
|
|
103
125
|
onCancel?: () => void;
|
|
104
126
|
},
|
|
105
127
|
) => {
|
|
128
|
+
if (isCancelled) {
|
|
129
|
+
callbacks?.onCancel?.();
|
|
130
|
+
void innerStream.cancel().catch(() => {});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
106
134
|
if (isClosed) {
|
|
107
135
|
throw new Error('Cannot add inner stream: outer stream is closed');
|
|
108
136
|
}
|
|
@@ -119,6 +147,10 @@ export function createStitchableStream<T>(): {
|
|
|
119
147
|
* finish processing and then close the outer stream.
|
|
120
148
|
*/
|
|
121
149
|
close: () => {
|
|
150
|
+
if (isCancelled) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
122
154
|
isClosed = true;
|
|
123
155
|
waitForNewStream.resolve();
|
|
124
156
|
|