From 87a3212856a9902ded0c2d4e6e376f3391fcc636 Mon Sep 17 00:00:00 2001 From: Guilherme Rodrigues Date: Mon, 5 Jan 2026 20:46:59 -0300 Subject: [PATCH] fix(openrouter): handle null callOptions in LLM binding tools - Add default empty object for callOptions destructuring to prevent 'Cannot destructure property abortSignal from null' error - Decode Uint8Array response.body to string for proper JSON serialization - Fixes LLM_DO_GENERATE and LLM_DO_STREAM when called without callOptions --- openrouter/server/tools/llm-binding.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openrouter/server/tools/llm-binding.ts b/openrouter/server/tools/llm-binding.ts index 5fb36b55..0432e7ce 100644 --- a/openrouter/server/tools/llm-binding.ts +++ b/openrouter/server/tools/llm-binding.ts @@ -481,7 +481,7 @@ export const createLLMStreamTool = (env: Env) => execute: async ({ context }) => { const { modelId, - callOptions: { abortSignal: _abortSignal, ...callOptions }, + callOptions: { abortSignal: _abortSignal, ...callOptions } = {}, } = context; env.MESH_REQUEST_CONTEXT.ensureAuthenticated(); @@ -516,7 +516,7 @@ export const createLLMGenerateTool = (env: Env) => execute: async ({ context }) => { const { modelId, - callOptions: { abortSignal: _abortSignal, ...callOptions }, + callOptions: { abortSignal: _abortSignal, ...callOptions } = {}, } = context; env.MESH_REQUEST_CONTEXT.ensureAuthenticated(); @@ -531,6 +531,12 @@ export const createLLMGenerateTool = (env: Env) => callOptions as LanguageModelV2CallOptions, ); + // Clean up response.body if it's a Uint8Array (raw HTTP response) + // This ensures JSON serialization works correctly over MCP + if (result?.response?.body instanceof Uint8Array) { + result.response.body = new TextDecoder().decode(result.response.body); + } + return result as unknown as z.infer; }, });