bin/ 230 CLI tools (ask-*, br-*, agent-*, roadid, carpool) scripts/ 99 automation scripts fleet/ Node configs and deployment workers/ Cloudflare Worker sources (roadpay, road-search, squad webhooks) roadc/ RoadC programming language roadnet/ Mesh network (5 APs, WireGuard) operator/ Memory system scripts config/ System configs dotfiles/ Shell configs docs/ Documentation BlackRoad OS — Pave Tomorrow. RoadChain-SHA2048: d1a24f55318d338b RoadChain-Identity: alexa@sovereign RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
351 lines
11 KiB
Python
Executable File
351 lines
11 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
BlackRoad Code Library Search
|
|
Search and retrieve components from the code library.
|
|
"""
|
|
|
|
import sqlite3
|
|
import json
|
|
from pathlib import Path
|
|
from typing import List, Dict, Optional
|
|
from datetime import datetime, timedelta
|
|
import re
|
|
|
|
class LibrarySearch:
|
|
"""Search interface for the code library."""
|
|
|
|
def __init__(self, library_path: str = "~/blackroad-code-library"):
|
|
self.library_path = Path(library_path).expanduser()
|
|
self.db_path = self.library_path / "index" / "components.db"
|
|
|
|
if not self.db_path.exists():
|
|
raise FileNotFoundError(f"Library database not found at {self.db_path}. Run scanner first.")
|
|
|
|
def search(self, query: str, filters: Optional[Dict] = None, limit: int = 10) -> List[Dict]:
|
|
"""
|
|
Search for components.
|
|
|
|
Args:
|
|
query: Search query (matches name, tags, description)
|
|
filters: Optional filters (language, type, framework, min_quality, max_age_days)
|
|
limit: Max results to return
|
|
|
|
Returns:
|
|
List of matching components
|
|
"""
|
|
filters = filters or {}
|
|
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
# Build query
|
|
sql = """
|
|
SELECT * FROM components
|
|
WHERE (
|
|
name LIKE ? OR
|
|
tags LIKE ? OR
|
|
description LIKE ? OR
|
|
type LIKE ?
|
|
)
|
|
"""
|
|
params = [f"%{query}%"] * 4
|
|
|
|
# Add filters
|
|
if 'language' in filters:
|
|
sql += " AND language = ?"
|
|
params.append(filters['language'])
|
|
|
|
if 'type' in filters:
|
|
sql += " AND type = ?"
|
|
params.append(filters['type'])
|
|
|
|
if 'framework' in filters:
|
|
sql += " AND framework = ?"
|
|
params.append(filters['framework'])
|
|
|
|
if 'min_quality' in filters:
|
|
sql += " AND quality_score >= ?"
|
|
params.append(filters['min_quality'])
|
|
|
|
if 'max_age_days' in filters:
|
|
cutoff_date = (datetime.now() - timedelta(days=filters['max_age_days'])).isoformat()
|
|
sql += " AND (last_used_at >= ? OR created_at >= ?)"
|
|
params.extend([cutoff_date, cutoff_date])
|
|
|
|
if 'repo' in filters:
|
|
sql += " AND repo = ?"
|
|
params.append(filters['repo'])
|
|
|
|
# Order by quality and recency
|
|
sql += " ORDER BY quality_score DESC, created_at DESC LIMIT ?"
|
|
params.append(limit)
|
|
|
|
cursor.execute(sql, params)
|
|
rows = cursor.fetchall()
|
|
|
|
conn.close()
|
|
|
|
return [dict(row) for row in rows]
|
|
|
|
def search_by_tag(self, tag: str, limit: int = 10) -> List[Dict]:
|
|
"""Search components by tag."""
|
|
return self.search(tag, limit=limit)
|
|
|
|
def get_component(self, component_id: str) -> Optional[Dict]:
|
|
"""Get a specific component by ID."""
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT * FROM components WHERE id = ?", (component_id,))
|
|
row = cursor.fetchone()
|
|
|
|
conn.close()
|
|
|
|
return dict(row) if row else None
|
|
|
|
def get_similar_components(self, component_id: str, limit: int = 5) -> List[Dict]:
|
|
"""
|
|
Find similar components based on:
|
|
- Same type
|
|
- Overlapping tags
|
|
- Same language/framework
|
|
"""
|
|
component = self.get_component(component_id)
|
|
if not component:
|
|
return []
|
|
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
# Find components with similar characteristics
|
|
cursor.execute("""
|
|
SELECT * FROM components
|
|
WHERE id != ?
|
|
AND (
|
|
type = ? OR
|
|
language = ? OR
|
|
framework = ? OR
|
|
tags LIKE ?
|
|
)
|
|
ORDER BY quality_score DESC
|
|
LIMIT ?
|
|
""", (
|
|
component_id,
|
|
component['type'],
|
|
component['language'],
|
|
f"%{json.loads(component['tags'])[0]}%",
|
|
limit
|
|
))
|
|
|
|
rows = cursor.fetchall()
|
|
conn.close()
|
|
|
|
return [dict(row) for row in rows]
|
|
|
|
def get_stats(self) -> Dict:
|
|
"""Get library statistics."""
|
|
conn = sqlite3.connect(self.db_path)
|
|
cursor = conn.cursor()
|
|
|
|
stats = {}
|
|
|
|
# Total components
|
|
cursor.execute("SELECT COUNT(*) FROM components")
|
|
stats['total_components'] = cursor.fetchone()[0]
|
|
|
|
# By language
|
|
cursor.execute("""
|
|
SELECT language, COUNT(*) as count
|
|
FROM components
|
|
GROUP BY language
|
|
ORDER BY count DESC
|
|
""")
|
|
stats['by_language'] = dict(cursor.fetchall())
|
|
|
|
# By type
|
|
cursor.execute("""
|
|
SELECT type, COUNT(*) as count
|
|
FROM components
|
|
GROUP BY type
|
|
ORDER BY count DESC
|
|
""")
|
|
stats['by_type'] = dict(cursor.fetchall())
|
|
|
|
# By framework
|
|
cursor.execute("""
|
|
SELECT framework, COUNT(*) as count
|
|
FROM components
|
|
WHERE framework IS NOT NULL
|
|
GROUP BY framework
|
|
ORDER BY count DESC
|
|
""")
|
|
stats['by_framework'] = dict(cursor.fetchall())
|
|
|
|
# Quality distribution
|
|
cursor.execute("""
|
|
SELECT
|
|
ROUND(quality_score) as score,
|
|
COUNT(*) as count
|
|
FROM components
|
|
GROUP BY ROUND(quality_score)
|
|
ORDER BY score DESC
|
|
""")
|
|
stats['quality_distribution'] = dict(cursor.fetchall())
|
|
|
|
# Repository stats
|
|
cursor.execute("SELECT * FROM repositories ORDER BY component_count DESC")
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT * FROM repositories ORDER BY component_count DESC")
|
|
stats['repositories'] = [dict(row) for row in cursor.fetchall()]
|
|
|
|
conn.close()
|
|
|
|
return stats
|
|
|
|
def format_result(self, component: Dict) -> str:
|
|
"""Format a component result for display."""
|
|
tags = json.loads(component['tags'])
|
|
deps = json.loads(component['dependencies'])
|
|
|
|
output = f"""
|
|
{'='*70}
|
|
⭐ {component['name']} (Quality: {component['quality_score']}/10)
|
|
{'='*70}
|
|
|
|
Type: {component['type']}
|
|
Language: {component['language']}
|
|
Framework: {component.get('framework') or 'N/A'}
|
|
Repository: {component['repo']}
|
|
Location: {component['file_path']}:{component['start_line']}-{component['end_line']}
|
|
|
|
Tags: {', '.join(tags[:8])}
|
|
Dependencies: {', '.join(deps[:5]) if deps else 'None'}
|
|
|
|
Description:
|
|
{component['description']}
|
|
|
|
Code Preview:
|
|
{component['code_snippet']}
|
|
...
|
|
|
|
Full path: {component['file_path']}
|
|
"""
|
|
return output
|
|
|
|
def format_results(self, components: List[Dict]) -> str:
|
|
"""Format multiple results for display."""
|
|
if not components:
|
|
return "No components found."
|
|
|
|
output = f"\nFound {len(components)} component(s):\n"
|
|
|
|
for i, comp in enumerate(components, 1):
|
|
tags = json.loads(comp['tags'])
|
|
output += f"\n{i}. ⭐ {comp['name']} ({comp['language']}/{comp['type']}) - {comp['quality_score']:.1f}/10\n"
|
|
output += f" 📍 {comp['repo']}/{Path(comp['file_path']).name}:{comp['start_line']}\n"
|
|
output += f" 🏷️ {', '.join(tags[:5])}\n"
|
|
|
|
return output
|
|
|
|
|
|
def main():
|
|
"""CLI interface for library search."""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description='Search the BlackRoad code library')
|
|
parser.add_argument('query', nargs='?', help='Search query')
|
|
parser.add_argument('--library', default='~/blackroad-code-library', help='Library path')
|
|
parser.add_argument('--language', help='Filter by language')
|
|
parser.add_argument('--type', help='Filter by type')
|
|
parser.add_argument('--framework', help='Filter by framework')
|
|
parser.add_argument('--min-quality', type=float, help='Minimum quality score')
|
|
parser.add_argument('--max-age', type=int, help='Max age in days')
|
|
parser.add_argument('--limit', type=int, default=10, help='Max results')
|
|
parser.add_argument('--stats', action='store_true', help='Show library statistics')
|
|
parser.add_argument('--id', help='Get specific component by ID')
|
|
parser.add_argument('--similar', help='Find similar components to ID')
|
|
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
search = LibrarySearch(args.library)
|
|
except FileNotFoundError as e:
|
|
print(f"Error: {e}")
|
|
print("Hint: Run the scanner first to create the library database.")
|
|
return
|
|
|
|
# Show stats
|
|
if args.stats:
|
|
stats = search.get_stats()
|
|
print("\n📊 Library Statistics")
|
|
print("=" * 70)
|
|
print(f"\nTotal Components: {stats['total_components']}")
|
|
|
|
print("\nBy Language:")
|
|
for lang, count in stats['by_language'].items():
|
|
print(f" {lang}: {count}")
|
|
|
|
print("\nBy Type:")
|
|
for type_, count in stats['by_type'].items():
|
|
print(f" {type_}: {count}")
|
|
|
|
if stats['by_framework']:
|
|
print("\nBy Framework:")
|
|
for framework, count in stats['by_framework'].items():
|
|
print(f" {framework}: {count}")
|
|
|
|
print("\nRepositories:")
|
|
for repo in stats['repositories'][:10]:
|
|
print(f" {repo['name']}: {repo['component_count']} components")
|
|
|
|
return
|
|
|
|
# Get specific component
|
|
if args.id:
|
|
comp = search.get_component(args.id)
|
|
if comp:
|
|
print(search.format_result(comp))
|
|
else:
|
|
print(f"Component {args.id} not found.")
|
|
return
|
|
|
|
# Find similar components
|
|
if args.similar:
|
|
comps = search.get_similar_components(args.similar, args.limit)
|
|
print(search.format_results(comps))
|
|
return
|
|
|
|
# Search
|
|
if not args.query:
|
|
parser.print_help()
|
|
return
|
|
|
|
filters = {}
|
|
if args.language:
|
|
filters['language'] = args.language
|
|
if args.type:
|
|
filters['type'] = args.type
|
|
if args.framework:
|
|
filters['framework'] = args.framework
|
|
if args.min_quality:
|
|
filters['min_quality'] = args.min_quality
|
|
if args.max_age:
|
|
filters['max_age_days'] = args.max_age
|
|
|
|
results = search.search(args.query, filters, args.limit)
|
|
print(search.format_results(results))
|
|
|
|
# If only one result, show details
|
|
if len(results) == 1:
|
|
print("\n" + "=" * 70)
|
|
print("Showing details for single result:")
|
|
print(search.format_result(results[0]))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|