fix(ai): force recovery summary when final tools fail (Fix 6)

This commit is contained in:
2026-05-16 12:25:00 -07:00
parent 36c9dd47fb
commit 24a7689d69

View File

@@ -272,6 +272,26 @@ ${projectsText}
Today's date: ${new Date().toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" })}.`; 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) { export async function POST(request: Request) {
await ensureChatTables(); await ensureChatTables();
@@ -752,9 +772,14 @@ export async function POST(request: Request) {
lastTurnHadTools && lastTurnHadTools &&
(round >= MAX_TOOL_ROUNDS || (round >= MAX_TOOL_ROUNDS ||
!!loopBreakReason || !!loopBreakReason ||
assistantText.trim().length === 0); assistantText.trim().length === 0 ||
lastToolResultsHadFailure(messages));
if (needsRecovery) { 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 const reason = loopBreakReason
? `LOOP DETECTED: ${loopBreakReason}. Stop trying that approach. ` ? `LOOP DETECTED: ${loopBreakReason}. Stop trying that approach. `
: round >= MAX_TOOL_ROUNDS : round >= MAX_TOOL_ROUNDS
@@ -764,7 +789,7 @@ export async function POST(request: Request) {
const summary = await callVibnChat({ const summary = await callVibnChat({
systemPrompt: systemPrompt:
systemPrompt + systemPrompt +
`\n\n[RECOVERY] ${reason}Send the user 13 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 13 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, messages,
tools: [], tools: [],
temperature: 0.3, temperature: 0.3,