From 0dcebdb88a8b5f0ddad3c347f31474aa98d863e4 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Tue, 29 Sep 2026 22:19:42 -0500 Subject: [PATCH] refactor(ai): rename flattened tool helper --- packages/ai/src/protocols/anthropic-messages.ts | 7 +++---- packages/ai/src/protocols/bedrock-converse.ts | 2 +- packages/ai/src/protocols/gemini.ts | 2 +- packages/ai/src/protocols/meta-messages.ts | 2 +- packages/ai/src/protocols/meta-responses.ts | 2 +- packages/ai/src/protocols/mistral-chat.ts | 2 +- packages/ai/src/protocols/open-responses.ts | 2 +- packages/ai/src/protocols/openai-chat.ts | 2 +- packages/ai/src/protocols/openai-responses.ts | 2 +- packages/ai/src/protocols/shared.ts | 7 ++----- packages/ai/src/protocols/xai-responses.ts | 2 +- packages/core/src/aisdk.ts | 2 +- 12 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/ai/src/protocols/anthropic-messages.ts b/packages/ai/src/protocols/anthropic-messages.ts index 98a17b4370c..6b582c6ba97 100644 --- a/packages/ai/src/protocols/anthropic-messages.ts +++ b/packages/ai/src/protocols/anthropic-messages.ts @@ -1031,10 +1031,9 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques // messages. Tools live highest in the cache hierarchy, so when callers // over-mark we keep their tool hints and shed the message-tail ones first. const breakpoints = Cache.newBreakpoints(ANTHROPIC_BREAKPOINT_CAP) - const definitions = ProviderShared.toolDefinitions(request.tools) - const tools = definitions.length === 0 ? undefined : definitions.map((tool) => lowerTool(breakpoints, tool)) + const tools = ProviderShared.flatTools(request.tools).map((tool) => lowerTool(breakpoints, tool)) // Anthropic rejects tool_choice when tools are absent; "none" is only meaningful with tools present. - const toolChoice = tools === undefined || !request.toolChoice ? undefined : yield* lowerToolChoice(request.toolChoice) + const toolChoice = tools.length === 0 || !request.toolChoice ? undefined : yield* lowerToolChoice(request.toolChoice) const systemParts = request.system.filter((part) => part.text.length > 0) const system = systemParts.length === 0 @@ -1057,7 +1056,7 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques model: request.model.id, system, messages, - tools, + tools: tools.length === 0 ? undefined : tools, tool_choice: toolChoice, stream: true as const, max_tokens: maxTokens, diff --git a/packages/ai/src/protocols/bedrock-converse.ts b/packages/ai/src/protocols/bedrock-converse.ts index 9a153a7121c..a97bd088e02 100644 --- a/packages/ai/src/protocols/bedrock-converse.ts +++ b/packages/ai/src/protocols/bedrock-converse.ts @@ -463,7 +463,7 @@ const applyThinkingBindingDefault = (request: LLMRequest, thinking: Readonly 0 const generation = request.generation const options = yield* decodeOptions(request.providerOptions ?? {}) diff --git a/packages/ai/src/protocols/meta-messages.ts b/packages/ai/src/protocols/meta-messages.ts index 663380c6bb1..b9f7c76be1a 100644 --- a/packages/ai/src/protocols/meta-messages.ts +++ b/packages/ai/src/protocols/meta-messages.ts @@ -26,7 +26,7 @@ const Body = Schema.Struct({ }) const fromRequest = Effect.fn("MetaMessages.fromRequest")(function* (request: LLMRequest) { - const tools = ProviderShared.toolDefinitions(request.tools) + const tools = ProviderShared.flatTools(request.tools) const body = yield* AnthropicMessages.protocol.body.from(request) return { ...body, diff --git a/packages/ai/src/protocols/meta-responses.ts b/packages/ai/src/protocols/meta-responses.ts index b11dfdb9a80..62ea68aa185 100644 --- a/packages/ai/src/protocols/meta-responses.ts +++ b/packages/ai/src/protocols/meta-responses.ts @@ -67,7 +67,7 @@ const adapter = { const fromRequest = Effect.fn("MetaResponses.fromRequest")(function* (request: LLMRequest) { const key = request.model.route.providerMetadataKey ?? String(request.model.provider) - const tools = ProviderShared.toolDefinitions(request.tools) + const tools = ProviderShared.flatTools(request.tools) const projected = LLMRequest.update(request, { messages: request.messages.map((message) => Message.make({ diff --git a/packages/ai/src/protocols/mistral-chat.ts b/packages/ai/src/protocols/mistral-chat.ts index 0e226c3f5f2..5681b892120 100644 --- a/packages/ai/src/protocols/mistral-chat.ts +++ b/packages/ai/src/protocols/mistral-chat.ts @@ -390,7 +390,7 @@ export const fromRequest = Effect.fn("MistralChat.fromRequest")(function* (reque tool: (name) => ({ type: "function" as const, function: { name } }), }) : undefined - const tools = ProviderShared.toolDefinitions(request.tools) + const tools = ProviderShared.flatTools(request.tools) return { model: request.model.id, messages: yield* lowerMessages(request), diff --git a/packages/ai/src/protocols/open-responses.ts b/packages/ai/src/protocols/open-responses.ts index 4fff347c5b8..33ee5077cb7 100644 --- a/packages/ai/src/protocols/open-responses.ts +++ b/packages/ai/src/protocols/open-responses.ts @@ -816,7 +816,7 @@ export const fromRequestWithAdapter = Effect.fn("OpenResponses.fromRequestWithAd request: LLMRequest, adapter: ProviderAdapter, ) { - const tools = ProviderShared.toolDefinitions(request.tools) + const tools = ProviderShared.flatTools(request.tools) return { ...(yield* lowerConversation(request, adapter)), ...lowerGeneration(request), diff --git a/packages/ai/src/protocols/openai-chat.ts b/packages/ai/src/protocols/openai-chat.ts index ea08b228784..6b9d677562b 100644 --- a/packages/ai/src/protocols/openai-chat.ts +++ b/packages/ai/src/protocols/openai-chat.ts @@ -826,7 +826,7 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* ( const zaiToolStream = request.model.compatibility?.zaiToolStream ?? detectZaiToolStream(provider, baseURL, request.model.id) const hasHistory = hasToolHistory(request.messages) - const tools = ProviderShared.toolDefinitions(request.tools) + const tools = ProviderShared.flatTools(request.tools) const hasActiveTools = tools.length > 0 return { model: request.model.id, diff --git a/packages/ai/src/protocols/openai-responses.ts b/packages/ai/src/protocols/openai-responses.ts index e352f0f1d94..a69fe0d684f 100644 --- a/packages/ai/src/protocols/openai-responses.ts +++ b/packages/ai/src/protocols/openai-responses.ts @@ -181,7 +181,7 @@ const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (to type: "namespace" as const, name: tool.name, description: tool.description ?? `Tools in the ${tool.name} namespace.`, - tools: yield* Effect.forEach(ProviderShared.toolDefinitions(tool.tools), (leaf) => + tools: yield* Effect.forEach(ProviderShared.flatTools(tool.tools), (leaf) => OpenResponses.lowerTool(NAME, leaf), ), } diff --git a/packages/ai/src/protocols/shared.ts b/packages/ai/src/protocols/shared.ts index a0a1bd8bb06..1085d0ea702 100644 --- a/packages/ai/src/protocols/shared.ts +++ b/packages/ai/src/protocols/shared.ts @@ -287,11 +287,8 @@ export const unsupportedOperation = (input: { }), }) -/** - * Tool definitions of a route-lowered request. The route flattens namespaces - * before a flat protocol's `body.from`, so no namespace reaches this point. - */ -export const toolDefinitions = (tools: ReadonlyArray) => +/** The route flattens namespaces before a flat protocol's `body.from`, so only plain tools remain. */ +export const flatTools = (tools: ReadonlyArray) => tools.filter((tool): tool is ToolDefinition => tool.type === "tool") export const matchToolChoice = ( diff --git a/packages/ai/src/protocols/xai-responses.ts b/packages/ai/src/protocols/xai-responses.ts index da564cc318e..7407ae626c4 100644 --- a/packages/ai/src/protocols/xai-responses.ts +++ b/packages/ai/src/protocols/xai-responses.ts @@ -95,7 +95,7 @@ export const protocol = Protocol.make({ }) export const compact = ResponsesCompaction.make(adapter, (request) => - OpenResponses.lowerTools(ProviderShared.toolDefinitions(request.tools), adapter), + OpenResponses.lowerTools(ProviderShared.flatTools(request.tools), adapter), ) export * as XAIResponses from "./xai-responses.js" diff --git a/packages/core/src/aisdk.ts b/packages/core/src/aisdk.ts index f27ad01f375..20894fab656 100644 --- a/packages/core/src/aisdk.ts +++ b/packages/core/src/aisdk.ts @@ -487,7 +487,7 @@ function callOptions( presencePenalty: request.generation?.presencePenalty, frequencyPenalty: request.generation?.frequencyPenalty, seed: request.generation?.seed, - tools: ProviderShared.toolDefinitions(request.tools).map(tool), + tools: ProviderShared.flatTools(request.tools).map(tool), toolChoice: toolChoice(request.toolChoice), headers: request.http?.headers, providerOptions: requestProviderOptions(request.providerOptions, packageName, modelID, optionKey),