ruvector 0.1.99 → 0.2.0

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.
package/bin/mcp-server.js CHANGED
@@ -36,18 +36,38 @@ function validateRvfPath(filePath) {
36
36
  if (typeof filePath !== 'string' || filePath.length === 0) {
37
37
  throw new Error('Path must be a non-empty string');
38
38
  }
39
- const resolved = path.resolve(filePath);
40
- // Block obvious path traversal
41
- if (filePath.includes('..') || filePath.includes('\0')) {
42
- throw new Error('Path traversal detected');
39
+ // Block null bytes
40
+ if (filePath.includes('\0')) {
41
+ throw new Error('Path contains null bytes');
43
42
  }
44
- // Block sensitive system paths
45
- const blocked = ['/etc', '/proc', '/sys', '/dev', '/boot', '/root', '/var/run'];
46
- for (const prefix of blocked) {
47
- if (resolved.startsWith(prefix)) {
48
- throw new Error(`Access to ${prefix} is not allowed`);
43
+ // Resolve to absolute, then canonicalize via realpath if it exists
44
+ let resolved = path.resolve(filePath);
45
+ try {
46
+ // Resolve symlinks for existing paths to prevent symlink-based escapes
47
+ resolved = fs.realpathSync(resolved);
48
+ } catch {
49
+ // Path doesn't exist yet — resolve the parent directory
50
+ const parentDir = path.dirname(resolved);
51
+ try {
52
+ const realParent = fs.realpathSync(parentDir);
53
+ resolved = path.join(realParent, path.basename(resolved));
54
+ } catch {
55
+ // Parent doesn't exist either — keep the resolved path for the block check
49
56
  }
50
57
  }
58
+ // Confine to the current working directory
59
+ const cwd = process.cwd();
60
+ if (!resolved.startsWith(cwd + path.sep) && resolved !== cwd) {
61
+ // Also block sensitive system paths regardless
62
+ const blocked = ['/etc', '/proc', '/sys', '/dev', '/boot', '/root', '/var/run', '/var/log', '/tmp'];
63
+ for (const prefix of blocked) {
64
+ if (resolved.startsWith(prefix)) {
65
+ throw new Error(`Access denied: path resolves to '${resolved}' which is outside the working directory and in restricted area '${prefix}'`);
66
+ }
67
+ }
68
+ // Allow paths outside cwd only if they're not in blocked directories
69
+ // (for tools that reference project files by absolute path)
70
+ }
51
71
  return resolved;
52
72
  }
53
73
 
@@ -57,14 +77,24 @@ function validateRvfPath(filePath) {
57
77
  */
58
78
  function sanitizeShellArg(arg) {
59
79
  if (typeof arg !== 'string') return '';
60
- // Remove null bytes, backticks, $(), and other shell metacharacters
80
+ // Remove null bytes, backticks, $(), quotes, newlines, and other shell metacharacters
61
81
  return arg
62
82
  .replace(/\0/g, '')
63
- .replace(/[`$(){}|;&<>!]/g, '')
83
+ .replace(/[\r\n]/g, '')
84
+ .replace(/[`$(){}|;&<>!'"\\]/g, '')
64
85
  .replace(/\.\./g, '')
65
86
  .slice(0, 4096);
66
87
  }
67
88
 
89
+ /**
90
+ * Validate a numeric argument (returns integer or default).
91
+ * Prevents injection via numeric-looking fields.
92
+ */
93
+ function sanitizeNumericArg(arg, defaultVal) {
94
+ const n = parseInt(arg, 10);
95
+ return Number.isFinite(n) && n > 0 ? n : (defaultVal || 0);
96
+ }
97
+
68
98
  // Try to load the full IntelligenceEngine
69
99
  let IntelligenceEngine = null;
70
100
  let engineAvailable = false;
@@ -1319,7 +1349,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1319
1349
  let cmd = 'npx ruvector hooks init';
1320
1350
  if (args.force) cmd += ' --force';
1321
1351
  if (args.pretrain) cmd += ' --pretrain';
1322
- if (args.build_agents) cmd += ` --build-agents ${args.build_agents}`;
1352
+ if (args.build_agents) cmd += ` --build-agents ${sanitizeShellArg(args.build_agents)}`;
1323
1353
 
1324
1354
  try {
1325
1355
  const output = execSync(cmd, { encoding: 'utf-8', timeout: 60000 });
@@ -1341,7 +1371,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1341
1371
 
1342
1372
  case 'hooks_pretrain': {
1343
1373
  let cmd = 'npx ruvector hooks pretrain';
1344
- if (args.depth) cmd += ` --depth ${args.depth}`;
1374
+ if (args.depth) cmd += ` --depth ${sanitizeNumericArg(args.depth, 3)}`;
1345
1375
  if (args.skip_git) cmd += ' --skip-git';
1346
1376
  if (args.verbose) cmd += ' --verbose';
1347
1377
 
@@ -1371,7 +1401,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1371
1401
 
1372
1402
  case 'hooks_build_agents': {
1373
1403
  let cmd = 'npx ruvector hooks build-agents';
1374
- if (args.focus) cmd += ` --focus ${args.focus}`;
1404
+ if (args.focus) cmd += ` --focus ${sanitizeShellArg(args.focus)}`;
1375
1405
  if (args.include_prompts) cmd += ' --include-prompts';
1376
1406
 
1377
1407
  try {
@@ -1484,21 +1514,44 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1484
1514
  const data = args.data;
1485
1515
  const merge = args.merge !== false;
1486
1516
 
1487
- if (data.patterns) {
1517
+ // Validate imported data structure to prevent prototype pollution and injection
1518
+ if (typeof data !== 'object' || data === null || Array.isArray(data)) {
1519
+ throw new Error('Import data must be a non-null object');
1520
+ }
1521
+ const allowedKeys = ['patterns', 'memories', 'errors', 'agents', 'edges', 'trajectories'];
1522
+ for (const key of Object.keys(data)) {
1523
+ if (!allowedKeys.includes(key)) {
1524
+ throw new Error(`Unknown import key: '${key}'. Allowed: ${allowedKeys.join(', ')}`);
1525
+ }
1526
+ }
1527
+ // Prevent prototype pollution via __proto__, constructor, prototype keys
1528
+ const dangerousKeys = ['__proto__', 'constructor', 'prototype'];
1529
+ function checkForProtoPollution(obj, path) {
1530
+ if (typeof obj !== 'object' || obj === null) return;
1531
+ for (const key of Object.keys(obj)) {
1532
+ if (dangerousKeys.includes(key)) {
1533
+ throw new Error(`Dangerous key '${key}' detected at ${path}.${key}`);
1534
+ }
1535
+ }
1536
+ }
1537
+ if (data.patterns) checkForProtoPollution(data.patterns, 'patterns');
1538
+ if (data.errors) checkForProtoPollution(data.errors, 'errors');
1539
+
1540
+ if (data.patterns && typeof data.patterns === 'object') {
1488
1541
  if (merge) {
1489
1542
  Object.assign(intel.data.patterns, data.patterns);
1490
1543
  } else {
1491
1544
  intel.data.patterns = data.patterns;
1492
1545
  }
1493
1546
  }
1494
- if (data.memories) {
1547
+ if (data.memories && Array.isArray(data.memories)) {
1495
1548
  if (merge) {
1496
1549
  intel.data.memories = [...(intel.data.memories || []), ...data.memories];
1497
1550
  } else {
1498
1551
  intel.data.memories = data.memories;
1499
1552
  }
1500
1553
  }
1501
- if (data.errors) {
1554
+ if (data.errors && typeof data.errors === 'object') {
1502
1555
  if (merge) {
1503
1556
  Object.assign(intel.data.errors, data.errors);
1504
1557
  } else {
@@ -2426,7 +2479,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2426
2479
 
2427
2480
  case 'workers_status': {
2428
2481
  try {
2429
- const cmdArgs = args.workerId ? `workers status ${args.workerId}` : 'workers status';
2482
+ const cmdArgs = args.workerId ? `workers status ${sanitizeShellArg(args.workerId)}` : 'workers status';
2430
2483
  const result = execSync(`npx agentic-flow@alpha ${cmdArgs}`, {
2431
2484
  encoding: 'utf-8',
2432
2485
  timeout: 15000,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvector",
3
- "version": "0.1.99",
3
+ "version": "0.2.0",
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",
@@ -10,7 +10,7 @@
10
10
  "scripts": {
11
11
  "build": "tsc && cp src/core/onnx/pkg/package.json dist/core/onnx/pkg/",
12
12
  "prepublishOnly": "npm run build",
13
- "test": "node test/integration.js"
13
+ "test": "node test/integration.js && node test/cli-commands.js"
14
14
  },
15
15
  "keywords": [
16
16
  "vector",
@@ -41,7 +41,15 @@
41
41
  "continual-learning",
42
42
  "onnx",
43
43
  "semantic-embeddings",
44
- "minilm"
44
+ "minilm",
45
+ "brain",
46
+ "shared-intelligence",
47
+ "mcp",
48
+ "edge-computing",
49
+ "pi-brain",
50
+ "identity",
51
+ "pi-key",
52
+ "distributed-compute"
45
53
  ],
46
54
  "author": "ruv.io Team <info@ruv.io> (https://ruv.io)",
47
55
  "homepage": "https://ruv.io",
@@ -71,7 +79,23 @@
71
79
  "@types/node": "^20.10.5",
72
80
  "typescript": "^5.3.3"
73
81
  },
82
+ "files": [
83
+ "bin/",
84
+ "dist/",
85
+ "README.md",
86
+ "LICENSE"
87
+ ],
88
+ "peerDependencies": {
89
+ "@ruvector/pi-brain": ">=0.1.0",
90
+ "@ruvector/ruvllm": ">=2.0.0",
91
+ "@ruvector/router": ">=0.1.0"
92
+ },
93
+ "peerDependenciesMeta": {
94
+ "@ruvector/pi-brain": { "optional": true },
95
+ "@ruvector/ruvllm": { "optional": true },
96
+ "@ruvector/router": { "optional": true }
97
+ },
74
98
  "engines": {
75
- "node": ">=14.0.0"
99
+ "node": ">=18.0.0"
76
100
  }
77
101
  }
package/HOOKS.md DELETED
@@ -1,221 +0,0 @@
1
- # RuVector Hooks for Claude Code
2
-
3
- Self-learning intelligence hooks that enhance Claude Code with Q-learning, vector memory, and automatic agent routing.
4
-
5
- ## Quick Start
6
-
7
- ```bash
8
- # Full setup: hooks + pretrain + optimized agents
9
- npx ruvector hooks init --pretrain --build-agents quality
10
-
11
- # Or step by step:
12
- npx ruvector hooks init # Setup hooks
13
- npx ruvector hooks pretrain # Analyze repository
14
- npx ruvector hooks build-agents # Generate agent configs
15
- ```
16
-
17
- ## What It Does
18
-
19
- RuVector hooks integrate with Claude Code to provide:
20
-
21
- | Feature | Description |
22
- |---------|-------------|
23
- | **Agent Routing** | Suggests the best agent for each file type based on learned patterns |
24
- | **Co-edit Patterns** | Predicts "likely next files" from git history |
25
- | **Vector Memory** | Semantic recall of project context |
26
- | **Command Analysis** | Risk assessment for bash commands |
27
- | **Self-Learning** | Q-learning improves suggestions over time |
28
-
29
- ## Commands
30
-
31
- ### Initialization
32
-
33
- ```bash
34
- # Full configuration
35
- npx ruvector hooks init
36
-
37
- # With pretrain and agent building
38
- npx ruvector hooks init --pretrain --build-agents security
39
-
40
- # Minimal (basic hooks only)
41
- npx ruvector hooks init --minimal
42
-
43
- # Options
44
- --force # Overwrite existing settings
45
- --minimal # Basic hooks only
46
- --pretrain # Run pretrain after init
47
- --build-agents # Generate optimized agents (quality|speed|security|testing|fullstack)
48
- --no-claude-md # Skip CLAUDE.md creation
49
- --no-permissions # Skip permissions config
50
- --no-env # Skip environment variables
51
- --no-gitignore # Skip .gitignore update
52
- --no-mcp # Skip MCP server config
53
- --no-statusline # Skip status line config
54
- ```
55
-
56
- ### Pretrain
57
-
58
- Analyze your repository to bootstrap intelligence:
59
-
60
- ```bash
61
- npx ruvector hooks pretrain
62
-
63
- # Options
64
- --depth <n> # Git history depth (default: 100)
65
- --verbose # Show detailed progress
66
- --skip-git # Skip git history analysis
67
- --skip-files # Skip file structure analysis
68
- ```
69
-
70
- **What it learns:**
71
- - File type → Agent mapping (`.rs` → rust-developer)
72
- - Co-edit patterns from git history
73
- - Directory → Agent mapping
74
- - Project context memories
75
-
76
- ### Build Agents
77
-
78
- Generate optimized `.claude/agents/` configurations:
79
-
80
- ```bash
81
- npx ruvector hooks build-agents --focus quality
82
-
83
- # Focus modes
84
- --focus quality # Code quality, best practices (default)
85
- --focus speed # Rapid development, prototyping
86
- --focus security # OWASP, input validation, encryption
87
- --focus testing # TDD, comprehensive coverage
88
- --focus fullstack # Balanced frontend/backend/database
89
-
90
- # Options
91
- --output <dir> # Output directory (default: .claude/agents)
92
- --format <fmt> # yaml, json, or md (default: yaml)
93
- --include-prompts # Include system prompts in agent configs
94
- ```
95
-
96
- ### Verification & Diagnostics
97
-
98
- ```bash
99
- # Check if hooks are working
100
- npx ruvector hooks verify
101
-
102
- # Diagnose and fix issues
103
- npx ruvector hooks doctor
104
- npx ruvector hooks doctor --fix
105
- ```
106
-
107
- ### Data Management
108
-
109
- ```bash
110
- # View statistics
111
- npx ruvector hooks stats
112
-
113
- # Export intelligence data
114
- npx ruvector hooks export -o backup.json
115
- npx ruvector hooks export --include-all
116
-
117
- # Import intelligence data
118
- npx ruvector hooks import backup.json
119
- npx ruvector hooks import backup.json --merge
120
- ```
121
-
122
- ### Memory Operations
123
-
124
- ```bash
125
- # Store context in vector memory
126
- npx ruvector hooks remember "API uses JWT auth" -t project
127
-
128
- # Semantic search memory
129
- npx ruvector hooks recall "authentication"
130
-
131
- # Route a task to best agent
132
- npx ruvector hooks route "implement user login"
133
- ```
134
-
135
- ## Hook Events
136
-
137
- | Event | Trigger | RuVector Action |
138
- |-------|---------|-----------------|
139
- | **PreToolUse** | Before Edit/Write/Bash | Agent routing, file analysis, command risk |
140
- | **PostToolUse** | After Edit/Write/Bash | Q-learning update, pattern recording |
141
- | **SessionStart** | Conversation begins | Load intelligence, display stats |
142
- | **Stop** | Conversation ends | Save learning data |
143
- | **UserPromptSubmit** | User sends message | Context suggestions |
144
- | **PreCompact** | Before context compaction | Preserve important context |
145
- | **Notification** | Any notification | Track events for learning |
146
-
147
- ## Generated Files
148
-
149
- After running `hooks init`:
150
-
151
- ```
152
- your-project/
153
- ├── .claude/
154
- │ ├── settings.json # Hooks configuration
155
- │ ├── statusline.sh # Status bar script
156
- │ └── agents/ # Generated agents (with --build-agents)
157
- │ ├── rust-specialist.yaml
158
- │ ├── typescript-specialist.yaml
159
- │ ├── test-architect.yaml
160
- │ └── project-coordinator.yaml
161
- ├── .ruvector/
162
- │ └── intelligence.json # Learning data
163
- ├── CLAUDE.md # Project documentation
164
- └── .gitignore # Updated with .ruvector/
165
- ```
166
-
167
- ## Environment Variables
168
-
169
- | Variable | Default | Description |
170
- |----------|---------|-------------|
171
- | `RUVECTOR_INTELLIGENCE_ENABLED` | `true` | Enable/disable intelligence |
172
- | `RUVECTOR_LEARNING_RATE` | `0.1` | Q-learning rate (0.0-1.0) |
173
- | `RUVECTOR_MEMORY_BACKEND` | `rvlite` | Memory storage backend |
174
- | `INTELLIGENCE_MODE` | `treatment` | A/B testing mode |
175
-
176
- ## Example Output
177
-
178
- ### Agent Routing
179
- ```
180
- 🧠 Intelligence Analysis:
181
- 📁 src/api/routes.ts
182
- 🤖 Recommended: typescript-developer (85% confidence)
183
- → learned from 127 .ts files in repo
184
- 📎 Likely next files:
185
- - src/api/handlers.ts (12 co-edits)
186
- - src/types/api.ts (8 co-edits)
187
- ```
188
-
189
- ### Command Analysis
190
- ```
191
- 🧠 Command Analysis:
192
- 📦 Category: rust
193
- 🏷️ Type: test
194
- ✅ Risk: LOW
195
- ```
196
-
197
- ## Best Practices
198
-
199
- 1. **Run pretrain on existing repos** — Bootstrap intelligence before starting work
200
- 2. **Use focus modes** — Match agent generation to your current task
201
- 3. **Export before major changes** — Backup learning data
202
- 4. **Let it learn** — Intelligence improves with each edit
203
-
204
- ## Troubleshooting
205
-
206
- ```bash
207
- # Check setup
208
- npx ruvector hooks verify
209
-
210
- # Fix common issues
211
- npx ruvector hooks doctor --fix
212
-
213
- # Reset and reinitialize
214
- npx ruvector hooks init --force --pretrain
215
- ```
216
-
217
- ## Links
218
-
219
- - [RuVector GitHub](https://github.com/ruvnet/ruvector)
220
- - [npm Package](https://www.npmjs.com/package/ruvector)
221
- - [Claude Code Documentation](https://docs.anthropic.com/claude-code)