New:Socket for Asana Is Now Available.Learn more
Get Started

ai

Package Overview
Dependencies
Maintainers
5
Versions
1490
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.87
to
7.0.88
docs/07-reference/...rors/ai-tool-choice-violation-error.mdx

Sorry, the diff of this file is not supported yet

+80
import {
AISDKError,
type LanguageModelV4Content,
type LanguageModelV4ToolChoice,
} from '@ai-sdk/provider';
import type { FinishReason } from '../types/language-model';
const name = 'AI_ToolChoiceViolationError';
const marker = `vercel.ai.error.${name}`;
const symbol = Symbol.for(marker);
type EnforcedToolChoice = Extract<
LanguageModelV4ToolChoice,
{ type: 'required' } | { type: 'tool' }
>;
/**
* Thrown when a model response does not satisfy an enforced tool choice.
*/
export class ToolChoiceViolationError extends AISDKError {
private readonly [symbol] = true; // used in isInstance
/**
* The tool choice that the model response did not satisfy.
*/
readonly toolChoice: EnforcedToolChoice;
/**
* Reason why the model finished generating the response.
*/
readonly finishReason: FinishReason;
/**
* The provider that returned the response.
*/
readonly provider: string;
/**
* The model that returned the response.
*/
readonly modelId: string;
/**
* The normalized content returned by the model.
*
* This can be inspected to recover a tool call that the provider returned as
* text or reasoning instead of a structured tool call.
*/
readonly content: Array<LanguageModelV4Content>;
constructor({
toolChoice,
finishReason,
provider,
modelId,
content,
message = toolChoice.type === 'required'
? 'Model response did not contain a tool call even though tool choice was required.'
: `Model response did not contain a call to the required tool '${toolChoice.toolName}'.`,
}: {
toolChoice: EnforcedToolChoice;
finishReason: FinishReason;
provider: string;
modelId: string;
content: Array<LanguageModelV4Content>;
message?: string;
}) {
super({ name, message });
this.toolChoice = toolChoice;
this.finishReason = finishReason;
this.provider = provider;
this.modelId = modelId;
this.content = content;
}
static isInstance(error: unknown): error is ToolChoiceViolationError {
return AISDKError.hasMarker(error, marker);
}
}
+5
-5
{
"name": "ai",
"version": "7.0.87",
"version": "7.0.88",
"type": "module",

@@ -50,11 +50,11 @@ "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.",

"devDependencies": {
"@ai-sdk/amazon-bedrock": "5.0.69",
"@ai-sdk/amazon-bedrock": "5.0.70",
"@ai-sdk/deepseek": "3.0.37",
"@ai-sdk/google": "4.0.59",
"@ai-sdk/google": "4.0.60",
"@ai-sdk/groq": "4.0.35",
"@ai-sdk/huggingface": "2.0.41",
"@ai-sdk/moonshotai": "3.0.43",
"@ai-sdk/openai": "4.0.53",
"@ai-sdk/openai": "4.0.54",
"@ai-sdk/test-server": "2.0.1",
"@ai-sdk/xai": "4.0.50",
"@ai-sdk/xai": "4.0.51",
"@edge-runtime/vm": "^5.0.0",

@@ -61,0 +61,0 @@ "@smithy/eventstream-codec": "^4.3.3",

@@ -7,4 +7,9 @@ import type {

} from '@ai-sdk/provider';
import type { ProviderOptions, ToolSet } from '@ai-sdk/provider-utils';
import type {
InferToolSetContext,
ProviderOptions,
ToolSet,
} from '@ai-sdk/provider-utils';
import type { ContentPart } from '../generate-text/content-part';
import type { ToolOrder } from '../generate-text/tool-order';
import type { LanguageModelCallOptions } from '../prompt/language-model-call-options';

@@ -15,2 +20,3 @@ import type { Prompt } from '../prompt/prompt';

GlobalProviderModelId,
ToolChoice,
} from '../types/language-model';

@@ -79,5 +85,30 @@ import type { ProviderMetadata } from '../types/provider-metadata';

*/
export type StartTextBatchOptions = {
export type StartTextBatchOptions<TOOLS extends ToolSet = ToolSet> = {
model: BatchLanguageModel;
requests: ReadonlyArray<TextBatchRequest>;
/**
* Tools that the model can call for every request in the batch.
*
* Tool definitions are sent to the provider, but their `execute` functions
* are never invoked by batch processing.
*/
tools?: TOOLS;
/**
* The tool choice strategy. Default: 'auto'.
*/
toolChoice?: ToolChoice<NoInfer<TOOLS>>;
/**
* Controls the order in which tools are sent to the provider. Tools not
* listed are appended alphabetically.
*/
toolOrder?: ToolOrder<TOOLS>;
/**
* Context used when resolving dynamic tool descriptions.
*/
toolsContext?: InferToolSetContext<TOOLS>;
providerOptions?: ProviderOptions;

@@ -103,5 +134,14 @@

*/
export type BatchOperationOptions = {
export type BatchOperationOptions<TOOLS extends ToolSet = ToolSet> = {
model: BatchLanguageModel;
batch: BatchReference;
/**
* Definitions for client tools that were provided to `startTextBatch`.
*
* The definitions are used only to validate and normalize returned tool
* calls. Their `execute` functions are never invoked.
*/
tools?: TOOLS;
providerOptions?: ProviderOptions;

@@ -114,5 +154,5 @@ maxRetries?: number;

*/
export type TextBatchGenerationResult = {
export type TextBatchGenerationResult<TOOLS extends ToolSet = ToolSet> = {
/** Ordered normalized content, including citations, sources, and tool data. */
readonly content: Array<ContentPart<ToolSet>>;
readonly content: Array<ContentPart<TOOLS>>;
readonly text: string;

@@ -133,4 +173,4 @@ readonly finishReason: FinishReason;

*/
export type TextBatchItemResult =
| (TextBatchGenerationResult & {
export type TextBatchItemResult<TOOLS extends ToolSet = ToolSet> =
| (TextBatchGenerationResult<TOOLS> & {
readonly id: string;

@@ -137,0 +177,0 @@ readonly status: 'succeeded';

@@ -13,2 +13,4 @@ import {

import { parseToolCall } from '../generate-text/parse-tool-call';
import { prepareToolChoice } from '../prompt/prepare-tool-choice';
import { prepareTools } from '../prompt/prepare-tools';
import { logWarnings } from '../logger/log-warnings';

@@ -40,5 +42,9 @@ import { resolveLanguageModel } from '../model/resolve-model';

*/
export async function startTextBatch({
export async function startTextBatch<TOOLS extends ToolSet>({
model: modelArg,
requests,
tools,
toolChoice,
toolOrder,
toolsContext,
providerOptions,

@@ -49,3 +55,3 @@ webhookUrl,

timeout,
}: StartTextBatchOptions): Promise<StartTextBatchResult> {
}: StartTextBatchOptions<TOOLS>): Promise<StartTextBatchResult> {
validateRequests(requests);

@@ -59,2 +65,8 @@

const supportedUrls = await model.supportedUrls;
const preparedTools = await prepareTools({
tools,
toolOrder,
toolsContext,
});
const preparedToolChoice = prepareToolChoice({ toolChoice });
operationAbortSignal?.throwIfAborted();

@@ -76,2 +88,4 @@ const normalizedRequests = [];

}),
tools: preparedTools,
toolChoice: preparedToolChoice,
providerOptions: request.providerOptions,

@@ -128,3 +142,3 @@ },

timeout,
}: BatchOperationOptions): Promise<BatchStatus> {
}: Omit<BatchOperationOptions, 'tools'>): Promise<BatchStatus> {
const model = resolveBatchLanguageModel(modelArg);

@@ -161,5 +175,6 @@ validateBatchReference({ model, batch });

*/
export function getBatchResults({
export function getBatchResults<TOOLS extends ToolSet>({
model: modelArg,
batch,
tools,
providerOptions,

@@ -170,3 +185,3 @@ maxRetries,

timeout,
}: BatchOperationOptions) {
}: BatchOperationOptions<TOOLS>) {
const model = resolveBatchLanguageModel(modelArg);

@@ -187,6 +202,6 @@ validateBatchReference({ model, batch });

BatchV4ItemResult<LanguageModelV4GenerateResult>,
TextBatchItemResult
TextBatchItemResult<TOOLS>
> & { cancel?: (reason?: unknown) => void } = {
async transform(item, controller) {
controller.enqueue(await convertBatchItemResult(item));
controller.enqueue(await convertBatchItemResult({ item, tools }));
},

@@ -202,3 +217,3 @@

BatchV4ItemResult<LanguageModelV4GenerateResult>,
TextBatchItemResult
TextBatchItemResult<TOOLS>
>(transformer);

@@ -312,5 +327,9 @@

async function convertBatchItemResult(
item: BatchV4ItemResult<LanguageModelV4GenerateResult>,
): Promise<TextBatchItemResult> {
async function convertBatchItemResult<TOOLS extends ToolSet>({
item,
tools,
}: {
item: BatchV4ItemResult<LanguageModelV4GenerateResult>;
tools: TOOLS | undefined;
}): Promise<TextBatchItemResult<TOOLS>> {
if (item.status !== 'succeeded') {

@@ -323,9 +342,13 @@ return item;

status: 'succeeded',
...(await convertGenerateResult(item.result)),
...(await convertGenerateResult({ result: item.result, tools })),
};
}
async function convertGenerateResult(
result: LanguageModelV4GenerateResult,
): Promise<TextBatchGenerationResult> {
async function convertGenerateResult<TOOLS extends ToolSet>({
result,
tools,
}: {
result: LanguageModelV4GenerateResult;
tools: TOOLS | undefined;
}): Promise<TextBatchGenerationResult<TOOLS>> {
const toolCalls = await Promise.all(

@@ -337,5 +360,5 @@ result.content

.map(toolCall =>
parseToolCall<ToolSet>({
parseToolCall<TOOLS>({
toolCall,
tools: undefined,
tools,
repairToolCall: undefined,

@@ -348,3 +371,3 @@ refineToolInput: undefined,

);
const content = convertLanguageModelContent<ToolSet>({
const content = convertLanguageModelContent<TOOLS>({
content: result.content,

@@ -355,3 +378,3 @@ toolCalls,

toolApprovalResponses: [],
tools: undefined,
tools,
});

@@ -361,3 +384,3 @@

content,
text: content
text: result.content
.filter(

@@ -364,0 +387,0 @@ (part): part is Extract<typeof part, { type: 'text' }> =>

@@ -35,2 +35,3 @@ export {

export { ToolCallRepairError } from './tool-call-repair-error';
export { ToolChoiceViolationError } from './tool-choice-violation-error';
export { UnsupportedModelVersionError } from './unsupported-model-version-error';

@@ -37,0 +38,0 @@ export { UIMessageStreamError } from './ui-message-stream-error';

@@ -18,3 +18,3 @@ import type {

} from '@ai-sdk/provider-utils';
import { NoOutputGeneratedError } from '../error';
import { NoOutputGeneratedError, ToolChoiceViolationError } from '../error';
import { logWarnings } from '../logger/log-warnings';

@@ -1077,2 +1077,3 @@ import { resolveLanguageModel } from '../model/resolve-model';

);
const toolApprovalRequests: Record<

@@ -1137,2 +1138,25 @@ string,

const enforcedToolChoice =
stepToolChoice.type === 'required' ||
stepToolChoice.type === 'tool'
? stepToolChoice
: undefined;
if (
enforcedToolChoice != null &&
!stepToolCalls.some(
toolCall =>
enforcedToolChoice.type === 'required' ||
toolCall.toolName === enforcedToolChoice.toolName,
)
) {
throw new ToolChoiceViolationError({
toolChoice: enforcedToolChoice,
finishReason: currentModelResponse.finishReason.unified,
provider: stepModel.provider,
modelId: stepModel.modelId,
content: currentModelResponse.content,
});
}
// notify the tools that the tool calls are available:

@@ -1139,0 +1163,0 @@ for (const toolCall of stepToolCalls) {

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 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