ai 7.0.26 → 7.0.27

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,16 @@
1
1
  # ai
2
2
 
3
+ ## 7.0.27
4
+
5
+ ### Patch Changes
6
+
7
+ - ac01b79: Allow validating assistant UI messages with empty parts so persisted errored responses remain loadable.
8
+ - 2696562: `experimental_streamTranscribe` result promises now resolve without consuming `fullStream`: accessing any result promise consumes the stream internally. Previously `await result.text` alone deadlocked on transform backpressure. Because live transcription streams can be unbounded, `fullStream` is explicitly single-consumer (no replay buffering): access it once, before any result promise, when both stream parts and final results are needed.
9
+ - Updated dependencies [31c7be8]
10
+ - Updated dependencies [4d096f6]
11
+ - @ai-sdk/provider-utils@5.0.10
12
+ - @ai-sdk/gateway@4.0.20
13
+
3
14
  ## 7.0.26
4
15
 
5
16
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -8840,6 +8840,11 @@ interface StreamTranscriptionResult {
8840
8840
  readonly providerMetadata: PromiseLike<Record<string, JSONObject>>;
8841
8841
  /**
8842
8842
  * Full stream of transcription parts.
8843
+ *
8844
+ * This is a single-consumer live stream and can only be accessed once.
8845
+ * Access it before any result promise when both stream parts and final
8846
+ * results are needed; accessing a result promise first consumes the stream
8847
+ * internally and makes `fullStream` unavailable.
8843
8848
  */
8844
8849
  readonly fullStream: AsyncIterableStream<TranscriptionStreamPart>;
8845
8850
  }
package/dist/index.js CHANGED
@@ -1089,7 +1089,7 @@ import {
1089
1089
  } from "@ai-sdk/provider-utils";
1090
1090
 
1091
1091
  // src/version.ts
1092
- var VERSION = true ? "7.0.26" : "0.0.0-test";
1092
+ var VERSION = true ? "7.0.27" : "0.0.0-test";
1093
1093
 
1094
1094
  // src/util/download/download.ts
1095
1095
  var download = async ({
@@ -10891,7 +10891,19 @@ var uiMessagesSchema = lazySchema2(
10891
10891
  })
10892
10892
  })
10893
10893
  ])
10894
- ).nonempty("Message must contain at least one part")
10894
+ )
10895
+ }).superRefine((message, context) => {
10896
+ if (message.role !== "assistant" && message.parts.length === 0) {
10897
+ context.addIssue({
10898
+ origin: "array",
10899
+ code: "too_small",
10900
+ minimum: 1,
10901
+ inclusive: true,
10902
+ input: message.parts,
10903
+ path: ["parts"],
10904
+ message: "Message must contain at least one part"
10905
+ });
10906
+ }
10895
10907
  })
10896
10908
  ).nonempty("Messages array must not be empty")
10897
10909
  )
@@ -16089,35 +16101,60 @@ function streamTranscribe({
16089
16101
  transform.writable.abort(reason).catch(() => {
16090
16102
  });
16091
16103
  });
16104
+ let streamOwner = "unclaimed";
16105
+ function consumeStream2() {
16106
+ if (streamOwner === "full-stream" || streamOwner === "result-promises") {
16107
+ return;
16108
+ }
16109
+ streamOwner = "result-promises";
16110
+ const reader = transform.readable.getReader();
16111
+ void (async () => {
16112
+ while (!(await reader.read()).done) {
16113
+ }
16114
+ })().catch(() => {
16115
+ });
16116
+ }
16117
+ function getFullStream() {
16118
+ if (streamOwner !== "unclaimed") {
16119
+ throw new Error(
16120
+ streamOwner === "full-stream" ? "fullStream can only be accessed once." : "fullStream cannot be accessed after a result promise."
16121
+ );
16122
+ }
16123
+ streamOwner = "full-stream";
16124
+ return asAsyncIterableStream(transform.readable);
16125
+ }
16092
16126
  return {
16093
16127
  get text() {
16128
+ consumeStream2();
16094
16129
  return textPromise.promise;
16095
16130
  },
16096
16131
  get segments() {
16132
+ consumeStream2();
16097
16133
  return segmentsPromise.promise;
16098
16134
  },
16099
16135
  get language() {
16136
+ consumeStream2();
16100
16137
  return languagePromise.promise;
16101
16138
  },
16102
16139
  get durationInSeconds() {
16140
+ consumeStream2();
16103
16141
  return durationInSecondsPromise.promise;
16104
16142
  },
16105
16143
  get warnings() {
16144
+ consumeStream2();
16106
16145
  return warningsPromise.promise;
16107
16146
  },
16108
16147
  get responses() {
16148
+ consumeStream2();
16109
16149
  return responsesPromise.promise;
16110
16150
  },
16111
16151
  get providerMetadata() {
16152
+ consumeStream2();
16112
16153
  return providerMetadataPromise.promise;
16113
16154
  },
16114
- // `transform.readable` is fresh and exclusively owned here, so attach the
16115
- // async iterator in place rather than piping through another transform.
16116
- // The extra transform (as `createAsyncIterableStream` would add) chains two
16117
- // transforms fed by the active model pipe below and surfaces a spurious
16118
- // unhandled `undefined` rejection when the consumer cancels early on
16119
- // Node.js 26.
16120
- fullStream: asAsyncIterableStream(transform.readable)
16155
+ get fullStream() {
16156
+ return getFullStream();
16157
+ }
16121
16158
  };
16122
16159
  }
16123
16160