ai 7.0.142 → 7.0.144

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.
@@ -1,4 +1,5 @@
1
1
  import {
2
+ AISDKError,
2
3
  getErrorMessage,
3
4
  UnsupportedFunctionalityError,
4
5
  type LanguageModelV4,
@@ -44,6 +45,7 @@ import { standardizePrompt } from '../prompt/standardize-prompt';
44
45
  import { wrapGatewayError } from '../prompt/wrap-gateway-error';
45
46
  import type { TelemetryDispatcher } from '../telemetry/telemetry';
46
47
  import type { TelemetryOptions } from '../telemetry/telemetry-options';
48
+ import { getGlobalTelemetryIntegrations } from '../telemetry/telemetry-registry';
47
49
  import { createTextStreamResponse } from '../text-stream/create-text-stream-response';
48
50
  import { pipeTextStreamToResponse } from '../text-stream/pipe-text-stream-to-response';
49
51
  import { toTextStream } from '../text-stream/to-text-stream';
@@ -68,6 +70,7 @@ import { toUIMessageStream as toUIMessageStreamHelper } from '../ui-message-stre
68
70
  import type { InferUIMessageChunk } from '../ui-message-stream/ui-message-chunks';
69
71
  import type { UIMessageStreamResponseInit } from '../ui-message-stream/ui-message-stream-response-init';
70
72
  import {
73
+ asAsyncIterableStream,
71
74
  createAsyncIterableStream,
72
75
  type AsyncIterableStream,
73
76
  } from '../util/async-iterable-stream';
@@ -111,6 +114,10 @@ import type {
111
114
  OnLanguageModelCallStartCallback,
112
115
  } from './language-model-events';
113
116
  import { text, type Output } from './output';
117
+ import {
118
+ createSingleConsumerStreamTextResult,
119
+ type StreamTextSingleConsumerResult,
120
+ } from './stream-text-single-consumer-result';
114
121
  import type {
115
122
  InferCompleteOutput,
116
123
  InferElementOutput,
@@ -171,6 +178,14 @@ import {
171
178
  prepareToolCallConcurrency,
172
179
  } from './tool-call-concurrency';
173
180
 
181
+ /** Internal policy, fixed before the model request starts. */
182
+ type StreamTextRetention = {
183
+ /** Keep a replay branch for independently consumed stream projections. */
184
+ replay: boolean;
185
+ /** Collect complete content for results, callbacks, or subsequent steps. */
186
+ collectContent: boolean;
187
+ };
188
+
174
189
  const originalGenerateId = createIdGenerator({
175
190
  prefix: 'aitxt',
176
191
  size: 24,
@@ -284,6 +299,12 @@ export type StreamTextOnAbortCallback<
284
299
  RUNTIME_CONTEXT extends Context,
285
300
  > = Callback<GenerateTextAbortEvent<TOOLS, RUNTIME_CONTEXT>>;
286
301
 
302
+ type StreamTextOptions<
303
+ TOOLS extends ToolSet,
304
+ RUNTIME_CONTEXT extends Context,
305
+ OUTPUT extends Output,
306
+ > = Parameters<typeof streamTextInternal<TOOLS, RUNTIME_CONTEXT, OUTPUT>>[0];
307
+
287
308
  /**
288
309
  * Generate a text and call tools for a given prompt using a language model.
289
310
  *
@@ -356,6 +377,60 @@ export function streamText<
356
377
  TOOLS extends ToolSet,
357
378
  RUNTIME_CONTEXT extends Context = Context,
358
379
  OUTPUT extends Output = Output<string, string, never>,
380
+ >(
381
+ options: StreamTextOptions<TOOLS, RUNTIME_CONTEXT, OUTPUT>,
382
+ ): StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT> {
383
+ return streamTextInternal<TOOLS, RUNTIME_CONTEXT, OUTPUT>(options);
384
+ }
385
+
386
+ /**
387
+ * Stream text with a single consumer, without replay or final-content getters.
388
+ * Accepts the same options as streamText and uses the same execution engine.
389
+ */
390
+ export function streamTextLowMemory<
391
+ TOOLS extends ToolSet,
392
+ RUNTIME_CONTEXT extends Context = Context,
393
+ OUTPUT extends Output = Output<string, string, never>,
394
+ >(
395
+ options: StreamTextOptions<TOOLS, RUNTIME_CONTEXT, OUTPUT>,
396
+ ): StreamTextSingleConsumerResult<TOOLS, RUNTIME_CONTEXT, OUTPUT> {
397
+ const telemetry = options.telemetry ?? options.experimental_telemetry;
398
+ const integrations =
399
+ telemetry?.integrations != null
400
+ ? asArray(telemetry.integrations)
401
+ : getGlobalTelemetryIntegrations();
402
+
403
+ // Decide before execution so getter access cannot change collection.
404
+ const collectContent =
405
+ (options.tools != null && Object.keys(options.tools).length > 0) ||
406
+ options.toolChoice != null ||
407
+ options.output != null ||
408
+ options.prepareStep != null ||
409
+ options.stopWhen != null ||
410
+ options.onEnd != null ||
411
+ options.onFinish != null ||
412
+ options.onStepEnd != null ||
413
+ options.onStepFinish != null ||
414
+ options.onAbort != null ||
415
+ options.onLanguageModelCallEnd != null ||
416
+ options.experimental_onLanguageModelCallEnd != null ||
417
+ (telemetry?.isEnabled !== false && integrations.length > 0);
418
+
419
+ return createSingleConsumerStreamTextResult(
420
+ streamTextInternal<TOOLS, RUNTIME_CONTEXT, OUTPUT>({
421
+ ...options,
422
+ _internal: {
423
+ ...options._internal,
424
+ retention: { replay: false, collectContent },
425
+ },
426
+ }),
427
+ );
428
+ }
429
+
430
+ function streamTextInternal<
431
+ TOOLS extends ToolSet,
432
+ RUNTIME_CONTEXT extends Context = Context,
433
+ OUTPUT extends Output = Output<string, string, never>,
359
434
  >({
360
435
  model,
361
436
  tools,
@@ -416,6 +491,7 @@ export function streamText<
416
491
  now = originalNow,
417
492
  generateId = originalGenerateId,
418
493
  generateCallId = originalGenerateCallId,
494
+ retention = { replay: true, collectContent: true },
419
495
  } = {},
420
496
  ...settings
421
497
  }: LanguageModelCallOptions &
@@ -781,6 +857,8 @@ export function streamText<
781
857
  now?: () => number;
782
858
  generateId?: IdGenerator;
783
859
  generateCallId?: IdGenerator;
860
+ /** Internal policy used by the streaming-only facade. */
861
+ retention?: StreamTextRetention;
784
862
  };
785
863
  }): StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT> {
786
864
  const resolvedToolCallConcurrency =
@@ -812,6 +890,7 @@ export function streamText<
812
890
  onToolExecutionEnd ?? experimental_onToolCallFinish;
813
891
  const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
814
892
  return new DefaultStreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>({
893
+ retention,
815
894
  model: resolveLanguageModel(model),
816
895
  telemetry,
817
896
  headers,
@@ -922,6 +1001,7 @@ function createOutputTransformStream<
922
1001
  OUTPUT extends Output,
923
1002
  >(
924
1003
  output: OUTPUT,
1004
+ collectOutput = true,
925
1005
  ): TransformStream<
926
1006
  InternalTextStreamPart<TOOLS>,
927
1007
  InternalEnrichedStreamPart<TOOLS, InferPartialOutput<OUTPUT>>
@@ -983,6 +1063,14 @@ function createOutputTransformStream<
983
1063
  InternalEnrichedStreamPart<TOOLS, InferPartialOutput<OUTPUT>>
984
1064
  >({
985
1065
  async transform(chunk, controller) {
1066
+ if (!collectOutput) {
1067
+ controller.enqueue(
1068
+ isStreamRetryBoundaryPart(chunk)
1069
+ ? chunk
1070
+ : { part: chunk, partialOutput: undefined },
1071
+ );
1072
+ return;
1073
+ }
986
1074
  if (isStreamRetryBoundaryPart(chunk)) {
987
1075
  resetOutputState();
988
1076
  controller.enqueue(chunk);
@@ -1204,7 +1292,11 @@ class DefaultStreamTextResult<
1204
1292
 
1205
1293
  private tools: TOOLS | undefined;
1206
1294
 
1295
+ private readonly retention: StreamTextRetention;
1296
+ private streamClaimed = false;
1297
+
1207
1298
  constructor({
1299
+ retention,
1208
1300
  model,
1209
1301
  telemetry,
1210
1302
  headers,
@@ -1260,6 +1352,7 @@ class DefaultStreamTextResult<
1260
1352
  download,
1261
1353
  include,
1262
1354
  }: {
1355
+ retention: StreamTextRetention;
1263
1356
  model: LanguageModelV4;
1264
1357
  telemetry: TelemetryOptions<RUNTIME_CONTEXT, TOOLS> | undefined;
1265
1358
  headers: Record<string, string | undefined> | undefined;
@@ -1348,6 +1441,7 @@ class DefaultStreamTextResult<
1348
1441
  onToolExecutionStart: undefined | OnToolExecutionStartCallback<TOOLS>;
1349
1442
  onToolExecutionEnd: undefined | OnToolExecutionEndCallback<TOOLS>;
1350
1443
  }) {
1444
+ this.retention = retention;
1351
1445
  this.outputSpecification = output;
1352
1446
  this.tools = tools;
1353
1447
  const resolvedToolCallers = resolveToolCallerConfiguration({
@@ -1381,7 +1475,7 @@ class DefaultStreamTextResult<
1381
1475
  let recordedRequest: Omit<LanguageModelRequestMetadata, 'messages'> = {};
1382
1476
  let recordedRequestMessages: Array<ModelMessage> = [];
1383
1477
  let recordedWarnings: Array<CallWarning> = [];
1384
- const recordedSteps: StepResult<TOOLS, RUNTIME_CONTEXT>[] = [];
1478
+ let recordedSteps: StepResult<TOOLS, RUNTIME_CONTEXT>[] = [];
1385
1479
  const initialResponseMessages: Array<ResponseMessage> = [];
1386
1480
  let stepMessagesForNextStep: Array<ModelMessage> | undefined;
1387
1481
  let currentStepMessages: Array<ModelMessage> = [];
@@ -1499,7 +1593,7 @@ class DefaultStreamTextResult<
1499
1593
  part.type === 'tool-approval-response' ||
1500
1594
  part.type === 'tool-error'
1501
1595
  ) {
1502
- recordedContent.push(part);
1596
+ if (retention.collectContent) recordedContent.push(part);
1503
1597
  }
1504
1598
 
1505
1599
  if (part.type === 'text-start') {
@@ -1509,7 +1603,8 @@ class DefaultStreamTextResult<
1509
1603
  providerMetadata: part.providerMetadata,
1510
1604
  };
1511
1605
 
1512
- recordedContent.push(activeTextContent[part.id]);
1606
+ if (retention.collectContent)
1607
+ recordedContent.push(activeTextContent[part.id]);
1513
1608
  }
1514
1609
 
1515
1610
  if (part.type === 'text-delta') {
@@ -1526,7 +1621,7 @@ class DefaultStreamTextResult<
1526
1621
  return;
1527
1622
  }
1528
1623
 
1529
- activeText.text += part.text;
1624
+ if (retention.collectContent) activeText.text += part.text;
1530
1625
  activeText.providerMetadata =
1531
1626
  part.providerMetadata ?? activeText.providerMetadata;
1532
1627
  }
@@ -1562,7 +1657,8 @@ class DefaultStreamTextResult<
1562
1657
  providerMetadata: part.providerMetadata,
1563
1658
  };
1564
1659
 
1565
- recordedContent.push(activeReasoningContent[part.id]);
1660
+ if (retention.collectContent)
1661
+ recordedContent.push(activeReasoningContent[part.id]);
1566
1662
  }
1567
1663
 
1568
1664
  if (part.type === 'reasoning-delta') {
@@ -1579,7 +1675,7 @@ class DefaultStreamTextResult<
1579
1675
  return;
1580
1676
  }
1581
1677
 
1582
- activeReasoning.text += part.text;
1678
+ if (retention.collectContent) activeReasoning.text += part.text;
1583
1679
  activeReasoning.providerMetadata =
1584
1680
  part.providerMetadata ?? activeReasoning.providerMetadata;
1585
1681
  }
@@ -1605,17 +1701,18 @@ class DefaultStreamTextResult<
1605
1701
  }
1606
1702
 
1607
1703
  if (part.type === 'file' || part.type === 'reasoning-file') {
1608
- recordedContent.push({
1609
- type: part.type,
1610
- file: part.file,
1611
- ...(part.providerMetadata != null
1612
- ? { providerMetadata: part.providerMetadata }
1613
- : {}),
1614
- });
1704
+ if (retention.collectContent)
1705
+ recordedContent.push({
1706
+ type: part.type,
1707
+ file: part.file,
1708
+ ...(part.providerMetadata != null
1709
+ ? { providerMetadata: part.providerMetadata }
1710
+ : {}),
1711
+ });
1615
1712
  }
1616
1713
 
1617
1714
  if (part.type === 'tool-result' && !part.preliminary) {
1618
- recordedContent.push(part);
1715
+ if (retention.collectContent) recordedContent.push(part);
1619
1716
  }
1620
1717
 
1621
1718
  if (part.type === 'start-step') {
@@ -1719,7 +1816,7 @@ class DefaultStreamTextResult<
1719
1816
  self._totalUsage.resolve(totalUsage);
1720
1817
 
1721
1818
  // aggregate results:
1722
- self._steps.resolve(recordedSteps);
1819
+ self._steps.resolve(retention.replay ? recordedSteps : []);
1723
1820
 
1724
1821
  if (isAborted) {
1725
1822
  return;
@@ -1752,7 +1849,11 @@ class DefaultStreamTextResult<
1752
1849
  const parsedOutput =
1753
1850
  output == null
1754
1851
  ? undefined
1755
- : await self.getOutputPromise().catch(() => undefined);
1852
+ : await (
1853
+ retention.replay
1854
+ ? self.getOutputPromise()
1855
+ : self.parseOutput(finalStep)
1856
+ ).catch(() => undefined);
1756
1857
 
1757
1858
  await onEnd({
1758
1859
  ...event,
@@ -1806,6 +1907,17 @@ class DefaultStreamTextResult<
1806
1907
  ]);
1807
1908
  } catch (error) {
1808
1909
  controller.error(error);
1910
+ } finally {
1911
+ if (!retention.replay) {
1912
+ // Replace our references; never mutate arrays delivered to callbacks.
1913
+ recordedSteps = [];
1914
+ recordedContent = [];
1915
+ recordedRequestMessages = [];
1916
+ currentStepMessages = [];
1917
+ stepMessagesForNextStep = undefined;
1918
+ activeTextContent = createIdMap();
1919
+ activeReasoningContent = createIdMap();
1920
+ }
1809
1921
  }
1810
1922
  },
1811
1923
  });
@@ -1924,7 +2036,12 @@ class DefaultStreamTextResult<
1924
2036
  });
