ai 3.3.22 → 3.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # ai
2
2
 
3
+ ## 3.3.24
4
+
5
+ ### Patch Changes
6
+
7
+ - d87a655: fix (ai/core): provide fallback when globalThis.performance is not available
8
+
9
+ ## 3.3.23
10
+
11
+ ### Patch Changes
12
+
13
+ - b55e6f7: fix (ai/core): streamObject text stream in array mode must not include elements: prefix.
14
+
3
15
  ## 3.3.22
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1491,8 +1491,8 @@ function createAsyncIterableStream(source, transformer) {
1491
1491
  var noSchemaOutputStrategy = {
1492
1492
  type: "no-schema",
1493
1493
  jsonSchema: void 0,
1494
- validatePartialResult({ value }) {
1495
- return { success: true, value };
1494
+ validatePartialResult({ value, textDelta }) {
1495
+ return { success: true, value: { partial: value, textDelta } };
1496
1496
  },
1497
1497
  validateFinalResult(value) {
1498
1498
  return value === void 0 ? { success: false, error: new NoObjectGeneratedError() } : { success: true, value };
@@ -1506,8 +1506,15 @@ var noSchemaOutputStrategy = {
1506
1506
  var objectOutputStrategy = (schema) => ({
1507
1507
  type: "object",
1508
1508
  jsonSchema: schema.jsonSchema,
1509
- validatePartialResult({ value }) {
1510
- return { success: true, value };
1509
+ validatePartialResult({ value, textDelta }) {
1510
+ return {
1511
+ success: true,
1512
+ value: {
1513
+ // Note: currently no validation of partial results:
1514
+ partial: value,
1515
+ textDelta
1516
+ }
1517
+ };
1511
1518
  },
1512
1519
  validateFinalResult(value) {
1513
1520
  return (0, import_provider_utils5.safeValidateTypes)({ value, schema });
@@ -1521,7 +1528,7 @@ var objectOutputStrategy = (schema) => ({
1521
1528
  var arrayOutputStrategy = (schema) => {
1522
1529
  const { $schema, ...itemSchema } = schema.jsonSchema;
1523
1530
  return {
1524
- type: "object",
1531
+ type: "array",
1525
1532
  // wrap in object that contains array of elements, since most LLMs will not
1526
1533
  // be able to generate an array directly:
1527
1534
  // possible future optimization: use arrays directly when model supports grammar-guided generation
@@ -1534,10 +1541,8 @@ var arrayOutputStrategy = (schema) => {
1534
1541
  required: ["elements"],
1535
1542
  additionalProperties: false
1536
1543
  },
1537
- validatePartialResult({
1538
- value,
1539
- parseState
1540
- }) {
1544
+ validatePartialResult({ value, latestObject, isFirstDelta, isFinalDelta }) {
1545
+ var _a11;
1541
1546
  if (!(0, import_provider9.isJSONObject)(value) || !(0, import_provider9.isJSONArray)(value.elements)) {
1542
1547
  return {
1543
1548
  success: false,
@@ -1552,7 +1557,7 @@ var arrayOutputStrategy = (schema) => {
1552
1557
  for (let i = 0; i < inputArray.length; i++) {
1553
1558
  const element = inputArray[i];
1554
1559
  const result = (0, import_provider_utils5.safeValidateTypes)({ value: element, schema });
1555
- if (i === inputArray.length - 1 && (!result.success || parseState !== "successful-parse")) {
1560
+ if (i === inputArray.length - 1 && !isFinalDelta) {
1556
1561
  continue;
1557
1562
  }
1558
1563
  if (!result.success) {
@@ -1560,7 +1565,25 @@ var arrayOutputStrategy = (schema) => {
1560
1565
  }
1561
1566
  resultArray.push(result.value);
1562
1567
  }
1563
- return { success: true, value: resultArray };
1568
+ const publishedElementCount = (_a11 = latestObject == null ? void 0 : latestObject.length) != null ? _a11 : 0;
1569
+ let textDelta = "";
1570
+ if (isFirstDelta) {
1571
+ textDelta += "[";
1572
+ }
1573
+ if (publishedElementCount > 0) {
1574
+ textDelta += ",";
1575
+ }
1576
+ textDelta += resultArray.slice(publishedElementCount).map((element) => JSON.stringify(element)).join(",");
1577
+ if (isFinalDelta) {
1578
+ textDelta += "]";
1579
+ }
1580
+ return {
1581
+ success: true,
1582
+ value: {
1583
+ partial: resultArray,
1584
+ textDelta
1585
+ }
1586
+ };
1564
1587
  },
1565
1588
  validateFinalResult(value) {
1566
1589
  if (!(0, import_provider9.isJSONObject)(value) || !(0, import_provider9.isJSONArray)(value.elements)) {
@@ -2060,6 +2083,12 @@ var DelayedPromise = class {
2060
2083
  }
2061
2084
  };
2062
2085
 
2086
+ // core/util/now.ts
2087
+ function now() {
2088
+ var _a11, _b;
2089
+ return (_b = (_a11 = globalThis == null ? void 0 : globalThis.performance) == null ? void 0 : _a11.now()) != null ? _b : Date.now();
2090
+ }
2091
+
2063
2092
  // core/generate-object/stream-object.ts
2064
2093
  async function streamObject({
2065
2094
  model,
@@ -2221,7 +2250,7 @@ async function streamObject({
2221
2250
  const {
2222
2251
  result: { stream, warnings, rawResponse },
2223
2252
  doStreamSpan,
2224
- startTimestamp
2253
+ startTimestampMs
2225
2254
  } = await retry(
2226
2255
  () => recordSpan({
2227
2256
  name: "ai.streamObject.doStream",
@@ -2251,8 +2280,7 @@ async function streamObject({
2251
2280
  tracer,
2252
2281
  endWhenDone: false,
2253
2282
  fn: async (doStreamSpan2) => ({
2254
- startTimestamp: performance.now(),
2255
- // get before the call
2283
+ startTimestampMs: now(),
2256
2284
  doStreamSpan: doStreamSpan2,
2257
2285
  result: await model.doStream(callOptions)
2258
2286
  })
@@ -2267,7 +2295,7 @@ async function streamObject({
2267
2295
  rootSpan,
2268
2296
  doStreamSpan,
2269
2297
  telemetry,
2270
- startTimestamp
2298
+ startTimestampMs
2271
2299
  });
2272
2300
  }
2273
2301
  });
@@ -2282,7 +2310,7 @@ var DefaultStreamObjectResult = class {
2282
2310
  rootSpan,
2283
2311
  doStreamSpan,
2284
2312
  telemetry,
2285
- startTimestamp
2313
+ startTimestampMs
2286
2314
  }) {
2287
2315
  this.warnings = warnings;
2288
2316
  this.rawResponse = rawResponse;
@@ -2301,17 +2329,18 @@ var DefaultStreamObjectResult = class {
2301
2329
  let object;
2302
2330
  let error;
2303
2331
  let accumulatedText = "";
2304
- let delta = "";
2332
+ let textDelta = "";
2305
2333
  let latestObjectJson = void 0;
2306
2334
  let latestObject = void 0;
2307
- let firstChunk = true;
2335
+ let isFirstChunk = true;
2336
+ let isFirstDelta = true;
2308
2337
  const self = this;
2309
2338
  this.originalStream = stream.pipeThrough(
2310
2339
  new TransformStream({
2311
2340
  async transform(chunk, controller) {
2312
- if (firstChunk) {
2313
- const msToFirstChunk = performance.now() - startTimestamp;
2314
- firstChunk = false;
2341
+ if (isFirstChunk) {
2342
+ const msToFirstChunk = now() - startTimestampMs;
2343
+ isFirstChunk = false;
2315
2344
  doStreamSpan.addEvent("ai.stream.firstChunk", {
2316
2345
  "ai.stream.msToFirstChunk": msToFirstChunk
2317
2346
  });
@@ -2321,36 +2350,37 @@ var DefaultStreamObjectResult = class {
2321
2350
  }
2322
2351
  if (typeof chunk === "string") {
2323
2352
  accumulatedText += chunk;
2324
- delta += chunk;
2353
+ textDelta += chunk;
2325
2354
  const { value: currentObjectJson, state: parseState } = (0, import_ui_utils2.parsePartialJson)(accumulatedText);
2326
2355
  if (currentObjectJson !== void 0 && !(0, import_ui_utils2.isDeepEqualData)(latestObjectJson, currentObjectJson)) {
2327
2356
  const validationResult = outputStrategy.validatePartialResult({
2328
2357
  value: currentObjectJson,
2329
- parseState
2358
+ textDelta,
2359
+ latestObject,
2360
+ isFirstDelta,
2361
+ isFinalDelta: parseState === "successful-parse"
2330
2362
  });
2331
- if (validationResult.success && !(0, import_ui_utils2.isDeepEqualData)(latestObject, validationResult.value)) {
2363
+ if (validationResult.success && !(0, import_ui_utils2.isDeepEqualData)(latestObject, validationResult.value.partial)) {
2332
2364
  latestObjectJson = currentObjectJson;
2333
- latestObject = validationResult.value;
2365
+ latestObject = validationResult.value.partial;
2334
2366
  controller.enqueue({
2335
2367
  type: "object",
2336
2368
  object: latestObject
2337
2369
  });
2338
2370
  controller.enqueue({
2339
2371
  type: "text-delta",
2340
- textDelta: delta
2372
+ textDelta: validationResult.value.textDelta
2341
2373
  });
2342
- delta = "";
2374
+ textDelta = "";
2375
+ isFirstDelta = false;
2343
2376
  }
2344
2377
  }
2345
2378
  return;
2346
2379
  }
2347
2380
  switch (chunk.type) {
2348
2381
  case "finish": {
2349
- if (delta !== "") {
2350
- controller.enqueue({
2351
- type: "text-delta",
2352
- textDelta: delta
2353
- });
2382
+ if (textDelta !== "") {
2383
+ controller.enqueue({ type: "text-delta", textDelta });
2354
2384
  }
2355
2385
  finishReason = chunk.finishReason;
2356
2386
  usage = calculateCompletionTokenUsage(chunk.usage);
@@ -3367,7 +3397,7 @@ async function streamText({
3367
3397
  const {
3368
3398
  result: { stream: stream2, warnings: warnings2, rawResponse: rawResponse2 },
3369
3399
  doStreamSpan: doStreamSpan2,
3370
- startTimestamp: startTimestamp2
3400
+ startTimestampMs: startTimestampMs2
3371
3401
  } = await retry(
3372
3402
  () => recordSpan({
3373
3403
  name: "ai.streamText.doStream",
@@ -3396,7 +3426,7 @@ async function streamText({
3396
3426
  tracer,
3397
3427
  endWhenDone: false,
3398
3428
  fn: async (doStreamSpan3) => ({
3399
- startTimestamp: performance.now(),
3429
+ startTimestampMs: now(),
3400
3430
  // get before the call
3401
3431
  doStreamSpan: doStreamSpan3,
3402
3432
  result: await model.doStream({
@@ -3426,7 +3456,7 @@ async function streamText({
3426
3456
  rawResponse: rawResponse2
3427
3457
  },
3428
3458
  doStreamSpan: doStreamSpan2,
3429
- startTimestamp: startTimestamp2
3459
+ startTimestampMs: startTimestampMs2
3430
3460
  };
3431
3461
  };
3432
3462
  const promptMessages = await convertToLanguageModelPrompt({
@@ -3436,7 +3466,7 @@ async function streamText({
3436
3466
  const {
3437
3467
  result: { stream, warnings, rawResponse },
3438
3468
  doStreamSpan,
3439
- startTimestamp
3469
+ startTimestampMs
3440
3470
  } = await startRoundtrip({
3441
3471
  promptType: validatePrompt({ system, prompt, messages }).type,
3442
3472
  promptMessages
@@ -3450,7 +3480,7 @@ async function streamText({
3450
3480
  rootSpan,
3451
3481
  doStreamSpan,
3452
3482
  telemetry,
3453
- startTimestamp,
3483
+ startTimestampMs,
3454
3484
  maxToolRoundtrips,
3455
3485
  startRoundtrip,
3456
3486
  promptMessages
@@ -3468,7 +3498,7 @@ var DefaultStreamTextResult = class {
3468
3498
  rootSpan,
3469
3499
  doStreamSpan,
3470
3500
  telemetry,
3471
- startTimestamp,
3501
+ startTimestampMs,
3472
3502
  maxToolRoundtrips,
3473
3503
  startRoundtrip,
3474
3504
  promptMessages
@@ -3499,7 +3529,7 @@ var DefaultStreamTextResult = class {
3499
3529
  const self = this;
3500
3530
  function addRoundtripStream({
3501
3531
  stream: stream2,
3502
- startTimestamp: startTimestamp2,
3532
+ startTimestamp,
3503
3533
  doStreamSpan: doStreamSpan2,
3504
3534
  currentToolRoundtrip,
3505
3535
  promptMessages: promptMessages2,
@@ -3526,7 +3556,7 @@ var DefaultStreamTextResult = class {
3526
3556
  new TransformStream({
3527
3557
  async transform(chunk, controller) {
3528
3558
  if (roundtripFirstChunk) {
3529
- const msToFirstChunk = performance.now() - startTimestamp2;
3559
+ const msToFirstChunk = now() - startTimestamp;
3530
3560
  roundtripFirstChunk = false;
3531
3561
  doStreamSpan2.addEvent("ai.stream.firstChunk", {
3532
3562
  "ai.stream.msToFirstChunk": msToFirstChunk
@@ -3630,7 +3660,11 @@ var DefaultStreamTextResult = class {
3630
3660
  (message) => convertToLanguageModelMessage(message, null)
3631
3661
  )
3632
3662
  );
3633
- const { result, doStreamSpan: doStreamSpan3, startTimestamp: startTimestamp3 } = await startRoundtrip({
3663
+ const {
3664
+ result,
3665
+ doStreamSpan: doStreamSpan3,
3666
+ startTimestampMs: startTimestamp2
3667
+ } = await startRoundtrip({
3634
3668
  promptType: "messages",
3635
3669
  promptMessages: promptMessages2
3636
3670
  });
@@ -3638,7 +3672,7 @@ var DefaultStreamTextResult = class {
3638
3672
  self.rawResponse = result.rawResponse;
3639
3673
  addRoundtripStream({
3640
3674
  stream: result.stream,
3641
- startTimestamp: startTimestamp3,
3675
+ startTimestamp: startTimestamp2,
3642
3676
  doStreamSpan: doStreamSpan3,
3643
3677
  currentToolRoundtrip: currentToolRoundtrip + 1,
3644
3678
  promptMessages: promptMessages2,
@@ -3701,7 +3735,7 @@ var DefaultStreamTextResult = class {
3701
3735
  }
3702
3736
  addRoundtripStream({
3703
3737
  stream,
3704
- startTimestamp,
3738
+ startTimestamp: startTimestampMs,
3705
3739
  doStreamSpan,
3706
3740
  currentToolRoundtrip: 0,
3707
3741
  promptMessages,