Spaces:
Sleeping
Sleeping
| // ─── Retry engine ───────────────────────────────────────────────────────────── | |
| // Decides if and how to retry a failed/poor LLM response. | |
| // S-RETRY-WIRE: usa validateGate invece di validateOutput raw. | |
| // validateGate unifica normalize/sanitize/repair/quality/antiRewriteGuard | |
| // e produce un retryHint chirurgico quando referenceCode è fornito. | |
| import { validateGate } from "./validationGate"; | |
| export interface RetryDecision { | |
| shouldRetry: boolean; | |
| reason: string; | |
| augmentedPrompt?: string; | |
| priority: "immediate" | "deferred" | "skip"; | |
| } | |
| export interface RetryContext { | |
| task: string; | |
| output: string; | |
| iter: number; | |
| maxIter: number; | |
| toolResults?: string[]; | |
| /** | |
| * S-RETRY-WIRE: snapshot "noto buono" del codice per antiRewriteGuard. | |
| * Se fornito, validateGate rileva rewrite/incompletezza/import injection | |
| * e inietta il retryHint chirurgico nel prompt del retry. | |
| */ | |
| referenceCode?: string; | |
| } | |
| export function decideRetry(ctx: RetryContext): RetryDecision { | |
| // Never retry near the iteration ceiling | |
| if (ctx.iter >= ctx.maxIter - 2) { | |
| return { shouldRetry: false, reason: "limite iterazioni raggiunto", priority: "skip" }; | |
| } | |
| // S-RETRY-WIRE: validateGate sostituisce validateOutput. | |
| // referenceCode attiva auditOutput() → hint chirurgico anti-rewrite/incompletezza/injection. | |
| const gate = validateGate(ctx.output, { | |
| taskHint: ctx.task, | |
| referenceCode: ctx.referenceCode, | |
| }); | |
| // "accept" e "repaired" → nessun retry necessario | |
| if (gate.verdict === "accept" || gate.verdict === "repaired") { | |
| return { shouldRetry: false, reason: "output valido", priority: "skip" }; | |
| } | |
| const issueStr = gate.issues.join(", "); | |
| // S-RETRY-WIRE: retryHint del gate contiene già i constraint chirurgici | |
| // (NON riscrivere / Includi tutte le classi / Non introdurre deps esterne). | |
| // IMPORTANT: non menzionare mai "la risposta precedente" — istruzione interna pura. | |
| let augmentedPrompt = gate.retryHint | |
| ? gate.retryHint + " Rispondi in modo preciso e completo. Fornisci direttamente la risposta corretta senza meta-commenti." | |
| : "Rispondi alla domanda dell'utente in modo preciso e completo. Non commentare eventuali problemi precedenti."; | |
| if (ctx.toolResults && ctx.toolResults.length > 0) { | |
| const dataStr = ctx.toolResults.slice(0, 3).join("\n\n"); | |
| augmentedPrompt += ` Usa questi dati reali già disponibili:\n${dataStr}`; | |
| } else { | |
| augmentedPrompt += " Sii accurato, completo e in italiano."; | |
| } | |
| const shouldRetry = gate.verdict === "retry" || gate.verdict === "reject"; | |
| return { | |
| shouldRetry, | |
| reason: issueStr, | |
| augmentedPrompt, | |
| priority: gate.quality < 2 ? "immediate" : "deferred", | |
| }; | |
| } | |
| /** Quick check: should this output trigger a retry? */ | |
| export function shouldRetry(output: string, task?: string): boolean { | |
| const gate = validateGate(output, { taskHint: task }); | |
| return gate.verdict === "retry" || gate.verdict === "reject"; | |
| } | |