UNPKG

@claude-vector/cli

Version:

CLI for Claude-integrated vector search

176 lines (143 loc) • 5.02 kB
/** * Open command - Open a file from search results */ import chalk from 'chalk'; import { spawn } from 'child_process'; import { promises as fs } from 'fs'; import path from 'path'; import { SessionManager, QueryOptimizer } from '@claude-vector/claude-tools'; export async function openCommand(index, options) { try { // 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.red('āŒ No recent search results found')); console.log(chalk.gray('Perform a search first:'), chalk.cyan('claude-search search "query"')); return; } // Validate index const resultIndex = parseInt(index) - 1; if (isNaN(resultIndex) || resultIndex < 0 || resultIndex >= (lastSearch.results?.length || 0)) { console.log(chalk.red('āŒ Invalid result index')); console.log(chalk.gray('Available results:'), `1-${lastSearch.results?.length || 0}`); return; } // Get the result const result = lastSearch.results[resultIndex]; const filePath = result.file || result.chunk?.file || result.chunk?.metadata?.file; if (!filePath) { console.log(chalk.red('āŒ File path not found in result')); return; } // Determine line number const lineNumber = result.chunk?.startLine || result.chunk?.metadata?.startLine || result.startLine || 1; // Determine editor const editor = options.editor || process.env.EDITOR || detectEditor(); console.log(chalk.bold('\nšŸ“‚ Opening file:')); console.log(chalk.gray('File:'), filePath); console.log(chalk.gray('Line:'), lineNumber); console.log(chalk.gray('Editor:'), editor); // Record this action as implicit positive feedback await recordOpenAction(lastSearch, resultIndex); // Open the file openInEditor(editor, filePath, lineNumber); } catch (error) { console.error(chalk.red(`\nāŒ Failed to open file: ${error.message}`)); if (process.env.DEBUG) { console.error(chalk.gray(error.stack)); } } } async function recordOpenAction(lastSearch, resultIndex) { try { // Initialize modules const sessionManager = new SessionManager(); const queryOptimizer = new QueryOptimizer(); // Record as positive feedback (opening = useful) const feedback = { useful: true, rating: 4, // Implicit rating for opened results resultIds: [resultIndex], taskType: lastSearch.taskType || 'general', action: 'opened' }; await queryOptimizer.recordFeedback(lastSearch.query, feedback); // Add to session activity const session = await sessionManager.getCurrentSessionStatus(); if (session) { await sessionManager.addActivity('file-opened', { query: lastSearch.query, file: lastSearch.results[resultIndex].file || lastSearch.results[resultIndex].chunk?.file || lastSearch.results[resultIndex].chunk?.metadata?.file, resultIndex: resultIndex }); } // Save learning data await queryOptimizer.saveHistory(); console.log(chalk.dim('āœ“ Action recorded for learning')); } catch (error) { // Don't fail the open command if recording fails if (process.env.DEBUG) { console.error(chalk.yellow('Warning: Failed to record action:'), error.message); } } } function detectEditor() { // Try to detect common editors const editors = ['code', 'vim', 'nvim', 'emacs', 'subl', 'atom', 'nano']; for (const editor of editors) { try { // Check if editor exists const result = spawn('which', [editor], { stdio: 'pipe' }); if (result.status === 0) { return editor; } } catch (error) { // Continue trying other editors } } // Default to vi if nothing else found return 'vi'; } function openInEditor(editor, filePath, lineNumber) { let args = []; // Editor-specific arguments switch (editor) { case 'code': case 'code-insiders': args = ['-g', `${filePath}:${lineNumber}`]; break; case 'vim': case 'nvim': args = [`+${lineNumber}`, filePath]; break; case 'emacs': args = [`+${lineNumber}`, filePath]; break; case 'subl': args = [`${filePath}:${lineNumber}`]; break; case 'atom': args = [`${filePath}:${lineNumber}`]; break; case 'nano': args = [`+${lineNumber}`, filePath]; break; default: // Generic: just open the file args = [filePath]; } // Spawn the editor const child = spawn(editor, args, { stdio: 'inherit', detached: true }); // Don't wait for editor to close child.unref(); console.log(chalk.green('\nāœ“ File opened in editor')); }