Sorry, the diff of this file is not supported yet
| 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'; |
+43
-20
@@ -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
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
6908796
0.26%639
0.31%72219
0.39%