From 173eabd8bf2b5493c83d455e429ad3ec2df0fe93 Mon Sep 17 00:00:00 2001 From: mawkone Date: Tue, 9 Jun 2026 14:30:36 -0700 Subject: [PATCH] chore(telemetry): jack up MAX_TOOL_ROUNDS to 150 for ultimate custom app-building runway --- app/api/chat/route.ts | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 1ee676d2..d8d8a3c4 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -821,6 +821,7 @@ export async function POST(request: Request) { isConversational(message.trim()); let lastVerifySig: string | null = null; + let lastRoundToolSig: string | null = null; let fileHashes = new Map(); let stallRounds = 0; @@ -996,7 +997,25 @@ export async function POST(request: Request) { // 1. Compute verify signature const verifySig = getRoundVerifySignature(currentRoundResults); - // 2. Check for actual state progress (did files change, did a plan update, did a mutating tool succeed, or did the error set change?) + // 2. Compute deterministic tool signature to track exact repetitions + const currentRoundToolSig = resp.toolCalls + .map((tc) => { + const sortKeys = (obj: any): any => { + if (typeof obj !== "object" || obj === null) return obj; + if (Array.isArray(obj)) return obj.map(sortKeys); + return Object.keys(obj) + .sort() + .reduce((acc, key) => { + acc[key] = sortKeys(obj[key]); + return acc; + }, {} as any); + }; + return `${tc.name}:${JSON.stringify(sortKeys(tc.args || {}))}`; + }) + .sort() + .join(";;"); + + // 3. Check for actual state progress (did files change, did a plan update, did a mutating tool succeed, or did the error set change?) const { progressed, nextHashes } = checkRoundProgress( currentRoundResults, fileHashes, @@ -1027,7 +1046,13 @@ export async function POST(request: Request) { } } - if (!progressed) { + // A stall is ONLY when the AI executes the exact same tools with the exact same inputs without making progress. + // If the AI is actively exploring different files, it is allowed to continue. + if ( + !progressed && + lastRoundToolSig && + currentRoundToolSig === lastRoundToolSig + ) { stallRounds++; } else { stallRounds = 0; @@ -1035,9 +1060,11 @@ export async function POST(request: Request) { if (stallRounds >= 2) { loopBreakReason = - "Stalled (No file state progress or diagnostic advancement made for 2 rounds)"; + "Stalled (Repeated the exact same tool calls twice without advancing)"; } + lastRoundToolSig = currentRoundToolSig; + if (loopBreakReason) break; }