ai 3.0.33 → 3.0.34

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.
@@ -175,7 +175,319 @@ function getMutableAIState(...args) {
175
175
  }
176
176
 
177
177
  // rsc/streamable.tsx
178
+ import zodToJsonSchema2 from "zod-to-json-schema";
179
+
180
+ // core/util/detect-image-mimetype.ts
181
+ var mimeTypeSignatures = [
182
+ { mimeType: "image/gif", bytes: [71, 73, 70] },
183
+ { mimeType: "image/png", bytes: [137, 80, 78, 71] },
184
+ { mimeType: "image/jpeg", bytes: [255, 216] },
185
+ { mimeType: "image/webp", bytes: [82, 73, 70, 70] }
186
+ ];
187
+ function detectImageMimeType(image) {
188
+ for (const { bytes, mimeType } of mimeTypeSignatures) {
189
+ if (image.length >= bytes.length && bytes.every((byte, index) => image[index] === byte)) {
190
+ return mimeType;
191
+ }
192
+ }
193
+ return void 0;
194
+ }
195
+
196
+ // core/prompt/data-content.ts
197
+ import { InvalidDataContentError } from "@ai-sdk/provider";
198
+ import {
199
+ convertBase64ToUint8Array,
200
+ convertUint8ArrayToBase64
201
+ } from "@ai-sdk/provider-utils";
202
+ function convertDataContentToUint8Array(content) {
203
+ if (content instanceof Uint8Array) {
204
+ return content;
205
+ }
206
+ if (typeof content === "string") {
207
+ return convertBase64ToUint8Array(content);
208
+ }
209
+ if (content instanceof ArrayBuffer) {
210
+ return new Uint8Array(content);
211
+ }
212
+ throw new InvalidDataContentError({ content });
213
+ }
214
+
215
+ // core/prompt/convert-to-language-model-prompt.ts
216
+ function convertToLanguageModelPrompt(prompt) {
217
+ const languageModelMessages = [];
218
+ if (prompt.system != null) {
219
+ languageModelMessages.push({ role: "system", content: prompt.system });
220
+ }
221
+ switch (prompt.type) {
222
+ case "prompt": {
223
+ languageModelMessages.push({
224
+ role: "user",
225
+ content: [{ type: "text", text: prompt.prompt }]
226
+ });
227
+ break;
228
+ }
229
+ case "messages": {
230
+ languageModelMessages.push(
231
+ ...prompt.messages.map((message) => {
232
+ switch (message.role) {
233
+ case "user": {
234
+ if (typeof message.content === "string") {
235
+ return {
236
+ role: "user",
237
+ content: [{ type: "text", text: message.content }]
238
+ };
239
+ }
240
+ return {
241
+ role: "user",
242
+ content: message.content.map(
243
+ (part) => {
244
+ var _a;
245
+ switch (part.type) {
246
+ case "text": {
247
+ return part;
248
+ }
249
+ case "image": {
250
+ if (part.image instanceof URL) {
251
+ return {
252
+ type: "image",
253
+ image: part.image,
254
+ mimeType: part.mimeType
255
+ };
256
+ }
257
+ const imageUint8 = convertDataContentToUint8Array(
258
+ part.image
259
+ );
260
+ return {
261
+ type: "image",
262
+ image: imageUint8,
263
+ mimeType: (_a = part.mimeType) != null ? _a : detectImageMimeType(imageUint8)
264
+ };
265
+ }
266
+ }
267
+ }
268
+ )
269
+ };
270
+ }
271
+ case "assistant": {
272
+ if (typeof message.content === "string") {
273
+ return {
274
+ role: "assistant",
275
+ content: [{ type: "text", text: message.content }]
276
+ };
277
+ }
278
+ return { role: "assistant", content: message.content };
279
+ }
280
+ case "tool": {
281
+ return message;
282
+ }
283
+ }
284
+ })
285
+ );
286
+ break;
287
+ }
288
+ default: {
289
+ const _exhaustiveCheck = prompt;
290
+ throw new Error(`Unsupported prompt type: ${_exhaustiveCheck}`);
291
+ }
292
+ }
293
+ return languageModelMessages;
294
+ }
295
+
296
+ // core/prompt/get-validated-prompt.ts
297
+ import { InvalidPromptError } from "@ai-sdk/provider";
298
+ function getValidatedPrompt(prompt) {
299
+ if (prompt.prompt == null && prompt.messages == null) {
300
+ throw new InvalidPromptError({
301
+ prompt,
302
+ message: "prompt or messages must be defined"
303
+ });
304
+ }
305
+ if (prompt.prompt != null && prompt.messages != null) {
306
+ throw new InvalidPromptError({
307
+ prompt,
308
+ message: "prompt and messages cannot be defined at the same time"
309
+ });
310
+ }
311
+ return prompt.prompt != null ? {
312
+ type: "prompt",
313
+ prompt: prompt.prompt,
314
+ messages: void 0,
315
+ system: prompt.system
316
+ } : {
317
+ type: "messages",
318
+ prompt: void 0,
319
+ messages: prompt.messages,
320
+ // only possible case bc of checks above
321
+ system: prompt.system
322
+ };
323
+ }
324
+
325
+ // core/prompt/prepare-call-settings.ts
326
+ import { InvalidArgumentError } from "@ai-sdk/provider";
327
+ function prepareCallSettings({
328
+ maxTokens,
329
+ temperature,
330
+ topP,
331
+ presencePenalty,
332
+ frequencyPenalty,
333
+ seed,
334
+ maxRetries
335
+ }) {
336
+ if (maxTokens != null) {
337
+ if (!Number.isInteger(maxTokens)) {
338
+ throw new InvalidArgumentError({
339
+ parameter: "maxTokens",
340
+ value: maxTokens,
341
+ message: "maxTokens must be an integer"
342
+ });
343
+ }
344
+ if (maxTokens < 1) {
345
+ throw new InvalidArgumentError({
346
+ parameter: "maxTokens",
347
+ value: maxTokens,
348
+ message: "maxTokens must be >= 1"
349
+ });
350
+ }
351
+ }
352
+ if (temperature != null) {
353
+ if (typeof temperature !== "number") {
354
+ throw new InvalidArgumentError({
355
+ parameter: "temperature",
356
+ value: temperature,
357
+ message: "temperature must be a number"
358
+ });
359
+ }
360
+ }
361
+ if (topP != null) {
362
+ if (typeof topP !== "number") {
363
+ throw new InvalidArgumentError({
364
+ parameter: "topP",
365
+ value: topP,
366
+ message: "topP must be a number"
367
+ });
368
+ }
369
+ }
370
+ if (presencePenalty != null) {
371
+ if (typeof presencePenalty !== "number") {
372
+ throw new InvalidArgumentError({
373
+ parameter: "presencePenalty",
374
+ value: presencePenalty,
375
+ message: "presencePenalty must be a number"
376
+ });
377
+ }
378
+ }
379
+ if (frequencyPenalty != null) {
380
+ if (typeof frequencyPenalty !== "number") {
381
+ throw new InvalidArgumentError({
382
+ parameter: "frequencyPenalty",
383
+ value: frequencyPenalty,
384
+ message: "frequencyPenalty must be a number"
385
+ });
386
+ }
387
+ }
388
+ if (seed != null) {
389
+ if (!Number.isInteger(seed)) {
390
+ throw new InvalidArgumentError({
391
+ parameter: "seed",
392
+ value: seed,
393
+ message: "seed must be an integer"
394
+ });
395
+ }
396
+ }
397
+ if (maxRetries != null) {
398
+ if (!Number.isInteger(maxRetries)) {
399
+ throw new InvalidArgumentError({
400
+ parameter: "maxRetries",
401
+ value: maxRetries,
402
+ message: "maxRetries must be an integer"
403
+ });
404
+ }
405
+ if (maxRetries < 0) {
406
+ throw new InvalidArgumentError({
407
+ parameter: "maxRetries",
408
+ value: maxRetries,
409
+ message: "maxRetries must be >= 0"
410
+ });
411
+ }
412
+ }
413
+ return {
414
+ maxTokens,
415
+ temperature: temperature != null ? temperature : 0,
416
+ topP,
417
+ presencePenalty,
418
+ frequencyPenalty,
419
+ seed,
420
+ maxRetries: maxRetries != null ? maxRetries : 2
421
+ };
422
+ }
423
+
424
+ // core/util/convert-zod-to-json-schema.ts
178
425
  import zodToJsonSchema from "zod-to-json-schema";