1925
2037
 
1926
2038
  this.baseStream = stream
1927
- .pipeThrough(createOutputTransformStream(output ?? text()))
2039
+ .pipeThrough(
2040
+ createOutputTransformStream(
2041
+ output ?? text(),
2042
+ retention.replay || output != null,
2043
+ ),
2044
+ )
1928
2045
  .pipeThrough(eventProcessor);
1929
2046
 
1930
2047
  const { maxRetries } = prepareRetries({
@@ -2474,6 +2591,7 @@ class DefaultStreamTextResult<
2474
2591
  },
2475
2592
  _internal: {
2476
2593
  now,
2594
+ collectContent: retention.collectContent,
2477
2595
  },
2478
2596
  ...stepCallSettings,
2479
2597
  }),
@@ -3179,7 +3297,7 @@ class DefaultStreamTextResult<
3179
3297
  get steps() {
3180
3298
  // when any of the promises are accessed, the stream is consumed
3181
3299
  // so it resolves without needing to consume the stream separately
3182
- this.consumeStream();
3300
+ if (this.retention.replay) this.consumeStream();
3183
3301
 
3184
3302
  return this._steps.promise;
3185
3303
  }
@@ -3279,7 +3397,7 @@ class DefaultStreamTextResult<
3279
3397
  get totalUsage() {
3280
3398
  // when any of the promises are accessed, the stream is consumed
3281
3399
  // so it resolves without needing to consume the stream separately
3282
- this.consumeStream();
3400
+ if (this.retention.replay) this.consumeStream();
3283
3401
 
3284
3402
  return this._totalUsage.promise;
3285
3403
  }
