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 ❤️.

96 lines (88 loc) 3.57 kB
import { generate } from '../lib/generate.js'; import { logInputOutput } from '../utils/promptLogHelper.js'; function logRoutingDecision(context) { logInputOutput('planResolver', 'output', context.analysis?.routingDecision ?? {}); } export const planResolverStep = { name: 'planResolver', // 🔒 Hard contract requires: ['userQuery', 'intent'], produces: [ 'analysis.routingDecision', 'analysis.planSuggestion', ], async run(context) { context.analysis || (context.analysis = {}); const prompt = ` You are a routing classifier, not a problem solver. User query: ${context.initContext?.userQuery} Repo section: ${context.initContext?.repoTree} ${context.analysis?.folderCapsulesHuman} Decide ONE of the following: RESOLVED: - Only if the user can be answered immediately - The answer must be short (1–2 paragraphs) - No code blocks - No step-by-step instructions - No file-level documentation PLAN: - If the task requires reading, modifying, generating, or validating code - If the answer would be long, structured, or procedural - If files are mentioned or implied `.trim(); try { const genInput = { query: context.initContext?.userQuery ?? '', content: prompt, }; const genOutput = await generate(genInput); console.log('PlanResolverOutput: ', genInput.data); const raw = String(genOutput.data ?? '').trim(); logInputOutput('planResolver raw', 'output', raw); const isResolved = raw.startsWith('RESOLVED:'); const isPlan = raw.startsWith('PLAN:'); const resolvedText = raw.replace(/^RESOLVED:\s*/i, '').trim(); const incompleteAnswerPatterns = [ /possible/i, /provide/i, /need/i, /cannot/i, /missing/i, /unknown/i, /unspecified/i, /unavailable/i, /undefined/i, /incomplete/i, /insufficient/i, /ambiguous/i, /unclear/i, /requires/i, /lack/i, /omitted/i, ]; const requiresMoreWork = incompleteAnswerPatterns.some(p => p.test(resolvedText)); if (isResolved && resolvedText && !requiresMoreWork) { context.analysis.routingDecision = { decision: 'final-answer', answer: resolvedText, rationale: 'Request can be fully resolved immediately without further steps.', confidence: 0.8, }; } else { const planText = isPlan ? raw.replace(/^PLAN:\s*/i, '').trim() : resolvedText; context.analysis.planSuggestion = { text: planText, }; context.analysis.routingDecision = { decision: 'needs-plan', rationale: isPlan ? 'Model explicitly indicated planning or execution is required.' : 'Request cannot be completed without further steps or execution.', confidence: isPlan ? 0.6 : 0.4, }; } logRoutingDecision(context); } catch (err) { console.warn('⚠️ planResolver failed:', err); context.analysis.routingDecision = { decision: 'needs-plan', rationale: 'planResolver encountered an internal error.', confidence: 0.2, }; } }, };