Add evaluation framework and fix call graph extraction

- Add evaluation test suite with TypeScript and Python fixtures
- Fix MCP server to defer CodeGraph init until rootUri received
- Fix call edge extraction by calling resolveReferences() after indexAll/sync
- Fix glob matching for root-level files (e.g., **/*.py now matches auth.py)
- Fix duplicate node extraction for methods inside classes
- Update context tests to use buildContext for semantic search + graph traversal
- Export unused formatter functions to fix build

Evaluation results:
- TypeScript: 96% precision, 79% recall, 85% F1
- Python: 99% precision, 80% recall, 85% F1

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Colby McHenry
2026-01-18 18:48:22 -06:00
co-authored by Claude Opus 4.5
parent e306114607
commit 6b672f9152
30 changed files with 2600 additions and 129 deletions
@@ -0,0 +1,79 @@
"""Authentication service."""
import hashlib
import secrets
from datetime import datetime
from typing import Optional, Tuple
from models import User
from database import db
from validation import validate_email, validate_password
def hash_password(password: str) -> str:
"""Hash a password for storage."""
salt = secrets.token_hex(16)
hash_obj = hashlib.sha256((password + salt).encode())
return f"{salt}:{hash_obj.hexdigest()}"
def verify_password(password: str, password_hash: str) -> bool:
"""Verify a password against its hash."""
salt, stored_hash = password_hash.split(":")
hash_obj = hashlib.sha256((password + salt).encode())
return hash_obj.hexdigest() == stored_hash
def generate_token() -> str:
"""Generate a secure random token."""
return secrets.token_urlsafe(32)
class AuthService:
def __init__(self):
self.tokens: dict = {}
def register(self, email: str, password: str, name: str) -> Tuple[bool, str]:
"""Register a new user."""
if not validate_email(email):
return False, "Invalid email format"
if not validate_password(password):
return False, "Password too weak"
if db.get_user_by_email(email):
return False, "Email already registered"
user = User(
id=generate_token(),
email=email,
name=name,
password_hash=hash_password(password),
created_at=datetime.now(),
)
db.create_user(user)
return True, user.id
def login(self, email: str, password: str) -> Optional[str]:
"""Authenticate user and return token."""
user = db.get_user_by_email(email)
if not user:
return None
if not verify_password(password, user.password_hash):
return None
token = generate_token()
self.tokens[token] = user.id
return token
def logout(self, token: str) -> None:
"""Invalidate a token."""
self.tokens.pop(token, None)
def get_user_id(self, token: str) -> Optional[str]:
"""Get user ID from token."""
return self.tokens.get(token)
auth_service = AuthService()