@@ -3287,7 +3405,7 @@ class DefaultStreamTextResult<
3287
3405
  get finishReason() {
3288
3406
  // when any of the promises are accessed, the stream is consumed
3289
3407
  // so it resolves without needing to consume the stream separately
3290
- this.consumeStream();
3408
+ if (this.retention.replay) this.consumeStream();
3291
3409
 
3292
3410
  return this._finishReason.promise;
3293
3411
  }
@@ -3295,7 +3413,7 @@ class DefaultStreamTextResult<
3295
3413
  get rawFinishReason() {
3296
3414
  // when any of the promises are accessed, the stream is consumed
3297
3415
  // so it resolves without needing to consume the stream separately
3298
- this.consumeStream();
3416
+ if (this.retention.replay) this.consumeStream();
3299
3417
 
3300
3418
  return this._rawFinishReason.promise;
3301
3419
  }
@@ -3309,17 +3427,69 @@ class DefaultStreamTextResult<
3309
3427
  * However, the LLM results are expected to be small enough to not cause issues.
3310
3428
  */
3311
3429
  private teeStream() {
3430
+ if (!this.retention.replay) {
3431
+ if (this.streamClaimed) {
3432
+ throw new AISDKError({
3433
+ name: 'AI_StreamAlreadyConsumedError',
3434
+ message:
3435
+ 'This result supports one stream consumer. Choose one stream projection or response helper.',
3436
+ });
3437
+ }
3438
+ this.streamClaimed = true;
3439
+ const reader = this.baseStream.getReader();
3440
+ const rejectResults = (error: unknown) =>
3441
+ this.rejectResultPromises(error);
3442
+ return new ReadableStream(
3443
+ {
3444
+ async pull(controller) {
3445
+ try {
3446
+ const { done, value } = await reader.read();
3447
+ if (done) {
3448
+ reader.releaseLock();
3449
+ controller.close();
3450
+ } else {
3451
+ controller.enqueue(value);
3452
+ }
3453
+ } catch (error) {
3454
+ rejectResults(error);
3455
+ reader.releaseLock();
3456
+ controller.error(error);
3457
+ }
3458
+ },
3459
+ async cancel(reason) {
3460
+ rejectResults(
3461
+ reason ??
3462
+ new DOMException('The stream was cancelled.', 'AbortError'),
3463
+ );
3464
+ try {
3465
+ await reader.cancel(reason);
3466
+ } finally {
3467
+ reader.releaseLock();
3468
+ }
3469
+ },
3470
+ },
3471
+ { highWaterMark: 0 },
3472
+ );
3473
+ }
3312
3474
  const [stream1, stream2] = this.baseStream.tee();
3313
3475
  this.baseStream = stream2;
3314
3476
  return stream1;
3315
3477
  }
