/** * execReinjectBlock.ts — S496: extracted from agentLoop.ts * * S83: Exec loop closure gate — quando il tool di esecuzione dell'iterazione * precedente ha prodotto output (exec/run_code/shell), riinietta l'output nel * contesto per far analizzare al modello il risultato prima di procedere. * * Limita il numero di re-inject a MAX_EXEC_REINJECT per evitare loop infiniti * su task di debug che non convergono. * * Restituisce { shouldContinue, newReinjectCount }: * - shouldContinue=true → caller deve fare `continue` nel loop * - shouldContinue=false → caller procede normalmente * * Muta loopMessages direttamente (by reference). * * @module execReinjectBlock */ import type { ApiMsg } from "./networkTools"; import { MAX_EXEC_REINJECT } from "./toolGate"; import { buildExecReinjectMessage } from "./execLoopGate"; // S501: usa modulo estratto invece di inline export interface ExecReinjectCtx { lastExecResultIter: number; execReinjectCount: number; iter: number; candidateText: string; lastExecTool: string; lastExecOutput: string; loopMessages: ApiMsg[]; onStatus: (msg: string) => void; /** eventRuntime.emit — passato come callback per evitare import circolare */ emitEvent: (evt: Record) => void; } export interface ExecReinjectResult { shouldContinue: boolean; newReinjectCount: number; } export function processExecReinject(ctx: ExecReinjectCtx): ExecReinjectResult { const { lastExecResultIter, execReinjectCount, iter, candidateText, lastExecTool, lastExecOutput, loopMessages, onStatus, emitEvent, } = ctx; // Gate: solo se il tool di exec è stato chiamato nell'iterazione precedente if ( lastExecResultIter !== iter - 1 || execReinjectCount >= MAX_EXEC_REINJECT || candidateText.includes("RISULTATO FINALE") || candidateText.toLowerCase().includes("task completat") || candidateText.toLowerCase().includes("compito completat") ) { return { shouldContinue: false, newReinjectCount: execReinjectCount }; } const newCount = execReinjectCount + 1; onStatus(`Analisi output esecuzione... (loop ${newCount}/${MAX_EXEC_REINJECT})`); // S501: usa buildExecReinjectMessage da execLoopGate.ts (modulo estratto, ora wired) loopMessages.push({ role: "user", content: buildExecReinjectMessage(lastExecTool, lastExecOutput) } as ApiMsg); emitEvent({ kind: "exec_loop_reinject", taskId: `loop-${iter}-${newCount}`, tool: lastExecTool, reinjectCount: newCount, outputSnippet: lastExecOutput.slice(0, 120), }); return { shouldContinue: true, newReinjectCount: newCount }; }