From 348e90b6070960a775c4e865bfb9a7c82c4f4358 Mon Sep 17 00:00:00 2001 From: gimenes Date: Thu, 19 Feb 2026 01:07:06 -0300 Subject: [PATCH 1/2] fix(chat): propagate toolApprovalLevel through agentic auto-sends Store toolApprovalLevel in user-message metadata so it is available via messages.at(-1)?.metadata on every subsequent auto-send (where requestMetadata is empty). Echo the value back from the server in the assistant-message metadata so the fallback chain is complete for multi-turn agentic flows. Without this fix, GATEWAY_SEARCH_TOOLS and GATEWAY_DESCRIBE_TOOLS always asked for approval on auto-sends even when the user had set approval to "yolo", because the server defaulted toolApprovalLevel to "none" when the field was absent from the request. Co-Authored-By: Claude Sonnet 4.6 --- apps/mesh/src/api/routes/decopilot/routes.ts | 1 + apps/mesh/src/web/components/chat/context.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/mesh/src/api/routes/decopilot/routes.ts b/apps/mesh/src/api/routes/decopilot/routes.ts index 96fd63f44d..06121ee9ad 100644 --- a/apps/mesh/src/api/routes/decopilot/routes.ts +++ b/apps/mesh/src/api/routes/decopilot/routes.ts @@ -320,6 +320,7 @@ app.post("/:org/decopilot/stream", async (c) => { }, created_at: new Date(), thread_id: mem.thread.id, + toolApprovalLevel, }; } if (part.type === "reasoning-start") { diff --git a/apps/mesh/src/web/components/chat/context.tsx b/apps/mesh/src/web/components/chat/context.tsx index c88cee674a..6eef7363fe 100644 --- a/apps/mesh/src/web/components/chat/context.tsx +++ b/apps/mesh/src/web/components/chat/context.tsx @@ -151,9 +151,8 @@ const createModelsTransport = ( const { system, tiptapDoc: _tiptapDoc, - toolApprovalLevel, ...metadata - } = requestMetadata as Metadata & { toolApprovalLevel?: string }; + } = requestMetadata as Metadata; const systemMessage: UIMessage | null = system ? { id: crypto.randomUUID(), @@ -166,7 +165,7 @@ const createModelsTransport = ( ? [systemMessage, ...userMessage] : userMessage; - // Fall back to last message metadata when requestMetadata is missing models/agent + // Fall back to last message metadata when requestMetadata is missing models/agent/toolApprovalLevel const lastMsgMeta = (messages.at(-1)?.metadata ?? {}) as Metadata; const mergedMetadata = { ...metadata, @@ -179,7 +178,9 @@ const createModelsTransport = ( body: { messages: allMessages, ...mergedMetadata, - ...(toolApprovalLevel && { toolApprovalLevel }), + ...(lastMsgMeta.toolApprovalLevel && { + toolApprovalLevel: lastMsgMeta.toolApprovalLevel, + }), }, }; }, @@ -768,6 +769,7 @@ export function ChatProvider({ children }: PropsWithChildren) { avatar: user?.image ?? undefined, name: user?.name ?? "you", }, + toolApprovalLevel: preferences.toolApprovalLevel, }; const metadata: Metadata = { From c7486935659ad5ca7bf95b3057348d6e8437f026 Mon Sep 17 00:00:00 2001 From: gimenes Date: Thu, 19 Feb 2026 01:27:42 -0300 Subject: [PATCH 2/2] fix(chat): persist temperature and windowSize through agentic auto-sends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both fields had server-side defaults (0.5 and DEFAULT_WINDOW_SIZE=50) and were absent from the message-metadata fallback chain, meaning every AI SDK auto-send (tool result → next step) silently reset them to their defaults rather than preserving the values from the originating request. Apply the same three-step pattern used for toolApprovalLevel: 1. Add temperature and windowSize to the Metadata interface so they can be carried in message metadata. 2. Echo both values from the server in the assistant-message metadata (part.type === "start") so they survive the round-trip. 3. Read them from lastMsgMeta in prepareSendMessagesRequest so every auto-send inherits the last-known values. windowSize is reconstructed into the memory object (which also requires thread_id) to satisfy the MemoryConfigSchema on the server. Co-Authored-By: Claude Sonnet 4.6 --- apps/mesh/src/api/routes/decopilot/routes.ts | 2 ++ apps/mesh/src/web/components/chat/context.tsx | 12 +++++++++++- apps/mesh/src/web/components/chat/types.ts | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/mesh/src/api/routes/decopilot/routes.ts b/apps/mesh/src/api/routes/decopilot/routes.ts index 06121ee9ad..97a154f2b2 100644 --- a/apps/mesh/src/api/routes/decopilot/routes.ts +++ b/apps/mesh/src/api/routes/decopilot/routes.ts @@ -321,6 +321,8 @@ app.post("/:org/decopilot/stream", async (c) => { created_at: new Date(), thread_id: mem.thread.id, toolApprovalLevel, + temperature, + windowSize, }; } if (part.type === "reasoning-start") { diff --git a/apps/mesh/src/web/components/chat/context.tsx b/apps/mesh/src/web/components/chat/context.tsx index 6eef7363fe..4e455c477d 100644 --- a/apps/mesh/src/web/components/chat/context.tsx +++ b/apps/mesh/src/web/components/chat/context.tsx @@ -165,7 +165,7 @@ const createModelsTransport = ( ? [systemMessage, ...userMessage] : userMessage; - // Fall back to last message metadata when requestMetadata is missing models/agent/toolApprovalLevel + // Fall back to last message metadata when requestMetadata is missing models/agent/toolApprovalLevel/temperature/windowSize const lastMsgMeta = (messages.at(-1)?.metadata ?? {}) as Metadata; const mergedMetadata = { ...metadata, @@ -181,6 +181,16 @@ const createModelsTransport = ( ...(lastMsgMeta.toolApprovalLevel && { toolApprovalLevel: lastMsgMeta.toolApprovalLevel, }), + ...(lastMsgMeta.temperature !== undefined && { + temperature: lastMsgMeta.temperature, + }), + ...(lastMsgMeta.windowSize !== undefined && + mergedMetadata.thread_id && { + memory: { + windowSize: lastMsgMeta.windowSize, + thread_id: mergedMetadata.thread_id, + }, + }), }, }; }, diff --git a/apps/mesh/src/web/components/chat/types.ts b/apps/mesh/src/web/components/chat/types.ts index 4902d37a4e..a22ed9abf0 100644 --- a/apps/mesh/src/web/components/chat/types.ts +++ b/apps/mesh/src/web/components/chat/types.ts @@ -67,6 +67,10 @@ export interface Metadata { tiptapDoc?: TiptapDoc; /** Tool approval level preference */ toolApprovalLevel?: "none" | "readonly" | "yolo"; + /** LLM sampling temperature (0–1). Persisted so auto-sends use the same value. */ + temperature?: number; + /** Conversation context window size (number of messages). Persisted so auto-sends use the same value. */ + windowSize?: number; usage?: { inputTokens?: number; outputTokens?: number;