UNPKG

scai

Version:

> **A local-first AI CLI for understanding, querying, and iterating on large codebases.** > **100% local • No token costs • No cloud • No prompt injection • Private by design**

115 lines (105 loc) 4.64 kB
// src/agents/analysisPlanGenStep.ts import { generate } from "../lib/generate.js"; import { PLAN_ACTIONS } from "../utils/planActions.js"; import { logInputOutput } from "../utils/promptLogHelper.js"; import { cleanupModule } from "../pipeline/modules/cleanupModule.js"; /** * ANALYSIS PLAN GENERATOR (single-step) * Generates exactly one analysis reasoning step per iteration. */ export const analysisPlanGenStep = { name: "analysisPlanGen", description: "Generates a single analysis reasoning step.", requires: ["analysis.intent", "analysis.focus", "analysis.routingDecision"], produces: ["analysis.planSuggestion"], async run(context) { context.analysis || (context.analysis = {}); context.execution || (context.execution = {}); // Ensure task exists (required for currentStep) if (!context.task) { throw new Error("analysisPlanGenStep: context.task must exist — ensure runBoot has been called"); } // 🔁 Always overwrite previous planSuggestion delete context.analysis.planSuggestion; // Use the DB-backed currentStep const currentStep = context.task.currentStep; if (!currentStep?.filePath) { context.analysis.planSuggestion = { plan: { steps: [] } }; logInputOutput("analysisPlanGen", "output", { steps: [] }); return; } const targetFile = currentStep.filePath; // Restrict actions to ANALYSIS only const effectiveActions = PLAN_ACTIONS.filter(a => a.groups?.includes("analysis")); if (!effectiveActions.length) { context.analysis.planSuggestion = { plan: { steps: [] } }; logInputOutput("analysisPlanGen", "output", { steps: [] }); return; } const actionsJson = JSON.stringify(effectiveActions, null, 2); const intentText = context.analysis.intent?.normalizedQuery ?? context.initContext?.userQuery ?? ""; const intentCategory = context.analysis.intent?.intentCategory ?? ""; const relevantFiles = JSON.stringify([targetFile], null, 2); const rationaleText = context.analysis.focus?.rationale ?? ""; const understandingText = context.analysis.understanding ? JSON.stringify(context.analysis.understanding, null, 2) : ""; const prompt = ` You are an autonomous coding agent. Produce **exactly one structured analysis step** that will advance understanding of the codebase, suitable for safe planning of transformations. Intent / task description: ${intentText} Task category: ${intentCategory} Allowed actions (analysis only): ${actionsJson} Relevant files: ${relevantFiles} Rationale / notes from pre-file check: ${rationaleText} Existing understanding of the codebase: ${understandingText} If this is NOT a coding, refactoring, or inline commenting task, return: { "step": null } Return a valid JSON object in this format: { "step": { "action": "analysisAction", "targetFile": "optional/path.ts", "description": "what this analysis step achieves", "metadata": {} } } `.trim(); try { const genInput = { query: intentText, content: prompt }; const genOutput = await generate(genInput); const raw = typeof genOutput.data === "string" ? genOutput.data : JSON.stringify(genOutput.data ?? "{}"); const cleaned = await cleanupModule.run({ query: intentText, content: raw }); const jsonString = typeof cleaned.content === "string" ? cleaned.content : JSON.stringify(cleaned.content ?? "{}"); const planObj = JSON.parse(jsonString); const steps = planObj.step ? [planObj.step] : []; const finalSteps = steps.map((step) => { const actionDef = PLAN_ACTIONS.find(a => a.action === step.action); return { ...step, groups: actionDef?.groups ?? ["analysis"], metadata: step.metadata ?? {}, }; }); context.analysis.planSuggestion = { plan: { steps: finalSteps } }; logInputOutput("analysisPlanGen", "output", finalSteps); console.log("🧠 [analysisPlanGenStep] EXIT (success)"); } catch (err) { console.warn("⚠️ [analysisPlanGenStep] FAILED to generate analysis plan:", err); context.analysis.planSuggestion = { plan: { steps: [] } }; logInputOutput("analysisPlanGen", "output", { steps: [] }); } } };