🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

ai

Package Overview
Dependencies
Maintainers
5
Versions
1355
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ai - npm Package Compare versions

Comparing version
7.0.26
to
7.0.27
+3
-3
package.json
{
"name": "ai",
"version": "7.0.26",
"version": "7.0.27",
"type": "module",

@@ -45,5 +45,5 @@ "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",

"dependencies": {
"@ai-sdk/gateway": "4.0.19",
"@ai-sdk/gateway": "4.0.20",
"@ai-sdk/provider": "4.0.3",
"@ai-sdk/provider-utils": "5.0.9"
"@ai-sdk/provider-utils": "5.0.10"
},

@@ -50,0 +50,0 @@ "devDependencies": {

@@ -84,4 +84,9 @@ import type { JSONObject, SharedV4ProviderMetadata } from '@ai-sdk/provider';

* Full stream of transcription parts.
*
* This is a single-consumer live stream and can only be accessed once.
* Access it before any result promise when both stream parts and final
* results are needed; accessing a result promise first consumes the stream
* internally and makes `fullStream` unavailable.
*/
readonly fullStream: AsyncIterableStream<TranscriptionStreamPart>;
}

@@ -288,32 +288,71 @@ import {

// Transcription streams can be unbounded (live microphone + raw chunks), so
// unlike streamText we cannot retain an unread tee branch for replay. The
// output stream has one owner: either fullStream, or the first result promise
// getter which claims and drains it internally.
let streamOwner: 'unclaimed' | 'full-stream' | 'result-promises' =
'unclaimed';
function consumeStream() {
if (streamOwner === 'full-stream' || streamOwner === 'result-promises') {
return;
}
streamOwner = 'result-promises';
const reader = transform.readable.getReader();
void (async () => {
while (!(await reader.read()).done) {
// drain; results surface via the promises
}
})().catch(() => {
// stream errors reject the promises via the pipe handler above
});
}
function getFullStream() {
if (streamOwner !== 'unclaimed') {
throw new Error(
streamOwner === 'full-stream'
? 'fullStream can only be accessed once.'
: 'fullStream cannot be accessed after a result promise.',
);
}
streamOwner = 'full-stream';
// Direct ownership preserves backpressure and cancellation: cancelling
// this stream reaches Transformer.cancel and aborts the model pipe.
return asAsyncIterableStream(transform.readable);
}
return {
get text() {
consumeStream();
return textPromise.promise;
},
get segments() {
consumeStream();
return segmentsPromise.promise;
},
get language() {
consumeStream();
return languagePromise.promise;
},
get durationInSeconds() {
consumeStream();
return durationInSecondsPromise.promise;
},
get warnings() {
consumeStream();
return warningsPromise.promise;
},
get responses() {
consumeStream();
return responsesPromise.promise;
},
get providerMetadata() {
consumeStream();
return providerMetadataPromise.promise;
},
// `transform.readable` is fresh and exclusively owned here, so attach the
// async iterator in place rather than piping through another transform.
// The extra transform (as `createAsyncIterableStream` would add) chains two
// transforms fed by the active model pipe below and surfaces a spurious
// unhandled `undefined` rejection when the consumer cancels early on
// Node.js 26.
fullStream: asAsyncIterableStream(transform.readable),
get fullStream() {
return getFullStream();
},
};
}

@@ -33,8 +33,8 @@ import { TypeValidationError, type JSONObject } from '@ai-sdk/provider';

.array(
z.object({
id: z.string(),
role: z.enum(['system', 'user', 'assistant']),
metadata: z.unknown().optional(),
parts: z
.array(
z
.object({
id: z.string(),
role: z.enum(['system', 'user', 'assistant']),
metadata: z.unknown().optional(),
parts: z.array(
z.union([

@@ -347,5 +347,17 @@ z.object({

]),
)
.nonempty('Message must contain at least one part'),
}),
),
})
.superRefine((message, context) => {
if (message.role !== 'assistant' && message.parts.length === 0) {
context.addIssue({
origin: 'array',
code: 'too_small',
minimum: 1,
inclusive: true,
input: message.parts,
path: ['parts'],
message: 'Message must contain at least one part',
});
}
}),
)

@@ -352,0 +364,0 @@ .nonempty('Messages array must not be empty'),

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet