UNPKG

@claude-vector/cli

Version:

CLI for Claude-integrated vector search

246 lines (214 loc) 7.43 kB
/** * Initialize command - Set up Claude Vector Search in a project */ import chalk from 'chalk'; import ora from 'ora'; import inquirer from 'inquirer'; import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs'; import { join } from 'path'; import { ProjectAdapter } from '@claude-vector/core'; export async function initCommand(options) { console.log(chalk.bold('\n🚀 Initializing Claude Vector Search\n')); const spinner = ora('Analyzing project...').start(); try { // Analyze project const adapter = new ProjectAdapter(process.cwd()); const projectInfo = await adapter.analyzeProject(); spinner.succeed(`Detected ${projectInfo.type} project (${projectInfo.language})`); // Check for existing config const configPath = join(process.cwd(), '.claude-search.config.js'); if (existsSync(configPath) && !options.force) { const { overwrite } = await inquirer.prompt([{ type: 'confirm', name: 'overwrite', message: 'Configuration already exists. Overwrite?', default: false }]); if (!overwrite) { console.log(chalk.yellow('\n⚠️ Initialization cancelled')); return; } } // Get configuration preferences const answers = await inquirer.prompt([ { type: 'confirm', name: 'useDefaults', message: 'Use recommended settings for your project?', default: true }, { type: 'list', name: 'embeddingModel', message: 'Select embedding model:', choices: [ { name: 'text-embedding-3-small (Fast, recommended)', value: 'text-embedding-3-small' }, { name: 'text-embedding-3-large (More accurate)', value: 'text-embedding-3-large' }, { name: 'text-embedding-ada-002 (Legacy)', value: 'text-embedding-ada-002' } ], when: (answers) => !answers.useDefaults }, { type: 'number', name: 'chunkSize', message: 'Maximum chunk size (tokens):', default: 1000, when: (answers) => !answers.useDefaults }, { type: 'checkbox', name: 'features', message: 'Select features to enable:', choices: [ { name: 'Auto-indexing on file changes', value: 'autoIndex', checked: true }, { name: 'Search result caching', value: 'cache', checked: true }, { name: 'Context persistence', value: 'persistence', checked: true }, { name: 'Error analysis', value: 'errorAnalysis', checked: true }, { name: 'Workflow automation', value: 'workflow', checked: true } ], when: (answers) => !answers.useDefaults } ]); // Generate configuration const config = generateConfig(projectInfo, answers); // Write configuration file spinner.start('Creating configuration...'); writeFileSync(configPath, config); spinner.succeed('Configuration created'); // Create directories spinner.start('Creating directories...'); const dirs = [ '.claude-vector-index', '.claude-vector-cache', '.claude-sessions' ]; for (const dir of dirs) { const dirPath = join(process.cwd(), dir); if (!existsSync(dirPath)) { mkdirSync(dirPath, { recursive: true }); } } spinner.succeed('Directories created'); // Update .gitignore spinner.start('Updating .gitignore...'); updateGitignore(); spinner.succeed('.gitignore updated'); // Check for API key if (!process.env.OPENAI_API_KEY) { console.log(chalk.yellow('\n⚠️ OpenAI API key not found')); console.log(chalk.gray('Set your API key with: export OPENAI_API_KEY=your-key')); } // Success message console.log(chalk.green('\n✅ Claude Vector Search initialized successfully!\n')); console.log(chalk.bold('Next steps:')); console.log(chalk.gray('1.'), 'Build the search index:', chalk.cyan('claude-search index')); console.log(chalk.gray('2.'), 'Start searching:', chalk.cyan('claude-search search "your query"')); console.log(chalk.gray('3.'), 'Start a task:', chalk.cyan('claude-search start "your task"')); // 正常終了 process.exit(0); } catch (error) { spinner.fail(`Initialization failed: ${error.message}`); process.exit(1); } } function generateConfig(projectInfo, answers) { const useDefaults = answers.useDefaults !== false; const config = `/** * Claude Vector Search Configuration * Generated for: ${projectInfo.type} project */ export default { // Project information project: { type: '${projectInfo.type}', language: '${projectInfo.language}', framework: ${projectInfo.framework ? `'${projectInfo.framework}'` : null} }, // File patterns patterns: { include: [ ${projectInfo.language === 'typescript' ? "'**/*.{ts,tsx}',\n " : ''}'**/*.{js,jsx}', '**/*.{md,mdx}', ${projectInfo.type === 'nextjs' ? "'app/**/*',\n 'pages/**/*',\n " : ''}'**/*.json' ], exclude: [ '**/node_modules/**', '**/dist/**', '**/build/**', '**/.next/**', '**/coverage/**', '**/.git/**', '**/tmp/**', '**/*.min.js' ] }, // Embedding settings embeddings: { model: '${useDefaults ? 'text-embedding-3-small' : answers.embeddingModel}', batchSize: 100, dimensions: ${useDefaults || answers.embeddingModel === 'text-embedding-3-small' ? 1536 : 3072} }, // Chunk processing chunks: { maxSize: ${useDefaults ? 1000 : answers.chunkSize}, minSize: 100, overlap: 200, splitByParagraph: true, preserveCodeBlocks: true }, // Search settings search: { threshold: 0.7, maxResults: 10, includeMetadata: true }, // Features features: { autoIndex: ${useDefaults || answers.features?.includes('autoIndex')}, cache: ${useDefaults || answers.features?.includes('cache')}, persistence: ${useDefaults || answers.features?.includes('persistence')}, errorAnalysis: ${useDefaults || answers.features?.includes('errorAnalysis')}, workflow: ${useDefaults || answers.features?.includes('workflow')} }, // Cache settings cache: { enabled: ${useDefaults || answers.features?.includes('cache')}, ttl: 3600, // 1 hour maxSize: '100MB' }, // Index settings index: { path: '.claude-vector-index', autoUpdate: ${useDefaults || answers.features?.includes('autoIndex')}, updateInterval: 300000 // 5 minutes } }; `; return config; } function updateGitignore() { const gitignorePath = join(process.cwd(), '.gitignore'); const ignorePatterns = [ '\n# Claude Vector Search', '.claude-vector-index/', '.claude-vector-cache/', '.claude-sessions/', '.env.local' ]; try { let content = ''; if (existsSync(gitignorePath)) { content = readFileSync(gitignorePath, 'utf-8'); } // Check if patterns already exist const patternsToAdd = ignorePatterns.filter(pattern => !content.includes(pattern.replace('\n# Claude Vector Search', '')) ); if (patternsToAdd.length > 0) { content += '\n' + patternsToAdd.join('\n') + '\n'; writeFileSync(gitignorePath, content); } } catch (error) { console.warn(chalk.yellow('Warning: Could not update .gitignore')); } }