@claude-vector/cli
Version:
CLI for Claude-integrated vector search
179 lines (146 loc) ⢠5.78 kB
JavaScript
/**
* 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`;
}
}