ai 3.3.5 → 3.3.7

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.
@@ -139,512 +139,704 @@ function getMutableAIState(...args) {
139
139
  return mutableState;
140
140
  }
141
141
 
142
- // rsc/constants.ts
143
- var STREAMABLE_VALUE_TYPE = Symbol.for("ui.streamable.value");
144
- var DEV_DEFAULT_STREAMABLE_WARNING_TIME = 15 * 1e3;
145
-
146
- // rsc/create-suspended-chunk.tsx
147
- import { Suspense } from "react";
148
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
149
- var R = [
150
- async ({
151
- c: current,
152
- n: next
153
- }) => {
154
- const chunk = await next;
155
- if (chunk.done) {
156
- return chunk.value;
157
- }
158
- if (chunk.append) {
159
- return /* @__PURE__ */ jsxs(Fragment, { children: [
160
- current,
161
- /* @__PURE__ */ jsx(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx(R, { c: chunk.value, n: chunk.next }) })
162
- ] });
142
+ // rsc/provider.tsx
143
+ import * as React from "react";
144
+ import { InternalAIProvider } from "./rsc-shared.mjs";
145
+ import { jsx } from "react/jsx-runtime";
146
+ async function innerAction({
147
+ action,
148
+ options
149
+ }, state, ...args) {
150
+ "use server";
151
+ return await withAIState(
152
+ {
153
+ state,
154
+ options
155
+ },
156
+ async () => {
157
+ const result = await action(...args);
158
+ sealMutableAIState();
159
+ return [getAIStateDeltaPromise(), result];
163
160
  }
164
- return /* @__PURE__ */ jsx(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx(R, { c: chunk.value, n: chunk.next }) });
165
- }
166
- ][0];
167
- function createSuspendedChunk(initialValue) {
168
- const { promise, resolve, reject } = createResolvablePromise();
169
- return {
170
- row: /* @__PURE__ */ jsx(Suspense, { fallback: initialValue, children: /* @__PURE__ */ jsx(R, { c: initialValue, n: promise }) }),
171
- resolve,
172
- reject
173
- };
161
+ );
174
162
  }