3316
3478
 
3317
3479
  get textStream(): AsyncIterableStream<string> {
3318
- return createAsyncIterableStream(toTextStream({ stream: this.stream }));
3480
+ return this.asIterableStream(toTextStream({ stream: this.stream }));
3481
+ }
3482
+
3483
+ private asIterableStream<T>(
3484
+ stream: ReadableStream<T>,
3485
+ ): AsyncIterableStream<T> {
3486
+ return this.retention.replay
3487
+ ? createAsyncIterableStream(stream)
3488
+ : asAsyncIterableStream(stream);
3319
3489
  }
3320
3490
 
3321
3491
  get stream(): AsyncIterableStream<TextStreamPart<TOOLS>> {
3322
- return createAsyncIterableStream(
3492
+ return this.asIterableStream(
3323
3493
  this.teeStream().pipeThrough(
3324
3494
  new TransformStream<
3325
3495
  EnrichedStreamPart<TOOLS, InferPartialOutput<OUTPUT>>,
@@ -3362,9 +3532,11 @@ class DefaultStreamTextResult<
3362
3532
  }
3363
3533
 
3364
3534
  async consumeStream(options?: ConsumeStreamOptions): Promise<void> {
3535
+ // A second consumer must not reject the first consumer's result promises.
3536
+ const stream = this.stream;
3365
3537
  try {
3366
3538
  await consumeStream({
3367
- stream: this.stream,
3539
+ stream,
3368
3540
  onError: error => {
3369
3541
  this.rejectResultPromises(error);
3370
3542
  options?.onError?.(error);
@@ -3383,7 +3555,13 @@ class DefaultStreamTextResult<
3383
3555
  }
3384
3556
 
3385
3557
  get partialOutputStream(): AsyncIterableStream<InferPartialOutput<OUTPUT>> {
3386
- return createAsyncIterableStream(
3558
+ if (!this.retention.replay && this.outputSpecification == null) {
3559
+ throw new UnsupportedFunctionalityError({
3560
+ functionality:
3561
+ 'partialOutputStream without an explicit output specification with experimental_streamTextLowMemory',
3562
+ });
3563
+ }
3564
+ return this.asIterableStream(
3387
3565
  this.teeStream().pipeThrough(
3388
3566
  new TransformStream<
3389
3567
  EnrichedStreamPart<TOOLS, InferPartialOutput<OUTPUT>>,
@@ -3410,27 +3588,31 @@ class DefaultStreamTextResult<
3410
3588
  });
3411
3589
  }
3412
3590
 
3413
- return createAsyncIterableStream(this.teeStream().pipeThrough(transform));
3591
+ return this.asIterableStream(this.teeStream().pipeThrough(transform));
3414
3592
  }
3415
3593
 
3416
3594
  private getOutputPromise(): Promise<InferCompleteOutput<OUTPUT>> {
3417
3595
  if (this.outputPromise == null) {
3418
- this.outputPromise = this.finalStep.then(step => {
3419
- const output = this.outputSpecification ?? text();
3420
- return output.parseCompleteOutput(
3421
- { text: step.text },
3422
- {
3423
- response: step.response,
3424
- usage: step.usage,
3425
- finishReason: step.finishReason,
3426
- },
3427
- );
3428
- });
3596
+ this.outputPromise = this.finalStep.then(step => this.parseOutput(step));
3429
3597
  }
3430
3598
 
3431
3599
  return this.outputPromise;
3432
3600
  }
3433
3601
 
3602
+ private parseOutput(
3603
+ step: StepResult<TOOLS, RUNTIME_CONTEXT>,
3604
+ ): Promise<InferCompleteOutput<OUTPUT>> {
3605
+ const output = this.outputSpecification ?? text();
3606
+ return output.parseCompleteOutput(
3607
+ { text: step.text },
3608
+ {
3609
+ response: step.response,
3610
+ usage: step.usage,
3611
+ finishReason: step.finishReason,
3612
+ },
3613
+ );
3614
+ }
3615
+
3434
3616
  get output(): Promise<InferCompleteOutput<OUTPUT>> {
3435
3617
  return this.getOutputPromise();
3436
3618
  }
package/src/ui/chat.ts CHANGED
@@ -196,7 +196,7 @@ export type ChatOnFinishCallback<UI_MESSAGE extends UIMessage> = (options: {
196
196
  export interface ChatInit<UI_MESSAGE extends UIMessage> {
197
197
  /**
198
198
  * A unique identifier for the chat. If not provided, a random one will be
199
- * generated.
199
+ * generated when first accessed.
200
200
  */
201
201
  id?: string;
202
202
 
@@ -249,7 +249,12 @@ export interface ChatInit<UI_MESSAGE extends UIMessage> {
249
249
  }
250
250
 
251
251
  export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
252
- readonly id: string;
252
+ private _id: string | undefined;
253
+
254
+ get id(): string {
255
+ return (this._id ??= this.generateId());
256
+ }
257
+
253
258
  readonly generateId: IdGenerator;
254
259
 
255
260
  protected state: ChatState<UI_MESSAGE>;
@@ -280,7 +285,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
280
285
 
281
286
  constructor({
282
287
  generateId = generateIdFunc,
283
- id = generateId(),
288
+ id,
284
289
  transport = new DefaultChatTransport(),
285
290
  messageMetadataSchema,
286
291
  dataPartSchemas,
@@ -293,7 +298,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
293
298
  }: Omit<ChatInit<UI_MESSAGE>, 'messages'> & {
294
299
  state: ChatState<UI_MESSAGE>;
295
300
  }) {
296
- this.id = id;
301
+ this._id = id;
297
302
  this.transport = transport;
298
303
  this.generateId = generateId;
299
304
  this.messageMetadataSchema = messageMetadataSchema;