UNPKG

@claude-vector/cli

Version:

CLI for Claude-integrated vector search

179 lines (146 loc) • 5.78 kB
/** * Feedback command - Provide feedback on search results */ import chalk from 'chalk'; import { SessionManager, QueryOptimizer } from '@claude-vector/claude-tools'; import { promises as fs } from 'fs'; import path from 'path'; import readline from 'readline/promises'; export async function feedbackCommand(rating, options) { console.log(chalk.bold('\nšŸ“ Search Feedback\n')); try { // Initialize modules const sessionManager = new SessionManager(); const queryOptimizer = new QueryOptimizer(); // Connect modules sessionManager.setModules({ queryOptimizer }); // Get current session const session = await sessionManager.getCurrentSessionStatus(); if (!session) { console.log(chalk.yellow('⚠ No active session found')); console.log(chalk.gray('Start a new session with:'), chalk.cyan('claude-search start "your task"')); return; } // Load last search results const lastSearchPath = path.join(process.cwd(), '.claude-last-search.json'); let lastSearch = null; try { const data = await fs.readFile(lastSearchPath, 'utf-8'); lastSearch = JSON.parse(data); } catch (error) { console.log(chalk.yellow('⚠ No recent search results found')); console.log(chalk.gray('Perform a search with:'), chalk.cyan('claude-search search "query"')); return; } // Handle session feedback if (options.session) { await handleSessionFeedback(sessionManager, session, rating); return; } // Handle search result feedback await handleSearchFeedback(queryOptimizer, lastSearch, rating, options); } catch (error) { console.error(chalk.red(`\nāŒ Feedback failed: ${error.message}`)); if (process.env.DEBUG) { console.error(chalk.gray(error.stack)); } } } async function handleSearchFeedback(queryOptimizer, lastSearch, rating, options) { console.log(chalk.bold('Last search:'), chalk.cyan(`"${lastSearch.query}"`)); console.log(chalk.gray('Results found:'), lastSearch.results?.length || 0); // If no rating provided, ask for it if (!rating) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rating = await rl.question(chalk.bold('\nHow useful were these results? (1-5): ')); rl.close(); } // Validate rating const numRating = parseInt(rating); if (isNaN(numRating) || numRating < 1 || numRating > 5) { console.log(chalk.red('āŒ Rating must be between 1 and 5')); return; } // Parse useful indices if provided let usefulIndices = []; if (options.useful) { usefulIndices = options.useful.split(',').map(i => parseInt(i.trim()) - 1); } else if (numRating >= 4 && lastSearch.results?.length > 0) { // If high rating, ask which specific results were useful console.log(chalk.bold('\nWhich results were most useful?')); lastSearch.results.slice(0, 10).forEach((result, i) => { console.log(chalk.gray(`${i + 1}.`), result.file || result.chunk?.file || 'Unknown file'); }); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const indices = await rl.question(chalk.gray('Enter numbers (comma-separated, or press enter to skip): ')); rl.close(); if (indices.trim()) { usefulIndices = indices.split(',').map(i => parseInt(i.trim()) - 1); } } // Record feedback const feedback = { useful: numRating >= 3, rating: numRating, resultIds: usefulIndices.map(i => lastSearch.results?.[i]?.id || i), taskType: lastSearch.taskType || 'general' }; await queryOptimizer.recordFeedback(lastSearch.query, feedback); // Show confirmation console.log(chalk.green('\nāœ“ Feedback recorded')); if (numRating >= 4) { console.log(chalk.gray('This will help improve future search results')); } else if (numRating <= 2) { console.log(chalk.gray('Tips for better results:')); console.log(chalk.gray('• Try more specific keywords')); console.log(chalk.gray('• Use function or class names')); console.log(chalk.gray('• Lower the threshold with'), chalk.cyan('--threshold 0.2')); } // Save learning data await queryOptimizer.saveHistory(); } async function handleSessionFeedback(sessionManager, session, rating) { console.log(chalk.bold('Current session:'), session.task); console.log(chalk.gray('Duration:'), formatDuration(session.duration)); console.log(chalk.gray('Searches performed:'), session.searchCount || 0); // If no rating provided, ask for it if (!rating) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rating = await rl.question(chalk.bold('\nHow productive was this session? (1-5): ')); // Ask for additional feedback const whatWorked = await rl.question(chalk.gray('What worked well? ')); const whatDidnt = await rl.question(chalk.gray('What could be improved? ')); rl.close(); // Record session feedback if (whatWorked || whatDidnt) { await sessionManager.addActivity('feedback', { rating: parseInt(rating), positive: whatWorked, negative: whatDidnt }); } } console.log(chalk.green('\nāœ“ Session feedback recorded')); console.log(chalk.gray('Thank you for helping improve Claude Search!')); } function formatDuration(seconds) { if (!seconds) return 'Unknown'; const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (hours > 0) { return `${hours}h ${minutes}m`; } else if (minutes > 0) { return `${minutes}m`; } else { return `${seconds}s`; } }