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 ❤️.
108 lines (96 loc) • 4.47 kB
JavaScript
// File: src/agents/transformPlanGenStep.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';
const MAX_STEPS = 100;
/**
* TRANSFORM PLAN GENERATOR
* Generates steps that perform concrete transformations or code changes.
*/
export const transformPlanGenStep = {
name: 'transformPlanGen',
description: 'Generates code transformation / modification steps.',
requires: ['analysis.intent', 'analysis.focus'],
produces: ['analysis.planSuggestion'],
async run(context) {
var _a, _b;
context.analysis || (context.analysis = {});
(_a = context.analysis).planSuggestion || (_a.planSuggestion = {});
(_b = context.analysis.planSuggestion).plan || (_b.plan = { steps: [] });
// Restrict actions to TRANSFORM group only
const effectiveActions = PLAN_ACTIONS.filter(a => a.groups?.includes('transform'));
const actionsJson = JSON.stringify(effectiveActions, null, 2);
const intentText = context.analysis.intent?.normalizedQuery ?? '';
const intentCategory = context.analysis.intent?.intentCategory ?? '';
const prompt = `
You are an autonomous coding agent.
Your task is to produce a structured plan describing how to implement actual code transformations
or modifications in the system to achieve the intended task.
Intent / task description:
${intentText}
If the intent indicates that this is NOT a coding, refactoring, or inline commenting task,
then return an empty plan object with an empty "steps" array:
{ "steps": [] }
Allowed actions (transformation only):
${actionsJson}
Task category:
${intentCategory}
Folder structure:
${context.analysis.folderCapsulesHuman ?? ''}
Existing relevant files:
${JSON.stringify(context.analysis.focus?.relevantFiles ?? {}, null, 2)}
Only perform transformations that are safe based on the existing analysis.
⚡ Phase guidance:
- Actions are grouped into phases: info, transform, finalize.
- Only include transform steps in this phase.
- Include a 'writeFile' step for each 'codeTransform' to persist changes to disk.
- Each step must include: "action", "targetFile" (optional), "description", "metadata"
❌ IMPORTANT: Do NOT include "info" steps here. Only plan actual code transformations.
Return a strictly valid JSON plan:
{
"steps": [
{ "action": "stepName", "targetFile": "optional/path.ts", "description": "explanation", "metadata": {} }
]
}
`.trim();
try {
console.log('TransformPlanGenStep prompt', prompt);
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 transform plan structure');
if (plan.steps.length > MAX_STEPS)
plan.steps = plan.steps.slice(0, MAX_STEPS);
// Map groups & metadata
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 ?? ['transform']
};
});
// Replace existing transform steps in planSuggestion
context.analysis.planSuggestion.plan.steps = [
...context.analysis.planSuggestion.plan.steps.filter(s => !s.groups?.includes('transform')),
...plan.steps
];
logInputOutput('transformPlanGen', 'output', plan);
}
catch (err) {
console.warn('⚠️ Failed to generate transform plan:', err);
}
}
};