claude-flow-novice 2.18.38 → 2.18.39

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.
@@ -1,12 +1,13 @@
1
1
  #!/bin/bash
2
- # SessionStart hook: Build RuVector Rust binary if missing
3
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
5
- RUVECTOR_DIR="$PROJECT_ROOT/.claude/skills/cfn-local-ruvector-accelerator"
6
- BINARY="$RUVECTOR_DIR/target/release/local-ruvector"
2
+ # SessionStart hook: Verify RuVector binary is available
3
+ BINARY="$HOME/.local/bin/local-ruvector"
7
4
 
8
- if [ ! -f "$BINARY" ]; then
9
- echo "[cfn-build-ruvector] Building RuVector..."
10
- command -v cargo &>/dev/null && cd "$RUVECTOR_DIR" && cargo build --release --quiet 2>/dev/null
11
- [ -f "$BINARY" ] && echo "[cfn-build-ruvector] ✅ Built" || echo "[cfn-build-ruvector] Build skipped"
5
+ # Check if binary exists in PATH or ~/.local/bin
6
+ if command -v local-ruvector &>/dev/null; then
7
+ echo "[cfn-build-ruvector] local-ruvector available in PATH"
8
+ elif [ -x "$BINARY" ]; then
9
+ echo "[cfn-build-ruvector] ✅ local-ruvector available at $BINARY"
10
+ else
11
+ echo "[cfn-build-ruvector] ⚠️ local-ruvector not found"
12
+ echo "[cfn-build-ruvector] Install with: ./scripts/install-ruvector-global.sh"
12
13
  fi
@@ -1,25 +1,17 @@
1
1
  #!/bin/bash
2
- # index-code.sh - Index codebase patterns for local RuVector with security controls
2
+ # index-code.sh - Index codebase using local-ruvector Rust binary
3
+ # This is a wrapper around the Rust binary for convenience
3
4
 
4
5
  set -e
5
6
 
6
7
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- STORAGE_PATH="${HOME}/.local-ruvector"
8
- DEFAULT_PATH="."
9
8
 
10
- # Security configuration
11
- MAX_FILES_TO_PROCESS=10000
12
- MAX_DEPTH=10
13
- SUSPICIOUS_PATTERNS=("node_modules" ".git" "/dist/" "/build/" "/target/" ".svn" ".hg" "__pycache__" ".pytest_cache")
14
-
15
- # Parse arguments
16
- PATH_TO_INDEX=""
17
- FILE_TYPES=("")
18
- PATTERNS=""
19
- VERBOSE=false
9
+ # Default values
10
+ PATH_TO_INDEX="."
11
+ FILE_TYPES="ts,tsx,js,jsx,py,sh,sql,rs"
20
12
  HELP=false
21
- MAX_FILES=${MAX_FILES_TO_PROCESS}
22
13
 
14
+ # Parse arguments
23
15
  while [[ $# -gt 0 ]]; do
24
16
  case $1 in
25
17
  --path)
@@ -27,27 +19,15 @@ while [[ $# -gt 0 ]]; do
27
19
  shift 2
28
20
  ;;
29
21
  --types)
30
- IFS=',' read -ra FILE_TYPES <<< "$2"
31
- shift 2
32
- ;;
33
- --patterns)
34
- PATTERNS="$2"
22
+ FILE_TYPES="$2"
35
23
  shift 2
36
24
  ;;
37
- --max-files)
38
- MAX_FILES="$2"
39
- shift 2
40
- ;;
41
- --verbose)
42
- VERBOSE=true
43
- shift
44
- ;;
45
25
  --help|-h)
46
26
  HELP=true
47
27
  shift
48
28
  ;;
49
29
  *)
50
- if [[ -z "$PATH_TO_INDEX" ]]; then
30
+ if [[ -z "$PATH_TO_INDEX" || "$PATH_TO_INDEX" == "." ]]; then
51
31
  PATH_TO_INDEX="$1"
52
32
  fi
53
33
  shift
