UNPKG

scai

Version:

> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** 100% local, private, GDPR-friendly, made in Denmark/EU with ❤️.

127 lines (117 loc) 4.76 kB
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'; const MAX_STEPS = 100; /** * INFO PLAN GENERATOR * Generates information-gathering steps only. */ export const infoPlanGen = { name: 'infoPlanGen', description: 'Generates an information-acquisition plan.', requires: ['userQuery', 'analysis.intent'], produces: ['analysis.planSuggestion'], async run(context) { context.analysis || (context.analysis = {}); // -------------------------------------------------- // Always discard any existing info plan // (planner may loop; old plans must not survive) // -------------------------------------------------- delete context.analysis.planSuggestion?.plan; // -------------------------------------------------- // Check for missing files // -------------------------------------------------- const missingFiles = Array.isArray(context.analysis.focus?.missingFiles) ? context.analysis.focus.missingFiles : []; if (missingFiles.length === 0) { console.log('ℹ️ No missing files — returning empty info plan.'); context.analysis.planSuggestion = { plan: { steps: [] } }; logInputOutput('infoPlanGen', 'output', { steps: [] }); return; } // -------------------------------------------------- // Restrict actions to INFO phase only // -------------------------------------------------- const effectiveActions = PLAN_ACTIONS.filter(a => a.groups?.includes('info')); const actionsJson = JSON.stringify(effectiveActions, null, 2); console.log('Actions: ', actionsJson); const intentText = context.analysis.intent?.normalizedQuery ?? context.initContext?.userQuery ?? ''; const intentCategory = context.analysis.intent?.intentCategory ?? ''; const prompt = ` You are an autonomous coding agent. Based on the allowed actions you task is to produce a structured plan describing what information should be gathered in order to understand and solve the task. Allowed actions (information acquisition only): ${actionsJson} Intent / task description: ${intentText} Below is gathered information about the repository: Task category: ${intentCategory} Folder structure: ${context.analysis.folderCapsulesHuman ?? ''} Existing relevant files: ${JSON.stringify(context.analysis.focus?.relevantFiles ?? {}, null, 2)} Missing files: ${JSON.stringify(missingFiles, null, 2)} Return a structured JSON plan describing which information to gather. JSON schema: { "steps": [ { "action": "stepName", "targetFile": "optional/path.ts", "description": "explanation", "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 ?? '{}'); let plan = JSON.parse(jsonString); if (!plan || !Array.isArray(plan.steps)) { throw new Error('Invalid info plan structure'); } if (plan.steps.length > MAX_STEPS) { plan.steps = plan.steps.slice(0, MAX_STEPS); } plan.steps = plan.steps.map((step) => { const actionDef = PLAN_ACTIONS.find(a => a.action === step.action); return { ...step, metadata: { ...step.metadata, routingConfidence: context.analysis?.routingDecision?.confidence ?? 0 }, groups: actionDef?.groups ?? [] }; }); context.analysis.planSuggestion = { plan }; logInputOutput('infoPlanGen', 'output', plan); } catch (err) { console.warn('⚠️ Failed to generate info plan:', err); context.analysis.planSuggestion = { plan: { steps: [] } }; logInputOutput('infoPlanGen', 'output', { steps: [] }); } } };