Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions cortex/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@

from rich import box
from rich.panel import Panel
from rich.status import Status
from rich.table import Table

from cortex.branding import console
from cortex.branding import console, cx_header
from cortex.validators import validate_api_key


Expand Down Expand Up @@ -56,45 +57,50 @@ def run_checks(self) -> int:
Returns:
int: Exit code reflecting system health status (0, 1, or 2)
"""
# Header
# Show banner once
# show_banner()
console.print()
console.print(
Panel.fit(
"[bold cyan]CORTEX SYSTEM CHECK[/bold cyan]", border_style="cyan", padding=(1, 4)
)
)

# Option 2: Stylized CX header with SYSTEM HEALTH CHECK
console.print("[bold cyan] ██████╗██╗ ██╗ SYSTEM HEALTH CHECK[/bold cyan]")
console.print("[bold cyan] ██╔════╝╚██╗██╔╝ ─────────────────────[/bold cyan]")
console.print("[bold cyan] ██║ ╚███╔╝ Running...[/bold cyan]")
console.print("[bold cyan] ██║ ██╔██╗ [/bold cyan]")
console.print("[bold cyan] ╚██████╗██╔╝ ██╗[/bold cyan]")
console.print("[bold cyan] ╚═════╝╚═╝ ╚═╝[/bold cyan]")
console.print()

# Run all check groups
self._print_section("Python & Dependencies")
self._check_python()
self._check_dependencies()
# Run checks with spinner
with console.status("[bold cyan][CX] Scanning system...[/bold cyan]", spinner="dots"):
# Python & Dependencies
self._print_section("Python & Dependencies")
self._check_python()
self._check_dependencies()

self._print_section("GPU & Acceleration")
self._check_gpu_driver()
self._check_cuda()
self._print_section("GPU & Acceleration")
self._check_gpu_driver()
self._check_cuda()

self._print_section("AI & Services")
self._check_ollama()
self._check_api_keys()
self._print_section("AI & Services")
self._check_ollama()
self._check_api_keys()

self._print_section("System Resources")
self._check_disk_space()
self._check_memory()
# System Resources
self._print_section("System Resources")
self._check_disk_space()
self._check_memory()

# Print summary
self._print_summary()

# Return appropriate exit code
if self.failures:
return 2 # Critical failures
elif self.warnings:
return 1 # Warnings only
return 0 # All good

def _print_section(self, title: str) -> None:
"""Print a section header for grouping checks."""
console.print(f"\n[bold cyan]{title}[/bold cyan]")
"""Print a section header using CX branding."""
cx_header(title)

def _print_check(
self,
Expand Down Expand Up @@ -164,15 +170,18 @@ def _check_dependencies(self) -> None:
name_overrides = {
"pyyaml": "yaml",
"typing-extensions": "typing_extensions",
"python-dotenv": "dotenv",
}

try:
with open(requirements_path) as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
raw_name = line.split("==")[0].split(">")[0].split("<")[0]
pkg_name = name_overrides.get(raw_name, raw_name)
raw_name = line.split("==")[0].split(">")[0].split("<")[0].strip()
pkg_name = name_overrides.get(
raw_name.lower(), raw_name.lower().replace("-", "_")
)
try:
__import__(pkg_name)
except ImportError:
Expand Down Expand Up @@ -229,7 +238,7 @@ def _check_gpu_driver(self) -> None:
# No GPU found - this is a warning, not a failure
self._print_check(
"WARN",
"No GPU detected (CPU-only mode supported, local inference will be slower)", # ← NEW
"No GPU detected (CPU-only mode supported, local inference will be slower)",
"Optional: Install NVIDIA/AMD drivers for acceleration",
)

Expand Down Expand Up @@ -315,7 +324,7 @@ def _check_api_keys(self) -> None:
self._print_check(
"WARN",
"No API keys configured (required for cloud models)",
"Configure API key: export ANTHROPIC_API_KEY=sk-... " "or run 'cortex wizard'",
"Configure API key: export ANTHROPIC_API_KEY=sk-... or run 'cortex wizard'",
)

def _check_disk_space(self) -> None:
Expand Down
Loading