Spaces:
Sleeping
Sleeping
| /** | |
| * executionPlanBlock.ts — S495: extracted from agentLoop.ts | |
| * | |
| * Wrapper per il blocco Execution Plan (S414/S421). | |
| * "Pensa prima di ogni azione" a livello macro — genera un piano strutturato | |
| * (auth → db → api → ui con checkpoint) PRIMA del primo LLM call. | |
| * | |
| * Trigger: _isCodeTask=true + ≥2 requisiti strutturati rilevati. | |
| * Output: { plan, planShort, planFull, epOrder } o null. | |
| * Mai blocca: tutto wrapped in try/catch (best-effort). | |
| * | |
| * @module executionPlanBlock | |
| */ | |
| import type { AgentStep } from "../storage"; | |
| import type { ExecutionPlan, ExecutionStep } from "../executionPlanner"; // S554: tipi espliciti | |
| export interface ExecutionPlanResult { | |
| plan: ExecutionPlan; // S554: was any — ExecutionPlan è esportato da executionPlanner | |
| planShort: string; | |
| planFull: string; | |
| epOrder: string[]; | |
| } | |
| /** | |
| * Tenta di generare un piano strutturato per il task di codice. | |
| * Restituisce null se il task è troppo semplice (< 2 requisiti) o in caso di errore. | |
| * | |
| * @param task — testo del task/messaggio utente | |
| * @param opts — opzioni: onStatus, onSteps, steps (per aggiungere __plan__ step) | |
| * @returns — ExecutionPlanResult o null | |
| */ | |
| export async function runExecutionPlanIfNeeded( | |
| task: string, | |
| opts?: { | |
| onStatus?: (msg: string) => void; | |
| onSteps?: (steps: AgentStep[]) => void; | |
| steps?: AgentStep[]; | |
| }, | |
| ): Promise<ExecutionPlanResult | null> { | |
| try { | |
| const { decomposeGoal } = await import("../requirementDecomposer"); | |
| const { planArchitecture } = await import("../architecturePlanner"); | |
| const { buildExecutionPlan, formatExecutionPlan, | |
| formatExecutionPlanCompact } = await import("../executionPlanner"); | |
| const _epSpec = decomposeGoal(task); | |
| if (_epSpec.requirements.length < 2) return null; | |
| // GAP-3: recupera i file rilevanti dal VFS PRIMA della pianificazione architetturale. | |
| // Permette a planArchitecture di rilevare lo stack tecnologico già in uso e pianificare | |
| // in modo coerente con il codebase esistente (es. non suggerire di aggiungere React | |
| // se .tsx già presenti, non suggerire un nuovo backend se .py già ci sono). | |
| // topK=8 / minScore=0.06: rete larga — vogliamo vedere l'architettura generale, non solo i file | |
| // più rilevanti per la query specifica. | |
| let _existingFiles: Array<{ path: string; lang: string }> = []; | |
| try { | |
| const { getRelevantFiles } = await import("../context/repoMap"); | |
| const _rf = await getRelevantFiles(task, 8, 0.06); | |
| _existingFiles = _rf.map(f => ({ path: f.path, lang: f.lang })); | |
| } catch { /* non-blocking — planner funziona anche senza contesto file */ } | |
| const _epArch = planArchitecture(task, _epSpec.requirements, _existingFiles); | |
| const _epPlan = buildExecutionPlan(task, _epSpec, _epArch); | |
| if (_epPlan.isMinimal) return null; | |
| const planFull = formatExecutionPlan(_epPlan); | |
| const planShort = formatExecutionPlanCompact(_epPlan); | |
| // Step visibile in UI: piano compatto con ordine moduli | |
| if (opts?.steps && opts.onSteps) { | |
| opts.steps.push({ | |
| tool: "__plan__", | |
| args: {}, | |
| result: planShort, | |
| status: "done", | |
| at: Date.now(), | |
| } as AgentStep); | |
| opts.onSteps([...opts.steps]); | |
| } | |
| opts?.onStatus?.(`Ho un piano, parto con ${_epPlan.steps[0]?.name ?? "l'analisi"}…`); | |
| // Fix 7 (S421): sincronizza ordine con GraphOrchestrator | |
| // S554: usa filesToCreate — il campo corretto di ExecutionStep (bug fix) | |
| const epOrder: string[] = _epPlan.steps.flatMap((s: ExecutionStep) => s.filesToCreate ?? []); | |
| if (epOrder.length > 0) { | |
| try { | |
| const { setEpPlanOrder } = await import("../agent/GraphOrchestrator"); | |
| setEpPlanOrder(epOrder); | |
| } catch { /* non-blocking */ } | |
| } | |
| return { plan: _epPlan, planShort, planFull, epOrder }; | |
| } catch { | |
| // Non-blocking — piano non disponibile, loop prosegue senza | |
| return null; | |
| } | |
| } | |