ruvector 0.1.46 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/cli.js +615 -3
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -2311,7 +2311,9 @@ hooksCmd.command('init')
2311
2311
  .option('--no-gitignore', 'Skip .gitignore update')
2312
2312
  .option('--no-mcp', 'Skip MCP server configuration')
2313
2313
  .option('--no-statusline', 'Skip statusLine configuration')
2314
- .action((opts) => {
2314
+ .option('--pretrain', 'Run pretrain after init to bootstrap intelligence')
2315
+ .option('--build-agents [focus]', 'Generate optimized agents (quality|speed|security|testing|fullstack)')
2316
+ .action(async (opts) => {
2315
2317
  const settingsPath = path.join(process.cwd(), '.claude', 'settings.json');
2316
2318
  const settingsDir = path.dirname(settingsPath);
2317
2319
  if (!fs.existsSync(settingsDir)) fs.mkdirSync(settingsDir, { recursive: true });
@@ -2353,7 +2355,8 @@ hooksCmd.command('init')
2353
2355
  'Bash(rm -rf /)',
2354
2356
  'Bash(sudo rm:*)',
2355
2357
  'Bash(chmod 777:*)',
2356
- 'Bash(:(){ :|:& };:)'
2358
+ 'Bash(mkfs:*)',
2359
+ 'Bash(dd if=/dev/zero:*)'
2357
2360
  ];
2358
2361
  console.log(chalk.blue(' ✓ Permissions configured (project-specific)'));
2359
2362
  }
@@ -2572,7 +2575,35 @@ npx ruvector hooks init --force # Overwrite existing
2572
2575
  }
2573
2576
 
2574
2577
  console.log(chalk.green('\n✅ RuVector hooks initialization complete!'));
2575
- console.log(chalk.dim(' Run `npx ruvector hooks verify` to test the setup'));
2578
+
2579
+ // Run pretrain if requested
2580
+ if (opts.pretrain) {
2581
+ console.log(chalk.yellow('\n📚 Running pretrain to bootstrap intelligence...\n'));
2582
+ const { execSync } = require('child_process');
2583
+ try {
2584
+ execSync('npx ruvector hooks pretrain', { stdio: 'inherit' });
2585
+ } catch (e) {
2586
+ console.log(chalk.yellow('⚠️ Pretrain completed with warnings'));
2587
+ }
2588
+ }
2589
+
2590
+ // Build agents if requested
2591
+ if (opts.buildAgents) {
2592
+ const focus = typeof opts.buildAgents === 'string' ? opts.buildAgents : 'quality';
2593
+ console.log(chalk.yellow(`\n🏗️ Building optimized agents (focus: ${focus})...\n`));
2594
+ const { execSync } = require('child_process');
2595
+ try {
2596
+ execSync(`npx ruvector hooks build-agents --focus ${focus} --include-prompts`, { stdio: 'inherit' });
2597
+ } catch (e) {
2598
+ console.log(chalk.yellow('⚠️ Agent build completed with warnings'));
2599
+ }
2600
+ }
2601
+
2602
+ if (!opts.pretrain && !opts.buildAgents) {
2603
+ console.log(chalk.dim(' Run `npx ruvector hooks verify` to test the setup'));
2604
+ console.log(chalk.dim(' Run `npx ruvector hooks pretrain` to bootstrap intelligence'));
2605
+ console.log(chalk.dim(' Run `npx ruvector hooks build-agents` to generate optimized agents'));
2606
+ }
2576
2607
  });
2577
2608
 
2578
2609
  hooksCmd.command('stats').description('Show intelligence statistics').action(() => {
@@ -2996,4 +3027,585 @@ hooksCmd.command('import')
2996
3027
  }
2997
3028
  });
2998
3029
 
