scai
Version:
> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** > **100% local • No token cost • Private by design • GDPR-friendly** — made in Denmark/EU with ❤️.
100 lines (88 loc) • 3.13 kB
JavaScript
// File: src/modules/contextReviewStep.ts
import { generate } from "../lib/generate.js";
import { logInputOutput } from "../utils/promptLogHelper.js";
export async function contextReviewStep(context) {
const analysis = context.analysis;
if (!analysis) {
throw new Error("[contextReviewStep] No analysis state available.");
}
const intent = analysis.intent ?? {
intent: "",
intentCategory: "",
normalizedQuery: "",
confidence: 0,
};
const focus = analysis.focus ?? {
relevantFiles: [],
missingFiles: [],
rationale: "",
};
const fileAnalysis = analysis.fileAnalysis ?? {};
const planDecision = analysis.planSuggestion?.plan
? "planExists"
: "needsPlan";
// ------------------------------
// Compress file-level analysis to high-signal summaries
// ------------------------------
const summarizedFiles = Object.entries(fileAnalysis)
.filter(([, fa]) => fa.intent === "relevant")
.map(([filePath, fa]) => ({
file: filePath,
role: fa.role ?? "unspecified",
relevance: fa.relevance,
proposedChangeScope: fa.proposedChanges?.scope ?? "none",
}));
// ------------------------------
// Build prompt using distilled conclusions only
// ------------------------------
const prompt = `
You are a meta-reasoning agent.
Your job is to determine whether enough relevant information
has been collected to directly answer the user's intent,
or whether more data must be gathered first.
Decision meanings:
- "executeOnQuery": The collected analysis and files are sufficient to answer the user's question.
- "gatherData": The current analysis is insufficient; more files or analysis are required.
User Intent:
${JSON.stringify(intent, null, 2)}
Relevant Files (paths only):
${JSON.stringify(focus.relevantFiles, null, 2)}
Missing Files:
${JSON.stringify(focus.missingFiles, null, 2)}
Why these files were selected:
${focus.rationale ?? "No rationale provided."}
Relevant File Summaries (high-signal only):
${JSON.stringify(summarizedFiles, null, 2)}
Plan Suggestion Status: ${planDecision}
Question:
Based on the above, is there enough information to answer the user's question directly?
Output STRICT JSON with shape:
{
"decision": "gatherData" | "executeOnQuery",
"reason": "concise explanation",
"missing": string[]
}
`.trim();
logInputOutput("contextReviewStep", "output", prompt);
const ai = await generate({
query: context.initContext?.userQuery ?? "",
content: prompt,
});
const text = typeof ai.data === "string" ? ai.data : JSON.stringify(ai.data);
logInputOutput("contextReviewStep", "output", text);
// ------------------------------
// Parse JSON or fallback
// ------------------------------
try {
return JSON.parse(text);
}
catch {
return {
decision: text.toLowerCase().includes("gather")
? "gatherData"
: "executeOnQuery",
reason: text,
missing: [],
};
}
}