/* eslint-disable no-console */ import { Command } from 'commander'; import chalk from 'chalk'; import { searchMemories, getMemoryStats } from '../utils/memory-store.js'; // ───────────────────────────────────────────────────────────────────────────── // rigstate ask "" // Searches local memories in .rigstate/memories/ using keyword matching. // Response time: <10ms (no API calls, no LLM, pure local search). // // Examples: // rigstate ask "Why Supabase?" // rigstate ask "typescript patterns" // rigstate ask "security" --limit 10 // ───────────────────────────────────────────────────────────────────────────── export function createAskCommand(): Command { return new Command('ask') .description('Search local memories instantly (<10ms, offline)') .argument('', 'Natural language query to search memories') .option('-n, --limit ', 'Maximum results to return', '5') .action(async (query: string, options) => { const limit = parseInt(options.limit, 10) || 5; const startTime = performance.now(); const results = searchMemories(query, limit); const elapsed = (performance.now() - startTime).toFixed(1); console.log(''); if (results.length === 0) { const stats = getMemoryStats(); console.log(chalk.yellow(`🔍 No memories found for: "${query}"`)); console.log(chalk.dim(` Searched ${stats.total} memories in ${elapsed}ms.`)); if (stats.total === 0) { console.log(''); console.log(chalk.dim(' No memories yet. Start with:')); console.log(chalk.white(' rigstate remember "We chose Supabase for real-time and RLS"')); } console.log(''); return; } console.log(chalk.bold(`🧠 ${results.length} memor${results.length === 1 ? 'y' : 'ies'} found`) + chalk.dim(` (${elapsed}ms)`)); console.log(chalk.dim('────────────────────────────────────────')); for (const { memory, score, matchedFields } of results) { const categoryColor = getCategoryColor(memory.category); const stars = '⭐'.repeat(Math.min(5, Math.ceil((memory.importance || 5) / 2))); console.log(''); console.log(` ${categoryColor(memory.category)} ${chalk.bold(memory.title)} ${chalk.dim(`[${stars}]`)}`); // Show a truncated preview of content const preview = memory.content.length > 120 ? memory.content.substring(0, 120) + '...' : memory.content; console.log(` ${chalk.white(preview)}`); // Tags if (memory.tags && memory.tags.length > 0) { console.log(` ${memory.tags.map(t => chalk.yellow(`#${t}`)).join(' ')}`); } // Metadata line const meta = [ chalk.dim(`score:${score.toFixed(1)}`), chalk.dim(`matched:${matchedFields.join(',')}`), chalk.dim(`source:${memory.source}`), ]; if (memory.created_at) { const date = new Date(memory.created_at).toLocaleDateString('nb-NO'); meta.push(chalk.dim(`date:${date}`)); } console.log(` ${meta.join(' ')}`); } console.log(''); console.log(chalk.dim('────────────────────────────────────────')); const stats = getMemoryStats(); console.log(chalk.dim(`Searched ${stats.total} memories in ${elapsed}ms`)); console.log(''); }); } // ── Helpers ────────────────────────────────────────────────────────────────── function getCategoryColor(category: string): (text: string) => string { const colors: Record string> = { 'ADR': chalk.bgBlue.white, 'DECISION': chalk.bgCyan.black, 'LESSON': chalk.bgYellow.black, 'CONTEXT': chalk.bgGreen.black, 'INSTRUCTION': chalk.bgMagenta.white, 'PATTERN': chalk.bgWhite.black, 'GOTCHA': chalk.bgRed.white, }; return colors[category] || chalk.dim; }