175
-
176
- // rsc/streamable.tsx
177
- function createStreamableUI(initialValue) {
178
- let currentValue = initialValue;
179
- let closed = false;
180
- let { row, resolve, reject } = createSuspendedChunk(initialValue);
181
- function assertStream(method) {
182
- if (closed) {
183
- throw new Error(method + ": UI stream is already closed.");
184
- }
163
+ function wrapAction(action, options) {
164
+ return innerAction.bind(null, { action, options });
165
+ }
166
+ function createAI({
167
+ actions,
168
+ initialAIState,
169
+ initialUIState,
170
+ onSetAIState,
171
+ onGetUIState
172
+ }) {
173
+ const wrappedActions = {};
174
+ for (const name8 in actions) {
175
+ wrappedActions[name8] = wrapAction(actions[name8], {
176
+ onSetAIState
177
+ });
185
178
  }
186
- let warningTimeout;
187
- function warnUnclosedStream() {
188
- if (process.env.NODE_ENV === "development") {
189
- if (warningTimeout) {
190
- clearTimeout(warningTimeout);
191
- }
192
- warningTimeout = setTimeout(() => {
193
- console.warn(
194
- "The streamable UI has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`."
195
- );
196
- }, DEV_DEFAULT_STREAMABLE_WARNING_TIME);
179
+ const wrappedSyncUIState = onGetUIState ? wrapAction(onGetUIState, {}) : void 0;
180
+ const AI = async (props) => {
181
+ var _a8, _b;
182
+ if ("useState" in React) {
183
+ throw new Error(
184
+ "This component can only be used inside Server Components."
185
+ );
197
186
  }
198
- }
199
- warnUnclosedStream();
200
- const streamable2 = {
201
- value: row,
202
- update(value) {
203
- assertStream(".update()");
204
- if (value === currentValue) {
205
- warnUnclosedStream();
206
- return streamable2;
207
- }
208
- const resolvable = createResolvablePromise();
209
- currentValue = value;
210
- resolve({ value: currentValue, done: false, next: resolvable.promise });
211
- resolve = resolvable.resolve;
212
- reject = resolvable.reject;
213
- warnUnclosedStream();
214
- return streamable2;
215
- },
216
- append(value) {
217
- assertStream(".append()");
218
- const resolvable = createResolvablePromise();
219
- currentValue = value;
220
- resolve({ value, done: false, append: true, next: resolvable.promise });
221
- resolve = resolvable.resolve;
222
- reject = resolvable.reject;
223
- warnUnclosedStream();
224
- return streamable2;
225
- },
226
- error(error) {
227
- assertStream(".error()");
228
- if (warningTimeout) {
229
- clearTimeout(warningTimeout);
230
- }
231
- closed = true;
232
- reject(error);
233
- return streamable2;
234
- },
235
- done(...args) {
236
- assertStream(".done()");
237
- if (warningTimeout) {
238
- clearTimeout(warningTimeout);
239
- }
240
- closed = true;
241
- if (args.length) {
242
- resolve({ value: args[0], done: true });
243
- return streamable2;
187
+ let uiState = (_a8 = props.initialUIState) != null ? _a8 : initialUIState;
188
+ let aiState = (_b = props.initialAIState) != null ? _b : initialAIState;
189
+ let aiStateDelta = void 0;
190
+ if (wrappedSyncUIState) {
191
+ const [newAIStateDelta, newUIState] = await wrappedSyncUIState(aiState);
192
+ if (newUIState !== void 0) {
193
+ aiStateDelta = newAIStateDelta;
194
+ uiState = newUIState;
244
195
  }
245
- resolve({ value: currentValue, done: true });
246
- return streamable2;
247
196
  }
197
+ return /* @__PURE__ */ jsx(
198
+ InternalAIProvider,
199
+ {
200
+ wrappedActions,
201
+ wrappedSyncUIState,
202
+ initialUIState: uiState,
203
+ initialAIState: aiState,
204
+ initialAIStatePatch: aiStateDelta,
205
+ children: props.children
206
+ }
207
+ );
248
208
  };
249
- return streamable2;
209
+ return AI;
250
210
  }
251
- var STREAMABLE_VALUE_INTERNAL_LOCK = Symbol("streamable.value.lock");
252
- function createStreamableValue(initialValue) {
253
- const isReadableStream = initialValue instanceof ReadableStream || typeof initialValue === "object" && initialValue !== null && "getReader" in initialValue && typeof initialValue.getReader === "function" && "locked" in initialValue && typeof initialValue.locked === "boolean";
254
- if (!isReadableStream) {
255
- return createStreamableValueImpl(initialValue);
211
+
212
+ // rsc/stream-ui/stream-ui.tsx
213
+ import { safeParseJSON } from "@ai-sdk/provider-utils";
214
+
215
+ // core/prompt/convert-to-language-model-prompt.ts
216
+ import { getErrorMessage } from "@ai-sdk/provider-utils";
217
+
218
+ // util/download-error.ts
219
+ import { AISDKError } from "@ai-sdk/provider";
220
+ var name = "AI_DownloadError";
221
+ var marker = `vercel.ai.error.${name}`;
222
+ var symbol = Symbol.for(marker);
223
+ var _a;
224
+ var DownloadError = class extends AISDKError {
225
+ constructor({
226
+ url,
227
+ statusCode,
228
+ statusText,
229
+ cause,
230
+ message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}`
231
+ }) {
232
+ super({ name, message, cause });
233
+ this[_a] = true;
234
+ this.url = url;
235
+ this.statusCode = statusCode;
236
+ this.statusText = statusText;
256
237
  }
257
- const streamableValue = createStreamableValueImpl();
258
- streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = true;
259
- (async () => {
260
- try {
261
- const reader = initialValue.getReader();
262
- while (true) {
263
- const { value, done } = await reader.read();
264
- if (done) {
265
- break;
266
- }
267
- streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false;
268
- if (typeof value === "string") {
269
- streamableValue.append(value);
270
- } else {
271
- streamableValue.update(value);
272
- }
273
- streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = true;
274
- }
275
- streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false;
276
- streamableValue.done();
277
- } catch (e) {
278
- streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false;
279
- streamableValue.error(e);
280
- }
281
- })();
282
- return streamableValue;
283
- }
284
- function createStreamableValueImpl(initialValue) {
285
- let closed = false;
286
- let locked = false;
287
- let resolvable = createResolvablePromise();
288
- let currentValue = initialValue;
289
- let currentError;
290
- let currentPromise = resolvable.promise;
291
- let currentPatchValue;
292
- function assertStream(method) {
293
- if (closed) {
294
- throw new Error(method + ": Value stream is already closed.");
295
- }
296
- if (locked) {
297
- throw new Error(
298
- method + ": Value stream is locked and cannot be updated."
299
- );
300
- }
238
+ static isInstance(error) {
239
+ return AISDKError.hasMarker(error, marker);
301
240
  }
302
- let warningTimeout;
303
- function warnUnclosedStream() {
304
- if (process.env.NODE_ENV === "development") {
305
- if (warningTimeout) {
306
- clearTimeout(warningTimeout);
307
- }
308
- warningTimeout = setTimeout(() => {
309
- console.warn(
310
- "The streamable value has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`."
311
- );
312
- }, DEV_DEFAULT_STREAMABLE_WARNING_TIME);
313
- }
241
+ /**
242
+ * @deprecated use `isInstance` instead
243
+ */
244
+ static isDownloadError(error) {
245
+ return error instanceof Error && error.name === name && typeof error.url === "string" && (error.statusCode == null || typeof error.statusCode === "number") && (error.statusText == null || typeof error.statusText === "string");
314
246
  }
315
- warnUnclosedStream();
316
- function createWrapped(initialChunk) {
317
- let init;
318
- if (currentError !== void 0) {
319
- init = { error: currentError };
320
- } else {
321
- if (currentPatchValue && !initialChunk) {
322
- init = { diff: currentPatchValue };
323
- } else {
324
- init = { curr: currentValue };
247
+ /**
248
+ * @deprecated Do not use this method. It will be removed in the next major version.
249
+ */
250
+ toJSON() {
251
+ return {
252
+ name: this.name,
253
+ message: this.message,
254
+ url: this.url,
255
+ statusCode: this.statusCode,
256
+ statusText: this.statusText,
257
+ cause: this.cause
258
+ };
259
+ }
260
+ };
261
+ _a = symbol;
262
+
263
+ // util/download.ts
264
+ async function download({
265
+ url,
266
+ fetchImplementation = fetch
267
+ }) {
268
+ var _a8;
269
+ const urlText = url.toString();
270
+ try {
271
+ const response = await fetchImplementation(urlText);
272
+ if (!response.ok) {
273
+ throw new DownloadError({
274
+ url: urlText,
275
+ statusCode: response.status,
276
+ statusText: response.statusText
277
+ });
278
+ }
279
+ return {
280
+ data: new Uint8Array(await response.arrayBuffer()),
281
+ mimeType: (_a8 = response.headers.get("content-type")) != null ? _a8 : void 0
282
+ };
283
+ } catch (error) {
284
+ if (DownloadError.isInstance(error)) {
285
+ throw error;
286
+ }
287
+ throw new DownloadError({ url: urlText, cause: error });
288
+ }
289
+ }
290
+
291
+ // core/util/detect-image-mimetype.ts
292
+ var mimeTypeSignatures = [
293
+ { mimeType: "image/gif", bytes: [71, 73, 70] },
294
+ { mimeType: "image/png", bytes: [137, 80, 78, 71] },
295
+ { mimeType: "image/jpeg", bytes: [255, 216] },
296
+ { mimeType: "image/webp", bytes: [82, 73, 70, 70] }
297
+ ];
298
+ function detectImageMimeType(image) {
299
+ for (const { bytes, mimeType } of mimeTypeSignatures) {
300
+ if (image.length >= bytes.length && bytes.every((byte, index) => image[index] === byte)) {
301
+ return mimeType;
302
+ }
303
+ }
304
+ return void 0;
305
+ }
306
+
307
+ // core/prompt/data-content.ts
308
+ import {
309
+ convertBase64ToUint8Array,
310
+ convertUint8ArrayToBase64
311
+ } from "@ai-sdk/provider-utils";
312
+
313
+ // core/prompt/invalid-data-content-error.ts
314
+ import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
315
+ var name2 = "AI_InvalidDataContentError";
316
+ var marker2 = `vercel.ai.error.${name2}`;
317
+ var symbol2 = Symbol.for(marker2);
318
+ var _a2;
319
+ var InvalidDataContentError = class extends AISDKError2 {
320
+ constructor({
321
+ content,
322
+ cause,
323
+ message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`
324
+ }) {
325
+ super({ name: name2, message, cause });
326
+ this[_a2] = true;
327
+ this.content = content;
328
+ }
329
+ static isInstance(error) {
330
+ return AISDKError2.hasMarker(error, marker2);
331
+ }
332
+ /**
333
+ * @deprecated use `isInstance` instead
334
+ */
335
+ static isInvalidDataContentError(error) {
336
+ return error instanceof Error && error.name === name2 && error.content != null;
337
+ }
338
+ /**
339
+ * @deprecated Do not use this method. It will be removed in the next major version.
340
+ */
341
+ toJSON() {
342
+ return {
343
+ name: this.name,
344
+ message: this.message,
345
+ stack: this.stack,
346
+ cause: this.cause,
347
+ content: this.content
348
+ };
349
+ }
350
+ };
351
+ _a2 = symbol2;
352
+
353
+ // core/prompt/data-content.ts
354
+ function convertDataContentToUint8Array(content) {
355
+ if (content instanceof Uint8Array) {
356
+ return content;
357
+ }
358
+ if (typeof content === "string") {
359
+ try {
360
+ return convertBase64ToUint8Array(content);
361
+ } catch (error) {
362
+ throw new InvalidDataContentError({
363
+ message: "Invalid data content. Content string is not a base64-encoded media.",
364
+ content,
365
+ cause: error
366
+ });
367
+ }
368
+ }
369
+ if (content instanceof ArrayBuffer) {
370
+ return new Uint8Array(content);
371
+ }
372
+ throw new InvalidDataContentError({ content });
373
+ }
374
+
375
+ // core/prompt/invalid-message-role-error.ts
376
+ import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
377
+ var name3 = "AI_InvalidMessageRoleError";
378
+ var marker3 = `vercel.ai.error.${name3}`;
379
+ var symbol3 = Symbol.for(marker3);
380
+ var _a3;
381
+ var InvalidMessageRoleError = class extends AISDKError3 {
382
+ constructor({
383
+ role,
384
+ message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`
385
+ }) {
386
+ super({ name: name3, message });
387
+ this[_a3] = true;
388
+ this.role = role;
389
+ }
390
+ static isInstance(error) {
391
+ return AISDKError3.hasMarker(error, marker3);
392
+ }
393
+ /**
394
+ * @deprecated use `isInstance` instead
395
+ */
396
+ static isInvalidMessageRoleError(error) {
397
+ return error instanceof Error && error.name === name3 && typeof error.role === "string";
398
+ }
399
+ /**
400
+ * @deprecated Do not use this method. It will be removed in the next major version.
401
+ */
402
+ toJSON() {
403
+ return {
404
+ name: this.name,
405
+ message: this.message,
406
+ stack: this.stack,
407
+ role: this.role
408
+ };
409
+ }
410
+ };
411
+ _a3 = symbol3;
412
+
413
+ // core/prompt/convert-to-language-model-prompt.ts
414
+ async function convertToLanguageModelPrompt({
415
+ prompt,
416
+ modelSupportsImageUrls = true,
417
+ downloadImplementation = download
418
+ }) {
419
+ const languageModelMessages = [];
420
+ if (prompt.system != null) {
421
+ languageModelMessages.push({ role: "system", content: prompt.system });
422
+ }
423
+ const downloadedImages = modelSupportsImageUrls || prompt.messages == null ? null : await downloadImages(prompt.messages, downloadImplementation);
424
+ const promptType = prompt.type;
425
+ switch (promptType) {
426
+ case "prompt": {
427
+ languageModelMessages.push({
428
+ role: "user",
429
+ content: [{ type: "text", text: prompt.prompt }]
430
+ });
431
+ break;
432
+ }
433
+ case "messages": {
434
+ languageModelMessages.push(
435
+ ...prompt.messages.map(
436
+ (message) => convertToLanguageModelMessage(message, downloadedImages)
437
+ )
438
+ );
439
+ break;
440
+ }
441
+ default: {
442
+ const _exhaustiveCheck = promptType;
443
+ throw new Error(`Unsupported prompt type: ${_exhaustiveCheck}`);
444
+ }
445
+ }
446
+ return languageModelMessages;
447
+ }
448
+ function convertToLanguageModelMessage(message, downloadedImages) {
449
+ const role = message.role;
450
+ switch (role) {
451
+ case "system": {
452
+ return { role: "system", content: message.content };
453
+ }
454
+ case "user": {
455
+ if (typeof message.content === "string") {
456
+ return {
457
+ role: "user",
458
+ content: [{ type: "text", text: message.content }]
459
+ };
460
+ }
461
+ return {
462
+ role: "user",
463
+ content: message.content.map(
464
+ (part) => {
465
+ var _a8, _b, _c;
466
+ switch (part.type) {
467
+ case "text": {
468
+ return part;
469
+ }
470
+ case "image": {
471
+ if (part.image instanceof URL) {
472
+ if (downloadedImages == null) {
473
+ return {
474
+ type: "image",
475
+ image: part.image,
476
+ mimeType: part.mimeType
477
+ };
478
+ } else {
479
+ const downloadedImage = downloadedImages[part.image.toString()];
480
+ return {
481
+ type: "image",
482
+ image: downloadedImage.data,
483
+ mimeType: (_a8 = part.mimeType) != null ? _a8 : downloadedImage.mimeType
484
+ };
485
+ }
486
+ }
487
+ if (typeof part.image === "string") {
488
+ try {
489
+ const url = new URL(part.image);
490
+ switch (url.protocol) {
491
+ case "http:":
492
+ case "https:": {
493
+ if (downloadedImages == null) {
494
+ return {
495
+ type: "image",
496
+ image: url,
497
+ mimeType: part.mimeType
498
+ };
499
+ } else {
500
+ const downloadedImage = downloadedImages[part.image];
501
+ return {
502
+ type: "image",
503
+ image: downloadedImage.data,
504
+ mimeType: (_b = part.mimeType) != null ? _b : downloadedImage.mimeType
505
+ };
506
+ }
507
+ }
508
+ case "data:": {
509
+ try {
510
+ const [header, base64Content] = part.image.split(",");
511
+ const mimeType = header.split(";")[0].split(":")[1];
512
+ if (mimeType == null || base64Content == null) {
513
+ throw new Error("Invalid data URL format");
514
+ }
515
+ return {
516
+ type: "image",
517
+ image: convertDataContentToUint8Array(base64Content),
518
+ mimeType
519
+ };
520
+ } catch (error) {
521
+ throw new Error(
522
+ `Error processing data URL: ${getErrorMessage(
523
+ message
524
+ )}`
525
+ );
526
+ }
527
+ }
528
+ default: {
529
+ throw new Error(
530
+ `Unsupported URL protocol: ${url.protocol}`
531
+ );
532
+ }
533
+ }
534
+ } catch (_ignored) {
535
+ }
536
+ }
537
+ const imageUint8 = convertDataContentToUint8Array(part.image);
538
+ return {
539
+ type: "image",
540
+ image: imageUint8,
541
+ mimeType: (_c = part.mimeType) != null ? _c : detectImageMimeType(imageUint8)
542
+ };
543
+ }
544
+ }
545
+ }
546
+ )
547
+ };
548
+ }
549
+ case "assistant": {
550
+ if (typeof message.content === "string") {
551
+ return {
552
+ role: "assistant",
553
+ content: [{ type: "text", text: message.content }]
554
+ };
325
555
  }
556
+ return {
557
+ role: "assistant",
558
+ content: message.content.filter(
559
+ // remove empty text parts:
560
+ (part) => part.type !== "text" || part.text !== ""
561
+ )
562
+ };
326
563
  }
327
- if (currentPromise) {
328
- init.next = currentPromise;
329
- }
330
- if (initialChunk) {
331
- init.type = STREAMABLE_VALUE_TYPE;
564
+ case "tool": {
565
+ return message;
332
566
  }
333
- return init;
334
- }
335
- function updateValueStates(value) {
336
- currentPatchValue = void 0;
337
- if (typeof value === "string") {
338
- if (typeof currentValue === "string") {
339
- if (value.startsWith(currentValue)) {
340
- currentPatchValue = [0, value.slice(currentValue.length)];
341
- }
342
- }
567
+ default: {
568
+ const _exhaustiveCheck = role;
569
+ throw new InvalidMessageRoleError({ role: _exhaustiveCheck });
343
570
  }
344
- currentValue = value;
345
571
  }
346
- const streamable2 = {
347
- set [STREAMABLE_VALUE_INTERNAL_LOCK](state) {
348
- locked = state;
349
- },
350
- get value() {
351
- return createWrapped(true);
352
- },
353
- update(value) {
354
- assertStream(".update()");
355
- const resolvePrevious = resolvable.resolve;
356
- resolvable = createResolvablePromise();
357
- updateValueStates(value);
358
- currentPromise = resolvable.promise;
359
- resolvePrevious(createWrapped());
360
- warnUnclosedStream();
361
- return streamable2;
362
- },
363
- append(value) {
364
- assertStream(".append()");
365
- if (typeof currentValue !== "string" && typeof currentValue !== "undefined") {
366
- throw new Error(
367
- `.append(): The current value is not a string. Received: ${typeof currentValue}`
368
- );
369
- }
370
- if (typeof value !== "string") {
371
- throw new Error(
372
- `.append(): The value is not a string. Received: ${typeof value}`
373
- );
374
- }
375
- const resolvePrevious = resolvable.resolve;
376
- resolvable = createResolvablePromise();
377
- if (typeof currentValue === "string") {
378
- currentPatchValue = [0, value];
379
- currentValue = currentValue + value;
380
- } else {
381
- currentPatchValue = void 0;
382
- currentValue = value;
383
- }
384
- currentPromise = resolvable.promise;
385
- resolvePrevious(createWrapped());
386
- warnUnclosedStream();
387
- return streamable2;
388
- },
389
- error(error) {
390
- assertStream(".error()");
391
- if (warningTimeout) {
392
- clearTimeout(warningTimeout);
393
- }
394
- closed = true;
395
- currentError = error;
396
- currentPromise = void 0;
397
- resolvable.resolve({ error });
398
- return streamable2;
399
- },
400
- done(...args) {
401
- assertStream(".done()");
402
- if (warningTimeout) {
403
- clearTimeout(warningTimeout);
404
- }
405
- closed = true;
406
- currentPromise = void 0;
407
- if (args.length) {
408
- updateValueStates(args[0]);
409
- resolvable.resolve(createWrapped());
410
- return streamable2;
411
- }
412
- resolvable.resolve({});
413
- return streamable2;
414
- }
415
- };
416
- return streamable2;
417
572
  }
418
-
419
- // rsc/render.ts
420
- import zodToJsonSchema2 from "zod-to-json-schema";
421
-
422
- // util/retry-with-exponential-backoff.ts
423
- import { APICallError } from "@ai-sdk/provider";
424
- import { getErrorMessage, isAbortError } from "@ai-sdk/provider-utils";
425
-
426
- // util/delay.ts
427
- async function delay(delayInMs) {
428
- return new Promise((resolve) => setTimeout(resolve, delayInMs));
573
+ async function downloadImages(messages, downloadImplementation) {
574
+ const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
575
+ (content) => Array.isArray(content)
576
+ ).flat().filter((part) => part.type === "image").map((part) => part.image).map(
577
+ (part) => (
578
+ // support string urls in image parts:
579
+ typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part
580
+ )
581
+ ).filter((image) => image instanceof URL);
582
+ const downloadedImages = await Promise.all(
583
+ urls.map(async (url) => ({
584
+ url,
585
+ data: await downloadImplementation({ url })
586
+ }))
587
+ );
588
+ return Object.fromEntries(
589
+ downloadedImages.map(({ url, data }) => [url.toString(), data])
590
+ );
429
591
  }
430
592
 
431
- // util/retry-error.ts
432
- import { AISDKError } from "@ai-sdk/provider";
433
- var name = "AI_RetryError";
434
- var marker = `vercel.ai.error.${name}`;
435
- var symbol = Symbol.for(marker);
436
- var _a;
437
- var RetryError = class extends AISDKError {
438
- constructor({
439
- message,
440
- reason,
441
- errors
442
- }) {
443
- super({ name, message });
444
- this[_a] = true;
445
- this.reason = reason;
446
- this.errors = errors;
447
- this.lastError = errors[errors.length - 1];
448
- }
449
- static isInstance(error) {
450
- return AISDKError.hasMarker(error, marker);
451
- }
452
- /**
453
- * @deprecated use `isInstance` instead
454
- */
455
- static isRetryError(error) {
456
- return error instanceof Error && error.name === name && typeof error.reason === "string" && Array.isArray(error.errors);
593
+ // core/prompt/get-validated-prompt.ts
594
+ import { InvalidPromptError } from "@ai-sdk/provider";
595
+ function getValidatedPrompt(prompt) {
596
+ if (prompt.prompt == null && prompt.messages == null) {
597
+ throw new InvalidPromptError({
598
+ prompt,
599
+ message: "prompt or messages must be defined"
600
+ });
457
601
  }
458
- /**
459
- * @deprecated Do not use this method. It will be removed in the next major version.
460
- */
461
- toJSON() {
462
- return {
463
- name: this.name,
464
- message: this.message,
465
- reason: this.reason,
466
- lastError: this.lastError,
467
- errors: this.errors
468
- };
602
+ if (prompt.prompt != null && prompt.messages != null) {
603
+ throw new InvalidPromptError({
604
+ prompt,
605
+ message: "prompt and messages cannot be defined at the same time"
606
+ });
469
607
  }
470
- };
471
- _a = symbol;
472
-
473
- // util/retry-with-exponential-backoff.ts
474
- var retryWithExponentialBackoff = ({
475
- maxRetries = 2,
476
- initialDelayInMs = 2e3,
477
- backoffFactor = 2
478
- } = {}) => async (f) => _retryWithExponentialBackoff(f, {
479
- maxRetries,
480
- delayInMs: initialDelayInMs,
481
- backoffFactor
482
- });
483
- async function _retryWithExponentialBackoff(f, {
484
- maxRetries,
485
- delayInMs,
486
- backoffFactor
487
- }, errors = []) {
488
- try {
489
- return await f();
490
- } catch (error) {
491
- if (isAbortError(error)) {
492
- throw error;
493
- }
494
- if (maxRetries === 0) {
495
- throw error;
496
- }
497
- const errorMessage = getErrorMessage(error);
498
- const newErrors = [...errors, error];
499
- const tryNumber = newErrors.length;
500
- if (tryNumber > maxRetries) {
501
- throw new RetryError({
502
- message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`,
503
- reason: "maxRetriesExceeded",
504
- errors: newErrors
505
- });
506
- }
507
- if (error instanceof Error && APICallError.isAPICallError(error) && error.isRetryable === true && tryNumber <= maxRetries) {
508
- await delay(delayInMs);
509
- return _retryWithExponentialBackoff(
510
- f,
511
- { maxRetries, delayInMs: backoffFactor * delayInMs, backoffFactor },
512
- newErrors
513
- );
514
- }
515
- if (tryNumber === 1) {
516
- throw error;
608
+ if (prompt.messages != null) {
609
+ for (const message of prompt.messages) {
610
+ if (message.role === "system" && typeof message.content !== "string") {
611
+ throw new InvalidPromptError({
612
+ prompt,
613
+ message: "system message content must be a string"
614
+ });
615
+ }
517
616
  }
518
- throw new RetryError({
519
- message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`,
520
- reason: "errorNotRetryable",
521
- errors: newErrors
522
- });
523
617
  }
618
+ return prompt.prompt != null ? {
619
+ type: "prompt",
620
+ prompt: prompt.prompt,
621
+ messages: void 0,
622
+ system: prompt.system
623
+ } : {
624
+ type: "messages",
625
+ prompt: void 0,
626
+ messages: prompt.messages,
627
+ // only possible case bc of checks above
628
+ system: prompt.system
629
+ };
524
630
  }
525
631
 
526
- // core/prompt/convert-to-language-model-prompt.ts
527
- import { getErrorMessage as getErrorMessage2 } from "@ai-sdk/provider-utils";
528
-
529
- // util/download-error.ts
530
- import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
531
- var name2 = "AI_DownloadError";
532
- var marker2 = `vercel.ai.error.${name2}`;
533
- var symbol2 = Symbol.for(marker2);
534
- var _a2;
535
- var DownloadError = class extends AISDKError2 {
632
+ // errors/invalid-argument-error.ts
633
+ import { AISDKError as AISDKError4 } from "@ai-sdk/provider";
634
+ var name4 = "AI_InvalidArgumentError";
635
+ var marker4 = `vercel.ai.error.${name4}`;
636
+ var symbol4 = Symbol.for(marker4);
637
+ var _a4;
638
+ var InvalidArgumentError = class extends AISDKError4 {
536
639
  constructor({
537
- url,
538
- statusCode,
539
- statusText,
540
- cause,
541
- message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}`
640
+ parameter,
641
+ value,
642
+ message
542
643
  }) {
543
- super({ name: name2, message, cause });
544
- this[_a2] = true;
545
- this.url = url;
546
- this.statusCode = statusCode;
547
- this.statusText = statusText;
644
+ super({
645
+ name: name4,
646
+ message: `Invalid argument for parameter ${parameter}: ${message}`
647
+ });
648
+ this[_a4] = true;
649
+ this.parameter = parameter;
650
+ this.value = value;
548
651
  }
549
652
  static isInstance(error) {
550
- return AISDKError2.hasMarker(error, marker2);
653
+ return AISDKError4.hasMarker(error, marker4);
551
654
  }
552
655
  /**
553
656
  * @deprecated use `isInstance` instead
554
657
  */
555
- static isDownloadError(error) {
556
- return error instanceof Error && error.name === name2 && typeof error.url === "string" && (error.statusCode == null || typeof error.statusCode === "number") && (error.statusText == null || typeof error.statusText === "string");
658
+ static isInvalidArgumentError(error) {
659
+ return error instanceof Error && error.name === name4 && typeof error.parameter === "string" && typeof error.value === "string";
557
660
  }
558
- /**
559
- * @deprecated Do not use this method. It will be removed in the next major version.
560
- */
561
661
  toJSON() {
562
662
  return {
563
663
  name: this.name,
564
664
  message: this.message,
565
- url: this.url,
566
- statusCode: this.statusCode,
567
- statusText: this.statusText,
568
- cause: this.cause
665
+ stack: this.stack,
666
+ parameter: this.parameter,
667
+ value: this.value
569
668
  };
570
669
  }
571
670
  };
572
- _a2 = symbol2;
671
+ _a4 = symbol4;
573
672
 
574
- // util/download.ts
575
- async function download({
576
- url,
577
- fetchImplementation = fetch
673
+ // core/prompt/prepare-call-settings.ts
674
+ function prepareCallSettings({
675
+ maxTokens,
676
+ temperature,
677
+ topP,
678
+ presencePenalty,
679
+ frequencyPenalty,
680
+ stopSequences,
681
+ seed,
682
+ maxRetries
578
683
  }) {
579
- var _a8;
580
- const urlText = url.toString();
581
- try {
582
- const response = await fetchImplementation(urlText);
583
- if (!response.ok) {
584
- throw new DownloadError({
585
- url: urlText,
586
- statusCode: response.status,
587
- statusText: response.statusText
684
+ if (maxTokens != null) {
685
+ if (!Number.isInteger(maxTokens)) {
686
+ throw new InvalidArgumentError({
687
+ parameter: "maxTokens",
688
+ value: maxTokens,
689
+ message: "maxTokens must be an integer"
588
690
  });
589
691
  }
590
- return {
591
- data: new Uint8Array(await response.arrayBuffer()),
592
- mimeType: (_a8 = response.headers.get("content-type")) != null ? _a8 : void 0
593
- };
594
- } catch (error) {
595
- if (DownloadError.isInstance(error)) {
596
- throw error;
692
+ if (maxTokens < 1) {
693
+ throw new InvalidArgumentError({
694
+ parameter: "maxTokens",
695
+ value: maxTokens,
696
+ message: "maxTokens must be >= 1"
697
+ });
698
+ }
699
+ }
700
+ if (temperature != null) {
701
+ if (typeof temperature !== "number") {
702
+ throw new InvalidArgumentError({
703
+ parameter: "temperature",
704
+ value: temperature,
705
+ message: "temperature must be a number"
706
+ });
707
+ }
708
+ }
709
+ if (topP != null) {
710
+ if (typeof topP !== "number") {
711
+ throw new InvalidArgumentError({
712
+ parameter: "topP",
713
+ value: topP,
714
+ message: "topP must be a number"
715
+ });
716
+ }
717
+ }
718
+ if (presencePenalty != null) {
719
+ if (typeof presencePenalty !== "number") {
720
+ throw new InvalidArgumentError({
721
+ parameter: "presencePenalty",
722
+ value: presencePenalty,
723
+ message: "presencePenalty must be a number"
724
+ });
725
+ }
726
+ }
727
+ if (frequencyPenalty != null) {
728
+ if (typeof frequencyPenalty !== "number") {
729
+ throw new InvalidArgumentError({
730
+ parameter: "frequencyPenalty",
731
+ value: frequencyPenalty,
732
+ message: "frequencyPenalty must be a number"
733
+ });
734
+ }
735
+ }
736
+ if (seed != null) {
737
+ if (!Number.isInteger(seed)) {
738
+ throw new InvalidArgumentError({
739
+ parameter: "seed",
740
+ value: seed,
741
+ message: "seed must be an integer"
742
+ });
743
+ }
744
+ }
745
+ if (maxRetries != null) {
746
+ if (!Number.isInteger(maxRetries)) {
747
+ throw new InvalidArgumentError({
748
+ parameter: "maxRetries",
749
+ value: maxRetries,
750
+ message: "maxRetries must be an integer"
751
+ });
752
+ }
753
+ if (maxRetries < 0) {
754
+ throw new InvalidArgumentError({
755
+ parameter: "maxRetries",
756
+ value: maxRetries,
757
+ message: "maxRetries must be >= 0"
758
+ });
597
759
  }
598
- throw new DownloadError({ url: urlText, cause: error });
599
760
  }
761
+ return {
762
+ maxTokens,
763
+ temperature: temperature != null ? temperature : 0,
764
+ topP,
765
+ presencePenalty,
766
+ frequencyPenalty,
767
+ stopSequences: stopSequences != null && stopSequences.length > 0 ? stopSequences : void 0,
768
+ seed,
769
+ maxRetries: maxRetries != null ? maxRetries : 2
770
+ };
600
771
  }
601
772
 
602
- // core/util/detect-image-mimetype.ts
603
- var mimeTypeSignatures = [
604
- { mimeType: "image/gif", bytes: [71, 73, 70] },
605
- { mimeType: "image/png", bytes: [137, 80, 78, 71] },
606
- { mimeType: "image/jpeg", bytes: [255, 216] },
607
- { mimeType: "image/webp", bytes: [82, 73, 70, 70] }
608
- ];
609
- function detectImageMimeType(image) {
610
- for (const { bytes, mimeType } of mimeTypeSignatures) {
611
- if (image.length >= bytes.length && bytes.every((byte, index) => image[index] === byte)) {
612
- return mimeType;
613
- }
773
+ // core/prompt/prepare-tools-and-tool-choice.ts
774
+ import { asSchema } from "@ai-sdk/ui-utils";
775
+
776
+ // core/util/is-non-empty-object.ts
777
+ function isNonEmptyObject(object) {
778
+ return object != null && Object.keys(object).length > 0;
779
+ }
780
+
781
+ // core/prompt/prepare-tools-and-tool-choice.ts
782
+ function prepareToolsAndToolChoice({
783
+ tools,
784
+ toolChoice
785
+ }) {
786
+ if (!isNonEmptyObject(tools)) {
787
+ return {
788
+ tools: void 0,
789
+ toolChoice: void 0
790
+ };
614
791
  }
615
- return void 0;
792
+ return {
793
+ tools: Object.entries(tools).map(([name8, tool]) => ({
794
+ type: "function",
795
+ name: name8,
796
+ description: tool.description,
797
+ parameters: asSchema(tool.parameters).jsonSchema
798
+ })),
799
+ toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName }
800
+ };
616
801
  }
617
802
 
618
- // core/prompt/data-content.ts
619
- import {
620
- convertBase64ToUint8Array,
621
- convertUint8ArrayToBase64
622
- } from "@ai-sdk/provider-utils";
803
+ // core/types/token-usage.ts
804
+ function calculateCompletionTokenUsage(usage) {
805
+ return {
806
+ promptTokens: usage.promptTokens,
807
+ completionTokens: usage.completionTokens,
808
+ totalTokens: usage.promptTokens + usage.completionTokens
809
+ };
810
+ }
623
811
 
624
- // core/prompt/invalid-data-content-error.ts
625
- import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
626
- var name3 = "AI_InvalidDataContentError";
627
- var marker3 = `vercel.ai.error.${name3}`;
628
- var symbol3 = Symbol.for(marker3);
629
- var _a3;
630
- var InvalidDataContentError = class extends AISDKError3 {
812
+ // errors/invalid-tool-arguments-error.ts
813
+ import { AISDKError as AISDKError5, getErrorMessage as getErrorMessage2 } from "@ai-sdk/provider";
814
+ var name5 = "AI_InvalidToolArgumentsError";
815
+ var marker5 = `vercel.ai.error.${name5}`;
816
+ var symbol5 = Symbol.for(marker5);
817
+ var _a5;
818
+ var InvalidToolArgumentsError = class extends AISDKError5 {
631
819
  constructor({
632
- content,
820
+ toolArgs,
821
+ toolName,
633
822
  cause,
634
- message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`
823
+ message = `Invalid arguments for tool ${toolName}: ${getErrorMessage2(
824
+ cause
825
+ )}`
635
826
  }) {
636
- super({ name: name3, message, cause });
637
- this[_a3] = true;
638
- this.content = content;
827
+ super({ name: name5, message, cause });
828
+ this[_a5] = true;
829
+ this.toolArgs = toolArgs;
830
+ this.toolName = toolName;
639
831
  }
640
832
  static isInstance(error) {
641
- return AISDKError3.hasMarker(error, marker3);
833
+ return AISDKError5.hasMarker(error, marker5);
642
834
  }
643
835
  /**
644
836
  * @deprecated use `isInstance` instead
645
837
  */
646
- static isInvalidDataContentError(error) {
647
- return error instanceof Error && error.name === name3 && error.content != null;
838
+ static isInvalidToolArgumentsError(error) {
839
+ return error instanceof Error && error.name === name5 && typeof error.toolName === "string" && typeof error.toolArgs === "string";
648
840
  }
649
841
  /**
650
842
  * @deprecated Do not use this method. It will be removed in the next major version.
@@ -653,59 +845,40 @@ var InvalidDataContentError = class extends AISDKError3 {
653
845
  return {
654
846
  name: this.name,
655
847
  message: this.message,
656
- stack: this.stack,
657
848
  cause: this.cause,
658
- content: this.content
849
+ stack: this.stack,
850
+ toolName: this.toolName,
851
+ toolArgs: this.toolArgs
659
852
  };
660
- }
661
- };
662
- _a3 = symbol3;
663
-
664
- // core/prompt/data-content.ts
665
- function convertDataContentToUint8Array(content) {
666
- if (content instanceof Uint8Array) {
667
- return content;
668
- }
669
- if (typeof content === "string") {
670
- try {
671
- return convertBase64ToUint8Array(content);
672
- } catch (error) {
673
- throw new InvalidDataContentError({
674
- message: "Invalid data content. Content string is not a base64-encoded media.",
675
- content,
676
- cause: error
677
- });
678
- }
679
- }
680
- if (content instanceof ArrayBuffer) {
681
- return new Uint8Array(content);
682
- }
683
- throw new InvalidDataContentError({ content });
684
- }
853
+ }
854
+ };
855
+ _a5 = symbol5;
685
856
 
686
- // core/prompt/invalid-message-role-error.ts
687
- import { AISDKError as AISDKError4 } from "@ai-sdk/provider";
688
- var name4 = "AI_InvalidMessageRoleError";
689
- var marker4 = `vercel.ai.error.${name4}`;
690
- var symbol4 = Symbol.for(marker4);
691
- var _a4;
692
- var InvalidMessageRoleError = class extends AISDKError4 {
857
+ // errors/no-such-tool-error.ts
858
+ import { AISDKError as AISDKError6 } from "@ai-sdk/provider";
859
+ var name6 = "AI_NoSuchToolError";
860
+ var marker6 = `vercel.ai.error.${name6}`;
861
+ var symbol6 = Symbol.for(marker6);
862
+ var _a6;
863
+ var NoSuchToolError = class extends AISDKError6 {
693
864
  constructor({
694
- role,
695
- message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`
865
+ toolName,
866
+ availableTools = void 0,
867
+ message = `Model tried to call unavailable tool '${toolName}'. ${availableTools === void 0 ? "No tools are available." : `Available tools: ${availableTools.join(", ")}.`}`
696
868
  }) {
697
- super({ name: name4, message });
698
- this[_a4] = true;
699
- this.role = role;
869
+ super({ name: name6, message });
870
+ this[_a6] = true;
871
+ this.toolName = toolName;
872
+ this.availableTools = availableTools;
700
873
  }
701
874
  static isInstance(error) {
702
- return AISDKError4.hasMarker(error, marker4);
875
+ return AISDKError6.hasMarker(error, marker6);
703
876
  }
704
877
  /**
705
878
  * @deprecated use `isInstance` instead
706
879
  */
707
- static isInvalidMessageRoleError(error) {
708
- return error instanceof Error && error.name === name4 && typeof error.role === "string";
880
+ static isNoSuchToolError(error) {
881
+ return error instanceof Error && error.name === name6 && "toolName" in error && error.toolName != void 0 && typeof error.name === "string";
709
882
  }
710
883
  /**
711
884
  * @deprecated Do not use this method. It will be removed in the next major version.
@@ -715,528 +888,429 @@ var InvalidMessageRoleError = class extends AISDKError4 {
715
888
  name: this.name,
716
889
  message: this.message,
717
890
  stack: this.stack,
718
- role: this.role
891
+ toolName: this.toolName,
892
+ availableTools: this.availableTools
719
893
  };
720
894
  }
721
895
  };
722
- _a4 = symbol4;
896
+ _a6 = symbol6;
723
897
 
724
- // core/prompt/convert-to-language-model-prompt.ts
725
- async function convertToLanguageModelPrompt({
726
- prompt,
727
- modelSupportsImageUrls = true,
728
- downloadImplementation = download
729
- }) {
730
- const languageModelMessages = [];
731
- if (prompt.system != null) {
732
- languageModelMessages.push({ role: "system", content: prompt.system });
733
- }
734
- const downloadedImages = modelSupportsImageUrls || prompt.messages == null ? null : await downloadImages(prompt.messages, downloadImplementation);
735
- const promptType = prompt.type;
736
- switch (promptType) {
737
- case "prompt": {
738
- languageModelMessages.push({
739
- role: "user",
740
- content: [{ type: "text", text: prompt.prompt }]
741
- });
742
- break;
743
- }
744
- case "messages": {
745
- languageModelMessages.push(
746
- ...prompt.messages.map(
747
- (message) => convertToLanguageModelMessage(message, downloadedImages)
748
- )
749
- );
750
- break;
751
- }
752
- default: {
753
- const _exhaustiveCheck = promptType;
754
- throw new Error(`Unsupported prompt type: ${_exhaustiveCheck}`);
755
- }
756
- }
757
- return languageModelMessages;
758
- }
759
- function convertToLanguageModelMessage(message, downloadedImages) {
760
- const role = message.role;
761
- switch (role) {
762
- case "system": {
763
- return { role: "system", content: message.content };
764
- }
765
- case "user": {
766
- if (typeof message.content === "string") {
767
- return {
768
- role: "user",
769
- content: [{ type: "text", text: message.content }]
770
- };
771
- }
772
- return {
773
- role: "user",
774
- content: message.content.map(
775
- (part) => {
776
- var _a8, _b, _c;
777
- switch (part.type) {
778
- case "text": {
779
- return part;
780
- }
781
- case "image": {
782
- if (part.image instanceof URL) {
783
- if (downloadedImages == null) {
784
- return {
785
- type: "image",
786
- image: part.image,
787
- mimeType: part.mimeType
788
- };
789
- } else {
790
- const downloadedImage = downloadedImages[part.image.toString()];
791
- return {
792
- type: "image",
793
- image: downloadedImage.data,
794
- mimeType: (_a8 = part.mimeType) != null ? _a8 : downloadedImage.mimeType
795
- };
796
- }
797
- }
798
- if (typeof part.image === "string") {
799
- try {
800
- const url = new URL(part.image);
801
- switch (url.protocol) {
802
- case "http:":
803
- case "https:": {
804
- if (downloadedImages == null) {
805
- return {
806
- type: "image",
807
- image: url,
808
- mimeType: part.mimeType
809
- };
810
- } else {
811
- const downloadedImage = downloadedImages[part.image];
812
- return {
813
- type: "image",
814
- image: downloadedImage.data,
815
- mimeType: (_b = part.mimeType) != null ? _b : downloadedImage.mimeType
816
- };
817
- }
818
- }
819
- case "data:": {
820
- try {
821
- const [header, base64Content] = part.image.split(",");
822
- const mimeType = header.split(";")[0].split(":")[1];
823
- if (mimeType == null || base64Content == null) {
824
- throw new Error("Invalid data URL format");
825
- }
826
- return {
827
- type: "image",
828
- image: convertDataContentToUint8Array(base64Content),
829
- mimeType
830
- };
831
- } catch (error) {
832
- throw new Error(
833
- `Error processing data URL: ${getErrorMessage2(
834
- message
835
- )}`
836
- );
837
- }
838
- }
839
- default: {
840
- throw new Error(
841
- `Unsupported URL protocol: ${url.protocol}`
842
- );
843
- }
844
- }
845
- } catch (_ignored) {
846
- }
847
- }
848
- const imageUint8 = convertDataContentToUint8Array(part.image);
849
- return {
850
- type: "image",
851
- image: imageUint8,
852
- mimeType: (_c = part.mimeType) != null ? _c : detectImageMimeType(imageUint8)
853
- };
854
- }
855
- }
856
- }
857
- )
858
- };
859
- }
860
- case "assistant": {
861
- if (typeof message.content === "string") {
862
- return {
863
- role: "assistant",
864
- content: [{ type: "text", text: message.content }]
865
- };
866
- }
867
- return {
868
- role: "assistant",
869
- content: message.content.filter(
870
- // remove empty text parts:
871
- (part) => part.type !== "text" || part.text !== ""
872
- )
873
- };
874
- }
875
- case "tool": {
876
- return message;
877
- }
878
- default: {
879
- const _exhaustiveCheck = role;
880
- throw new InvalidMessageRoleError({ role: _exhaustiveCheck });
881
- }
882
- }
898
+ // util/is-async-generator.ts
899
+ function isAsyncGenerator(value) {
900
+ return value != null && typeof value === "object" && Symbol.asyncIterator in value;
883
901
  }
884
- async function downloadImages(messages, downloadImplementation) {
885
- const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
886
- (content) => Array.isArray(content)
887
- ).flat().filter((part) => part.type === "image").map((part) => part.image).map(
888
- (part) => (
889
- // support string urls in image parts:
890
- typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part
891
- )
892
- ).filter((image) => image instanceof URL);
893
- const downloadedImages = await Promise.all(
894
- urls.map(async (url) => ({
895
- url,
896
- data: await downloadImplementation({ url })
897
- }))
898
- );
899
- return Object.fromEntries(
900
- downloadedImages.map(({ url, data }) => [url.toString(), data])
901
- );
902
+
903
+ // util/is-generator.ts
904
+ function isGenerator(value) {
905
+ return value != null && typeof value === "object" && Symbol.iterator in value;
902
906
  }
903
907
 
904
- // core/prompt/get-validated-prompt.ts
905
- import { InvalidPromptError } from "@ai-sdk/provider";
906
- function getValidatedPrompt(prompt) {
907
- if (prompt.prompt == null && prompt.messages == null) {
908
- throw new InvalidPromptError({
909
- prompt,
910
- message: "prompt or messages must be defined"
911
- });
912
- }
913
- if (prompt.prompt != null && prompt.messages != null) {
914
- throw new InvalidPromptError({
915
- prompt,
916
- message: "prompt and messages cannot be defined at the same time"
917
- });
918
- }
919
- if (prompt.messages != null) {
920
- for (const message of prompt.messages) {
921
- if (message.role === "system" && typeof message.content !== "string") {
922
- throw new InvalidPromptError({
923
- prompt,
924
- message: "system message content must be a string"
925
- });
926
- }
927
- }
928
- }
929
- return prompt.prompt != null ? {
930
- type: "prompt",
931
- prompt: prompt.prompt,
932
- messages: void 0,
933
- system: prompt.system
934
- } : {
935
- type: "messages",
936
- prompt: void 0,
937
- messages: prompt.messages,
938
- // only possible case bc of checks above
939
- system: prompt.system
940
- };
908
+ // util/retry-with-exponential-backoff.ts
909
+ import { APICallError } from "@ai-sdk/provider";
910
+ import { getErrorMessage as getErrorMessage3, isAbortError } from "@ai-sdk/provider-utils";
911
+
912
+ // util/delay.ts
913
+ async function delay(delayInMs) {
914
+ return delayInMs === void 0 ? Promise.resolve() : new Promise((resolve) => setTimeout(resolve, delayInMs));
941
915
  }
942
916
 
943
- // errors/invalid-argument-error.ts
944
- import { AISDKError as AISDKError5 } from "@ai-sdk/provider";
945
- var name5 = "AI_InvalidArgumentError";
946
- var marker5 = `vercel.ai.error.${name5}`;
947
- var symbol5 = Symbol.for(marker5);
948
- var _a5;
949
- var InvalidArgumentError = class extends AISDKError5 {
917
+ // util/retry-error.ts
918
+ import { AISDKError as AISDKError7 } from "@ai-sdk/provider";
919
+ var name7 = "AI_RetryError";
920
+ var marker7 = `vercel.ai.error.${name7}`;
921
+ var symbol7 = Symbol.for(marker7);
922
+ var _a7;
923
+ var RetryError = class extends AISDKError7 {
950
924
  constructor({
951
- parameter,
952
- value,
953
- message
925
+ message,
926
+ reason,
927
+ errors
954
928
  }) {
955
- super({
956
- name: name5,
957
- message: `Invalid argument for parameter ${parameter}: ${message}`
958
- });
959
- this[_a5] = true;
960
- this.parameter = parameter;
961
- this.value = value;
929
+ super({ name: name7, message });
930
+ this[_a7] = true;
931
+ this.reason = reason;
932
+ this.errors = errors;
933
+ this.lastError = errors[errors.length - 1];
962
934
  }
963
935
  static isInstance(error) {
964
- return AISDKError5.hasMarker(error, marker5);
936
+ return AISDKError7.hasMarker(error, marker7);
965
937
  }
966
938
  /**
967
939
  * @deprecated use `isInstance` instead
968
940
  */
969
- static isInvalidArgumentError(error) {
970
- return error instanceof Error && error.name === name5 && typeof error.parameter === "string" && typeof error.value === "string";
941
+ static isRetryError(error) {
942
+ return error instanceof Error && error.name === name7 && typeof error.reason === "string" && Array.isArray(error.errors);
971
943
  }
944
+ /**
945
+ * @deprecated Do not use this method. It will be removed in the next major version.
946
+ */
972
947
  toJSON() {
973
948
  return {
974
949
  name: this.name,
975
950
  message: this.message,
976
- stack: this.stack,
977
- parameter: this.parameter,
978
- value: this.value
951
+ reason: this.reason,
952
+ lastError: this.lastError,
953
+ errors: this.errors
979
954
  };
980
955
  }
981
956
  };
982
- _a5 = symbol5;
957
+ _a7 = symbol7;
983
958
 
984
- // core/prompt/prepare-call-settings.ts
985
- function prepareCallSettings({
986
- maxTokens,
987
- temperature,
988
- topP,
989
- presencePenalty,
990
- frequencyPenalty,
991
- stopSequences,
992
- seed,
993
- maxRetries
994
- }) {
995
- if (maxTokens != null) {
996
- if (!Number.isInteger(maxTokens)) {
997
- throw new InvalidArgumentError({
998
- parameter: "maxTokens",
999
- value: maxTokens,
1000
- message: "maxTokens must be an integer"
1001
- });
1002
- }
1003
- if (maxTokens < 1) {
1004
- throw new InvalidArgumentError({
1005
- parameter: "maxTokens",
1006
- value: maxTokens,
1007
- message: "maxTokens must be >= 1"
1008
- });
1009
- }
1010
- }
1011
- if (temperature != null) {
1012
- if (typeof temperature !== "number") {
1013
- throw new InvalidArgumentError({
1014
- parameter: "temperature",
1015
- value: temperature,
1016
- message: "temperature must be a number"
1017
- });
959
+ // util/retry-with-exponential-backoff.ts
960
+ var retryWithExponentialBackoff = ({
961
+ maxRetries = 2,
962
+ initialDelayInMs = 2e3,
963
+ backoffFactor = 2
964
+ } = {}) => async (f) => _retryWithExponentialBackoff(f, {
965
+ maxRetries,
966
+ delayInMs: initialDelayInMs,
967
+ backoffFactor
968
+ });
969
+ async function _retryWithExponentialBackoff(f, {
970
+ maxRetries,
971
+ delayInMs,
972
+ backoffFactor
973
+ }, errors = []) {
974
+ try {
975
+ return await f();
976
+ } catch (error) {
977
+ if (isAbortError(error)) {
978
+ throw error;
1018
979
  }
1019
- }
1020
- if (topP != null) {
1021
- if (typeof topP !== "number") {
1022
- throw new InvalidArgumentError({
1023
- parameter: "topP",
1024
- value: topP,
1025
- message: "topP must be a number"
1026
- });
980
+ if (maxRetries === 0) {
981
+ throw error;
1027
982
  }
1028
- }
1029
- if (presencePenalty != null) {
1030
- if (typeof presencePenalty !== "number") {
1031
- throw new InvalidArgumentError({
1032
- parameter: "presencePenalty",
1033
- value: presencePenalty,
1034
- message: "presencePenalty must be a number"
983
+ const errorMessage = getErrorMessage3(error);
984
+ const newErrors = [...errors, error];
985
+ const tryNumber = newErrors.length;
986
+ if (tryNumber > maxRetries) {
987
+ throw new RetryError({
988
+ message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`,
989
+ reason: "maxRetriesExceeded",
990
+ errors: newErrors
1035
991
  });
1036
992
  }
1037
- }
1038
- if (frequencyPenalty != null) {
1039
- if (typeof frequencyPenalty !== "number") {
1040
- throw new InvalidArgumentError({
1041
- parameter: "frequencyPenalty",
1042
- value: frequencyPenalty,
1043
- message: "frequencyPenalty must be a number"
1044
- });
993
+ if (error instanceof Error && APICallError.isAPICallError(error) && error.isRetryable === true && tryNumber <= maxRetries) {
994
+ await delay(delayInMs);
995
+ return _retryWithExponentialBackoff(
996
+ f,
997
+ { maxRetries, delayInMs: backoffFactor * delayInMs, backoffFactor },
998
+ newErrors
999
+ );
1045
1000
  }
1046
- }
1047
- if (seed != null) {
1048
- if (!Number.isInteger(seed)) {
1049
- throw new InvalidArgumentError({
1050
- parameter: "seed",
1051
- value: seed,
1052
- message: "seed must be an integer"
1053
- });
1001
+ if (tryNumber === 1) {
1002
+ throw error;
1054
1003
  }
1004
+ throw new RetryError({
1005
+ message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`,
1006
+ reason: "errorNotRetryable",
1007
+ errors: newErrors
1008
+ });
1055
1009
  }
1056
- if (maxRetries != null) {
1057
- if (!Number.isInteger(maxRetries)) {
1058
- throw new InvalidArgumentError({
1059
- parameter: "maxRetries",
1060
- value: maxRetries,
1061
- message: "maxRetries must be an integer"
1062
- });
1010
+ }
1011
+
1012
+ // util/constants.ts
1013
+ var HANGING_STREAM_WARNING_TIME_MS = 15 * 1e3;
1014
+
1015
+ // rsc/streamable-ui/create-suspended-chunk.tsx
1016
+ import { Suspense } from "react";
1017
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
1018
+ var R = [
1019
+ async ({
1020
+ c: current,
1021
+ n: next
1022
+ }) => {
1023
+ const chunk = await next;
1024
+ if (chunk.done) {
1025
+ return chunk.value;
1063
1026
  }
1064
- if (maxRetries < 0) {
1065
- throw new InvalidArgumentError({
1066
- parameter: "maxRetries",
1067
- value: maxRetries,
1068
- message: "maxRetries must be >= 0"
1069
- });
1027
+ if (chunk.append) {
1028
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1029
+ current,
1030
+ /* @__PURE__ */ jsx2(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx2(R, { c: chunk.value, n: chunk.next }) })
1031
+ ] });
1070
1032
  }
1033
+ return /* @__PURE__ */ jsx2(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx2(R, { c: chunk.value, n: chunk.next }) });
1071
1034
  }
1035
+ ][0];
1036
+ function createSuspendedChunk(initialValue) {
1037
+ const { promise, resolve, reject } = createResolvablePromise();
1072
1038
  return {
1073
- maxTokens,
1074
- temperature: temperature != null ? temperature : 0,
1075
- topP,
1076
- presencePenalty,
1077
- frequencyPenalty,
1078
- stopSequences: stopSequences != null && stopSequences.length > 0 ? stopSequences : void 0,
1079
- seed,
1080
- maxRetries: maxRetries != null ? maxRetries : 2
1081
- };
1082
- }
1083
-
1084
- // core/types/token-usage.ts
1085
- function calculateCompletionTokenUsage(usage) {
1086
- return {
1087
- promptTokens: usage.promptTokens,
1088
- completionTokens: usage.completionTokens,
1089
- totalTokens: usage.promptTokens + usage.completionTokens
1039
+ row: /* @__PURE__ */ jsx2(Suspense, { fallback: initialValue, children: /* @__PURE__ */ jsx2(R, { c: initialValue, n: promise }) }),
1040
+ resolve,
1041
+ reject
1090
1042
  };
1091
1043
  }
1092
1044
 
1093
- // core/util/schema.ts
1094
- import { validatorSymbol } from "@ai-sdk/provider-utils";
1095
- import zodToJsonSchema from "zod-to-json-schema";
1096
- var schemaSymbol = Symbol.for("vercel.ai.schema");
1097
- function jsonSchema(jsonSchema2, {
1098
- validate
1099
- } = {}) {
1100
- return {
1101
- [schemaSymbol]: true,
1102
- _type: void 0,
1103
- // should never be used directly
1104
- [validatorSymbol]: true,
1105
- jsonSchema: jsonSchema2,
1106
- validate
1107
- };
1108
- }
1109
- function isSchema(value) {
1110
- return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value;
1111
- }
1112
- function asSchema(schema) {
1113
- return isSchema(schema) ? schema : zodSchema(schema);
1114
- }
1115
- function zodSchema(zodSchema2) {
1116
- return jsonSchema(
1117
- // we assume that zodToJsonSchema will return a valid JSONSchema7:
1118
- zodToJsonSchema(zodSchema2),
1119
- {
1120
- validate: (value) => {
1121
- const result = zodSchema2.safeParse(value);
1122
- return result.success ? { success: true, value: result.data } : { success: false, error: result.error };
1045
+ // rsc/streamable-ui/create-streamable-ui.tsx
1046
+ function createStreamableUI(initialValue) {
1047
+ let currentValue = initialValue;
1048
+ let closed = false;
1049
+ let { row, resolve, reject } = createSuspendedChunk(initialValue);
1050
+ function assertStream(method) {
1051
+ if (closed) {
1052
+ throw new Error(method + ": UI stream is already closed.");
1053
+ }
1054
+ }
1055
+ let warningTimeout;
1056
+ function warnUnclosedStream() {
1057
+ if (process.env.NODE_ENV === "development") {
1058
+ if (warningTimeout) {
1059
+ clearTimeout(warningTimeout);
1060
+ }
1061
+ warningTimeout = setTimeout(() => {
1062
+ console.warn(
1063
+ "The streamable UI has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`."
1064
+ );
1065
+ }, HANGING_STREAM_WARNING_TIME_MS);
1066
+ }
1067
+ }
1068
+ warnUnclosedStream();
1069
+ const streamable2 = {
1070
+ value: row,
1071
+ update(value) {
1072
+ assertStream(".update()");
1073
+ if (value === currentValue) {
1074
+ warnUnclosedStream();
1075
+ return streamable2;
1076
+ }
1077
+ const resolvable = createResolvablePromise();
1078
+ currentValue = value;
1079
+ resolve({ value: currentValue, done: false, next: resolvable.promise });
1080
+ resolve = resolvable.resolve;
1081
+ reject = resolvable.reject;
1082
+ warnUnclosedStream();
1083
+ return streamable2;
1084
+ },
1085
+ append(value) {
1086
+ assertStream(".append()");
1087
+ const resolvable = createResolvablePromise();
1088
+ currentValue = value;
1089
+ resolve({ value, done: false, append: true, next: resolvable.promise });
1090
+ resolve = resolvable.resolve;
1091
+ reject = resolvable.reject;
1092
+ warnUnclosedStream();
1093
+ return streamable2;
1094
+ },
1095
+ error(error) {
1096
+ assertStream(".error()");
1097
+ if (warningTimeout) {
1098
+ clearTimeout(warningTimeout);
1099
+ }
1100
+ closed = true;
1101
+ reject(error);
1102
+ return streamable2;
1103
+ },
1104
+ done(...args) {
1105
+ assertStream(".done()");
1106
+ if (warningTimeout) {
1107
+ clearTimeout(warningTimeout);
1108
+ }
1109
+ closed = true;
1110
+ if (args.length) {
1111
+ resolve({ value: args[0], done: true });
1112
+ return streamable2;
1123
1113
  }
1114
+ resolve({ value: currentValue, done: true });
1115
+ return streamable2;
1124
1116
  }
1125
- );
1126
- }
1127
-
1128
- // core/util/is-non-empty-object.ts
1129
- function isNonEmptyObject(object) {
1130
- return object != null && Object.keys(object).length > 0;
1117
+ };
1118
+ return streamable2;
1131
1119
  }
1132
1120
 
1133
- // core/prompt/prepare-tools-and-tool-choice.ts
1134
- function prepareToolsAndToolChoice({
1121
+ // rsc/stream-ui/stream-ui.tsx
1122
+ var defaultTextRenderer = ({ content }) => content;
1123
+ async function streamUI({
1124
+ model,
1135
1125
  tools,
1136
- toolChoice
1126
+ toolChoice,
1127
+ system,
1128
+ prompt,
1129
+ messages,
1130
+ maxRetries,
1131
+ abortSignal,
1132
+ headers,
1133
+ initial,
1134
+ text,
1135
+ onFinish,
1136
+ ...settings
1137
1137
  }) {
1138
- if (!isNonEmptyObject(tools)) {
1139
- return {
1140
- tools: void 0,
1141
- toolChoice: void 0
1142
- };
1138
+ if (typeof model === "string") {
1139
+ throw new Error(
1140
+ "`model` cannot be a string in `streamUI`. Use the actual model instance instead."
1141
+ );
1143
1142
  }
1144
- return {
1145
- tools: Object.entries(tools).map(([name8, tool]) => ({
1146
- type: "function",
1147
- name: name8,
1148
- description: tool.description,
1149
- parameters: asSchema(tool.parameters).jsonSchema
1150
- })),
1151
- toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName }
1152
- };
1153
- }
1154
-
1155
- // errors/invalid-tool-arguments-error.ts
1156
- import { AISDKError as AISDKError6, getErrorMessage as getErrorMessage3 } from "@ai-sdk/provider";
1157
- var name6 = "AI_InvalidToolArgumentsError";
1158
- var marker6 = `vercel.ai.error.${name6}`;
1159
- var symbol6 = Symbol.for(marker6);
1160
- var _a6;
1161
- var InvalidToolArgumentsError = class extends AISDKError6 {
1162
- constructor({
1163
- toolArgs,
1164
- toolName,
1165
- cause,
1166
- message = `Invalid arguments for tool ${toolName}: ${getErrorMessage3(
1167
- cause
1168
- )}`
1169
- }) {
1170
- super({ name: name6, message, cause });
1171
- this[_a6] = true;
1172
- this.toolArgs = toolArgs;
1173
- this.toolName = toolName;
1143
+ if ("functions" in settings) {
1144
+ throw new Error(
1145
+ "`functions` is not supported in `streamUI`, use `tools` instead."
1146
+ );
1174
1147
  }
1175
- static isInstance(error) {
1176
- return AISDKError6.hasMarker(error, marker6);
1148
+ if ("provider" in settings) {
1149
+ throw new Error(
1150
+ "`provider` is no longer needed in `streamUI`. Use `model` instead."
1151
+ );
1177
1152
  }
1178
- /**
1179
- * @deprecated use `isInstance` instead
1180
- */
1181
- static isInvalidToolArgumentsError(error) {
1182
- return error instanceof Error && error.name === name6 && typeof error.toolName === "string" && typeof error.toolArgs === "string";
1153
+ if (tools) {
1154
+ for (const [name8, tool] of Object.entries(tools)) {
1155
+ if ("render" in tool) {
1156
+ throw new Error(
1157
+ "Tool definition in `streamUI` should not have `render` property. Use `generate` instead. Found in tool: " + name8
1158
+ );
1159
+ }
1160
+ }
1183
1161
  }
1184
- /**
1185
- * @deprecated Do not use this method. It will be removed in the next major version.
1186
- */
1187
- toJSON() {
1188
- return {
1189
- name: this.name,
1190
- message: this.message,
1191
- cause: this.cause,
1192
- stack: this.stack,
1193
- toolName: this.toolName,
1194
- toolArgs: this.toolArgs
1195
- };
1162
+ const ui = createStreamableUI(initial);
1163
+ const textRender = text || defaultTextRenderer;
1164
+ let finished;
1165
+ async function render2({
1166
+ args,
1167
+ renderer,
1168
+ streamableUI,
1169
+ isLastCall = false
1170
+ }) {
1171
+ if (!renderer)
1172
+ return;
1173
+ const renderFinished = createResolvablePromise();
1174
+ finished = finished ? finished.then(() => renderFinished.promise) : renderFinished.promise;
1175
+ const rendererResult = renderer(...args);
1176
+ if (isAsyncGenerator(rendererResult) || isGenerator(rendererResult)) {
1177
+ while (true) {
1178
+ const { done, value } = await rendererResult.next();
1179
+ const node = await value;
1180
+ if (isLastCall && done) {
1181
+ streamableUI.done(node);
1182
+ } else {
1183
+ streamableUI.update(node);
1184
+ }
1185
+ if (done)
1186
+ break;
1187
+ }
1188
+ } else {
1189
+ const node = await rendererResult;
1190
+ if (isLastCall) {
1191
+ streamableUI.done(node);
1192
+ } else {
1193
+ streamableUI.update(node);
1194
+ }
1195
+ }
1196
+ renderFinished.resolve(void 0);
1196
1197
  }
1197
- };
1198
- _a6 = symbol6;
1198
+ const retry = retryWithExponentialBackoff({ maxRetries });
1199
+ const validatedPrompt = getValidatedPrompt({ system, prompt, messages });
1200
+ const result = await retry(
1201
+ async () => model.doStream({
1202
+ mode: {
1203
+ type: "regular",
1204
+ ...prepareToolsAndToolChoice({ tools, toolChoice })
1205
+ },
1206
+ ...prepareCallSettings(settings),
1207
+ inputFormat: validatedPrompt.type,
1208
+ prompt: await convertToLanguageModelPrompt({
1209
+ prompt: validatedPrompt,
1210
+ modelSupportsImageUrls: model.supportsImageUrls
1211
+ }),
1212
+ abortSignal,
1213
+ headers
1214
+ })
1215
+ );
1216
+ const [stream, forkedStream] = result.stream.tee();
1217
+ (async () => {
1218
+ try {
1219
+ let content = "";
1220
+ let hasToolCall = false;
1221
+ const reader = forkedStream.getReader();
1222
+ while (true) {
1223
+ const { done, value } = await reader.read();
1224
+ if (done)
1225
+ break;
1226
+ switch (value.type) {
1227
+ case "text-delta": {
1228
+ content += value.textDelta;
1229
+ render2({
1230
+ renderer: textRender,
1231
+ args: [{ content, done: false, delta: value.textDelta }],
1232
+ streamableUI: ui
1233
+ });
1234
+ break;
1235
+ }
1236
+ case "tool-call-delta": {
1237
+ hasToolCall = true;
1238
+ break;
1239
+ }
1240
+ case "tool-call": {
1241
+ const toolName = value.toolName;
1242
+ if (!tools) {
1243
+ throw new NoSuchToolError({ toolName });
1244
+ }
1245
+ const tool = tools[toolName];
1246
+ if (!tool) {
1247
+ throw new NoSuchToolError({
1248
+ toolName,
1249
+ availableTools: Object.keys(tools)
1250
+ });
1251
+ }
1252
+ hasToolCall = true;
1253
+ const parseResult = safeParseJSON({
1254
+ text: value.args,
1255
+ schema: tool.parameters
1256
+ });
1257
+ if (parseResult.success === false) {
1258
+ throw new InvalidToolArgumentsError({
1259
+ toolName,
1260
+ toolArgs: value.args,
1261
+ cause: parseResult.error
1262
+ });
1263
+ }
1264
+ render2({
1265
+ renderer: tool.generate,
1266
+ args: [
1267
+ parseResult.value,
1268
+ {
1269
+ toolName,
1270
+ toolCallId: value.toolCallId
1271
+ }
1272
+ ],
1273
+ streamableUI: ui,
1274
+ isLastCall: true
1275
+ });
1276
+ break;
1277
+ }
1278
+ case "error": {
1279
+ throw value.error;
1280
+ }
1281
+ case "finish": {
1282
+ onFinish == null ? void 0 : onFinish({
1283
+ finishReason: value.finishReason,
1284
+ usage: calculateCompletionTokenUsage(value.usage),
1285
+ value: ui.value,
1286
+ warnings: result.warnings,
1287
+ rawResponse: result.rawResponse
1288
+ });
1289
+ }
1290
+ }
1291
+ }
1292
+ if (!hasToolCall) {
1293
+ render2({
1294
+ renderer: textRender,
1295
+ args: [{ content, done: true }],
1296
+ streamableUI: ui,
1297
+ isLastCall: true
1298
+ });
1299
+ }
1300
+ await finished;
1301
+ } catch (error) {
1302
+ ui.error(error);
1303
+ }
1304
+ })();
1305
+ return {
1306
+ ...result,
1307
+ stream,
1308
+ value: ui.value
1309
+ };
1310
+ }
1199
1311
 
1200
- // errors/no-such-tool-error.ts
1201
- import { AISDKError as AISDKError7 } from "@ai-sdk/provider";
1202
- var name7 = "AI_NoSuchToolError";
1203
- var marker7 = `vercel.ai.error.${name7}`;
1204
- var symbol7 = Symbol.for(marker7);
1205
- var _a7;
1206
- var NoSuchToolError = class extends AISDKError7 {
1207
- constructor({
1208
- toolName,
1209
- availableTools = void 0,
1210
- message = `Model tried to call unavailable tool '${toolName}'. ${availableTools === void 0 ? "No tools are available." : `Available tools: ${availableTools.join(", ")}.`}`
1211
- }) {
1212
- super({ name: name7, message });
1213
- this[_a7] = true;
1214
- this.toolName = toolName;
1215
- this.availableTools = availableTools;
1216
- }
1217
- static isInstance(error) {
1218
- return AISDKError7.hasMarker(error, marker7);
1219
- }
1220
- /**
1221
- * @deprecated use `isInstance` instead
1222
- */
1223
- static isNoSuchToolError(error) {
1224
- return error instanceof Error && error.name === name7 && "toolName" in error && error.toolName != void 0 && typeof error.name === "string";
1225
- }
1226
- /**
1227
- * @deprecated Do not use this method. It will be removed in the next major version.
1228
- */
1229
- toJSON() {
1230
- return {
1231
- name: this.name,
1232
- message: this.message,
1233
- stack: this.stack,
1234
- toolName: this.toolName,
1235
- availableTools: this.availableTools
1236
- };
1237
- }
1238
- };
1239
- _a7 = symbol7;
1312
+ // rsc/stream-ui/render.ts
1313
+ import zodToJsonSchema from "zod-to-json-schema";
1240
1314
 
1241
1315
  // streams/ai-stream.ts
1242
1316
  import {
@@ -1364,7 +1438,6 @@ function readableFromAsyncIterable(iterable) {
1364
1438
 
1365
1439
  // streams/stream-data.ts
1366
1440
  import { formatStreamPart } from "@ai-sdk/ui-utils";
1367
- var STREAM_DATA_WARNING_TIME_MS = 15 * 1e3;
1368
1441
  function createStreamDataTransformer() {
1369
1442
  const encoder = new TextEncoder();
1370
1443
  const decoder = new TextDecoder();
@@ -1708,7 +1781,7 @@ async function consumeStream(stream) {
1708
1781
  }
1709
1782
  }
1710
1783
 
1711
- // rsc/render.ts
1784
+ // rsc/stream-ui/render.ts
1712
1785
  function render(options) {
1713
1786
  const ui = createStreamableUI(options.initial);
1714
1787
  const text = options.text ? options.text : ({ content }) => content;
@@ -1717,7 +1790,7 @@ function render(options) {
1717
1790
  return {
1718
1791
  name: name8,
1719
1792
  description,
1720
- parameters: zodToJsonSchema2(parameters)
1793
+ parameters: zodToJsonSchema(parameters)
1721
1794
  };
1722
1795
  }
1723
1796
  ) : void 0;
@@ -1728,7 +1801,7 @@ function render(options) {
1728
1801
  function: {
1729
1802
  name: name8,
1730
1803
  description,
1731
- parameters: zodToJsonSchema2(parameters)
1804
+ parameters: zodToJsonSchema(parameters)
1732
1805
  }
1733
1806
  };
1734
1807
  }
@@ -1809,308 +1882,206 @@ function render(options) {
1809
1882
  async experimental_onToolCall(toolCallPayload) {
1810
1883
  var _a8, _b;
1811
1884
  hasFunction = true;
1812
- for (const tool of toolCallPayload.tools) {
1813
- handleRender(
1814
- tool.func.arguments,
1815
- (_b = (_a8 = options.tools) == null ? void 0 : _a8[tool.func.name]) == null ? void 0 : _b.render,
1816
- ui
1817
- );
1818
- }
1819
- }
1820
- } : {},
1821
- onText(chunk) {
1822
- content += chunk;
1823
- handleRender({ content, done: false, delta: chunk }, text, ui);
1824
- },
1825
- async onFinal() {
1826
- if (hasFunction) {
1827
- await finished;
1828
- ui.done();
1829
- return;
1830
- }
1831
- handleRender({ content, done: true }, text, ui);
1832
- await finished;
1833
- ui.done();
1834
- }
1835
- }
1836
- )
1837
- );
1838
- })();
1839
- return ui.value;
1840
- }
1841
-
1842
- // rsc/stream-ui/stream-ui.tsx
1843
- import { safeParseJSON } from "@ai-sdk/provider-utils";
1844
-
1845
- // util/is-async-generator.ts
1846
- function isAsyncGenerator(value) {
1847
- return value != null && typeof value === "object" && Symbol.asyncIterator in value;
1848
- }
1849
-
1850
- // util/is-generator.ts
1851
- function isGenerator(value) {
1852
- return value != null && typeof value === "object" && Symbol.iterator in value;
1853
- }
1854
-
1855
- // rsc/stream-ui/stream-ui.tsx
1856
- var defaultTextRenderer = ({ content }) => content;
1857
- async function streamUI({
1858
- model,
1859
- tools,
1860
- toolChoice,
1861
- system,
1862
- prompt,
1863
- messages,
1864
- maxRetries,
1865
- abortSignal,
1866
- headers,
1867
- initial,
1868
- text,
1869
- onFinish,
1870
- ...settings
1871
- }) {
1872
- if (typeof model === "string") {
1873
- throw new Error(
1874
- "`model` cannot be a string in `streamUI`. Use the actual model instance instead."
1875
- );
1876
- }
1877
- if ("functions" in settings) {
1878
- throw new Error(
1879
- "`functions` is not supported in `streamUI`, use `tools` instead."
1880
- );
1881
- }
1882
- if ("provider" in settings) {
1883
- throw new Error(
1884
- "`provider` is no longer needed in `streamUI`. Use `model` instead."
1885
- );
1886
- }
1887
- if (tools) {
1888
- for (const [name8, tool] of Object.entries(tools)) {
1889
- if ("render" in tool) {
1890
- throw new Error(
1891
- "Tool definition in `streamUI` should not have `render` property. Use `generate` instead. Found in tool: " + name8
1892
- );
1893
- }
1894
- }
1895
- }
1896
- const ui = createStreamableUI(initial);
1897
- const textRender = text || defaultTextRenderer;
1898
- let finished;
1899
- async function render2({
1900
- args,
1901
- renderer,
1902
- streamableUI,
1903
- isLastCall = false
1904
- }) {
1905
- if (!renderer)
1906
- return;
1907
- const renderFinished = createResolvablePromise();
1908
- finished = finished ? finished.then(() => renderFinished.promise) : renderFinished.promise;
1909
- const rendererResult = renderer(...args);
1910
- if (isAsyncGenerator(rendererResult) || isGenerator(rendererResult)) {
1911
- while (true) {
1912
- const { done, value } = await rendererResult.next();
1913
- const node = await value;
1914
- if (isLastCall && done) {
1915
- streamableUI.done(node);
1916
- } else {
1917
- streamableUI.update(node);
1918
- }
1919
- if (done)
1920
- break;
1921
- }
1922
- } else {
1923
- const node = await rendererResult;
1924
- if (isLastCall) {
1925
- streamableUI.done(node);
1926
- } else {
1927
- streamableUI.update(node);
1928
- }
1929
- }
1930
- renderFinished.resolve(void 0);
1931
- }
1932
- const retry = retryWithExponentialBackoff({ maxRetries });
1933
- const validatedPrompt = getValidatedPrompt({ system, prompt, messages });
1934
- const result = await retry(
1935
- async () => model.doStream({
1936
- mode: {
1937
- type: "regular",
1938
- ...prepareToolsAndToolChoice({ tools, toolChoice })
1939
- },
1940
- ...prepareCallSettings(settings),
1941
- inputFormat: validatedPrompt.type,
1942
- prompt: await convertToLanguageModelPrompt({
1943
- prompt: validatedPrompt,
1944
- modelSupportsImageUrls: model.supportsImageUrls
1945
- }),
1946
- abortSignal,
1947
- headers
1948
- })
1949
- );
1950
- const [stream, forkedStream] = result.stream.tee();
1951
- (async () => {
1952
- try {
1953
- let content = "";
1954
- let hasToolCall = false;
1955
- const reader = forkedStream.getReader();
1956
- while (true) {
1957
- const { done, value } = await reader.read();
1958
- if (done)
1959
- break;
1960
- switch (value.type) {
1961
- case "text-delta": {
1962
- content += value.textDelta;
1963
- render2({
1964
- renderer: textRender,
1965
- args: [{ content, done: false, delta: value.textDelta }],
1966
- streamableUI: ui
1967
- });
1968
- break;
1969
- }
1970
- case "tool-call-delta": {
1971
- hasToolCall = true;
1972
- break;
1973
- }
1974
- case "tool-call": {
1975
- const toolName = value.toolName;
1976
- if (!tools) {
1977
- throw new NoSuchToolError({ toolName });
1978
- }
1979
- const tool = tools[toolName];
1980
- if (!tool) {
1981
- throw new NoSuchToolError({
1982
- toolName,
1983
- availableTools: Object.keys(tools)
1984
- });
1985
- }
1986
- hasToolCall = true;
1987
- const parseResult = safeParseJSON({
1988
- text: value.args,
1989
- schema: tool.parameters
1990
- });
1991
- if (parseResult.success === false) {
1992
- throw new InvalidToolArgumentsError({
1993
- toolName,
1994
- toolArgs: value.args,
1995
- cause: parseResult.error
1996
- });
1997
- }
1998
- render2({
1999
- renderer: tool.generate,
2000
- args: [
2001
- parseResult.value,
2002
- {
2003
- toolName,
2004
- toolCallId: value.toolCallId
2005
- }
2006
- ],
2007
- streamableUI: ui,
2008
- isLastCall: true
2009
- });
2010
- break;
2011
- }
2012
- case "error": {
2013
- throw value.error;
2014
- }
2015
- case "finish": {
2016
- onFinish == null ? void 0 : onFinish({
2017
- finishReason: value.finishReason,
2018
- usage: calculateCompletionTokenUsage(value.usage),
2019
- value: ui.value,
2020
- warnings: result.warnings,
2021
- rawResponse: result.rawResponse
2022
- });
1885
+ for (const tool of toolCallPayload.tools) {
1886
+ handleRender(
1887
+ tool.func.arguments,
1888
+ (_b = (_a8 = options.tools) == null ? void 0 : _a8[tool.func.name]) == null ? void 0 : _b.render,
1889
+ ui
1890
+ );
1891
+ }
1892
+ }
1893
+ } : {},
1894
+ onText(chunk) {
1895
+ content += chunk;
1896
+ handleRender({ content, done: false, delta: chunk }, text, ui);
1897
+ },
1898
+ async onFinal() {
1899
+ if (hasFunction) {
1900
+ await finished;
1901
+ ui.done();
1902
+ return;
1903
+ }
1904
+ handleRender({ content, done: true }, text, ui);
1905
+ await finished;
1906
+ ui.done();
2023
1907
  }
2024
1908
  }
2025
- }
2026
- if (!hasToolCall) {
2027
- render2({
2028
- renderer: textRender,
2029
- args: [{ content, done: true }],
2030
- streamableUI: ui,
2031
- isLastCall: true
2032
- });
2033
- }
2034
- await finished;
2035
- } catch (error) {
2036
- ui.error(error);
2037
- }
1909
+ )
1910
+ );
2038
1911
  })();
2039
- return {
2040
- ...result,
2041
- stream,
2042
- value: ui.value
2043
- };
1912
+ return ui.value;
2044
1913
  }
2045
1914
 
2046
- // rsc/provider.tsx
2047
- import * as React2 from "react";
2048
- import { InternalAIProvider } from "./rsc-shared.mjs";
2049
- import { jsx as jsx2 } from "react/jsx-runtime";
2050
- async function innerAction({
2051
- action,
2052
- options
2053
- }, state, ...args) {
2054
- "use server";
2055
- return await withAIState(
2056
- {
2057
- state,
2058
- options
2059
- },
2060
- async () => {
2061
- const result = await action(...args);
2062
- sealMutableAIState();
2063
- return [getAIStateDeltaPromise(), result];
1915
+ // rsc/streamable-value/streamable-value.ts
1916
+ var STREAMABLE_VALUE_TYPE = Symbol.for("ui.streamable.value");
1917
+
1918
+ // rsc/streamable-value/create-streamable-value.ts
1919
+ var STREAMABLE_VALUE_INTERNAL_LOCK = Symbol("streamable.value.lock");
1920
+ function createStreamableValue(initialValue) {
1921
+ const isReadableStream = initialValue instanceof ReadableStream || typeof initialValue === "object" && initialValue !== null && "getReader" in initialValue && typeof initialValue.getReader === "function" && "locked" in initialValue && typeof initialValue.locked === "boolean";
1922
+ if (!isReadableStream) {
1923
+ return createStreamableValueImpl(initialValue);
1924
+ }
1925
+ const streamableValue = createStreamableValueImpl();
1926
+ streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = true;
1927
+ (async () => {
1928
+ try {
1929
+ const reader = initialValue.getReader();
1930
+ while (true) {
1931
+ const { value, done } = await reader.read();
1932
+ if (done) {
1933
+ break;
1934
+ }
1935
+ streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false;
1936
+ if (typeof value === "string") {
1937
+ streamableValue.append(value);
1938
+ } else {
1939
+ streamableValue.update(value);
1940
+ }
1941
+ streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = true;
1942
+ }
1943
+ streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false;
1944
+ streamableValue.done();
1945
+ } catch (e) {
1946
+ streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false;
1947
+ streamableValue.error(e);
2064
1948
  }
2065
- );
2066
- }
2067
- function wrapAction(action, options) {
2068
- return innerAction.bind(null, { action, options });
1949
+ })();
1950
+ return streamableValue;
2069
1951
  }
2070
- function createAI({
2071
- actions,
2072
- initialAIState,
2073
- initialUIState,
2074
- onSetAIState,
2075
- onGetUIState
2076
- }) {
2077
- const wrappedActions = {};
2078
- for (const name8 in actions) {
2079
- wrappedActions[name8] = wrapAction(actions[name8], {
2080
- onSetAIState
2081
- });
2082
- }
2083
- const wrappedSyncUIState = onGetUIState ? wrapAction(onGetUIState, {}) : void 0;
2084
- const AI = async (props) => {
2085
- var _a8, _b;
2086
- if ("useState" in React2) {
1952
+ function createStreamableValueImpl(initialValue) {
1953
+ let closed = false;
1954
+ let locked = false;
1955
+ let resolvable = createResolvablePromise();
1956
+ let currentValue = initialValue;
1957
+ let currentError;
1958
+ let currentPromise = resolvable.promise;
1959
+ let currentPatchValue;
1960
+ function assertStream(method) {
1961
+ if (closed) {
1962
+ throw new Error(method + ": Value stream is already closed.");
1963
+ }
1964
+ if (locked) {
2087
1965
  throw new Error(
2088
- "This component can only be used inside Server Components."
1966
+ method + ": Value stream is locked and cannot be updated."
2089
1967
  );
2090
1968
  }
2091
- let uiState = (_a8 = props.initialUIState) != null ? _a8 : initialUIState;
2092
- let aiState = (_b = props.initialAIState) != null ? _b : initialAIState;
2093
- let aiStateDelta = void 0;
2094
- if (wrappedSyncUIState) {
2095
- const [newAIStateDelta, newUIState] = await wrappedSyncUIState(aiState);
2096
- if (newUIState !== void 0) {
2097
- aiStateDelta = newAIStateDelta;
2098
- uiState = newUIState;
1969
+ }
1970
+ let warningTimeout;
1971
+ function warnUnclosedStream() {
1972
+ if (process.env.NODE_ENV === "development") {
1973
+ if (warningTimeout) {
1974
+ clearTimeout(warningTimeout);
2099
1975
  }
1976
+ warningTimeout = setTimeout(() => {
1977
+ console.warn(
1978
+ "The streamable value has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`."
1979
+ );
1980
+ }, HANGING_STREAM_WARNING_TIME_MS);
2100
1981
  }
2101
- return /* @__PURE__ */ jsx2(
2102
- InternalAIProvider,
2103
- {
2104
- wrappedActions,
2105
- wrappedSyncUIState,
2106
- initialUIState: uiState,
2107
- initialAIState: aiState,
2108
- initialAIStatePatch: aiStateDelta,
2109
- children: props.children
1982
+ }
1983
+ warnUnclosedStream();
1984
+ function createWrapped(initialChunk) {
1985
+ let init;
1986
+ if (currentError !== void 0) {
1987
+ init = { error: currentError };
1988
+ } else {
1989
+ if (currentPatchValue && !initialChunk) {
1990
+ init = { diff: currentPatchValue };
1991
+ } else {
1992
+ init = { curr: currentValue };
2110
1993
  }
2111
- );
1994
+ }
1995
+ if (currentPromise) {
1996
+ init.next = currentPromise;
1997
+ }
1998
+ if (initialChunk) {
1999
+ init.type = STREAMABLE_VALUE_TYPE;
2000
+ }
2001
+ return init;
2002
+ }
2003
+ function updateValueStates(value) {
2004
+ currentPatchValue = void 0;
2005
+ if (typeof value === "string") {
2006
+ if (typeof currentValue === "string") {
2007
+ if (value.startsWith(currentValue)) {
2008
+ currentPatchValue = [0, value.slice(currentValue.length)];
2009
+ }
2010
+ }
2011
+ }
2012
+ currentValue = value;
2013
+ }
2014
+ const streamable2 = {
2015
+ set [STREAMABLE_VALUE_INTERNAL_LOCK](state) {
2016
+ locked = state;
2017
+ },
2018
+ get value() {
2019
+ return createWrapped(true);
2020
+ },
2021
+ update(value) {
2022
+ assertStream(".update()");
2023
+ const resolvePrevious = resolvable.resolve;
2024
+ resolvable = createResolvablePromise();
2025
+ updateValueStates(value);
2026
+ currentPromise = resolvable.promise;
2027
+ resolvePrevious(createWrapped());
2028
+ warnUnclosedStream();
2029
+ return streamable2;
2030
+ },
2031
+ append(value) {
2032
+ assertStream(".append()");
2033
+ if (typeof currentValue !== "string" && typeof currentValue !== "undefined") {
2034
+ throw new Error(
2035
+ `.append(): The current value is not a string. Received: ${typeof currentValue}`
2036
+ );
2037
+ }
2038
+ if (typeof value !== "string") {
2039
+ throw new Error(
2040
+ `.append(): The value is not a string. Received: ${typeof value}`
2041
+ );
2042
+ }
2043
+ const resolvePrevious = resolvable.resolve;
2044
+ resolvable = createResolvablePromise();
2045
+ if (typeof currentValue === "string") {
2046
+ currentPatchValue = [0, value];
2047
+ currentValue = currentValue + value;
2048
+ } else {
2049
+ currentPatchValue = void 0;
2050
+ currentValue = value;
2051
+ }
2052
+ currentPromise = resolvable.promise;
2053
+ resolvePrevious(createWrapped());
2054
+ warnUnclosedStream();
2055
+ return streamable2;
2056
+ },
2057
+ error(error) {
2058
+ assertStream(".error()");
2059
+ if (warningTimeout) {
2060
+ clearTimeout(warningTimeout);
2061
+ }
2062
+ closed = true;
2063
+ currentError = error;
2064
+ currentPromise = void 0;
2065
+ resolvable.resolve({ error });
2066
+ return streamable2;
2067
+ },
2068
+ done(...args) {
2069
+ assertStream(".done()");
2070
+ if (warningTimeout) {
2071
+ clearTimeout(warningTimeout);
2072
+ }
2073
+ closed = true;
2074
+ currentPromise = void 0;
2075
+ if (args.length) {
2076
+ updateValueStates(args[0]);
2077
+ resolvable.resolve(createWrapped());
2078
+ return streamable2;
2079
+ }
2080
+ resolvable.resolve({});
2081
+ return streamable2;
2082
+ }
2112
2083
  };
2113
- return AI;
2084
+ return streamable2;
2114
2085
  }
2115
2086
  export {
2116
2087
  createAI,