ruvector 0.1.47 → 0.1.49

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 +362 -8
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -2095,19 +2095,39 @@ program
2095
2095
  // Self-Learning Intelligence Hooks
2096
2096
  // ============================================
2097
2097
 
2098
- const INTEL_PATH = path.join(require('os').homedir(), '.ruvector', 'intelligence.json');
2099
-
2100
2098
  class Intelligence {
2101
2099
  constructor() {
2100
+ this.intelPath = this.getIntelPath();
2102
2101
  this.data = this.load();
2103
2102
  this.alpha = 0.1;
2104
2103
  this.lastEditedFile = null;
2105
2104
  }
2106
2105
 
2106
+ // Prefer project-local storage, fall back to home directory
2107
+ getIntelPath() {
2108
+ const projectPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
2109
+ const homePath = path.join(require('os').homedir(), '.ruvector', 'intelligence.json');
2110
+
2111
+ // If project .ruvector exists, use it
2112
+ if (fs.existsSync(path.dirname(projectPath))) {
2113
+ return projectPath;
2114
+ }
2115
+ // If project .claude exists (hooks initialized), prefer project-local
2116
+ if (fs.existsSync(path.join(process.cwd(), '.claude'))) {
2117
+ return projectPath;
2118
+ }
2119
+ // If home .ruvector exists with data, use it
2120
+ if (fs.existsSync(homePath)) {
2121
+ return homePath;
2122
+ }
2123
+ // Default to project-local for new setups
2124
+ return projectPath;
2125
+ }
2126
+
2107
2127
  load() {
2108
2128
  try {
2109
- if (fs.existsSync(INTEL_PATH)) {
2110
- return JSON.parse(fs.readFileSync(INTEL_PATH, 'utf-8'));
2129
+ if (fs.existsSync(this.intelPath)) {
2130
+ return JSON.parse(fs.readFileSync(this.intelPath, 'utf-8'));
2111
2131
  }
2112
2132
  } catch {}
2113
2133
  return {
@@ -2123,9 +2143,9 @@ class Intelligence {
2123
2143
  }
2124
2144
 
2125
2145
  save() {
2126
- const dir = path.dirname(INTEL_PATH);
2146
+ const dir = path.dirname(this.intelPath);
2127
2147
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
2128
- fs.writeFileSync(INTEL_PATH, JSON.stringify(this.data, null, 2));
2148
+ fs.writeFileSync(this.intelPath, JSON.stringify(this.data, null, 2));
2129
2149
  }
2130
2150
 
2131
2151
  now() { return Math.floor(Date.now() / 1000); }
@@ -2311,7 +2331,9 @@ hooksCmd.command('init')
2311
2331
  .option('--no-gitignore', 'Skip .gitignore update')
2312
2332
  .option('--no-mcp', 'Skip MCP server configuration')
2313
2333
  .option('--no-statusline', 'Skip statusLine configuration')
2314
- .action((opts) => {
2334
+ .option('--pretrain', 'Run pretrain after init to bootstrap intelligence')
2335
+ .option('--build-agents [focus]', 'Generate optimized agents (quality|speed|security|testing|fullstack)')
2336
+ .action(async (opts) => {
2315
2337
  const settingsPath = path.join(process.cwd(), '.claude', 'settings.json');
2316
2338
  const settingsDir = path.dirname(settingsPath);
2317
2339
  if (!fs.existsSync(settingsDir)) fs.mkdirSync(settingsDir, { recursive: true });
@@ -2573,7 +2595,35 @@ npx ruvector hooks init --force # Overwrite existing
2573
2595
  }
2574
2596
 
2575
2597
  console.log(chalk.green('\nāœ… RuVector hooks initialization complete!'));
2576
- console.log(chalk.dim(' Run `npx ruvector hooks verify` to test the setup'));
2598
+
2599
+ // Run pretrain if requested
2600
+ if (opts.pretrain) {
2601
+ console.log(chalk.yellow('\nšŸ“š Running pretrain to bootstrap intelligence...\n'));
2602
+ const { execSync } = require('child_process');
2603
+ try {
2604
+ execSync('npx ruvector hooks pretrain', { stdio: 'inherit' });
2605
+ } catch (e) {
2606
+ console.log(chalk.yellow('āš ļø Pretrain completed with warnings'));
2607
+ }
2608
+ }
2609
+
2610
+ // Build agents if requested
2611
+ if (opts.buildAgents) {
2612
+ const focus = typeof opts.buildAgents === 'string' ? opts.buildAgents : 'quality';
2613
+ console.log(chalk.yellow(`\nšŸ—ļø Building optimized agents (focus: ${focus})...\n`));
2614
+ const { execSync } = require('child_process');
2615
+ try {
2616
+ execSync(`npx ruvector hooks build-agents --focus ${focus} --include-prompts`, { stdio: 'inherit' });
2617
+ } catch (e) {
2618
+ console.log(chalk.yellow('āš ļø Agent build completed with warnings'));
2619
+ }
2620
+ }
2621
+
2622
+ if (!opts.pretrain && !opts.buildAgents) {
2623
+ console.log(chalk.dim(' Run `npx ruvector hooks verify` to test the setup'));
2624
+ console.log(chalk.dim(' Run `npx ruvector hooks pretrain` to bootstrap intelligence'));
2625
+ console.log(chalk.dim(' Run `npx ruvector hooks build-agents` to generate optimized agents'));
2626
+ }
2577
2627
  });
2578
2628
 
2579
2629
  hooksCmd.command('stats').description('Show intelligence statistics').action(() => {
@@ -3274,4 +3324,308 @@ hooksCmd.command('pretrain')
3274
3324
  console.log(chalk.dim('\nThe intelligence layer will now provide better recommendations.'));
3275
3325
  });
3276
3326
 
3327
+ // Agent Builder - generate optimized agent configs based on pretrain
3328
+ hooksCmd.command('build-agents')
3329
+ .description('Generate optimized agent configurations based on repository analysis')
3330
+ .option('--focus <type>', 'Focus type: quality, speed, security, testing, fullstack', 'quality')
3331
+ .option('--output <dir>', 'Output directory', '.claude/agents')
3332
+ .option('--format <fmt>', 'Format: yaml, json, md', 'yaml')
3333
+ .option('--include-prompts', 'Include detailed system prompts')
3334
+ .action((opts) => {
3335
+ console.log(chalk.bold.cyan('\nšŸ—ļø RuVector Agent Builder\n'));
3336
+
3337
+ const intel = new Intelligence();
3338
+ const outputDir = path.join(process.cwd(), opts.output);
3339
+
3340
+ // Check if pretrained
3341
+ if (!intel.data.pretrained && Object.keys(intel.data.patterns || {}).length === 0) {
3342
+ console.log(chalk.yellow('āš ļø No pretrain data found. Running quick analysis...\n'));
3343
+ // Quick file analysis
3344
+ try {
3345
+ const { execSync } = require('child_process');
3346
+ const files = execSync('git ls-files 2>/dev/null', { encoding: 'utf-8' }).trim().split('\n');
3347
+ files.forEach(f => {
3348
+ const ext = path.extname(f);
3349
+ intel.data.patterns = intel.data.patterns || {};
3350
+ intel.data.patterns[`edit:${ext}`] = intel.data.patterns[`edit:${ext}`] || {};
3351
+ });
3352
+ } catch (e) { /* continue without git */ }
3353
+ }
3354
+
3355
+ // Analyze patterns to determine relevant agents
3356
+ const patterns = intel.data.patterns || {};
3357
+ const detectedLangs = new Set();
3358
+ const detectedFrameworks = new Set();
3359
+
3360
+ Object.keys(patterns).forEach(state => {
3361
+ if (state.includes('.rs')) detectedLangs.add('rust');
3362
+ if (state.includes('.ts') || state.includes('.js')) detectedLangs.add('typescript');
3363
+ if (state.includes('.tsx') || state.includes('.jsx')) detectedFrameworks.add('react');
3364
+ if (state.includes('.py')) detectedLangs.add('python');
3365
+ if (state.includes('.go')) detectedLangs.add('go');
3366
+ if (state.includes('.vue')) detectedFrameworks.add('vue');
3367
+ if (state.includes('.sql')) detectedFrameworks.add('database');
3368
+ });
3369
+
3370
+ // Detect project type from files
3371
+ const projectTypes = detectProjectType();
3372
+
3373
+ console.log(chalk.blue(` Detected languages: ${[...detectedLangs].join(', ') || 'generic'}`));
3374
+ console.log(chalk.blue(` Detected frameworks: ${[...detectedFrameworks].join(', ') || 'none'}`));
3375
+ console.log(chalk.blue(` Focus mode: ${opts.focus}\n`));
3376
+
3377
+ // Focus configurations
3378
+ const focusConfigs = {
3379
+ quality: {
3380
+ description: 'Emphasizes code quality, best practices, and maintainability',
3381
+ priorities: ['code-review', 'refactoring', 'documentation', 'testing'],
3382
+ temperature: 0.3
3383
+ },
3384
+ speed: {
3385
+ description: 'Optimized for rapid development and iteration',
3386
+ priorities: ['implementation', 'prototyping', 'quick-fixes'],
3387
+ temperature: 0.7
3388
+ },
3389
+ security: {
3390
+ description: 'Security-first development with vulnerability awareness',
3391
+ priorities: ['security-audit', 'input-validation', 'authentication', 'encryption'],
3392
+ temperature: 0.2
3393
+ },
3394
+ testing: {
3395
+ description: 'Test-driven development with comprehensive coverage',
3396
+ priorities: ['unit-tests', 'integration-tests', 'e2e-tests', 'mocking'],
3397
+ temperature: 0.4
3398
+ },
3399
+ fullstack: {
3400
+ description: 'Balanced full-stack development capabilities',
3401
+ priorities: ['frontend', 'backend', 'database', 'api-design'],
3402
+ temperature: 0.5
3403
+ }
3404
+ };
3405
+
3406
+ const focus = focusConfigs[opts.focus] || focusConfigs.quality;
3407
+
3408
+ // Agent templates based on detected stack
3409
+ const agents = [];
3410
+
3411
+ // Core agents based on detected languages
3412
+ if (detectedLangs.has('rust')) {
3413
+ agents.push({
3414
+ name: 'rust-specialist',
3415
+ type: 'rust-developer',
3416
+ description: 'Rust development specialist for this codebase',
3417
+ capabilities: ['cargo', 'unsafe-rust', 'async-rust', 'wasm', 'error-handling'],
3418
+ focus: focus.priorities,
3419
+ systemPrompt: opts.includePrompts ? `You are a Rust specialist for this project.
3420
+ Focus on: memory safety, zero-cost abstractions, idiomatic Rust patterns.
3421
+ Use cargo conventions, prefer Result over panic, leverage the type system.
3422
+ ${focus.description}` : null
3423
+ });
3424
+ }
3425
+
3426
+ if (detectedLangs.has('typescript')) {
3427
+ agents.push({
3428
+ name: 'typescript-specialist',
3429
+ type: 'typescript-developer',
3430
+ description: 'TypeScript development specialist',
3431
+ capabilities: ['types', 'generics', 'decorators', 'async-await', 'modules'],
3432
+ focus: focus.priorities,
3433
+ systemPrompt: opts.includePrompts ? `You are a TypeScript specialist for this project.
3434
+ Focus on: strict typing, type inference, generic patterns, module organization.
3435
+ Prefer type safety over any, use discriminated unions, leverage utility types.
3436
+ ${focus.description}` : null
3437
+ });
3438
+ }
3439
+
3440
+ if (detectedLangs.has('python')) {
3441
+ agents.push({
3442
+ name: 'python-specialist',
3443
+ type: 'python-developer',
3444
+ description: 'Python development specialist',
3445
+ capabilities: ['typing', 'async', 'testing', 'packaging', 'data-science'],
3446
+ focus: focus.priorities,
3447
+ systemPrompt: opts.includePrompts ? `You are a Python specialist for this project.
3448
+ Focus on: type hints, PEP standards, pythonic idioms, virtual environments.
3449
+ Use dataclasses, prefer pathlib, leverage context managers.
3450
+ ${focus.description}` : null
3451
+ });
3452
+ }
3453
+
3454
+ if (detectedLangs.has('go')) {
3455
+ agents.push({
3456
+ name: 'go-specialist',
3457
+ type: 'go-developer',
3458
+ description: 'Go development specialist',
3459
+ capabilities: ['goroutines', 'channels', 'interfaces', 'testing', 'modules'],
3460
+ focus: focus.priorities,
3461
+ systemPrompt: opts.includePrompts ? `You are a Go specialist for this project.
3462
+ Focus on: simplicity, explicit error handling, goroutines, interface composition.
3463
+ Follow Go conventions, use go fmt, prefer composition over inheritance.
3464
+ ${focus.description}` : null
3465
+ });
3466
+ }
3467
+
3468
+ // Framework-specific agents
3469
+ if (detectedFrameworks.has('react')) {
3470
+ agents.push({
3471
+ name: 'react-specialist',
3472
+ type: 'react-developer',
3473
+ description: 'React/Next.js development specialist',
3474
+ capabilities: ['hooks', 'state-management', 'components', 'ssr', 'testing'],
3475
+ focus: focus.priorities,
3476
+ systemPrompt: opts.includePrompts ? `You are a React specialist for this project.
3477
+ Focus on: functional components, hooks, state management, performance optimization.
3478
+ Prefer composition, use memo wisely, follow React best practices.
3479
+ ${focus.description}` : null
3480
+ });
3481
+ }
3482
+
3483
+ if (detectedFrameworks.has('database')) {
3484
+ agents.push({
3485
+ name: 'database-specialist',
3486
+ type: 'database-specialist',
3487
+ description: 'Database design and optimization specialist',
3488
+ capabilities: ['schema-design', 'queries', 'indexing', 'migrations', 'orm'],
3489
+ focus: focus.priorities,
3490
+ systemPrompt: opts.includePrompts ? `You are a database specialist for this project.
3491
+ Focus on: normalized schemas, efficient queries, proper indexing, data integrity.
3492
+ Consider performance implications, use transactions appropriately.
3493
+ ${focus.description}` : null
3494
+ });
3495
+ }
3496
+
3497
+ // Focus-specific agents
3498
+ if (opts.focus === 'testing' || opts.focus === 'quality') {
3499
+ agents.push({
3500
+ name: 'test-architect',
3501
+ type: 'test-engineer',
3502
+ description: 'Testing and quality assurance specialist',
3503
+ capabilities: ['unit-tests', 'integration-tests', 'mocking', 'coverage', 'tdd'],
3504
+ focus: ['testing', 'quality', 'reliability'],
3505
+ systemPrompt: opts.includePrompts ? `You are a testing specialist for this project.
3506
+ Focus on: comprehensive test coverage, meaningful assertions, test isolation.
3507
+ Write tests first when possible, mock external dependencies, aim for >80% coverage.
3508
+ ${focus.description}` : null
3509
+ });
3510
+ }
3511
+
3512
+ if (opts.focus === 'security') {
3513
+ agents.push({
3514
+ name: 'security-auditor',
3515
+ type: 'security-specialist',
3516
+ description: 'Security audit and hardening specialist',
3517
+ capabilities: ['vulnerability-scan', 'auth', 'encryption', 'input-validation', 'owasp'],
3518
+ focus: ['security', 'compliance', 'hardening'],
3519
+ systemPrompt: opts.includePrompts ? `You are a security specialist for this project.
3520
+ Focus on: OWASP top 10, input validation, authentication, authorization, encryption.
3521
+ Never trust user input, use parameterized queries, implement defense in depth.
3522
+ ${focus.description}` : null
3523
+ });
3524
+ }
3525
+
3526
+ // Add coordinator agent
3527
+ agents.push({
3528
+ name: 'project-coordinator',
3529
+ type: 'coordinator',
3530
+ description: 'Coordinates multi-agent workflows for this project',
3531
+ capabilities: ['task-decomposition', 'agent-routing', 'context-management'],
3532
+ focus: focus.priorities,
3533
+ routes: agents.filter(a => a.name !== 'project-coordinator').map(a => ({
3534
+ pattern: a.capabilities[0],
3535
+ agent: a.name
3536
+ }))
3537
+ });
3538
+
3539
+ // Create output directory
3540
+ if (!fs.existsSync(outputDir)) {
3541
+ fs.mkdirSync(outputDir, { recursive: true });
3542
+ }
3543
+
3544
+ // Generate agent files
3545
+ agents.forEach(agent => {
3546
+ let content;
3547
+ const filename = `${agent.name}.${opts.format}`;
3548
+ const filepath = path.join(outputDir, filename);
3549
+
3550
+ if (opts.format === 'yaml') {
3551
+ const yaml = [
3552
+ `# Auto-generated by RuVector Agent Builder`,
3553
+ `# Focus: ${opts.focus}`,
3554
+ `# Generated: ${new Date().toISOString()}`,
3555
+ ``,
3556
+ `name: ${agent.name}`,
3557
+ `type: ${agent.type}`,
3558
+ `description: ${agent.description}`,
3559
+ ``,
3560
+ `capabilities:`,
3561
+ ...agent.capabilities.map(c => ` - ${c}`),
3562
+ ``,
3563
+ `focus:`,
3564
+ ...agent.focus.map(f => ` - ${f}`),
3565
+ ];
3566
+ if (agent.systemPrompt) {
3567
+ yaml.push(``, `system_prompt: |`);
3568
+ agent.systemPrompt.split('\n').forEach(line => yaml.push(` ${line}`));
3569
+ }
3570
+ if (agent.routes) {
3571
+ yaml.push(``, `routes:`);
3572
+ agent.routes.forEach(r => yaml.push(` - pattern: "${r.pattern}"`, ` agent: ${r.agent}`));
3573
+ }
3574
+ content = yaml.join('\n');
3575
+ } else if (opts.format === 'json') {
3576
+ content = JSON.stringify(agent, null, 2);
3577
+ } else {
3578
+ // Markdown format
3579
+ content = [
3580
+ `# ${agent.name}`,
3581
+ ``,
3582
+ `**Type:** ${agent.type}`,
3583
+ `**Description:** ${agent.description}`,
3584
+ ``,
3585
+ `## Capabilities`,
3586
+ ...agent.capabilities.map(c => `- ${c}`),
3587
+ ``,
3588
+ `## Focus Areas`,
3589
+ ...agent.focus.map(f => `- ${f}`),
3590
+ ].join('\n');
3591
+ if (agent.systemPrompt) {
3592
+ content += `\n\n## System Prompt\n\n\`\`\`\n${agent.systemPrompt}\n\`\`\``;
3593
+ }
3594
+ }
3595
+
3596
+ fs.writeFileSync(filepath, content);
3597
+ console.log(chalk.green(` āœ“ Created ${filename}`));
3598
+ });
3599
+
3600
+ // Create index file
3601
+ const indexContent = opts.format === 'yaml'
3602
+ ? `# RuVector Agent Configuration\n# Focus: ${opts.focus}\n\nagents:\n${agents.map(a => ` - ${a.name}`).join('\n')}`
3603
+ : JSON.stringify({ focus: opts.focus, agents: agents.map(a => a.name) }, null, 2);
3604
+
3605
+ fs.writeFileSync(path.join(outputDir, `index.${opts.format === 'md' ? 'json' : opts.format}`), indexContent);
3606
+
3607
+ // Update settings to reference agents
3608
+ const settingsPath = path.join(process.cwd(), '.claude', 'settings.json');
3609
+ if (fs.existsSync(settingsPath)) {
3610
+ try {
3611
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
3612
+ settings.agentConfig = {
3613
+ directory: opts.output,
3614
+ focus: opts.focus,
3615
+ agents: agents.map(a => a.name),
3616
+ generated: new Date().toISOString()
3617
+ };
3618
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
3619
+ console.log(chalk.blue('\n āœ“ Updated .claude/settings.json with agent config'));
3620
+ } catch (e) { /* ignore settings errors */ }
3621
+ }
3622
+
3623
+ console.log(chalk.bold.green(`\nāœ… Generated ${agents.length} optimized agents in ${opts.output}/\n`));
3624
+ console.log(chalk.cyan('Agents created:'));
3625
+ agents.forEach(a => {
3626
+ console.log(` šŸ¤– ${chalk.bold(a.name)}: ${a.description}`);
3627
+ });
3628
+ console.log(chalk.dim(`\nFocus mode "${opts.focus}": ${focus.description}`));
3629
+ });
3630
+
3277
3631
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvector",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
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",