UNPKG

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

80 lines (79 loc) 2.78 kB
import fs from 'fs'; import readline from 'readline'; import chalk from 'chalk'; import { searchFiles } from '../db/fileIndex.js'; import { sanitizeQueryForFts } from '../utils/sanitizeQuery.js'; import { NUM_TOPFILES, RELATED_FILES_LIMIT, getIndexDir } from '../constants.js'; import { MainAgent } from '../agents/MainAgent.js'; import { buildLightContext } from '../utils/buildContextualPrompt.js'; export async function runAskCommand(query) { // STEP 0: Get user query if (!query) query = await promptOnce('💬 Ask your question:\n'); query = query.trim(); if (!query) { console.error('❌ No question provided.\n👉 Usage: scai ask "your question"'); return; } console.log(`📁 Using index root: ${getIndexDir()}`); // STEP 1: FTS Search const safeQuery = sanitizeQueryForFts(query); const start = Date.now(); const results = await searchFiles(query, safeQuery, RELATED_FILES_LIMIT); console.log(`⏱️ searchFiles took ${Date.now() - start}ms and returned ${results.length} result(s)`); if (results.length === 0) { console.log(chalk.redBright('❌ No results found.')); return; } // STEP 2: Build topFiles (with code) const topResults = results.slice(0, NUM_TOPFILES); const topFiles = topResults.map(r => { let code = ''; try { code = fs.readFileSync(r.path, 'utf-8'); } catch (err) { console.warn(`⚠️ Failed to read file: ${r.path}`); } return { path: r.path, summary: r.summary ?? undefined, code, }; }); console.log(chalk.greenBright(`🎯 Selected top ${topFiles.length} file(s):`)); topFiles.forEach(f => console.log(` → ${f.path}`)); // STEP 3: Related files (all results except topFiles) const relatedFiles = results.slice(NUM_TOPFILES).map(f => ({ id: f.id, path: f.path, summary: f.summary ?? undefined, })); // STEP 4: Build context prompt const promptArgs = { topFiles, relatedFiles, query, }; const context = await buildLightContext(promptArgs); // STEP 5: Run agent try { console.log('\n🤖 Launching autonomous agent...'); const agent = new MainAgent(context); await agent.run(); } catch (err) { console.error('❌ Autonomous agent run failed:', err); } } // helper function promptOnce(promptText) { return new Promise(resolve => { console.log(promptText); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.question('> ', answer => { rl.close(); resolve(answer.trim()); }); }); }