@claude-vector/cli
Version:
CLI for Claude-integrated vector search
176 lines (143 loc) ⢠5.02 kB
JavaScript
/**
* 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'));
}