add option to skip provider tool call validation

This commit is contained in:
Markus Ylisiurunen 2025-12-07 17:24:06 +02:00
parent 2e3ff4a15a
commit 0196308266
12 changed files with 38 additions and 4 deletions

View file

@ -92,6 +92,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
options?: AnthropicOptions,
): AssistantMessageEventStream => {
const stream = new AssistantMessageEventStream();
const shouldValidateToolCalls = options?.validateToolCallsAtProvider !== false;
(async () => {
const output: AssistantMessage = {
@ -233,7 +234,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
block.arguments = parseStreamingJson(block.partialJson);
// Validate tool arguments if tool definition is available
if (context.tools) {
if (shouldValidateToolCalls && context.tools) {
const tool = context.tools.find((t) => t.name === block.name);
if (tool) {
block.arguments = validateToolArguments(tool, block);

View file

@ -43,6 +43,7 @@ export const streamGoogle: StreamFunction<"google-generative-ai"> = (
options?: GoogleOptions,
): AssistantMessageEventStream => {
const stream = new AssistantMessageEventStream();
const shouldValidateToolCalls = options?.validateToolCallsAtProvider !== false;
(async () => {
const output: AssistantMessage = {
@ -167,7 +168,7 @@ export const streamGoogle: StreamFunction<"google-generative-ai"> = (
};
// Validate tool arguments if tool definition is available
if (context.tools) {
if (shouldValidateToolCalls && context.tools) {
const tool = context.tools.find((t) => t.name === toolCall.name);
if (tool) {
toolCall.arguments = validateToolArguments(tool, toolCall);

View file

@ -37,6 +37,7 @@ export const streamOpenAICompletions: StreamFunction<"openai-completions"> = (
options?: OpenAICompletionsOptions,
): AssistantMessageEventStream => {
const stream = new AssistantMessageEventStream();
const shouldValidateToolCalls = options?.validateToolCallsAtProvider !== false;
(async () => {
const output: AssistantMessage = {
@ -86,7 +87,7 @@ export const streamOpenAICompletions: StreamFunction<"openai-completions"> = (
block.arguments = JSON.parse(block.partialArgs || "{}");
// Validate tool arguments if tool definition is available
if (context.tools) {
if (shouldValidateToolCalls && context.tools) {
const tool = context.tools.find((t) => t.name === block.name);
if (tool) {
block.arguments = validateToolArguments(tool, block);

View file

@ -45,6 +45,7 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses"> = (
options?: OpenAIResponsesOptions,
): AssistantMessageEventStream => {
const stream = new AssistantMessageEventStream();
const shouldValidateToolCalls = options?.validateToolCallsAtProvider !== false;
// Start async processing
(async () => {
@ -240,7 +241,7 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses"> = (
};
// Validate tool arguments if tool definition is available
if (context.tools) {
if (shouldValidateToolCalls && context.tools) {
const tool = context.tools.find((t) => t.name === toolCall.name);
if (tool) {
toolCall.arguments = validateToolArguments(tool, toolCall);

View file

@ -120,6 +120,7 @@ function mapOptionsForApi<TApi extends Api>(
maxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),
signal: options?.signal,
apiKey: apiKey || options?.apiKey,
validateToolCallsAtProvider: options?.validateToolCallsAtProvider ?? true,
};
switch (model.api) {

View file

@ -37,6 +37,12 @@ export interface StreamOptions {
maxTokens?: number;
signal?: AbortSignal;
apiKey?: string;
/**
* Controls whether providers validate streamed tool calls against the tool schema.
* Defaults to true. Set to false to skip provider-level validation and allow
* downstream consumers (e.g., agentLoop) to handle validation failures.
*/
validateToolCallsAtProvider?: boolean;
}
// Unified options with reasoning passed to streamSimple() and completeSimple()