Files
timmy-config/extensions/smart_model_routing.py
Timmy 167697c1ed
Some checks failed
Architecture Lint / Linter Tests (pull_request) Successful in 28s
Smoke Test / smoke (pull_request) Failing after 23s
Validate Config / YAML Lint (pull_request) Failing after 11s
Validate Config / JSON Validate (pull_request) Successful in 13s
Validate Config / Python Syntax & Import Check (pull_request) Failing after 31s
Validate Config / Python Test Suite (pull_request) Has been skipped
Validate Config / Shell Script Lint (pull_request) Failing after 23s
Validate Config / Cron Syntax Check (pull_request) Successful in 5s
Validate Config / Deploy Script Dry Run (pull_request) Successful in 7s
Validate Config / Playbook Schema Validation (pull_request) Successful in 15s
Validate Training Data / validate (pull_request) Failing after 18s
PR Checklist / pr-checklist (pull_request) Failing after 3m57s
Architecture Lint / Lint Repository (pull_request) Failing after 15s
feat(extensions): port active agent modules as timmy-sidecar extensions
- Moved 3 actively-used custom agent modules to timmy-config/extensions/
  - shield.py (crisis & jailbreak detection)
  - privacy_filter.py (PII stripping for remote API calls)
  - smart_model_routing.py (cheap vs strong model heuristic)
- Updated deploy.sh to copy extensions/ to ~/.hermes/agent/
- Added comprehensive migration doc in docs/AGENT_EXTENSION_MIGRATION.md
- Archived 16 dead/unused agent/*.py modules to agent/archive/ in hermes-agent

This is SIDECAR-3 — restructure agent/* extensions as sidecar skills.

Docs: Closes #339
2026-04-25 20:23:47 -04:00

50 lines
1.7 KiB
Python

"""Smart model routing — decide cheap vs strong model.
Reimplements agent/smart_model_routing.py as a timmy-config extension.
Original was a custom hermes-agent module.
"""
from __future__ import annotations
import os
import re
from typing import Any, Dict, Optional
_COMPLEX_KEYWORDS = {
"debug", "debugging", "implement", "implementation", "refactor", "patch",
"traceback", "stacktrace", "exception", "error", "analyze", "analysis",
"investigate", "architecture", "design", "compare", "benchmark", "optimize",
"optimise", "review", "terminal", "shell", "tool", "tools", "pytest",
"test", "tests", "plan", "planning", "delegate", "subagent", "cron",
"docker", "kubernetes",
}
_URL_RE = re.compile(r"https?://|www\.", re.IGNORECASE)
def _contains_complex_keyword(text: str) -> bool:
lowered = text.lower()
return any(word in lowered for word in _COMPLEX_KEYWORDS)
def _contains_url(text: str) -> bool:
return bool(_URL_RE.search(text))
def needs_strong_model(messages: list[Dict[str, Any]], threshold: float = 0.3) -> bool:
"""Return True if the request needs a strong (expensive) model."""
if not messages:
return False
text = messages[-1].get('content', '')
if not text:
return False
keyword_hits = sum(1 for kw in _COMPLEX_KEYWORDS if kw in text.lower())
total_keywords = len(_COMPLEX_KEYWORDS)
score = keyword_hits / total_keywords if total_keywords else 0.0
if score >= threshold:
return True
if _contains_url(text):
return True
return False
def should_use_cheap_model(messages: list[Dict[str, Any]], cheap_model: str, strong_model: str) -> bool:
"""Return True if the request can safely use the cheap model."""
return not needs_strong_model(messages)