426
+ function convertZodToJSONSchema(zodSchema) {
427
+ return zodToJsonSchema(zodSchema);
428
+ }
429
+
430
+ // core/util/retry-with-exponential-backoff.ts
431
+ import { APICallError, RetryError } from "@ai-sdk/provider";
432
+ import { getErrorMessage, isAbortError } from "@ai-sdk/provider-utils";
433
+
434
+ // core/util/delay.ts
435
+ async function delay(delayInMs) {
436
+ return new Promise((resolve) => setTimeout(resolve, delayInMs));
437
+ }
438
+
439
+ // core/util/retry-with-exponential-backoff.ts
440
+ var retryWithExponentialBackoff = ({
441
+ maxRetries = 2,
442
+ initialDelayInMs = 2e3,
443
+ backoffFactor = 2
444
+ } = {}) => async (f) => _retryWithExponentialBackoff(f, {
445
+ maxRetries,
446
+ delayInMs: initialDelayInMs,
447
+ backoffFactor
448
+ });
449
+ async function _retryWithExponentialBackoff(f, {
450
+ maxRetries,
451
+ delayInMs,
452
+ backoffFactor
453
+ }, errors = []) {
454
+ try {
455
+ return await f();
456
+ } catch (error) {
457
+ if (isAbortError(error)) {
458
+ throw error;
459
+ }
460
+ if (maxRetries === 0) {
461
+ throw error;
462
+ }
463
+ const errorMessage = getErrorMessage(error);
464
+ const newErrors = [...errors, error];
465
+ const tryNumber = newErrors.length;
466
+ if (tryNumber > maxRetries) {
467
+ throw new RetryError({
468
+ message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`,
469
+ reason: "maxRetriesExceeded",
470
+ errors: newErrors
471
+ });
472
+ }
473
+ if (error instanceof Error && APICallError.isAPICallError(error) && error.isRetryable === true && tryNumber <= maxRetries) {
474
+ await delay(delayInMs);
475
+ return _retryWithExponentialBackoff(
476
+ f,
477
+ { maxRetries, delayInMs: backoffFactor * delayInMs, backoffFactor },
478
+ newErrors
479
+ );
480
+ }
481
+ if (tryNumber === 1) {
482
+ throw error;
483
+ }
484
+ throw new RetryError({
485
+ message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`,
486
+ reason: "errorNotRetryable",
487
+ errors: newErrors
488
+ });
489
+ }
490
+ }
179
491
 
180
492
  // shared/stream-parts.ts
181
493
  var textStreamPart = {
@@ -1044,7 +1356,7 @@ function render(options) {
1044
1356
  return {
1045
1357
  name,
1046
1358
  description,
1047
- parameters: zodToJsonSchema(parameters)
1359
+ parameters: zodToJsonSchema2(parameters)
1048
1360
  };
1049
1361
  }
1050
1362
  ) : void 0;
@@ -1055,7 +1367,7 @@ function render(options) {
1055
1367
  function: {
1056
1368
  name,
1057
1369
  description,
1058
- parameters: zodToJsonSchema(parameters)
1370
+ parameters: zodToJsonSchema2(parameters)
1059
1371
  }
1060
1372
  };
1061
1373
  }
