ctrlshiftleft
Version:
AI-powered toolkit for embedding QA and security testing into development workflows
66 lines (59 loc) • 1.99 kB
text/typescript
import { Command } from 'commander';
import { OpenAIAgent } from '../core/openaiAgent';
import path from 'path';
import fs from 'fs';
import { globSync } from 'glob';
/**
* Perform a semantic code search
* @param query Search query
* @param files Optional array of file paths to search within
* @returns Search results with file paths and relevance scores
*/
export async function semantic_search({
query,
files = []
}: {
query: string;
files?: string[]
}) {
const openaiAgent = new OpenAIAgent();
// If no files specified, get all TypeScript/JavaScript files in src directory
if (!files || files.length === 0) {
const srcPath = path.resolve(process.cwd(), 'src');
if (fs.existsSync(srcPath)) {
files = globSync(path.join(srcPath, '**/*.{ts,tsx,js,jsx}'), {
ignore: ['**/node_modules/**', '**/*.test.{ts,tsx,js,jsx}', '**/*.spec.{ts,tsx,js,jsx}']
});
}
}
// Read content of each file
const filesContent = files.map(filePath => {
try {
const content = fs.readFileSync(filePath, 'utf8');
return { filePath, content };
} catch (error) {
console.error(`Error reading file ${filePath}:`, error);
return null;
}
}).filter((file): file is { filePath: string; content: string } => file !== null);
try {
const results = await openaiAgent.performSemanticSearch(query, filesContent);
return results;
} catch (error) {
console.error('Error performing semantic search:', error);
return [];
}
}
/**
* Register the semantic-search command
*/
export const semanticSearchCommand = (program: Command): void => {
program
.command('semantic-search <query>')
.description('Perform a semantic code search')
.option('-f, --files <files...>', 'Specific files to search within')
.action(async (query, options) => {
const results = await semantic_search({ query, files: options.files });
console.log(JSON.stringify(results, null, 2));
});
};