ai 7.0.18 → 7.0.20
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 +28 -0
- package/dist/index.d.ts +58 -5
- package/dist/index.js +168 -79
- package/dist/index.js.map +1 -1
- package/dist/internal/index.js +43 -31
- package/dist/internal/index.js.map +1 -1
- package/docs/02-foundations/02-providers-and-models.mdx +57 -52
- package/docs/02-getting-started/00-choosing-a-provider.mdx +1 -16
- package/docs/02-getting-started/01-navigating-the-library.mdx +12 -12
- package/docs/02-getting-started/02-nextjs-app-router.mdx +2 -36
- package/docs/02-getting-started/03-nextjs-pages-router.mdx +2 -36
- package/docs/02-getting-started/04-svelte.mdx +2 -34
- package/docs/02-getting-started/05-nuxt.mdx +2 -36
- package/docs/02-getting-started/06-nodejs.mdx +1 -18
- package/docs/02-getting-started/07-expo.mdx +3 -62
- package/docs/02-getting-started/08-tanstack-start.mdx +2 -36
- package/docs/02-getting-started/09-coding-agents.mdx +2 -32
- package/docs/03-agents/07-workflow-agent.mdx +1 -1
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +3 -12
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +44 -0
- package/docs/03-ai-sdk-core/30-embeddings.mdx +18 -18
- package/docs/03-ai-sdk-core/38-video-generation.mdx +22 -3
- package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +1 -28
- package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +7 -7
- package/docs/03-ai-sdk-harnesses/06-workflow-utilities.mdx +1 -16
- package/docs/03-ai-sdk-harnesses/08-terminal-ui.mdx +1 -28
- package/docs/04-ai-sdk-ui/01-overview.mdx +5 -5
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx +3 -2
- package/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +1 -1
- package/docs/07-reference/02-ai-sdk-ui/index.mdx +5 -5
- package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +2 -2
- package/package.json +4 -4
- package/src/agent/tool-loop-agent-settings.ts +7 -0
- package/src/generate-text/collect-tool-approvals.ts +17 -4
- package/src/generate-text/execute-tool-call.ts +3 -2
- package/src/generate-text/execute-tools-from-stream.ts +2 -1
- package/src/generate-text/generate-text.ts +14 -5
- package/src/generate-text/index.ts +1 -0
- package/src/generate-text/invoke-tool-callbacks-from-stream.ts +6 -4
- package/src/generate-text/parse-tool-call.ts +5 -4
- package/src/generate-text/resolve-tool-approval.ts +9 -6
- package/src/generate-text/stream-language-model-call.ts +2 -1
- package/src/generate-text/stream-text.ts +12 -3
- package/src/generate-text/to-response-messages.ts +4 -3
- package/src/generate-text/tool-approval-signature.ts +4 -40
- package/src/generate-text/tool-fingerprint.ts +76 -0
- package/src/generate-text/validate-tool-approvals.ts +6 -1
- package/src/generate-video/generate-video.ts +96 -21
- package/src/ui/convert-to-model-messages.ts +3 -2
- package/src/ui/process-ui-message-stream.ts +3 -0
- package/src/ui/validate-ui-messages.ts +2 -1
- package/src/util/canonical-hash.ts +44 -0
- package/src/util/get-own.ts +18 -0
- package/src/util/write-to-server-response.ts +9 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '@ai-sdk/provider-utils';
|
|
12
12
|
import { createToolModelOutput } from '../prompt/create-tool-model-output';
|
|
13
13
|
import { MessageConversionError } from '../prompt/message-conversion-error';
|
|
14
|
+
import { getOwn } from '../util/get-own';
|
|
14
15
|
import {
|
|
15
16
|
getToolName,
|
|
16
17
|
isCustomContentUIPart,
|
|
@@ -256,7 +257,7 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
|
|
|
256
257
|
part.state === 'output-error'
|
|
257
258
|
? part.errorText
|
|
258
259
|
: part.output,
|
|
259
|
-
tool: options?.tools
|
|
260
|
+
tool: getOwn(options?.tools, toolName),
|
|
260
261
|
errorMode:
|
|
261
262
|
part.state === 'output-error' ? 'json' : 'none',
|
|
262
263
|
}),
|
|
@@ -375,7 +376,7 @@ export async function convertToModelMessages<UI_MESSAGE extends UIMessage>(
|
|
|
375
376
|
toolPart.state === 'output-error'
|
|
376
377
|
? toolPart.errorText
|
|
377
378
|
: toolPart.output,
|
|
378
|
-
tool: options?.tools
|
|
379
|
+
tool: getOwn(options?.tools, toolName),
|
|
379
380
|
errorMode:
|
|
380
381
|
toolPart.state === 'output-error' ? 'text' : 'none',
|
|
381
382
|
}),
|
|
@@ -731,6 +731,9 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
|
|
|
731
731
|
approved: chunk.approved,
|
|
732
732
|
...(chunk.reason != null ? { reason: chunk.reason } : {}),
|
|
733
733
|
...(approval.isAutomatic === true ? { isAutomatic: true } : {}),
|
|
734
|
+
...(approval.signature != null
|
|
735
|
+
? { signature: approval.signature }
|
|
736
|
+
: {}),
|
|
734
737
|
};
|
|
735
738
|
if (chunk.providerExecuted != null) {
|
|
736
739
|
toolInvocation.providerExecuted = chunk.providerExecuted;
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { z } from 'zod/v4';
|
|
10
10
|
import { InvalidArgumentError } from '../error';
|
|
11
11
|
import { jsonValueSchema } from '../types/json-value';
|
|
12
|
+
import { getOwn } from '../util/get-own';
|
|
12
13
|
import { providerMetadataSchema } from '../types/provider-metadata';
|
|
13
14
|
import type {
|
|
14
15
|
DataUIPart,
|
|
@@ -456,7 +457,7 @@ export async function safeValidateUIMessages<UI_MESSAGE extends UIMessage>({
|
|
|
456
457
|
InferUIMessageTools<UI_MESSAGE>
|
|
457
458
|
>;
|
|
458
459
|
const toolName = toolPart.type.slice(5);
|
|
459
|
-
const tool = tools
|
|
460
|
+
const tool = getOwn(tools, toolName);
|
|
460
461
|
|
|
461
462
|
if (
|
|
462
463
|
!tool &&
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils';
|
|
2
|
+
|
|
3
|
+
const encoder = new TextEncoder();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deterministic JSON serialization: object keys are sorted so that two
|
|
7
|
+
* structurally-equal values always produce the same string regardless of key
|
|
8
|
+
* insertion order. Used as the input to content hashing.
|
|
9
|
+
*/
|
|
10
|
+
export function canonicalJSON(value: unknown): string {
|
|
11
|
+
if (value === null || value === undefined) {
|
|
12
|
+
return JSON.stringify(value);
|
|
13
|
+
}
|
|
14
|
+
if (typeof value !== 'object') {
|
|
15
|
+
return JSON.stringify(value);
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
return `[${value.map(canonicalJSON).join(',')}]`;
|
|
19
|
+
}
|
|
20
|
+
const keys = Object.keys(value as Record<string, unknown>).sort();
|
|
21
|
+
const entries = keys.map(
|
|
22
|
+
k =>
|
|
23
|
+
`${JSON.stringify(k)}:${canonicalJSON((value as Record<string, unknown>)[k])}`,
|
|
24
|
+
);
|
|
25
|
+
return `{${entries.join(',')}}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function toBase64url(bytes: Uint8Array): string {
|
|
29
|
+
return convertUint8ArrayToBase64(bytes)
|
|
30
|
+
.replace(/\+/g, '-')
|
|
31
|
+
.replace(/\//g, '_')
|
|
32
|
+
.replace(/=+$/g, '');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Canonical SHA-256 digest (base64url) of an arbitrary JSON-serializable value.
|
|
37
|
+
*/
|
|
38
|
+
export async function hashCanonical(value: unknown): Promise<string> {
|
|
39
|
+
const digest = await crypto.subtle.digest(
|
|
40
|
+
'SHA-256',
|
|
41
|
+
encoder.encode(canonicalJSON(value)),
|
|
42
|
+
);
|
|
43
|
+
return toBase64url(new Uint8Array(digest));
|
|
44
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads a property by an untrusted key, ignoring inherited prototype members.
|
|
3
|
+
*
|
|
4
|
+
* Tool sets, tool contexts, and similar lookup objects are indexed by names
|
|
5
|
+
* that can come from model output or client-supplied message history. Plain
|
|
6
|
+
* bracket access (`obj[name]`) resolves names such as `constructor`,
|
|
7
|
+
* `toString`, or `__proto__` to values on `Object.prototype`, which would slip
|
|
8
|
+
* past the `== null` / `!value` guards that treat an unknown name as "not
|
|
9
|
+
* present". This helper returns `undefined` unless `key` is an own property.
|
|
10
|
+
*/
|
|
11
|
+
export function getOwn<T extends object>(
|
|
12
|
+
obj: T | undefined | null,
|
|
13
|
+
key: string,
|
|
14
|
+
): T[keyof T] | undefined {
|
|
15
|
+
return obj != null && Object.hasOwn(obj, key)
|
|
16
|
+
? obj[key as keyof T]
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ServerResponse } from 'node:http';
|
|
2
2
|
|
|
3
|
+
type FlushableServerResponse = ServerResponse & {
|
|
4
|
+
flush?: () => void;
|
|
5
|
+
};
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* Writes the content of a stream to a server response.
|
|
5
9
|
*/
|
|
@@ -32,6 +36,11 @@ export function writeToServerResponse({
|
|
|
32
36
|
|
|
33
37
|
// Respect backpressure: if write() returns false, wait for 'drain' event
|
|
34
38
|
const canContinue = response.write(value);
|
|
39
|
+
const flush = (response as FlushableServerResponse).flush;
|
|
40
|
+
if (typeof flush === 'function') {
|
|
41
|
+
flush.call(response);
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
if (!canContinue) {
|
|
36
45
|
await new Promise<void>(resolve => {
|
|
37
46
|
response.once('drain', resolve);
|