@@ -55,391 +35,57 @@ while [[ $# -gt 0 ]]; do
55
35
  esac
56
36
  done
57
37
 
58
- # Security validation functions
59
- validate_path() {
60
- local path="$1"
61
-
62
- # Reject null bytes and control characters
63
- if [[ "$path" =~ $'\0' ]]; then
64
- echo "❌ Error: Path contains null bytes" >&2
65
- exit 1
66
- fi
67
-
68
- # Reject absolute paths that aren't under the base
69
- if [[ "$path" == /* && "$path" != "$PATH_TO_INDEX"/* ]]; then
70
- echo "❌ Error: Absolute path outside base directory: $path" >&2
71
- exit 1
72
- fi
73
-
74
- # Reject suspicious patterns
75
- for pattern in "${SUSPICIOUS_PATTERNS[@]}"; do
76
- if [[ "$path" == *"$pattern"* ]]; then
77
- echo "❌ Error: Path contains suspicious pattern '$pattern': $path" >&2
78
- exit 1
79
- fi
80
- done
81
-
82
- # Reject paths with too many ..
83
- if [[ $(echo "$path" | grep -o '\.\.' | wc -l) -gt 5 ]]; then
84
- echo "❌ Error: Too many parent directory references: $path" >&2
85
- exit 1
86
- fi
87
- }
88
-
89
- validate_file_type() {
90
- local ft="$1"
91
-
92
- # Only allow alphanumeric and common extensions
93
- if [[ ! "$ft" =~ ^[a-zA-Z0-9._-]+$ ]]; then
94
- echo "❌ Error: Invalid file type format: $ft" >&2
95
- exit 1
96
- fi
97
- }
98
-
99
38
  # Show help
100
39
  if [[ "$HELP" == true ]]; then
101
40
  cat << EOF
102
41
  Usage: index-code [OPTIONS] [PATH]
103
42
 
104
- Index codebase patterns for local RuVector search with security controls
43
+ Index codebase patterns using local-ruvector Rust binary
105
44
 
106
45
  Arguments:
107
46
  PATH Path to directory to index (default: current directory)
108
47
 
109
48
  Options:
110
49
  --path PATH Path to directory to index
111
- --types TYPES Comma-separated file types (default: rs,py,js,ts,go,java)
112
- --patterns PATTERNS Comma-separated patterns to focus on
113
- --max-files N Maximum files to process (default: 10000)
114
- --verbose Show detailed progress
50
+ --types TYPES Comma-separated file types (default: ts,tsx,js,jsx,py,sh,sql,rs)
115
51
  --help, -h Show this help
116
52
 
117
- Security Features:
118
- - Path traversal protection
119
- - File size limits (10MB per file)
120
- - Maximum files limit
121
- - Suspicious pattern detection
122
- - Input sanitization
53
+ Database Location:
54
+ ~/.local/share/ruvector/index_v2.db
123
55
 
124
56
  Examples:
125
- index-code --path ~/projects/my-rust-app
126
- index-code --types rs,py --patterns "error-handling,authentication"
127
- index-code --max-files 5000 --verbose
57
+ index-code --path ~/projects/my-app
58
+ index-code --types rs,py --path /path/to/project
128
59
 
129
60
  EOF
130
61
  exit 0
131
62
  fi
132
63
 
133
- # Set defaults
134
- if [[ -z "$PATH_TO_INDEX" ]]; then
135
- PATH_TO_INDEX="$DEFAULT_PATH"
136
- fi
137
-
138
- if [[ ${#FILE_TYPES[@]} -eq 0 ]]; then
139
- FILE_TYPES=("rs" "py" "js" "ts" "go" "java" "tsx" "jsx" "cpp" "c" "h" "cs" "php" "rb" "swift" "kt")
140
- fi
141
-
142
- # Validate max_files
143
- if ! [[ "$MAX_FILES" =~ ^[0-9]+$ ]] || [[ "$MAX_FILES" -lt 1 ]] || [[ "$MAX_FILES" -gt 100000 ]]; then
144
- echo "❌ Error: Invalid max-files value: $MAX_FILES (must be 1-100000)" >&2
64
+ # Find the binary
65
+ if command -v local-ruvector &>/dev/null; then
66
+ BINARY="local-ruvector"
67
+ elif [[ -x "$HOME/.local/bin/local-ruvector" ]]; then
68
+ BINARY="$HOME/.local/bin/local-ruvector"
69
+ else
70
+ echo " Error: local-ruvector binary not found"
71
+ echo " Install with: ./scripts/install-ruvector-global.sh"
145
72
  exit 1
146
73
  fi
147
74
 
148
- # Validate path
149
- validate_path "$PATH_TO_INDEX"
150
-
151
- # Convert to absolute path and canonicalize
152
- PATH_TO_INDEX="$(cd "$PATH_TO_INDEX" && pwd -P)"
153
-
154
- # Additional security check - ensure we're not in a system directory
155
- if [[ "$PATH_TO_INDEX" == /etc/* ]] || [[ "$PATH_TO_INDEX" == /usr/bin/* ]] || [[ "$PATH_TO_INDEX" == /bin/* ]] || [[ "$PATH_TO_INDEX" == /sbin/* ]]; then
156
- echo "❌ Error: Cannot index system directory: $PATH_TO_INDEX" >&2
75
+ # Convert to absolute path
76
+ PATH_TO_INDEX="$(cd "$PATH_TO_INDEX" 2>/dev/null && pwd)" || {
77
+ echo "❌ Error: Directory not found: $PATH_TO_INDEX"
157
78
  exit 1
158
- fi
159
-
160
- # Validate file types
161
- for ft in "${FILE_TYPES[@]}"; do
162
- validate_file_type "$ft"
163
- done
164
-
165
- # Convert array to comma-separated string for Python
166
- FILE_TYPES_STR=$(IFS=','; echo "${FILE_TYPES[*]}")
79
+ }
167
80
 
168
81
  echo "🔍 Indexing code patterns in: $PATH_TO_INDEX"
169
- echo "📄 File types: ${FILE_TYPES[*]}"
170
- echo "🔒 Security: Path traversal protection enabled"
171
- echo "📊 Maximum files: $MAX_FILES"
172
- if [[ -n "$PATTERNS" ]]; then
173
- echo "🎯 Focusing on patterns: $PATTERNS"
174
- fi
175
-
176
- # Initialize search engine
177
- cd "$SCRIPT_DIR"
178
- python3 -c "
179
- import sys
180
- import os
181
- import json
182
- import hashlib
183
- import stat
184
- from pathlib import Path
185
- from search_engine_v2 import SearchEngine
186
- from security import SecurityError, PathValidator, ResourceMonitor, safe_file_read
187
-
188
- # Security checks
189
- def is_safe_file(file_path):
190
- \"\"\"Check if file is safe to process\"\"\"
191
- try:
192
- # Check file permissions
193
- file_stat = file_path.stat()
194
-
195
- # Reject world-writable files
196
- if file_stat.st_mode & stat.S_IWOTH:
197
- return False, \"File is world-writable\"
198
-
199
- # Reject files with suspicious permissions
200
- if file_stat.st_mode & 0o7777 != 0o644 and file_stat.st_mode & 0o7777 != 0o755:
201
- return False, f\"Suspicious file permissions: {oct(file_stat.st_mode & 0o7777)}\"
202
-
203
- # Check if file is owned by current user (on Unix systems)
204
- if hasattr(os, 'getuid') and file_stat.st_uid != os.getuid():
205
- return False, \"File not owned by current user\"
206
-
207
- return True, None
208
-
209
- except Exception as e:
210
- return False, f\"Error checking file: {e}\"
211
-
212
- def generate_pattern_id(file_path, content):
213
- \"\"\"Generate unique pattern ID with security\"\"\"
214
- # Use SHA-256 for better security
215
- hash_input = f'{file_path}:{len(content)}:{hashlib.sha256(content.encode()).hexdigest()}'
216
- hash_obj = hashlib.md5(hash_input.encode('utf-8'))
217
- return f'pattern_{hash_obj.hexdigest()[:16]}'
218
-
219
- def extract_functions(content, file_type):
220
- \"\"\"Extract functions/classes from code safely\"\"\"
221
- patterns = []
222
-
223
- # Limit content size for processing
224
- if len(content) > 50000:
225
- content = content[:50000]
226
-
227
- # Simple extraction based on language
228
- if file_type == 'rs':
229
- import re
230
- # Limit regex operations
231
- lines = content.split('\\n')[:1000] # Limit to first 1000 lines
232
-
233
- fn_pattern = r'^(pub\\s+)?(async\\s+)?(unsafe\\s+)?fn\\s+(\\w+)'
234
- struct_pattern = r'^(pub\\s+)?struct\\s+(\\w+)'
235
- impl_pattern = r'^impl\\s+(\\w+)\\s*(for\\s+(\\w+))?'
236
-
237
- for i, line in enumerate(lines):
238
- for pattern, type_name in [(fn_pattern, 'function'),
239
- (struct_pattern, 'struct'),
240
- (impl_pattern, 'impl')]:
241
- match = re.match(pattern, line)
242
- if match:
243
- patterns.append({
244
- 'type': type_name,
245
- 'name': match.groups()[-1][:100], # Limit name length
246
- 'line': i + 1,
247
- 'signature': line.strip()[:200] # Limit signature length
248
- })
249
-
250
- elif file_type == 'py':
251
- import re
252
- lines = content.split('\\n')[:1000]
253
-
254
- fn_pattern = r'^\\s*def\\s+(\\w+)'
255
- class_pattern = r'^\\s*class\\s+(\\w+)'
256
-
257
- for i, line in enumerate(lines):
258
- if re.match(fn_pattern, line):
259
- patterns.append({
260
- 'type': 'function',
261
- 'name': re.match(fn_pattern, line).group(1)[:100],
262
- 'line': i + 1,
263
- 'signature': line.strip()[:200]
264
- })
265
- elif re.match(class_pattern, line):
266
- patterns.append({
267
- 'type': 'class',
268
- 'name': re.match(class_pattern, line).group(1)[:100],
269
- 'line': i + 1,
270
- 'signature': line.strip()[:200]
271
- })
272
-
273
- return patterns[:50] # Limit number of patterns per file
274
-
275
- # Initialize security
276
- try:
277
- validator = PathValidator('${PATH_TO_INDEX}')
278
- monitor = ResourceMonitor()
279
-
280
- # Initialize engine with security
281
- engine = SearchEngine('${STORAGE_PATH}/storage')
282
-
283
- print('📂 Scanning files with security checks...')
284
-
285
- # Parse file types from shell
286
- file_types = '${FILE_TYPES_STR}'.split(',')
287
- verbose = '${VERBOSE}' == 'true'
288
- max_files = ${MAX_FILES}
289
-
290
- # Index files with security
291
- indexed_count = 0
292
- pattern_count = 0
293
- skipped_count = 0
294
- error_count = 0
295
-
296
- for file_type in file_types:
297
- file_type = file_type.strip()
298
- if not file_type:
299
- continue
300
-
301
- pattern = f'**/*.{file_type}'
302
-
303
- # Use pathlib's rglob with depth limit
304
- try:
305
- files = list(Path('${PATH_TO_INDEX}').rglob(pattern))
306
- except Exception as e:
307
- print(f'⚠️ Error scanning for {file_type} files: {e}')
308
- continue
309
-
310
- # Limit total files
311
- if indexed_count >= max_files:
312
- print(f'⚠️ Reached maximum file limit ({max_files}), stopping')
313
- break
314
-
315
- for file_path in files:
316
- # Check file limit
317
- if indexed_count >= max_files:
318
- break
319
-
320
- if file_path.is_file():
321
- try:
322
- # Validate path
323
- safe_path = validator.validate_path(file_path)
324
-
325
- # Additional safety checks
326
- is_safe, reason = is_safe_file(safe_path)
327
- if not is_safe:
328
- if verbose:
329
- print(f' ⚠️ Skipped {file_path}: {reason}')
330
- skipped_count += 1
331
- continue
332
-
333
- # Check file size before reading
334
- monitor.check_file_size(safe_path)
335
-
336
- # Safely read file
337
- content = safe_file_read(safe_path)
338
-
339
- # Skip very small files
340
- if len(content) < 50:
341
- continue
342
-
343
- # Limit content size
344
- if len(content) > 1000000: # 1MB limit
345
- content = content[:1000000]
346
- if verbose:
347
- print(f' ⚠️ Truncated large file: {file_path}')
348
-
349
- # Generate pattern ID
350
- pattern_id = generate_pattern_id(str(safe_path), content)
351
-
352
- # Extract functions/classes safely
353
- patterns = extract_functions(content, file_type)
354
-
355
- # Prepare metadata with security
356
- metadata = {
357
- 'file_size': len(content),
358
- 'line_count': len(content.split('\\n')),
359
- 'patterns': patterns,
360
- 'last_modified': safe_path.stat().st_mtime,
361
- 'indexed_by': 'secure-index-code',
362
- 'security_verified': True
363
- }
364
-
365
- # Store pattern with security
366
- success = engine.add_pattern(
367
- pattern_id=pattern_id,
368
- file_path=str(safe_path),
369
- file_type=file_type,
370
- content=content,
371
- metadata=metadata
372
- )
373
-
374
- if success:
375
- indexed_count += 1
376
- pattern_count += len(patterns)
377
- monitor.record_file_processed(len(content))
378
-
379
- if verbose and indexed_count % 100 == 0:
380
- stats = monitor.get_stats()
381
- print(f' 📊 Processed {indexed_count} files, {stats[\"bytes_processed\"]:,} bytes')
382
- else:
383
- error_count += 1
384
-
385
- except SecurityError as e:
386
- if verbose:
387
- print(f' 🔒 Security violation: {file_path} - {e}')
388
- skipped_count += 1
389
- continue
390
- except Exception as e:
391
- if verbose:
392
- print(f' ⚠️ Skipped {file_path}: {e}')
393
- error_count += 1
394
- continue
395
-
396
- print(f'\\n🎉 Indexing completed with security controls!')
397
- print(f' ✅ Successfully indexed: {indexed_count} files')
398
- print(f' 📋 Total patterns: {pattern_count}')
399
- print(f' ⚠️ Skipped files: {skipped_count}')
400
- print(f' ❌ Errors: {error_count}')
401
- print(f' 📍 Storage: ${STORAGE_PATH}')
402
-
403
- # Show resource usage
404
- stats = monitor.get_stats()
405
- print(f'\\n📊 Resource Usage:')
406
- print(f' Files processed: {stats[\"files_processed\"]:,}')
407
- print(f' Bytes processed: {stats[\"bytes_processed\"]:,}')
408
- print(f' Processing time: {stats[\"elapsed_seconds\"]:.2f}s')
409
- print(f' Throughput: {stats[\"bytes_per_second\"]:,.0f} bytes/s')
410
-
411
- # Show stats
412
- stats = engine.get_stats()
413
- print(f'\\n📈 Database Stats:')
414
- print(f' Total patterns: {stats[\"total_patterns\"]:,}')
415
- print(f' Average success rate: {stats[\"avg_success_rate\"]:.2f}')
416
- print(f' Total usage: {stats[\"total_usage\"]:,}')
417
- print(f' Unique file types: {stats[\"unique_file_types\"]}')
418
- print(f' Database size: {stats[\"database_size_bytes\"] / (1024*1024):.1f} MB')
419
- print(f' Total embeddings: {stats[\"total_embeddings\"]:,}')
420
-
421
- # Security summary
422
- print(f'\\n🔒 Security Summary:')
423
- print(f' ✅ Path traversal protection: Active')
424
- print(f' ✅ File size limits: Enforced')
425
- print(f' ✅ Input sanitization: Active')
426
- print(f' ✅ Permission checks: Active')
82
+ echo "📄 File types: $FILE_TYPES"
83
+ echo "🗄️ Database: ~/.local/share/ruvector/index_v2.db"
84
+ echo ""
427
85
 
428
- except SecurityError as e:
429
- print(f'\\n❌ Security error: {e}')
430
- sys.exit(1)
431
- except Exception as e:
432
- print(f'\\n❌ Unexpected error: {e}')
433
- import traceback
434
- traceback.print_exc()
435
- sys.exit(1)
436
- "
86
+ # Run the indexer
87
+ $BINARY index --path "$PATH_TO_INDEX" --types "$FILE_TYPES"
437
88
 
438
89
  echo ""
439
- echo "✅ Indexing complete with security validation!"
440
- echo "🔒 Security features were applied during indexing"
441
- echo "💡 Query patterns with: query-local --pattern 'your search term'"
442
- echo "📊 View stats: query-local --stats"
443
-
444
- # Make script executable
445
- chmod +x "${BASH_SOURCE[0]}"
90
+ echo "✅ Indexing complete!"
91
+ echo "💡 Query patterns with: sqlite3 ~/.local/share/ruvector/index_v2.db \"SELECT * FROM entities WHERE name LIKE '%keyword%';\""
@@ -34,7 +34,7 @@ for ext in "${file_types[@]}"; do
34
34
  fi
35
35
 
36
36
  # Index this file type
37
- ./target/release/local-ruvector index --path ../.. --types ${ext} --force
37
+ local-ruvector index --path ../.. --types ${ext} --force
38
38
 
39
39
  if [ $? -eq 0 ]; then
40
40
  echo "✅ Successfully indexed .${ext} files"
@@ -1,112 +1,73 @@
1
1
  #!/bin/bash
2
- # init-local-ruvector.sh - One-command setup for local RuVector
2
+ # init-local-ruvector.sh - Verify and setup local RuVector
3
+ # Ensures the Rust binary is installed and PATH is configured
3
4
 
4
5
  set -e
5
6
 
6
- STORAGE_PATH="${HOME}/.local-ruvector"
7
7
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+ BINARY_PATH="$HOME/.local/bin/local-ruvector"
9
+ DB_PATH="$HOME/.local/share/ruvector/index_v2.db"
8
10
 
9
- echo "🚀 Initializing Local RuVector Accelerator..."
10
-
11
- # Create storage directory structure
12
- echo "📁 Creating storage structure at ${STORAGE_PATH}..."
13
- mkdir -p "${STORAGE_PATH}/storage"
14
- mkdir -p "${STORAGE_PATH}/indexes"
15
- mkdir -p "${STORAGE_PATH}/config"
16
-
17
- # Create default config
18
- echo "⚙️ Creating default configuration..."
19
- cat > "${STORAGE_PATH}/config/settings.json" << EOF
20
- {
21
- "version": "1.0",
22
- "embedding_dimension": 1536,
23
- "similarity_threshold": 0.7,
24
- "max_patterns_per_query": 100,
25
- "cache_size": 1000,
26
- "auto_cleanup": {
27
- "enabled": true,
28
- "days_old": 30,
29
- "min_usage": 5
30
- }
31
- }
32
- EOF
11
+ echo "🚀 Checking Local RuVector Installation..."
12
+ echo ""
33
13
 
34
- # Initialize Python environment
35
- echo "🐍 Setting up Python environment..."
36
- if command -v python3 &> /dev/null; then
37
- PYTHON="python3"
38
- elif command -v python &> /dev/null; then
39
- PYTHON="python"
14
+ # Check if binary exists in PATH
15
+ if command -v local-ruvector &>/dev/null; then
16
+ BINARY_LOCATION=$(command -v local-ruvector)
17
+ VERSION=$(local-ruvector --version 2>/dev/null || echo "unknown")
18
+ echo "✅ local-ruvector found in PATH"
19
+ echo " Location: $BINARY_LOCATION"
20
+ echo " Version: $VERSION"
21
+ elif [[ -x "$BINARY_PATH" ]]; then
22
+ VERSION=$($BINARY_PATH --version 2>/dev/null || echo "unknown")
23
+ echo "✅ local-ruvector found at $BINARY_PATH"
24
+ echo " Version: $VERSION"
25
+ echo ""
26
+ echo "⚠️ Binary not in PATH. Add to your shell profile:"
27
+ echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
40
28
  else
41
- echo "❌ Error: Python not found. Please install Python 3.7+"
29
+ echo "❌ local-ruvector binary not found"
30
+ echo ""
31
+ echo "📦 Installation options:"
32
+ echo ""
33
+ echo " Option 1 - Use install script (if available):"
34
+ echo " ./scripts/install-ruvector-global.sh"
35
+ echo ""
36
+ echo " Option 2 - Build from source (requires Rust):"
37
+ echo " cd $SCRIPT_DIR"
38
+ echo " cargo build --release"
39
+ echo " cp target/release/local-ruvector ~/.local/bin/"
40
+ echo ""
42
41
  exit 1
43
42
  fi
44
43
 
45
- # Install required Python packages
46
- echo "📦 Installing required packages..."
47
- ${PYTHON} -m pip install --quiet numpy scikit-learn sqlite3 2>/dev/null || {
48
- echo "⚠️ Installing required packages system-wide..."
49
- ${PYTHON} -m pip install numpy scikit-learn
50
- }
51
-
52
- # Test imports
53
- echo "🧪 Testing dependencies..."
54
- ${PYTHON} -c "
55
- import numpy as np
56
- from sklearn.metrics.pairwise import cosine_similarity
57
- import sqlite3
58
- print('✅ All dependencies imported successfully')
59
- " || {
60
- echo "❌ Error: Failed to import required dependencies"
61
- exit 1
62
- }
63
-
64
- # Create CLI links
65
- echo "🔗 Creating CLI commands..."
66
- chmod +x "${SCRIPT_DIR}/index-code.sh"
67
- chmod +x "${SCRIPT_DIR}/query-local.sh"
68
-
69
- # Create convenience symlinks
70
- BIN_DIR="${HOME}/.local/bin"
71
- mkdir -p "${BIN_DIR}"
72
-
73
- # Remove old symlinks if they exist
74
- rm -f "${BIN_DIR}/index-code" "${BIN_DIR}/query-local"
75
-
76
- # Create new symlinks
77
- ln -s "${SCRIPT_DIR}/index-code.sh" "${BIN_DIR}/index-code"
78
- ln -s "${SCRIPT_DIR}/query-local.sh" "${BIN_DIR}/query-local"
44
+ echo ""
79
45
 
80
- # Check if BIN_DIR is in PATH
81
- if [[ ":$PATH:" != *":${BIN_DIR}:"* ]]; then
82
- echo ""
83
- echo "⚠️ Add ${BIN_DIR} to your PATH:"
84
- echo " export PATH=\"\$PATH:${BIN_DIR}\""
85
- echo " echo 'export PATH=\"\$PATH:${BIN_DIR}\"' >> ~/.bashrc"
46
+ # Check database
47
+ if [[ -f "$DB_PATH" ]]; then
48
+ DB_SIZE=$(du -h "$DB_PATH" | cut -f1)
49
+ ENTITY_COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM entities;" 2>/dev/null || echo "0")
50
+ PROJECT_COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(DISTINCT project_root) FROM entities WHERE project_root != '';" 2>/dev/null || echo "0")
51
+
52
+ echo "✅ Database found"
53
+ echo " Location: $DB_PATH"
54
+ echo " Size: $DB_SIZE"
55
+ echo " Entities: $ENTITY_COUNT"
56
+ echo " Projects: $PROJECT_COUNT"
57
+ else
58
+ echo "⚠️ No database found at $DB_PATH"
59
+ echo " Index a project with: local-ruvector index --path /your/project"
86
60
  fi
87
61
 
88
- # Initialize the database
89
- echo "🗄️ Initializing database..."
90
- ${PYTHON} -c "
91
- import sys
92
- sys.path.append('${SCRIPT_DIR}')
93
- from search_engine_v2 import SearchEngine
94
- engine = SearchEngine('${STORAGE_PATH}/storage')
95
- print('✅ Database initialized')
96
- "
97
-
98
62
  echo ""
99
- echo "🎉 Local RuVector Accelerator initialized successfully!"
63
+ echo "📖 Quick Start:"
64
+ echo " # Index a project"
65
+ echo " local-ruvector index --path ~/projects/my-app --types ts,tsx,js,jsx,py"
100
66
  echo ""
101
- echo "📍 Storage location: ${STORAGE_PATH}"
102
- echo "📖 Quick start:"
103
- echo " index-code --path /path/to/project"
104
- echo " query-local --pattern 'authentication middleware'"
67
+ echo " # Query via SQL"
68
+ echo " sqlite3 $DB_PATH \"SELECT file_path, name FROM entities WHERE name LIKE '%auth%' LIMIT 10;\""
105
69
  echo ""
106
- echo "💡 For help:"
107
- echo " index-code --help"
108
- echo " query-local --help"
109
- EOF
110
-
111
- # Make script executable
112
- chmod +x "${BASH_SOURCE[0]}"
70
+ echo " # Semantic search"
71
+ echo " local-ruvector query \"authentication middleware\""
72
+ echo ""
73
+ echo "🎉 Local RuVector is ready!"
@@ -1,18 +1,17 @@
1
1
  #!/bin/bash
2
- # query-local.sh - Query local RuVector for patterns
2
+ # query-local.sh - Query local RuVector for patterns using Rust binary
3
+ # This is a wrapper around the Rust binary for convenience
3
4
 
4
5
  set -e
5
6
 
6
7
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- STORAGE_PATH="${HOME}/.local-ruvector"
8
+ DB_PATH="$HOME/.local/share/ruvector/index_v2.db"
8
9
 
9
10
  # Parse arguments
10
11
  PATTERN=""
11
12
  FILE_TYPE=""
12
13
  LIMIT=10
13
- MIN_SIMILARITY=0.7
14
- SHOW_CONTENT=false
15
- JSON_OUTPUT=false
14
+ KIND=""
16
15
  HELP=false
17
16
 
18
17
  while [[ $# -gt 0 ]]; do
@@ -25,22 +24,14 @@ while [[ $# -gt 0 ]]; do
25
24
  FILE_TYPE="$2"
26
25
  shift 2
27
26
  ;;
28
- --limit)
29
- LIMIT="$2"
27
+ --kind)
28
+ KIND="$2"
30
29
  shift 2
31
30
  ;;
32
- --min-similarity)
33
- MIN_SIMILARITY="$2"
31
+ --limit)
32
+ LIMIT="$2"
34
33
  shift 2
35
34
  ;;
36
- --show-content)
37
- SHOW_CONTENT=true
38
- shift
39
- ;;
40
- --json)
41
- JSON_OUTPUT=true
42
- shift
43
- ;;
44
35
  --help|-h)
45
36
  HELP=true
46
37
  shift
@@ -59,111 +50,78 @@ if [[ "$HELP" == true ]] || [[ -z "$PATTERN" ]]; then
59
50
  cat << EOF
60
51
  Usage: query-local [OPTIONS] PATTERN
61
52
 
62
- Query local RuVector for similar code patterns
53
+ Query local RuVector database for code patterns
63
54
 
64
55
  Arguments:
65
- PATTERN Search pattern or description
56
+ PATTERN Search pattern (entity name or partial match)
66
57
 
67
58
  Options:
68
- --pattern PATTERN Search pattern or description
69
- --file-type TYPE Filter by file type (rs, py, js, etc.)
59
+ --pattern PATTERN Search pattern
60
+ --file-type TYPE Filter by file extension (rs, py, js, etc.)
61
+ --kind KIND Filter by entity kind (function, struct, class, etc.)
70
62
  --limit NUMBER Maximum results (default: 10)
71
- --min-similarity NUM Minimum similarity threshold (default: 0.7)
72
- --show-content Show full content of matching patterns
73
- --json Output results in JSON format
74
63
  --help, -h Show this help
75
64
 
65
+ Database Location:
66
+ $DB_PATH
67
+
76
68
  Examples:
77
- query-local "authentication middleware"
78
- query-local --file-type rs "error handling"
79
- query-local --limit 5 --show-content "database connection"
80
- query-local --json "API endpoint"
69
+ query-local "MyFunction"
70
+ query-local --kind function "auth"
71
+ query-local --file-type rs --limit 20 "handler"
72
+
73
+ Advanced SQL queries:
74
+ # Find all functions
75
+ sqlite3 $DB_PATH "SELECT file_path, name, line_number FROM entities WHERE kind = 'function' LIMIT 10;"
76
+
77
+ # Find by file path pattern
78
+ sqlite3 $DB_PATH "SELECT name, line_number FROM entities WHERE file_path LIKE '%auth%';"
79
+
80
+ # Count entities per project
81
+ sqlite3 $DB_PATH "SELECT project_root, COUNT(*) FROM entities GROUP BY project_root;"
81
82
 
82
83
  EOF
83
84
  exit 0
84
85
  fi
85
86
 
86
- # Check if storage exists
87
- if [[ ! -d "$STORAGE_PATH" ]]; then
88
- echo "❌ Error: Local RuVector not initialized"
89
- echo " Run: init-local-ruvector"
87
+ # Check if database exists
88
+ if [[ ! -f "$DB_PATH" ]]; then
89
+ echo "❌ Error: RuVector database not found at $DB_PATH"
90
+ echo " Run: local-ruvector index --path /your/project"
90
91
  exit 1
91
92
  fi
92
93
 
94
+ # Build SQL query
95
+ SQL="SELECT file_path, name, kind, line_number FROM entities WHERE name LIKE '%${PATTERN}%'"
96
+
97
+ if [[ -n "$FILE_TYPE" ]]; then
98
+ SQL="$SQL AND file_path LIKE '%.${FILE_TYPE}'"
99
+ fi
100
+
101
+ if [[ -n "$KIND" ]]; then
102
+ SQL="$SQL AND kind = '${KIND}'"
103
+ fi
104
+
105
+ SQL="$SQL LIMIT ${LIMIT};"
106
+
107
+ echo "🔍 Searching for: $PATTERN"
108
+ [[ -n "$FILE_TYPE" ]] && echo "📄 File type filter: $FILE_TYPE"
109
+ [[ -n "$KIND" ]] && echo "🏷️ Kind filter: $KIND"
110
+ echo ""
111
+
93
112
  # Run query
94
- cd "$SCRIPT_DIR"
95
- python3 -c "
96
- import sys
97
- import json
98
- from search_engine_v2 import SearchEngine
99
-
100
- # Initialize engine
101
- engine = SearchEngine('${STORAGE_PATH}/storage')
102
-
103
- # Perform search
104
- results = engine.search(
105
- query_pattern='${PATTERN}',
106
- file_type='${FILE_TYPE}' if '${FILE_TYPE}' else None,
107
- limit=${LIMIT},
108
- min_similarity=${MIN_SIMILARITY}
109
- )
110
-
111
- if not results:
112
- print('😔 No matching patterns found')
113
- print(f'💡 Try adjusting the similarity threshold (current: ${MIN_SIMILARITY})')
114
- sys.exit(0)
115
-
116
- # Format output
117
- if ${JSON_OUTPUT}:
118
- output = []
119
- for result in results:
120
- output.append({
121
- 'id': result['id'],
122
- 'file_path': result['file_path'],
123
- 'file_type': result['file_type'],
124
- 'similarity': round(result['similarity'], 3),
125
- 'composite_score': round(result['composite_score'], 3),
126
- 'success_rate': result['success_rate'],
127
- 'usage_count': result['usage_count'],
128
- 'metadata': result['metadata'],
129
- 'content': result['content'] if ${SHOW_CONTENT} else None
130
- })
131
- print(json.dumps(output, indent=2))
132
- else:
133
- print(f'🔍 Found {len(results)} patterns matching \"${PATTERN}\"')
134
- print()
135
-
136
- for i, result in enumerate(results, 1):
137
- print(f'{i}. {result[\"file_path\"]}')
138
- print(f' 📄 Type: {result[\"file_type\"]}')
139
- print(f' 🎯 Similarity: {result[\"similarity\"]:.3f}')
140
- print(f' ⭐ Score: {result[\"composite_score\"]:.3f}')
141
- print(f' ✅ Success Rate: {result[\"success_rate\"]:.2f}')
142
- print(f' 📊 Usage: {result[\"usage_count\"]} times')
143
-
144
- # Show patterns from metadata
145
- if result['metadata'] and 'patterns' in result['metadata']:
146
- patterns = result['metadata']['patterns']
147
- if patterns:
148
- print(f' 🔧 Contains: {len(patterns)} items')
149
- for pattern in patterns[:3]: # Show first 3
150
- print(f' - {pattern[\"type\"]}: {pattern[\"name\"]}')
151
- if len(patterns) > 3:
152
- print(f' ... and {len(patterns) - 3} more')
153
-
154
- # Show content if requested
155
- if ${SHOW_CONTENT}:
156
- print()
157
- print(' 📝 Content:')
158
- # Show first 20 lines
159
- lines = result['content'].split('\\n')
160
- for line in lines[:20]:
161
- print(f' {line}')
162
- if len(lines) > 20:
163
- print(f' ... ({len(lines) - 20} more lines)')
164
-
165
- print()
166
- "
167
-
168
- # Make script executable
169
- chmod +x "${BASH_SOURCE[0]}"
113
+ RESULTS=$(sqlite3 -header -column "$DB_PATH" "$SQL" 2>/dev/null)
114
+
115
+ if [[ -z "$RESULTS" ]]; then
116
+ echo "😔 No matching patterns found for '$PATTERN'"
117
+ echo ""
118
+ echo "💡 Tips:"
119
+ echo " - Try a broader search term"
120
+ echo " - Check if your project is indexed: sqlite3 $DB_PATH 'SELECT COUNT(*) FROM entities;'"
121
+ echo " - Reindex if needed: local-ruvector index --path /your/project"
122
+ else
123
+ echo "$RESULTS"
124
+ echo ""
125
+ COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM entities WHERE name LIKE '%${PATTERN}%';")
126
+ echo "📊 Total matches: $COUNT (showing up to $LIMIT)"
127
+ fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow-novice",
3
- "version": "2.18.38",
3
+ "version": "2.18.39",
4
4
  "description": "Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture\n\nIncludes Local RuVector Accelerator and all CFN skills for complete functionality.",
5
5
  "main": "index.js",
6
6
  "type": "module",
File without changes