hanzo 0.3.22__py3-none-any.whl → 0.3.24__py3-none-any.whl

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.

Potentially problematic release.


This version of hanzo might be problematic. Click here for more details.

@@ -0,0 +1,152 @@
1
+ """Router command for starting Hanzo router proxy."""
2
+
3
+ import os
4
+ import sys
5
+ import subprocess
6
+ from typing import Optional
7
+ from pathlib import Path
8
+
9
+ import click
10
+
11
+ from ..utils.output import console
12
+
13
+
14
+ @click.group(name="router")
15
+ def router_group():
16
+ """Manage Hanzo router (LLM proxy)."""
17
+ pass
18
+
19
+
20
+ @router_group.command(name="start")
21
+ @click.option("--port", "-p", default=4000, help="Port to run router on")
22
+ @click.option("--config", "-c", help="Config file path")
23
+ @click.option("--detach", "-d", is_flag=True, help="Run in background")
24
+ @click.pass_context
25
+ def start_router(ctx, port: int, config: Optional[str], detach: bool):
26
+ """Start the Hanzo router proxy server."""
27
+ # Find router directory
28
+ router_paths = [
29
+ Path.home() / "work" / "hanzo" / "router",
30
+ Path.home() / "hanzo" / "router",
31
+ Path.cwd().parent / "router",
32
+ ]
33
+
34
+ router_dir = None
35
+ for path in router_paths:
36
+ if path.exists() and (path / "litellm" / "proxy" / "proxy_server.py").exists():
37
+ router_dir = path
38
+ break
39
+
40
+ if not router_dir:
41
+ console.print("[red]Error:[/red] Hanzo router not found")
42
+ console.print("\nPlease clone the router:")
43
+ console.print(" git clone https://github.com/hanzoai/router.git ~/work/hanzo/router")
44
+ return
45
+
46
+ console.print(f"[green]✓[/green] Found router at {router_dir}")
47
+
48
+ # Prepare environment
49
+ env = os.environ.copy()
50
+ env["PYTHONPATH"] = str(router_dir) + ":" + env.get("PYTHONPATH", "")
51
+
52
+ # Build command
53
+ cmd = [
54
+ sys.executable,
55
+ "-m", "litellm.proxy.proxy_server",
56
+ "--port", str(port),
57
+ ]
58
+
59
+ if config:
60
+ # Use provided config
61
+ config_path = Path(config)
62
+ if not config_path.exists():
63
+ console.print(f"[red]Error:[/red] Config file not found: {config}")
64
+ return
65
+ cmd.extend(["--config", str(config_path)])
66
+ else:
67
+ # Check for default config
68
+ default_config = router_dir / "config.yaml"
69
+ if default_config.exists():
70
+ cmd.extend(["--config", str(default_config)])
71
+ console.print(f"[dim]Using config: {default_config}[/dim]")
72
+
73
+ console.print(f"\n[bold cyan]Starting Hanzo Router on port {port}[/bold cyan]")
74
+ console.print(f"API endpoint: http://localhost:{port}/v1")
75
+ console.print("\nPress Ctrl+C to stop\n")
76
+
77
+ try:
78
+ # Change to router directory and run
79
+ os.chdir(router_dir)
80
+
81
+ if detach:
82
+ # Run in background
83
+ process = subprocess.Popen(
84
+ cmd,
85
+ env=env,
86
+ stdout=subprocess.DEVNULL,
87
+ stderr=subprocess.DEVNULL,
88
+ start_new_session=True
89
+ )
90
+ console.print(f"[green]✓[/green] Router started in background (PID: {process.pid})")
91
+ console.print(f"Check status: curl http://localhost:{port}/health")
92
+ else:
93
+ # Run in foreground
94
+ subprocess.run(cmd, env=env)
95
+ except KeyboardInterrupt:
96
+ console.print("\n[yellow]Router stopped[/yellow]")
97
+ except Exception as e:
98
+ console.print(f"[red]Error starting router: {e}[/red]")
99
+
100
+
101
+ @router_group.command(name="stop")
102
+ @click.option("--port", "-p", default=4000, help="Port router is running on")
103
+ def stop_router(port: int):
104
+ """Stop the router."""
105
+ import signal
106
+
107
+ import psutil
108
+
109
+ found = False
110
+ for proc in psutil.process_iter(['pid', 'cmdline']):
111
+ try:
112
+ cmdline = proc.info['cmdline']
113
+ if cmdline and 'proxy_server' in ' '.join(cmdline) and str(port) in ' '.join(cmdline):
114
+ console.print(f"[yellow]Stopping router (PID: {proc.info['pid']})[/yellow]")
115
+ proc.send_signal(signal.SIGTERM)
116
+ proc.wait(timeout=5)
117
+ found = True
118
+ console.print("[green]✓[/green] Router stopped")
119
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.TimeoutExpired):
120
+ continue
121
+
122
+ if not found:
123
+ console.print(f"[yellow]No router found on port {port}[/yellow]")
124
+
125
+
126
+ @router_group.command(name="status")
127
+ @click.option("--port", "-p", default=4000, help="Port to check")
128
+ def router_status(port: int):
129
+ """Check router status."""
130
+ import httpx
131
+
132
+ try:
133
+ response = httpx.get(f"http://localhost:{port}/health", timeout=2.0)
134
+ if response.status_code == 200:
135
+ console.print(f"[green]✓[/green] Router is running on port {port}")
136
+
137
+ # Try to get models
138
+ try:
139
+ models_response = httpx.get(f"http://localhost:{port}/models", timeout=2.0)
140
+ if models_response.status_code == 200:
141
+ data = models_response.json()
142
+ if "data" in data:
143
+ console.print(f"Available models: {len(data['data'])}")
144
+ except Exception:
145
+ pass
146
+ else:
147
+ console.print(f"[yellow]Router responding but unhealthy (status: {response.status_code})[/yellow]")
148
+ except httpx.ConnectError:
149
+ console.print(f"[red]Router not running on port {port}[/red]")
150
+ console.print("\nStart with: hanzo router start")
151
+ except Exception as e:
152
+ console.print(f"[red]Error checking router: {e}[/red]")