@@ -1166,6 +1478,194 @@ function render(options) {
1166
1478
  return ui.value;
1167
1479
  }
1168
1480
 
1481
+ // rsc/stream-ui/stream-ui.tsx
1482
+ import {
1483
+ InvalidToolArgumentsError,
1484
+ NoSuchToolError
1485
+ } from "@ai-sdk/provider";
1486
+ import { safeParseJSON } from "@ai-sdk/provider-utils";
1487
+ var defaultTextRenderer = ({ content }) => content;
1488
+ async function experimental_streamUI({
1489
+ model,
1490
+ tools,
1491
+ system,
1492
+ prompt,
1493
+ messages,
1494
+ maxRetries,
1495
+ abortSignal,
1496
+ initial,
1497
+ text,
1498
+ ...settings
1499
+ }) {
1500
+ if (typeof model === "string") {
1501
+ throw new Error(
1502
+ "`model` cannot be a string in `experimental_streamUI`. Use the actual model instance instead."
1503
+ );
1504
+ }
1505
+ if ("functions" in settings) {
1506
+ throw new Error(
1507
+ "`functions` is not supported in `experimental_streamUI`, use `tools` instead."
1508
+ );
1509
+ }
1510
+ if ("provider" in settings) {
1511
+ throw new Error(
1512
+ "`provider` is no longer needed in `experimental_streamUI`. Use `model` instead."
1513
+ );
1514
+ }
1515
+ if (tools) {
1516
+ for (const [name, tool] of Object.entries(tools)) {
1517
+ if ("render" in tool) {
1518
+ throw new Error(
1519
+ "Tool definition in `experimental_streamUI` should not have `render` property. Use `generate` instead. Found in tool: " + name
1520
+ );
1521
+ }
1522
+ }
1523
+ }
1524
+ const ui = createStreamableUI(initial);
1525
+ const textRender = text || defaultTextRenderer;
1526
+ let finished;
1527
+ async function handleRender(args, renderer, res) {
1528
+ if (!renderer)
1529
+ return;
1530
+ const resolvable = createResolvablePromise();
1531
+ if (finished) {
1532
+ finished = finished.then(() => resolvable.promise);
1533
+ } else {
1534
+ finished = resolvable.promise;
1535
+ }
1536
+ const value = renderer(...args);
1537
+ if (value instanceof Promise || value && typeof value === "object" && "then" in value && typeof value.then === "function") {
1538
+ const node = await value;
1539
+ res.update(node);
1540
+ resolvable.resolve(void 0);
1541
+ } else if (value && typeof value === "object" && Symbol.asyncIterator in value) {
1542
+ const it = value;
1543
+ while (true) {
1544
+ const { done, value: value2 } = await it.next();
1545
+ res.update(value2);
1546
+ if (done)
1547
+ break;
1548
+ }
1549
+ resolvable.resolve(void 0);
1550
+ } else if (value && typeof value === "object" && Symbol.iterator in value) {
1551
+ const it = value;
1552
+ while (true) {
1553
+ const { done, value: value2 } = it.next();
1554
+ res.update(value2);
1555
+ if (done)
1556
+ break;
1557
+ }
1558
+ resolvable.resolve(void 0);
1559
+ } else {
1560
+ res.update(value);
1561
+ resolvable.resolve(void 0);
1562
+ }
1563
+ }
1564
+ const retry = retryWithExponentialBackoff({ maxRetries });
1565
+ const validatedPrompt = getValidatedPrompt({ system, prompt, messages });
1566
+ const result = await retry(
1567
+ () => model.doStream({
1568
+ mode: {
1569
+ type: "regular",
1570
+ tools: tools == null ? void 0 : Object.entries(tools).map(([name, tool]) => ({
1571
+ type: "function",
1572
+ name,
1573
+ description: tool.description,
1574
+ parameters: convertZodToJSONSchema(tool.parameters)
1575
+ }))
1576
+ },
1577
+ ...prepareCallSettings(settings),
1578
+ inputFormat: validatedPrompt.type,
1579
+ prompt: convertToLanguageModelPrompt(validatedPrompt),
1580
+ abortSignal
1581
+ })
1582
+ );
1583
+ const [stream, forkedStream] = result.stream.tee();
1584
+ (async () => {
1585
+ try {
1586
+ let content = "";
1587
+ let hasToolCall = false;
1588
+ const reader = forkedStream.getReader();
1589
+ while (true) {
1590
+ const { done, value } = await reader.read();
1591
+ if (done)
1592
+ break;
1593
+ switch (value.type) {
1594
+ case "text-delta": {
1595
+ content += value.textDelta;
1596
+ handleRender(
1597
+ [{ content, done: false, delta: value.textDelta }],
1598
+ textRender,
1599
+ ui
1600
+ );
1601
+ break;
1602
+ }
1603
+ case "tool-call-delta": {
1604
+ hasToolCall = true;
1605
+ break;
1606
+ }
1607
+ case "tool-call": {
1608
+ const toolName = value.toolName;
1609
+ if (!tools) {
1610
+ throw new NoSuchToolError({ toolName });
1611
+ }
1612
+ const tool = tools[toolName];
1613
+ if (!tool) {
1614
+ throw new NoSuchToolError({
1615
+ toolName,
1616
+ availableTools: Object.keys(tools)
1617
+ });
1618
+ }
1619
+ const parseResult = safeParseJSON({
1620
+ text: value.args,
1621
+ schema: tool.parameters
1622
+ });
1623
+ if (parseResult.success === false) {
1624
+ throw new InvalidToolArgumentsError({
1625
+ toolName,
1626
+ toolArgs: value.args,
1627
+ cause: parseResult.error
1628
+ });
1629
+ }
1630
+ handleRender(
1631
+ [
1632
+ parseResult.value,
1633
+ {
1634
+ toolName,
1635
+ toolCallId: value.toolCallId
1636
+ }
1637
+ ],
1638
+ tool.generate,
1639
+ ui
1640
+ );
1641
+ break;
1642
+ }
1643
+ case "error": {
1644
+ throw value.error;
1645
+ }
1646
+ case "finish": {
1647
+ }
1648
+ }
1649
+ }
1650
+ if (hasToolCall) {
1651
+ await finished;
1652
+ ui.done();
1653
+ } else {
1654
+ handleRender([{ content, done: true }], textRender, ui);
1655
+ await finished;
1656
+ ui.done();
1657
+ }
1658
+ } catch (error) {
1659
+ ui.error(error);
1660
+ }
1661
+ })();
1662
+ return {
1663
+ ...result,
1664
+ stream,
1665
+ value: ui.value
1666
+ };
1667
+ }
1668
+
1169
1669
  // rsc/provider.tsx
1170
1670
  import * as React2 from "react";
1171
1671
  import { InternalAIProvider } from "./rsc-shared.mjs";
@@ -1239,6 +1739,7 @@ export {
1239
1739
  createAI,
1240
1740
  createStreamableUI,
1241
1741
  createStreamableValue,
1742
+ experimental_streamUI,
1242
1743
  getAIState,
1243
1744
  getMutableAIState,
1244
1745
  render