diff --git a/vibn-frontend/app/api/chat/route.ts b/vibn-frontend/app/api/chat/route.ts index 1f72d6bd..d36c28a2 100644 --- a/vibn-frontend/app/api/chat/route.ts +++ b/vibn-frontend/app/api/chat/route.ts @@ -272,6 +272,26 @@ ${projectsText} Today's date: ${new Date().toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" })}.`; } +function lastToolResultsHadFailure(messages: ChatMessage[], lookback = 3) { + const toolMsgs = messages.filter((m) => m.role === "tool").slice(-lookback); + for (const tm of toolMsgs) { + const raw = typeof tm.content === "string" ? tm.content : ""; + try { + const parsed = JSON.parse(raw); + if (parsed.ok === false) return true; + if (typeof parsed.exitCode === "number" && parsed.exitCode !== 0) + return true; + if (parsed.healthCheck?.status && parsed.healthCheck.status >= 400) + return true; + if (typeof parsed.error === "string" && parsed.error.length > 0) + return true; + } catch { + // non-JSON result, skip + } + } + return false; +} + export async function POST(request: Request) { await ensureChatTables(); @@ -752,9 +772,14 @@ export async function POST(request: Request) { lastTurnHadTools && (round >= MAX_TOOL_ROUNDS || !!loopBreakReason || - assistantText.trim().length === 0); + assistantText.trim().length === 0 || + lastToolResultsHadFailure(messages)); if (needsRecovery) { + const failureNote = lastToolResultsHadFailure(messages) + ? "Your last tool calls returned failures or non-2xx health checks. " + + "Do NOT claim those operations succeeded. " + : ""; const reason = loopBreakReason ? `LOOP DETECTED: ${loopBreakReason}. Stop trying that approach. ` : round >= MAX_TOOL_ROUNDS @@ -764,7 +789,7 @@ export async function POST(request: Request) { const summary = await callVibnChat({ systemPrompt: systemPrompt + - `\n\n[RECOVERY] ${reason}Send the user 1–3 short sentences right now: (a) what you actually accomplished or learned, (b) the specific blocker (last error message verbatim if there is one), (c) what you'll try next OR a question for the user. Do NOT call any tools.`, + `\n\n[RECOVERY] ${reason}${failureNote}Send the user 1–3 short sentences right now: (a) what you actually accomplished or learned, (b) the specific blocker (last error message verbatim if there is one), (c) what you'll try next OR a question for the user. Do NOT call any tools.`, messages, tools: [], temperature: 0.3,