ai 7.0.33 → 7.0.35
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 +16 -0
- package/dist/index.d.ts +26 -10
- package/dist/index.js +119 -45
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +5 -2
- package/dist/internal/index.js +1 -1
- package/docs/03-ai-sdk-core/25-settings.mdx +15 -2
- package/docs/03-ai-sdk-core/65-devtools.mdx +23 -2
- package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +42 -0
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +4 -4
- package/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +10 -8
- package/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx +6 -1
- package/package.json +2 -2
- package/src/agent/agent.ts +4 -1
- package/src/agent/pipe-agent-ui-stream-to-response.ts +1 -1
- package/src/generate-object/stream-object-result.ts +4 -1
- package/src/generate-object/stream-object.ts +1 -1
- package/src/generate-text/generate-text-events.ts +2 -1
- package/src/generate-text/stream-text-result.ts +5 -2
- package/src/generate-text/stream-text.ts +113 -33
- package/src/prompt/index.ts +1 -0
- package/src/prompt/request-options.ts +20 -2
- package/src/text-stream/pipe-text-stream-to-response.ts +3 -2
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +3 -2
- package/src/util/create-stitchable-stream.ts +41 -15
- package/src/util/write-to-server-response.ts +2 -2
package/src/prompt/index.ts
CHANGED
|
@@ -5,7 +5,8 @@ import type { ToolSet } from '@ai-sdk/provider-utils';
|
|
|
5
5
|
* - A number representing milliseconds
|
|
6
6
|
* - An object with `totalMs` property for the total timeout in milliseconds
|
|
7
7
|
* - An object with `stepMs` property for the timeout of each step in milliseconds
|
|
8
|
-
* - An object with `
|
|
8
|
+
* - An object with `firstChunkMs` property for the timeout until the first content chunk of each step (streaming only)
|
|
9
|
+
* - An object with `chunkMs` property for the timeout between content chunks (streaming only)
|
|
9
10
|
* - An object with `toolMs` property for the default timeout for all tool executions
|
|
10
11
|
* - An object with `tools` property for per-tool timeout overrides using `{toolName}Ms` keys
|
|
11
12
|
*/
|
|
@@ -14,6 +15,7 @@ export type TimeoutConfiguration<TOOLS extends ToolSet> =
|
|
|
14
15
|
| {
|
|
15
16
|
totalMs?: number;
|
|
16
17
|
stepMs?: number;
|
|
18
|
+
firstChunkMs?: number;
|
|
17
19
|
chunkMs?: number;
|
|
18
20
|
toolMs?: number;
|
|
19
21
|
tools?: Partial<Record<`${keyof TOOLS & string}Ms`, number>>;
|
|
@@ -52,9 +54,25 @@ export function getStepTimeoutMs(
|
|
|
52
54
|
return timeout.stepMs;
|
|
53
55
|
}
|
|
54
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Extracts the first chunk timeout value in milliseconds from a TimeoutConfiguration.
|
|
59
|
+
* This timeout is for streaming only - it aborts if no content chunk is received within the specified duration.
|
|
60
|
+
*
|
|
61
|
+
* @param timeout - The timeout configuration.
|
|
62
|
+
* @returns The first chunk timeout in milliseconds, or undefined if no first chunk timeout is configured.
|
|
63
|
+
*/
|
|
64
|
+
export function getFirstChunkTimeoutMs(
|
|
65
|
+
timeout: TimeoutConfiguration<any> | undefined,
|
|
66
|
+
): number | undefined {
|
|
67
|
+
if (timeout == null || typeof timeout === 'number') {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
return timeout.firstChunkMs;
|
|
71
|
+
}
|
|
72
|
+
|
|
55
73
|
/**
|
|
56
74
|
* Extracts the chunk timeout value in milliseconds from a TimeoutConfiguration.
|
|
57
|
-
* This timeout is for streaming only - it aborts if no new chunk is received within the specified duration.
|
|
75
|
+
* This timeout is for streaming only - it aborts if no new content chunk is received within the specified duration.
|
|
58
76
|
*
|
|
59
77
|
* @param timeout - The timeout configuration.
|
|
60
78
|
* @returns The chunk timeout in milliseconds, or undefined if no chunk timeout is configured.
|
|
@@ -13,6 +13,7 @@ import { writeToServerResponse } from '../util/write-to-server-response';
|
|
|
13
13
|
* @param options.statusText - Optional HTTP status text.
|
|
14
14
|
* @param options.headers - Optional response headers.
|
|
15
15
|
* @param options.stream - The text stream to pipe.
|
|
16
|
+
* @returns A promise that resolves when the stream has been written.
|
|
16
17
|
*/
|
|
17
18
|
export function pipeTextStreamToResponse({
|
|
18
19
|
response,
|
|
@@ -23,8 +24,8 @@ export function pipeTextStreamToResponse({
|
|
|
23
24
|
}: {
|
|
24
25
|
response: ServerResponse;
|
|
25
26
|
stream: ReadableStream<string>;
|
|
26
|
-
} & ResponseInit): void {
|
|
27
|
-
writeToServerResponse({
|
|
27
|
+
} & ResponseInit): Promise<void> {
|
|
28
|
+
return writeToServerResponse({
|
|
28
29
|
response,
|
|
29
30
|
status,
|
|
30
31
|
statusText,
|
|
@@ -16,6 +16,7 @@ import type { UIMessageStreamResponseInit } from './ui-message-stream-response-i
|
|
|
16
16
|
* @param options.headers - Additional HTTP headers to include in the response.
|
|
17
17
|
* @param options.stream - The UI message chunk stream to send.
|
|
18
18
|
* @param options.consumeSseStream - Optional callback to consume a copy of the SSE stream independently.
|
|
19
|
+
* @returns A promise that resolves when the stream has been written.
|
|
19
20
|
*/
|
|
20
21
|
export function pipeUIMessageStreamToResponse({
|
|
21
22
|
response,
|
|
@@ -27,7 +28,7 @@ export function pipeUIMessageStreamToResponse({
|
|
|
27
28
|
}: {
|
|
28
29
|
response: ServerResponse;
|
|
29
30
|
stream: ReadableStream<UIMessageChunk>;
|
|
30
|
-
} & UIMessageStreamResponseInit): void {
|
|
31
|
+
} & UIMessageStreamResponseInit): Promise<void> {
|
|
31
32
|
let sseStream = stream.pipeThrough(new JsonToSseTransformStream());
|
|
32
33
|
|
|
33
34
|
// when the consumeSseStream is provided, we need to tee the stream
|
|
@@ -39,7 +40,7 @@ export function pipeUIMessageStreamToResponse({
|
|
|
39
40
|
consumeSseStream({ stream: stream2 }); // no await (do not block the response)
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
writeToServerResponse({
|
|
43
|
+
return writeToServerResponse({
|
|
43
44
|
response,
|
|
44
45
|
status,
|
|
45
46
|
statusText,
|
|
@@ -8,11 +8,21 @@ import { createResolvablePromise } from './create-resolvable-promise';
|
|
|
8
8
|
*/
|
|
9
9
|
export function createStitchableStream<T>(): {
|
|
10
10
|
stream: ReadableStream<T>;
|
|
11
|
-
addStream: (
|
|
11
|
+
addStream: (
|
|
12
|
+
innerStream: ReadableStream<T>,
|
|
13
|
+
callbacks?: {
|
|
14
|
+
onError?: (error: unknown) => void;
|
|
15
|
+
onCancel?: () => void;
|
|
16
|
+
},
|
|
17
|
+
) => void;
|
|
12
18
|
close: () => void;
|
|
13
19
|
terminate: () => void;
|
|
14
20
|
} {
|
|
15
|
-
let
|
|
21
|
+
let innerStreams: Array<{
|
|
22
|
+
reader: ReadableStreamDefaultReader<T>;
|
|
23
|
+
onError?: (error: unknown) => void;
|
|
24
|
+
onCancel?: () => void;
|
|
25
|
+
}> = [];
|
|
16
26
|
let controller: ReadableStreamDefaultController<T> | null = null;
|
|
17
27
|
let isClosed = false;
|
|
18
28
|
let waitForNewStream = createResolvablePromise<void>();
|
|
@@ -21,34 +31,39 @@ export function createStitchableStream<T>(): {
|
|
|
21
31
|
isClosed = true;
|
|
22
32
|
waitForNewStream.resolve();
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
innerStreams.forEach(({ reader, onCancel }) => {
|
|
35
|
+
onCancel?.();
|
|
36
|
+
reader.cancel();
|
|
37
|
+
});
|
|
38
|
+
innerStreams = [];
|
|
26
39
|
controller?.close();
|
|
27
40
|
};
|
|
28
41
|
|
|
29
42
|
const processPull = async () => {
|
|
30
43
|
// Case 1: Outer stream is closed and no more inner streams
|
|
31
|
-
if (isClosed &&
|
|
44
|
+
if (isClosed && innerStreams.length === 0) {
|
|
32
45
|
controller?.close();
|
|
33
46
|
return;
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
// Case 2: No inner streams available, but outer stream is open
|
|
37
50
|
// wait for a new inner stream to be added or the outer stream to close
|
|
38
|
-
if (
|
|
51
|
+
if (innerStreams.length === 0) {
|
|
39
52
|
waitForNewStream = createResolvablePromise<void>();
|
|
40
53
|
await waitForNewStream.promise;
|
|
41
54
|
return await processPull();
|
|
42
55
|
}
|
|
43
56
|
|
|
57
|
+
const currentStream = innerStreams[0];
|
|
58
|
+
|
|
44
59
|
try {
|
|
45
|
-
const { value, done } = await
|
|
60
|
+
const { value, done } = await currentStream.reader.read();
|
|
46
61
|
|
|
47
62
|
if (done) {
|
|
48
63
|
// Case 3: Current inner stream is done
|
|
49
|
-
|
|
64
|
+
innerStreams.shift(); // Remove the finished stream
|
|
50
65
|
|
|
51
|
-
if (
|
|
66
|
+
if (innerStreams.length === 0 && isClosed) {
|
|
52
67
|
// when closed and no more inner streams, stop pulling
|
|
53
68
|
controller?.close();
|
|
54
69
|
} else {
|
|
@@ -61,8 +76,9 @@ export function createStitchableStream<T>(): {
|
|
|
61
76
|
}
|
|
62
77
|
} catch (error) {
|
|
63
78
|
// Case 5: Current inner stream throws an error
|
|
79
|
+
currentStream.onError?.(error);
|
|
64
80
|
controller?.error(error);
|
|
65
|
-
|
|
81
|
+
innerStreams.shift(); // Remove the errored stream
|
|
66
82
|
terminate(); // we have errored, terminate all streams
|
|
67
83
|
}
|
|
68
84
|
};
|
|
@@ -74,19 +90,29 @@ export function createStitchableStream<T>(): {
|
|
|
74
90
|
},
|
|
75
91
|
pull: processPull,
|
|
76
92
|
async cancel() {
|
|
77
|
-
for (const reader of
|
|
93
|
+
for (const { reader, onCancel } of innerStreams) {
|
|
94
|
+
onCancel?.();
|
|
78
95
|
await reader.cancel();
|
|
79
96
|
}
|
|
80
|
-
|
|
97
|
+
innerStreams = [];
|
|
81
98
|
isClosed = true;
|
|
82
99
|
},
|
|
83
100
|
}),
|
|
84
|
-
addStream: (
|
|
101
|
+
addStream: (
|
|
102
|
+
innerStream: ReadableStream<T>,
|
|
103
|
+
callbacks?: {
|
|
104
|
+
onError?: (error: unknown) => void;
|
|
105
|
+
onCancel?: () => void;
|
|
106
|
+
},
|
|
107
|
+
) => {
|
|
85
108
|
if (isClosed) {
|
|
86
109
|
throw new Error('Cannot add inner stream: outer stream is closed');
|
|
87
110
|
}
|
|
88
111
|
|
|
89
|
-
|
|
112
|
+
innerStreams.push({
|
|
113
|
+
reader: innerStream.getReader(),
|
|
114
|
+
...callbacks,
|
|
115
|
+
});
|
|
90
116
|
waitForNewStream.resolve();
|
|
91
117
|
},
|
|
92
118
|
|
|
@@ -98,7 +124,7 @@ export function createStitchableStream<T>(): {
|
|
|
98
124
|
isClosed = true;
|
|
99
125
|
waitForNewStream.resolve();
|
|
100
126
|
|
|
101
|
-
if (
|
|
127
|
+
if (innerStreams.length === 0) {
|
|
102
128
|
controller?.close();
|
|
103
129
|
}
|
|
104
130
|
},
|
|
@@ -19,7 +19,7 @@ export function writeToServerResponse({
|
|
|
19
19
|
statusText?: string;
|
|
20
20
|
headers?: Record<string, string | number | string[]>;
|
|
21
21
|
stream: ReadableStream<Uint8Array>;
|
|
22
|
-
}): void {
|
|
22
|
+
}): Promise<void> {
|
|
23
23
|
const statusCode = status ?? 200;
|
|
24
24
|
if (statusText !== undefined) {
|
|
25
25
|
response.writeHead(statusCode, statusText, headers);
|
|
@@ -54,5 +54,5 @@ export function writeToServerResponse({
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
read();
|
|
57
|
+
return read();
|
|
58
58
|
}
|