3030
+ // Pretrain - analyze repo and bootstrap learning with agent swarm
3031
+ hooksCmd.command('pretrain')
3032
+ .description('Pretrain intelligence by analyzing the repository with agent swarm')
3033
+ .option('--depth <n>', 'Git history depth to analyze', '100')
3034
+ .option('--workers <n>', 'Number of parallel analysis workers', '4')
3035
+ .option('--skip-git', 'Skip git history analysis')
3036
+ .option('--skip-files', 'Skip file structure analysis')
3037
+ .option('--verbose', 'Show detailed progress')
3038
+ .action(async (opts) => {
3039
+ const { execSync, spawn } = require('child_process');
3040
+ console.log(chalk.bold.cyan('\n🧠 RuVector Pretrain - Repository Intelligence Bootstrap\n'));
3041
+
3042
+ const intel = new Intelligence();
3043
+ const startTime = Date.now();
3044
+ const stats = { files: 0, patterns: 0, memories: 0, coedits: 0 };
3045
+
3046
+ // Agent types for different file patterns
3047
+ const agentMapping = {
3048
+ // Rust
3049
+ '.rs': 'rust-developer',
3050
+ 'Cargo.toml': 'rust-developer',
3051
+ 'Cargo.lock': 'rust-developer',
3052
+ // JavaScript/TypeScript
3053
+ '.js': 'javascript-developer',
3054
+ '.jsx': 'react-developer',
3055
+ '.ts': 'typescript-developer',
3056
+ '.tsx': 'react-developer',
3057
+ '.mjs': 'javascript-developer',
3058
+ '.cjs': 'javascript-developer',
3059
+ 'package.json': 'node-developer',
3060
+ // Python
3061
+ '.py': 'python-developer',
3062
+ 'requirements.txt': 'python-developer',
3063
+ 'pyproject.toml': 'python-developer',
3064
+ 'setup.py': 'python-developer',
3065
+ // Go
3066
+ '.go': 'go-developer',
3067
+ 'go.mod': 'go-developer',
3068
+ // Web
3069
+ '.html': 'frontend-developer',
3070
+ '.css': 'frontend-developer',
3071
+ '.scss': 'frontend-developer',
3072
+ '.vue': 'vue-developer',
3073
+ '.svelte': 'svelte-developer',
3074
+ // Config
3075
+ '.json': 'config-specialist',
3076
+ '.yaml': 'config-specialist',
3077
+ '.yml': 'config-specialist',
3078
+ '.toml': 'config-specialist',
3079
+ // Docs
3080
+ '.md': 'documentation-specialist',
3081
+ '.mdx': 'documentation-specialist',
3082
+ // Tests
3083
+ '.test.js': 'test-engineer',
3084
+ '.test.ts': 'test-engineer',
3085
+ '.spec.js': 'test-engineer',
3086
+ '.spec.ts': 'test-engineer',
3087
+ '_test.go': 'test-engineer',
3088
+ '_test.rs': 'test-engineer',
3089
+ // DevOps
3090
+ 'Dockerfile': 'devops-engineer',
3091
+ 'docker-compose.yml': 'devops-engineer',
3092
+ '.github/workflows': 'cicd-engineer',
3093
+ 'Makefile': 'devops-engineer',
3094
+ // SQL
3095
+ '.sql': 'database-specialist',
3096
+ };
3097
+
3098
+ // Phase 1: Analyze file structure
3099
+ if (!opts.skipFiles) {
3100
+ console.log(chalk.yellow('📁 Phase 1: Analyzing file structure...\n'));
3101
+
3102
+ try {
3103
+ // Get all files in repo
3104
+ const files = execSync('git ls-files 2>/dev/null || find . -type f -not -path "./.git/*" -not -path "./node_modules/*" -not -path "./target/*"',
3105
+ { encoding: 'utf-8', maxBuffer: 50 * 1024 * 1024 }).trim().split('\n').filter(f => f);
3106
+
3107
+ const filesByType = {};
3108
+ const dirPatterns = {};
3109
+
3110
+ files.forEach(file => {
3111
+ stats.files++;
3112
+ const ext = path.extname(file);
3113
+ const basename = path.basename(file);
3114
+ const dir = path.dirname(file);
3115
+
3116
+ // Determine agent for this file
3117
+ let agent = 'coder'; // default
3118
+ if (agentMapping[basename]) {
3119
+ agent = agentMapping[basename];
3120
+ } else if (agentMapping[ext]) {
3121
+ agent = agentMapping[ext];
3122
+ } else if (file.includes('.test.') || file.includes('.spec.') || file.includes('_test.')) {
3123
+ agent = 'test-engineer';
3124
+ } else if (file.includes('.github/workflows')) {
3125
+ agent = 'cicd-engineer';
3126
+ }
3127
+
3128
+ // Track file types
3129
+ filesByType[ext] = (filesByType[ext] || 0) + 1;
3130
+
3131
+ // Track directory patterns
3132
+ const parts = dir.split('/');
3133
+ if (parts[0]) {
3134
+ dirPatterns[parts[0]] = dirPatterns[parts[0]] || { count: 0, agents: {} };
3135
+ dirPatterns[parts[0]].count++;
3136
+ dirPatterns[parts[0]].agents[agent] = (dirPatterns[parts[0]].agents[agent] || 0) + 1;
3137
+ }
3138
+
3139
+ // Create Q-learning pattern for this file type
3140
+ const state = `edit:${ext || 'unknown'}`;
3141
+ if (!intel.data.patterns[state]) {
3142
+ intel.data.patterns[state] = {};
3143
+ }
3144
+ intel.data.patterns[state][agent] = (intel.data.patterns[state][agent] || 0) + 0.5;
3145
+ stats.patterns++;
3146
+ });
3147
+
3148
+ // Log summary
3149
+ if (opts.verbose) {
3150
+ console.log(chalk.dim(' File types found:'));
3151
+ Object.entries(filesByType).sort((a, b) => b[1] - a[1]).slice(0, 10).forEach(([ext, count]) => {
3152
+ console.log(chalk.dim(` ${ext || '(no ext)'}: ${count} files`));
3153
+ });
3154
+ }
3155
+ console.log(chalk.green(` ✓ Analyzed ${stats.files} files`));
3156
+ console.log(chalk.green(` ✓ Created ${Object.keys(intel.data.patterns).length} routing patterns`));
3157
+
3158
+ } catch (e) {
3159
+ console.log(chalk.yellow(` ⚠ File analysis skipped: ${e.message}`));
3160
+ }
3161
+ }
3162
+
3163
+ // Phase 2: Analyze git history for co-edit patterns
3164
+ if (!opts.skipGit) {
3165
+ console.log(chalk.yellow('\n📜 Phase 2: Analyzing git history for co-edit patterns...\n'));
3166
+
3167
+ try {
3168
+ // Get commits with files changed
3169
+ const gitLog = execSync(
3170
+ `git log --name-only --pretty=format:"COMMIT:%H" -n ${opts.depth} 2>/dev/null`,
3171
+ { encoding: 'utf-8', maxBuffer: 50 * 1024 * 1024 }
3172
+ );
3173
+
3174
+ const commits = gitLog.split('COMMIT:').filter(c => c.trim());
3175
+ const coEditMap = {};
3176
+
3177
+ commits.forEach(commit => {
3178
+ const lines = commit.trim().split('\n').filter(l => l && !l.startsWith('COMMIT:'));
3179
+ const files = lines.slice(1).filter(f => f.trim()); // Skip the hash
3180
+
3181
+ // Track which files are edited together
3182
+ files.forEach(file1 => {
3183
+ files.forEach(file2 => {
3184
+ if (file1 !== file2) {
3185
+ const key = [file1, file2].sort().join('|');
3186
+ coEditMap[key] = (coEditMap[key] || 0) + 1;
3187
+ }
3188
+ });
3189
+ });
3190
+ });
3191
+
3192
+ // Find strong co-edit patterns (files edited together 3+ times)
3193
+ const strongPatterns = Object.entries(coEditMap)
3194
+ .filter(([, count]) => count >= 3)
3195
+ .sort((a, b) => b[1] - a[1]);
3196
+
3197
+ // Store as sequence patterns
3198
+ strongPatterns.slice(0, 100).forEach(([key, count]) => {
3199
+ const [file1, file2] = key.split('|');
3200
+ if (!intel.data.sequences) intel.data.sequences = {};
3201
+ if (!intel.data.sequences[file1]) intel.data.sequences[file1] = [];
3202
+
3203
+ const existing = intel.data.sequences[file1].find(s => s.file === file2);
3204
+ if (existing) {
3205
+ existing.score += count;
3206
+ } else {
3207
+ intel.data.sequences[file1].push({ file: file2, score: count });
3208
+ }
3209
+ stats.coedits++;
3210
+ });
3211
+
3212
+ console.log(chalk.green(` ✓ Analyzed ${commits.length} commits`));
3213
+ console.log(chalk.green(` ✓ Found ${strongPatterns.length} co-edit patterns`));
3214
+
3215
+ if (opts.verbose && strongPatterns.length > 0) {
3216
+ console.log(chalk.dim(' Top co-edit patterns:'));
3217
+ strongPatterns.slice(0, 5).forEach(([key, count]) => {
3218
+ const [f1, f2] = key.split('|');
3219
+ console.log(chalk.dim(` ${path.basename(f1)} ↔ ${path.basename(f2)}: ${count} times`));
3220
+ });
3221
+ }
3222
+
3223
+ } catch (e) {
3224
+ console.log(chalk.yellow(` ⚠ Git analysis skipped: ${e.message}`));
3225
+ }
3226
+ }
3227
+
3228
+ // Phase 3: Create vector memories from important files
3229
+ console.log(chalk.yellow('\n💾 Phase 3: Creating vector memories from key files...\n'));
3230
+
3231
+ try {
3232
+ const importantFiles = [
3233
+ 'README.md', 'CLAUDE.md', 'package.json', 'Cargo.toml',
3234
+ 'pyproject.toml', 'go.mod', '.claude/settings.json'
3235
+ ];
3236
+
3237
+ for (const filename of importantFiles) {
3238
+ const filePath = path.join(process.cwd(), filename);
3239
+ if (fs.existsSync(filePath)) {
3240
+ try {
3241
+ const content = fs.readFileSync(filePath, 'utf-8').slice(0, 2000); // First 2KB
3242
+ intel.data.memories = intel.data.memories || [];
3243
+ intel.data.memories.push({
3244
+ content: `[${filename}] ${content.replace(/\n/g, ' ').slice(0, 500)}`,
3245
+ type: 'project',
3246
+ created: new Date().toISOString(),
3247
+ embedding: intel.simpleEmbed ? intel.simpleEmbed(content) : null
3248
+ });
3249
+ stats.memories++;
3250
+ if (opts.verbose) console.log(chalk.dim(` ✓ ${filename}`));
3251
+ } catch (e) { /* skip unreadable files */ }
3252
+ }
3253
+ }
3254
+
3255
+ console.log(chalk.green(` ✓ Created ${stats.memories} memory entries`));
3256
+
3257
+ } catch (e) {
3258
+ console.log(chalk.yellow(` ⚠ Memory creation skipped: ${e.message}`));
3259
+ }
3260
+
3261
+ // Phase 4: Analyze directory structure for agent recommendations
3262
+ console.log(chalk.yellow('\n🗂️ Phase 4: Building directory-agent mappings...\n'));
3263
+
3264
+ try {
3265
+ const dirs = execSync('find . -type d -maxdepth 2 -not -path "./.git*" -not -path "./node_modules*" -not -path "./target*" 2>/dev/null || echo "."',
3266
+ { encoding: 'utf-8' }).trim().split('\n');
3267
+
3268
+ const dirAgentMap = {};
3269
+ dirs.forEach(dir => {
3270
+ const name = path.basename(dir);
3271
+ // Infer agent from directory name
3272
+ if (['src', 'lib', 'core'].includes(name)) dirAgentMap[dir] = 'coder';
3273
+ else if (['test', 'tests', '__tests__', 'spec'].includes(name)) dirAgentMap[dir] = 'test-engineer';
3274
+ else if (['docs', 'documentation'].includes(name)) dirAgentMap[dir] = 'documentation-specialist';
3275
+ else if (['scripts', 'bin'].includes(name)) dirAgentMap[dir] = 'devops-engineer';
3276
+ else if (['components', 'views', 'pages'].includes(name)) dirAgentMap[dir] = 'frontend-developer';
3277
+ else if (['api', 'routes', 'handlers'].includes(name)) dirAgentMap[dir] = 'backend-developer';
3278
+ else if (['models', 'entities', 'schemas'].includes(name)) dirAgentMap[dir] = 'database-specialist';
3279
+ else if (['.github', '.gitlab', 'ci'].includes(name)) dirAgentMap[dir] = 'cicd-engineer';
3280
+ });
3281
+
3282
+ // Store directory patterns
3283
+ intel.data.dirPatterns = dirAgentMap;
3284
+ console.log(chalk.green(` ✓ Mapped ${Object.keys(dirAgentMap).length} directories to agents`));
3285
+
3286
+ } catch (e) {
3287
+ console.log(chalk.yellow(` ⚠ Directory analysis skipped: ${e.message}`));
3288
+ }
3289
+
3290
+ // Save all learning data
3291
+ intel.data.pretrained = {
3292
+ date: new Date().toISOString(),
3293
+ stats: stats
3294
+ };
3295
+ intel.save();
3296
+
3297
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
3298
+ console.log(chalk.bold.green(`\n✅ Pretrain complete in ${elapsed}s!\n`));
3299
+ console.log(chalk.cyan('Summary:'));
3300
+ console.log(` 📁 ${stats.files} files analyzed`);
3301
+ console.log(` 🧠 ${stats.patterns} agent routing patterns`);
3302
+ console.log(` 🔗 ${stats.coedits} co-edit patterns`);
3303
+ console.log(` 💾 ${stats.memories} memory entries`);
3304
+ console.log(chalk.dim('\nThe intelligence layer will now provide better recommendations.'));
3305
+ });
3306
+
3307
+ // Agent Builder - generate optimized agent configs based on pretrain
3308
+ hooksCmd.command('build-agents')
3309
+ .description('Generate optimized agent configurations based on repository analysis')
3310
+ .option('--focus <type>', 'Focus type: quality, speed, security, testing, fullstack', 'quality')
3311
+ .option('--output <dir>', 'Output directory', '.claude/agents')
3312
+ .option('--format <fmt>', 'Format: yaml, json, md', 'yaml')
3313
+ .option('--include-prompts', 'Include detailed system prompts')
3314
+ .action((opts) => {
3315
+ console.log(chalk.bold.cyan('\n🏗️ RuVector Agent Builder\n'));
3316
+
3317
+ const intel = new Intelligence();
3318
+ const outputDir = path.join(process.cwd(), opts.output);
3319
+
3320
+ // Check if pretrained
3321
+ if (!intel.data.pretrained && Object.keys(intel.data.patterns || {}).length === 0) {
3322
+ console.log(chalk.yellow('⚠️ No pretrain data found. Running quick analysis...\n'));
3323
+ // Quick file analysis
3324
+ try {
3325
+ const { execSync } = require('child_process');
3326
+ const files = execSync('git ls-files 2>/dev/null', { encoding: 'utf-8' }).trim().split('\n');
3327
+ files.forEach(f => {
3328
+ const ext = path.extname(f);
3329
+ intel.data.patterns = intel.data.patterns || {};
3330
+ intel.data.patterns[`edit:${ext}`] = intel.data.patterns[`edit:${ext}`] || {};
3331
+ });
3332
+ } catch (e) { /* continue without git */ }
3333
+ }
3334
+
3335
+ // Analyze patterns to determine relevant agents
3336
+ const patterns = intel.data.patterns || {};
3337
+ const detectedLangs = new Set();
3338
+ const detectedFrameworks = new Set();
3339
+
3340
+ Object.keys(patterns).forEach(state => {
3341
+ if (state.includes('.rs')) detectedLangs.add('rust');
3342
+ if (state.includes('.ts') || state.includes('.js')) detectedLangs.add('typescript');
3343
+ if (state.includes('.tsx') || state.includes('.jsx')) detectedFrameworks.add('react');
3344
+ if (state.includes('.py')) detectedLangs.add('python');
3345
+ if (state.includes('.go')) detectedLangs.add('go');
3346
+ if (state.includes('.vue')) detectedFrameworks.add('vue');
3347
+ if (state.includes('.sql')) detectedFrameworks.add('database');
3348
+ });
3349
+
3350
+ // Detect project type from files
3351
+ const projectTypes = detectProjectType();
3352
+
3353
+ console.log(chalk.blue(` Detected languages: ${[...detectedLangs].join(', ') || 'generic'}`));
3354
+ console.log(chalk.blue(` Detected frameworks: ${[...detectedFrameworks].join(', ') || 'none'}`));
3355
+ console.log(chalk.blue(` Focus mode: ${opts.focus}\n`));
3356
+
3357
+ // Focus configurations
3358
+ const focusConfigs = {
3359
+ quality: {
3360
+ description: 'Emphasizes code quality, best practices, and maintainability',
3361
+ priorities: ['code-review', 'refactoring', 'documentation', 'testing'],
3362
+ temperature: 0.3
3363
+ },
3364
+ speed: {
3365
+ description: 'Optimized for rapid development and iteration',
3366
+ priorities: ['implementation', 'prototyping', 'quick-fixes'],
3367
+ temperature: 0.7
3368
+ },
3369
+ security: {
3370
+ description: 'Security-first development with vulnerability awareness',
3371
+ priorities: ['security-audit', 'input-validation', 'authentication', 'encryption'],
3372
+ temperature: 0.2
3373
+ },
3374
+ testing: {
3375
+ description: 'Test-driven development with comprehensive coverage',
3376
+ priorities: ['unit-tests', 'integration-tests', 'e2e-tests', 'mocking'],
3377
+ temperature: 0.4
3378
+ },
3379
+ fullstack: {
3380
+ description: 'Balanced full-stack development capabilities',
3381
+ priorities: ['frontend', 'backend', 'database', 'api-design'],
3382
+ temperature: 0.5
3383
+ }
3384
+ };
3385
+
3386
+ const focus = focusConfigs[opts.focus] || focusConfigs.quality;
3387
+
3388
+ // Agent templates based on detected stack
3389
+ const agents = [];
3390
+
3391
+ // Core agents based on detected languages
3392
+ if (detectedLangs.has('rust')) {
3393
+ agents.push({
3394
+ name: 'rust-specialist',
3395
+ type: 'rust-developer',
3396
+ description: 'Rust development specialist for this codebase',
3397
+ capabilities: ['cargo', 'unsafe-rust', 'async-rust', 'wasm', 'error-handling'],
3398
+ focus: focus.priorities,
3399
+ systemPrompt: opts.includePrompts ? `You are a Rust specialist for this project.
3400
+ Focus on: memory safety, zero-cost abstractions, idiomatic Rust patterns.
3401
+ Use cargo conventions, prefer Result over panic, leverage the type system.
3402
+ ${focus.description}` : null
3403
+ });
3404
+ }
3405
+
3406
+ if (detectedLangs.has('typescript')) {
3407
+ agents.push({
3408
+ name: 'typescript-specialist',
3409
+ type: 'typescript-developer',
3410
+ description: 'TypeScript development specialist',
3411
+ capabilities: ['types', 'generics', 'decorators', 'async-await', 'modules'],
3412
+ focus: focus.priorities,
3413
+ systemPrompt: opts.includePrompts ? `You are a TypeScript specialist for this project.
3414
+ Focus on: strict typing, type inference, generic patterns, module organization.
3415
+ Prefer type safety over any, use discriminated unions, leverage utility types.
3416
+ ${focus.description}` : null
3417
+ });
3418
+ }
3419
+
3420
+ if (detectedLangs.has('python')) {
3421
+ agents.push({
3422
+ name: 'python-specialist',
3423
+ type: 'python-developer',
3424
+ description: 'Python development specialist',
3425
+ capabilities: ['typing', 'async', 'testing', 'packaging', 'data-science'],
3426
+ focus: focus.priorities,
3427
+ systemPrompt: opts.includePrompts ? `You are a Python specialist for this project.
3428
+ Focus on: type hints, PEP standards, pythonic idioms, virtual environments.
3429
+ Use dataclasses, prefer pathlib, leverage context managers.
3430
+ ${focus.description}` : null
3431
+ });
3432
+ }
3433
+
3434
+ if (detectedLangs.has('go')) {
3435
+ agents.push({
3436
+ name: 'go-specialist',
3437
+ type: 'go-developer',
3438
+ description: 'Go development specialist',
3439
+ capabilities: ['goroutines', 'channels', 'interfaces', 'testing', 'modules'],
3440
+ focus: focus.priorities,
3441
+ systemPrompt: opts.includePrompts ? `You are a Go specialist for this project.
3442
+ Focus on: simplicity, explicit error handling, goroutines, interface composition.
3443
+ Follow Go conventions, use go fmt, prefer composition over inheritance.
3444
+ ${focus.description}` : null
3445
+ });
3446
+ }
3447
+
3448
+ // Framework-specific agents
3449
+ if (detectedFrameworks.has('react')) {
3450
+ agents.push({
3451
+ name: 'react-specialist',
3452
+ type: 'react-developer',
3453
+ description: 'React/Next.js development specialist',
3454
+ capabilities: ['hooks', 'state-management', 'components', 'ssr', 'testing'],
3455
+ focus: focus.priorities,
3456
+ systemPrompt: opts.includePrompts ? `You are a React specialist for this project.
3457
+ Focus on: functional components, hooks, state management, performance optimization.
3458
+ Prefer composition, use memo wisely, follow React best practices.
3459
+ ${focus.description}` : null
3460
+ });
3461
+ }
3462
+
3463
+ if (detectedFrameworks.has('database')) {
3464
+ agents.push({
3465
+ name: 'database-specialist',
3466
+ type: 'database-specialist',
3467
+ description: 'Database design and optimization specialist',
3468
+ capabilities: ['schema-design', 'queries', 'indexing', 'migrations', 'orm'],
3469
+ focus: focus.priorities,
3470
+ systemPrompt: opts.includePrompts ? `You are a database specialist for this project.
3471
+ Focus on: normalized schemas, efficient queries, proper indexing, data integrity.
3472
+ Consider performance implications, use transactions appropriately.
3473
+ ${focus.description}` : null
3474
+ });
3475
+ }
3476
+
3477
+ // Focus-specific agents
3478
+ if (opts.focus === 'testing' || opts.focus === 'quality') {
3479
+ agents.push({
3480
+ name: 'test-architect',
3481
+ type: 'test-engineer',
3482
+ description: 'Testing and quality assurance specialist',
3483
+ capabilities: ['unit-tests', 'integration-tests', 'mocking', 'coverage', 'tdd'],
3484
+ focus: ['testing', 'quality', 'reliability'],
3485
+ systemPrompt: opts.includePrompts ? `You are a testing specialist for this project.
3486
+ Focus on: comprehensive test coverage, meaningful assertions, test isolation.
3487
+ Write tests first when possible, mock external dependencies, aim for >80% coverage.
3488
+ ${focus.description}` : null
3489
+ });
3490
+ }
3491
+
3492
+ if (opts.focus === 'security') {
3493
+ agents.push({
3494
+ name: 'security-auditor',
3495
+ type: 'security-specialist',
3496
+ description: 'Security audit and hardening specialist',
3497
+ capabilities: ['vulnerability-scan', 'auth', 'encryption', 'input-validation', 'owasp'],
3498
+ focus: ['security', 'compliance', 'hardening'],
3499
+ systemPrompt: opts.includePrompts ? `You are a security specialist for this project.
3500
+ Focus on: OWASP top 10, input validation, authentication, authorization, encryption.
3501
+ Never trust user input, use parameterized queries, implement defense in depth.
3502
+ ${focus.description}` : null
3503
+ });
3504
+ }
3505
+
3506
+ // Add coordinator agent
3507
+ agents.push({
3508
+ name: 'project-coordinator',
3509
+ type: 'coordinator',
3510
+ description: 'Coordinates multi-agent workflows for this project',
3511
+ capabilities: ['task-decomposition', 'agent-routing', 'context-management'],
3512
+ focus: focus.priorities,
3513
+ routes: agents.filter(a => a.name !== 'project-coordinator').map(a => ({
3514
+ pattern: a.capabilities[0],
3515
+ agent: a.name
3516
+ }))
3517
+ });
3518
+
3519
+ // Create output directory
3520
+ if (!fs.existsSync(outputDir)) {
3521
+ fs.mkdirSync(outputDir, { recursive: true });
3522
+ }
3523
+
3524
+ // Generate agent files
3525
+ agents.forEach(agent => {
3526
+ let content;
3527
+ const filename = `${agent.name}.${opts.format}`;
3528
+ const filepath = path.join(outputDir, filename);
3529
+
3530
+ if (opts.format === 'yaml') {
3531
+ const yaml = [
3532
+ `# Auto-generated by RuVector Agent Builder`,
3533
+ `# Focus: ${opts.focus}`,
3534
+ `# Generated: ${new Date().toISOString()}`,
3535
+ ``,
3536
+ `name: ${agent.name}`,
3537
+ `type: ${agent.type}`,
3538
+ `description: ${agent.description}`,
3539
+ ``,
3540
+ `capabilities:`,
3541
+ ...agent.capabilities.map(c => ` - ${c}`),
3542
+ ``,
3543
+ `focus:`,
3544
+ ...agent.focus.map(f => ` - ${f}`),
3545
+ ];
3546
+ if (agent.systemPrompt) {
3547
+ yaml.push(``, `system_prompt: |`);
3548
+ agent.systemPrompt.split('\n').forEach(line => yaml.push(` ${line}`));
3549
+ }
3550
+ if (agent.routes) {
3551
+ yaml.push(``, `routes:`);
3552
+ agent.routes.forEach(r => yaml.push(` - pattern: "${r.pattern}"`, ` agent: ${r.agent}`));
3553
+ }
3554
+ content = yaml.join('\n');
3555
+ } else if (opts.format === 'json') {
3556
+ content = JSON.stringify(agent, null, 2);
3557
+ } else {
3558
+ // Markdown format
3559
+ content = [
3560
+ `# ${agent.name}`,
3561
+ ``,
3562
+ `**Type:** ${agent.type}`,
3563
+ `**Description:** ${agent.description}`,
3564
+ ``,
3565
+ `## Capabilities`,
3566
+ ...agent.capabilities.map(c => `- ${c}`),
3567
+ ``,
3568
+ `## Focus Areas`,
3569
+ ...agent.focus.map(f => `- ${f}`),
3570
+ ].join('\n');
3571
+ if (agent.systemPrompt) {
3572
+ content += `\n\n## System Prompt\n\n\`\`\`\n${agent.systemPrompt}\n\`\`\``;
3573
+ }
3574
+ }
3575
+
3576
+ fs.writeFileSync(filepath, content);
3577
+ console.log(chalk.green(` ✓ Created ${filename}`));
3578
+ });
3579
+
3580
+ // Create index file
3581
+ const indexContent = opts.format === 'yaml'
3582
+ ? `# RuVector Agent Configuration\n# Focus: ${opts.focus}\n\nagents:\n${agents.map(a => ` - ${a.name}`).join('\n')}`
3583
+ : JSON.stringify({ focus: opts.focus, agents: agents.map(a => a.name) }, null, 2);
3584
+
3585
+ fs.writeFileSync(path.join(outputDir, `index.${opts.format === 'md' ? 'json' : opts.format}`), indexContent);
3586
+
3587
+ // Update settings to reference agents
3588
+ const settingsPath = path.join(process.cwd(), '.claude', 'settings.json');
3589
+ if (fs.existsSync(settingsPath)) {
3590
+ try {
3591
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
3592
+ settings.agentConfig = {
3593
+ directory: opts.output,
3594
+ focus: opts.focus,
3595
+ agents: agents.map(a => a.name),
3596
+ generated: new Date().toISOString()
3597
+ };
3598
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
3599
+ console.log(chalk.blue('\n ✓ Updated .claude/settings.json with agent config'));
3600
+ } catch (e) { /* ignore settings errors */ }
3601
+ }
3602
+
3603
+ console.log(chalk.bold.green(`\n✅ Generated ${agents.length} optimized agents in ${opts.output}/\n`));
3604
+ console.log(chalk.cyan('Agents created:'));
3605
+ agents.forEach(a => {
3606
+ console.log(` 🤖 ${chalk.bold(a.name)}: ${a.description}`);
3607
+ });
3608
+ console.log(chalk.dim(`\nFocus mode "${opts.focus}": ${focus.description}`));
3609
+ });
3610
+
2999
3611
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvector",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "High-performance vector database for Node.js with automatic native/WASM fallback",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",