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.
- hanzo/base_agent.py +516 -0
- hanzo/batch_orchestrator.py +988 -0
- hanzo/cli.py +7 -5
- hanzo/commands/chat.py +57 -16
- hanzo/commands/{cluster.py → node.py} +128 -128
- hanzo/commands/repl.py +5 -2
- hanzo/commands/router.py +152 -0
- hanzo/dev.py +407 -249
- hanzo/fallback_handler.py +79 -53
- hanzo/interactive/repl.py +52 -32
- hanzo/mcp_server.py +8 -3
- hanzo/memory_manager.py +146 -123
- hanzo/model_registry.py +399 -0
- hanzo/rate_limiter.py +60 -75
- hanzo/streaming.py +92 -71
- hanzo-0.3.24.dist-info/METADATA +276 -0
- {hanzo-0.3.22.dist-info → hanzo-0.3.24.dist-info}/RECORD +19 -15
- hanzo-0.3.22.dist-info/METADATA +0 -137
- {hanzo-0.3.22.dist-info → hanzo-0.3.24.dist-info}/WHEEL +0 -0
- {hanzo-0.3.22.dist-info → hanzo-0.3.24.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Node management commands."""
|
|
2
2
|
|
|
3
3
|
from typing import List, Optional
|
|
4
4
|
|
|
@@ -9,14 +9,14 @@ from rich.progress import Progress, TextColumn, SpinnerColumn
|
|
|
9
9
|
from ..utils.output import console
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
@click.group(name="
|
|
13
|
-
def
|
|
14
|
-
"""Manage local AI
|
|
12
|
+
@click.group(name="node")
|
|
13
|
+
def cluster():
|
|
14
|
+
"""Manage local AI node."""
|
|
15
15
|
pass
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
@
|
|
19
|
-
@click.option("--name", "-n", default="hanzo-local", help="
|
|
18
|
+
@cluster.command()
|
|
19
|
+
@click.option("--name", "-n", default="hanzo-local", help="Node name")
|
|
20
20
|
@click.option("--port", "-p", default=8000, type=int, help="API port")
|
|
21
21
|
@click.option("--models", "-m", multiple=True, help="Models to load")
|
|
22
22
|
@click.option(
|
|
@@ -27,14 +27,14 @@ def cluster_group():
|
|
|
27
27
|
)
|
|
28
28
|
@click.pass_context
|
|
29
29
|
async def start(ctx, name: str, port: int, models: tuple, device: str):
|
|
30
|
-
"""Start local AI
|
|
31
|
-
await
|
|
30
|
+
"""Start local AI node."""
|
|
31
|
+
await start_node(ctx, name, port, list(models) if models else None, device)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
async def
|
|
34
|
+
async def start_node(
|
|
35
35
|
ctx, name: str, port: int, models: Optional[List[str]] = None, device: str = "auto"
|
|
36
36
|
):
|
|
37
|
-
"""Start a local
|
|
37
|
+
"""Start a local node via hanzo-cluster."""
|
|
38
38
|
try:
|
|
39
39
|
from hanzo_cluster import HanzoCluster
|
|
40
40
|
except ImportError:
|
|
@@ -42,33 +42,33 @@ async def start_cluster(
|
|
|
42
42
|
console.print("Install with: pip install hanzo[cluster]")
|
|
43
43
|
return
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
node = HanzoCluster(name=name, port=port, device=device)
|
|
46
46
|
|
|
47
47
|
with Progress(
|
|
48
48
|
SpinnerColumn(),
|
|
49
49
|
TextColumn("[progress.description]{task.description}"),
|
|
50
50
|
console=console,
|
|
51
51
|
) as progress:
|
|
52
|
-
task = progress.add_task("Starting
|
|
52
|
+
task = progress.add_task("Starting node...", total=None)
|
|
53
53
|
|
|
54
54
|
try:
|
|
55
|
-
await
|
|
55
|
+
await node.start(models=models)
|
|
56
56
|
progress.update(task, completed=True)
|
|
57
57
|
except Exception as e:
|
|
58
58
|
progress.stop()
|
|
59
|
-
console.print(f"[red]Failed to start
|
|
59
|
+
console.print(f"[red]Failed to start node: {e}[/red]")
|
|
60
60
|
return
|
|
61
61
|
|
|
62
|
-
console.print(f"[green]✓[/green]
|
|
62
|
+
console.print(f"[green]✓[/green] Node started at http://localhost:{port}")
|
|
63
63
|
console.print("Press Ctrl+C to stop\n")
|
|
64
64
|
|
|
65
|
-
# Show
|
|
66
|
-
info = await
|
|
67
|
-
console.print("[cyan]
|
|
65
|
+
# Show node info
|
|
66
|
+
info = await node.info()
|
|
67
|
+
console.print("[cyan]Node Information:[/cyan]")
|
|
68
68
|
console.print(f" Name: {info.get('name', name)}")
|
|
69
69
|
console.print(f" Port: {info.get('port', port)}")
|
|
70
70
|
console.print(f" Device: {info.get('device', device)}")
|
|
71
|
-
console.print(f"
|
|
71
|
+
console.print(f" Workers: {info.get('nodes', 1)}")
|
|
72
72
|
if models := info.get("models", models):
|
|
73
73
|
console.print(f" Models: {', '.join(models)}")
|
|
74
74
|
|
|
@@ -76,58 +76,58 @@ async def start_cluster(
|
|
|
76
76
|
|
|
77
77
|
try:
|
|
78
78
|
# Stream logs
|
|
79
|
-
async for log in
|
|
79
|
+
async for log in node.stream_logs():
|
|
80
80
|
console.print(log, end="")
|
|
81
81
|
except KeyboardInterrupt:
|
|
82
|
-
console.print("\n[yellow]Stopping
|
|
83
|
-
await
|
|
84
|
-
console.print("[green]✓[/green]
|
|
82
|
+
console.print("\n[yellow]Stopping node...[/yellow]")
|
|
83
|
+
await node.stop()
|
|
84
|
+
console.print("[green]✓[/green] Node stopped")
|
|
85
85
|
|
|
86
86
|
|
|
87
|
-
@
|
|
88
|
-
@click.option("--name", "-n", default="hanzo-local", help="
|
|
87
|
+
@cluster.command()
|
|
88
|
+
@click.option("--name", "-n", default="hanzo-local", help="Node name")
|
|
89
89
|
@click.pass_context
|
|
90
90
|
async def stop(ctx, name: str):
|
|
91
|
-
"""Stop local AI
|
|
91
|
+
"""Stop local AI node."""
|
|
92
92
|
try:
|
|
93
93
|
from hanzo_cluster import HanzoCluster
|
|
94
94
|
except ImportError:
|
|
95
95
|
console.print("[red]Error:[/red] hanzo-cluster not installed")
|
|
96
96
|
return
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
node = HanzoCluster(name=name)
|
|
99
99
|
|
|
100
|
-
console.print("[yellow]Stopping
|
|
100
|
+
console.print("[yellow]Stopping node...[/yellow]")
|
|
101
101
|
try:
|
|
102
|
-
await
|
|
103
|
-
console.print("[green]✓[/green]
|
|
102
|
+
await node.stop()
|
|
103
|
+
console.print("[green]✓[/green] Node stopped")
|
|
104
104
|
except Exception as e:
|
|
105
|
-
console.print(f"[red]Failed to stop
|
|
105
|
+
console.print(f"[red]Failed to stop node: {e}[/red]")
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
@
|
|
109
|
-
@click.option("--name", "-n", default="hanzo-local", help="
|
|
108
|
+
@cluster.command()
|
|
109
|
+
@click.option("--name", "-n", default="hanzo-local", help="Node name")
|
|
110
110
|
@click.pass_context
|
|
111
111
|
async def status(ctx, name: str):
|
|
112
|
-
"""Show
|
|
112
|
+
"""Show node status."""
|
|
113
113
|
try:
|
|
114
114
|
from hanzo_cluster import HanzoCluster
|
|
115
115
|
except ImportError:
|
|
116
116
|
console.print("[red]Error:[/red] hanzo-cluster not installed")
|
|
117
117
|
return
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
node = HanzoCluster(name=name)
|
|
120
120
|
|
|
121
121
|
try:
|
|
122
|
-
status = await
|
|
122
|
+
status = await node.status()
|
|
123
123
|
|
|
124
124
|
if status.get("running"):
|
|
125
|
-
console.print("[green]✓[/green]
|
|
125
|
+
console.print("[green]✓[/green] Node is running")
|
|
126
126
|
|
|
127
|
-
# Show
|
|
128
|
-
console.print("\n[cyan]
|
|
127
|
+
# Show node info
|
|
128
|
+
console.print("\n[cyan]Node Information:[/cyan]")
|
|
129
129
|
console.print(f" Name: {status.get('name', name)}")
|
|
130
|
-
console.print(f"
|
|
130
|
+
console.print(f" Workers: {status.get('nodes', 0)}")
|
|
131
131
|
console.print(f" Status: {status.get('state', 'unknown')}")
|
|
132
132
|
|
|
133
133
|
# Show models
|
|
@@ -136,25 +136,25 @@ async def status(ctx, name: str):
|
|
|
136
136
|
for model in models:
|
|
137
137
|
console.print(f" • {model}")
|
|
138
138
|
|
|
139
|
-
# Show
|
|
140
|
-
if
|
|
141
|
-
console.print("\n[cyan]
|
|
142
|
-
for
|
|
139
|
+
# Show worker details
|
|
140
|
+
if workers := status.get("node_details", []):
|
|
141
|
+
console.print("\n[cyan]Workers:[/cyan]")
|
|
142
|
+
for worker in workers:
|
|
143
143
|
console.print(
|
|
144
|
-
f" • {
|
|
144
|
+
f" • {worker.get('name', 'unknown')} ({worker.get('state', 'unknown')})"
|
|
145
145
|
)
|
|
146
|
-
if device :=
|
|
146
|
+
if device := worker.get("device"):
|
|
147
147
|
console.print(f" Device: {device}")
|
|
148
148
|
else:
|
|
149
|
-
console.print("[yellow]![/yellow]
|
|
150
|
-
console.print("Start with: hanzo
|
|
149
|
+
console.print("[yellow]![/yellow] Node is not running")
|
|
150
|
+
console.print("Start with: hanzo node start")
|
|
151
151
|
|
|
152
152
|
except Exception as e:
|
|
153
153
|
console.print(f"[red]Error checking status: {e}[/red]")
|
|
154
154
|
|
|
155
155
|
|
|
156
|
-
@
|
|
157
|
-
@click.option("--name", "-n", default="hanzo-local", help="
|
|
156
|
+
@cluster.command()
|
|
157
|
+
@click.option("--name", "-n", default="hanzo-local", help="Node name")
|
|
158
158
|
@click.pass_context
|
|
159
159
|
async def models(ctx, name: str):
|
|
160
160
|
"""List available models."""
|
|
@@ -164,17 +164,17 @@ async def models(ctx, name: str):
|
|
|
164
164
|
console.print("[red]Error:[/red] hanzo-cluster not installed")
|
|
165
165
|
return
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
node = HanzoCluster(name=name)
|
|
168
168
|
|
|
169
169
|
try:
|
|
170
|
-
models = await
|
|
170
|
+
models = await node.list_models()
|
|
171
171
|
|
|
172
172
|
if models:
|
|
173
173
|
table = Table(title="Available Models")
|
|
174
174
|
table.add_column("Model ID", style="cyan")
|
|
175
175
|
table.add_column("Type", style="green")
|
|
176
176
|
table.add_column("Status", style="yellow")
|
|
177
|
-
table.add_column("
|
|
177
|
+
table.add_column("Worker", style="blue")
|
|
178
178
|
|
|
179
179
|
for model in models:
|
|
180
180
|
table.add_row(
|
|
@@ -187,69 +187,69 @@ async def models(ctx, name: str):
|
|
|
187
187
|
console.print(table)
|
|
188
188
|
else:
|
|
189
189
|
console.print("[yellow]No models loaded[/yellow]")
|
|
190
|
-
console.print("Load models with: hanzo
|
|
190
|
+
console.print("Load models with: hanzo node load <model>")
|
|
191
191
|
|
|
192
192
|
except Exception as e:
|
|
193
193
|
console.print(f"[red]Error: {e}[/red]")
|
|
194
194
|
|
|
195
195
|
|
|
196
|
-
@
|
|
196
|
+
@cluster.command()
|
|
197
197
|
@click.argument("model")
|
|
198
|
-
@click.option("--name", "-n", default="hanzo-local", help="
|
|
199
|
-
@click.option("--
|
|
198
|
+
@click.option("--name", "-n", default="hanzo-local", help="Node name")
|
|
199
|
+
@click.option("--worker", help="Target worker (default: auto-select)")
|
|
200
200
|
@click.pass_context
|
|
201
|
-
async def load(ctx, model: str, name: str,
|
|
202
|
-
"""Load a model into the
|
|
201
|
+
async def load(ctx, model: str, name: str, worker: str = None):
|
|
202
|
+
"""Load a model into the node."""
|
|
203
203
|
try:
|
|
204
204
|
from hanzo_cluster import HanzoCluster
|
|
205
205
|
except ImportError:
|
|
206
206
|
console.print("[red]Error:[/red] hanzo-cluster not installed")
|
|
207
207
|
return
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
node = HanzoCluster(name=name)
|
|
210
210
|
|
|
211
211
|
with console.status(f"Loading model '{model}'..."):
|
|
212
212
|
try:
|
|
213
|
-
result = await
|
|
213
|
+
result = await node.load_model(model, node=worker)
|
|
214
214
|
console.print(f"[green]✓[/green] Loaded model: {model}")
|
|
215
|
-
if
|
|
216
|
-
console.print(f"
|
|
215
|
+
if worker_name := result.get("node"):
|
|
216
|
+
console.print(f" Worker: {worker_name}")
|
|
217
217
|
except Exception as e:
|
|
218
218
|
console.print(f"[red]Failed to load model: {e}[/red]")
|
|
219
219
|
|
|
220
220
|
|
|
221
|
-
@
|
|
221
|
+
@cluster.command()
|
|
222
222
|
@click.argument("model")
|
|
223
|
-
@click.option("--name", "-n", default="hanzo-local", help="
|
|
223
|
+
@click.option("--name", "-n", default="hanzo-local", help="Node name")
|
|
224
224
|
@click.pass_context
|
|
225
225
|
async def unload(ctx, model: str, name: str):
|
|
226
|
-
"""Unload a model from the
|
|
226
|
+
"""Unload a model from the node."""
|
|
227
227
|
try:
|
|
228
228
|
from hanzo_cluster import HanzoCluster
|
|
229
229
|
except ImportError:
|
|
230
230
|
console.print("[red]Error:[/red] hanzo-cluster not installed")
|
|
231
231
|
return
|
|
232
232
|
|
|
233
|
-
|
|
233
|
+
node = HanzoCluster(name=name)
|
|
234
234
|
|
|
235
235
|
if click.confirm(f"Unload model '{model}'?"):
|
|
236
236
|
with console.status(f"Unloading model '{model}'..."):
|
|
237
237
|
try:
|
|
238
|
-
await
|
|
238
|
+
await node.unload_model(model)
|
|
239
239
|
console.print(f"[green]✓[/green] Unloaded model: {model}")
|
|
240
240
|
except Exception as e:
|
|
241
241
|
console.print(f"[red]Failed to unload model: {e}[/red]")
|
|
242
242
|
|
|
243
243
|
|
|
244
|
-
@
|
|
245
|
-
def
|
|
246
|
-
"""Manage
|
|
244
|
+
@cluster.group(name="worker")
|
|
245
|
+
def worker_group():
|
|
246
|
+
"""Manage node workers."""
|
|
247
247
|
pass
|
|
248
248
|
|
|
249
249
|
|
|
250
|
-
@
|
|
251
|
-
@click.option("--name", "-n", default="
|
|
252
|
-
@click.option("--
|
|
250
|
+
@worker_group.command(name="start")
|
|
251
|
+
@click.option("--name", "-n", default="worker-1", help="Worker name")
|
|
252
|
+
@click.option("--node", "-nd", default="hanzo-local", help="Node to join")
|
|
253
253
|
@click.option(
|
|
254
254
|
"--device",
|
|
255
255
|
type=click.Choice(["cpu", "gpu", "auto"]),
|
|
@@ -257,21 +257,21 @@ def node_group():
|
|
|
257
257
|
help="Device to use",
|
|
258
258
|
)
|
|
259
259
|
@click.option(
|
|
260
|
-
"--port", "-p", type=int, help="
|
|
260
|
+
"--port", "-p", type=int, help="Worker port (auto-assigned if not specified)"
|
|
261
261
|
)
|
|
262
262
|
@click.option("--blockchain", is_flag=True, help="Enable blockchain features")
|
|
263
263
|
@click.option("--network", is_flag=True, help="Enable network discovery")
|
|
264
264
|
@click.pass_context
|
|
265
|
-
async def
|
|
265
|
+
async def worker_start(
|
|
266
266
|
ctx,
|
|
267
267
|
name: str,
|
|
268
|
-
|
|
268
|
+
node: str,
|
|
269
269
|
device: str,
|
|
270
270
|
port: int,
|
|
271
271
|
blockchain: bool,
|
|
272
272
|
network: bool,
|
|
273
273
|
):
|
|
274
|
-
"""Start this machine as a
|
|
274
|
+
"""Start this machine as a worker in the node."""
|
|
275
275
|
try:
|
|
276
276
|
from hanzo_cluster import HanzoNode
|
|
277
277
|
|
|
@@ -282,22 +282,22 @@ async def node_start(
|
|
|
282
282
|
console.print("Install with: pip install hanzo[cluster,network]")
|
|
283
283
|
return
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
worker = HanzoNode(name=name, device=device, port=port)
|
|
286
286
|
|
|
287
287
|
with Progress(
|
|
288
288
|
SpinnerColumn(),
|
|
289
289
|
TextColumn("[progress.description]{task.description}"),
|
|
290
290
|
console=console,
|
|
291
291
|
) as progress:
|
|
292
|
-
task = progress.add_task(f"Starting
|
|
292
|
+
task = progress.add_task(f"Starting worker '{name}'...", total=None)
|
|
293
293
|
|
|
294
294
|
try:
|
|
295
|
-
# Start the
|
|
296
|
-
await
|
|
295
|
+
# Start the worker
|
|
296
|
+
await worker.start(cluster=node)
|
|
297
297
|
|
|
298
298
|
# Enable blockchain/network features if requested
|
|
299
299
|
if blockchain or network:
|
|
300
|
-
network_mgr = HanzoNetwork(node=
|
|
300
|
+
network_mgr = HanzoNetwork(node=worker)
|
|
301
301
|
if blockchain:
|
|
302
302
|
await network_mgr.enable_blockchain()
|
|
303
303
|
if network:
|
|
@@ -306,11 +306,11 @@ async def node_start(
|
|
|
306
306
|
progress.update(task, completed=True)
|
|
307
307
|
except Exception as e:
|
|
308
308
|
progress.stop()
|
|
309
|
-
console.print(f"[red]Failed to start
|
|
309
|
+
console.print(f"[red]Failed to start worker: {e}[/red]")
|
|
310
310
|
return
|
|
311
311
|
|
|
312
|
-
console.print(f"[green]✓[/green]
|
|
313
|
-
console.print(f"
|
|
312
|
+
console.print(f"[green]✓[/green] Worker '{name}' started")
|
|
313
|
+
console.print(f" Node: {node}")
|
|
314
314
|
console.print(f" Device: {device}")
|
|
315
315
|
if port:
|
|
316
316
|
console.print(f" Port: {port}")
|
|
@@ -324,20 +324,20 @@ async def node_start(
|
|
|
324
324
|
|
|
325
325
|
try:
|
|
326
326
|
# Stream logs
|
|
327
|
-
async for log in
|
|
327
|
+
async for log in worker.stream_logs():
|
|
328
328
|
console.print(log, end="")
|
|
329
329
|
except KeyboardInterrupt:
|
|
330
|
-
console.print("\n[yellow]Stopping
|
|
331
|
-
await
|
|
332
|
-
console.print("[green]✓[/green]
|
|
330
|
+
console.print("\n[yellow]Stopping worker...[/yellow]")
|
|
331
|
+
await worker.stop()
|
|
332
|
+
console.print("[green]✓[/green] Worker stopped")
|
|
333
333
|
|
|
334
334
|
|
|
335
|
-
@
|
|
336
|
-
@click.option("--name", "-n", help="
|
|
337
|
-
@click.option("--all", is_flag=True, help="Stop all
|
|
335
|
+
@worker_group.command(name="stop")
|
|
336
|
+
@click.option("--name", "-n", help="Worker name")
|
|
337
|
+
@click.option("--all", is_flag=True, help="Stop all workers")
|
|
338
338
|
@click.pass_context
|
|
339
|
-
async def
|
|
340
|
-
"""Stop a
|
|
339
|
+
async def worker_stop(ctx, name: str, all: bool):
|
|
340
|
+
"""Stop a worker."""
|
|
341
341
|
try:
|
|
342
342
|
from hanzo_cluster import HanzoNode
|
|
343
343
|
except ImportError:
|
|
@@ -345,30 +345,30 @@ async def node_stop(ctx, name: str, all: bool):
|
|
|
345
345
|
return
|
|
346
346
|
|
|
347
347
|
if all:
|
|
348
|
-
if click.confirm("Stop all
|
|
349
|
-
console.print("[yellow]Stopping all
|
|
348
|
+
if click.confirm("Stop all workers?"):
|
|
349
|
+
console.print("[yellow]Stopping all workers...[/yellow]")
|
|
350
350
|
try:
|
|
351
351
|
await HanzoNode.stop_all()
|
|
352
|
-
console.print("[green]✓[/green] All
|
|
352
|
+
console.print("[green]✓[/green] All workers stopped")
|
|
353
353
|
except Exception as e:
|
|
354
|
-
console.print(f"[red]Failed to stop
|
|
354
|
+
console.print(f"[red]Failed to stop workers: {e}[/red]")
|
|
355
355
|
elif name:
|
|
356
|
-
|
|
357
|
-
console.print(f"[yellow]Stopping
|
|
356
|
+
worker = HanzoNode(name=name)
|
|
357
|
+
console.print(f"[yellow]Stopping worker '{name}'...[/yellow]")
|
|
358
358
|
try:
|
|
359
|
-
await
|
|
360
|
-
console.print(f"[green]✓[/green]
|
|
359
|
+
await worker.stop()
|
|
360
|
+
console.print(f"[green]✓[/green] Worker stopped")
|
|
361
361
|
except Exception as e:
|
|
362
|
-
console.print(f"[red]Failed to stop
|
|
362
|
+
console.print(f"[red]Failed to stop worker: {e}[/red]")
|
|
363
363
|
else:
|
|
364
364
|
console.print("[red]Error:[/red] Specify --name or --all")
|
|
365
365
|
|
|
366
366
|
|
|
367
|
-
@
|
|
368
|
-
@click.option("--
|
|
367
|
+
@worker_group.command(name="list")
|
|
368
|
+
@click.option("--node", "-nd", help="Filter by node")
|
|
369
369
|
@click.pass_context
|
|
370
|
-
async def
|
|
371
|
-
"""List all
|
|
370
|
+
async def worker_list(ctx, node: str):
|
|
371
|
+
"""List all workers."""
|
|
372
372
|
try:
|
|
373
373
|
from hanzo_cluster import HanzoNode
|
|
374
374
|
except ImportError:
|
|
@@ -376,52 +376,52 @@ async def node_list(ctx, cluster: str):
|
|
|
376
376
|
return
|
|
377
377
|
|
|
378
378
|
try:
|
|
379
|
-
|
|
379
|
+
workers = await HanzoNode.list_nodes(cluster=node)
|
|
380
380
|
|
|
381
|
-
if
|
|
382
|
-
table = Table(title="
|
|
381
|
+
if workers:
|
|
382
|
+
table = Table(title="Node Workers")
|
|
383
383
|
table.add_column("Name", style="cyan")
|
|
384
|
-
table.add_column("
|
|
384
|
+
table.add_column("Node", style="green")
|
|
385
385
|
table.add_column("Device", style="yellow")
|
|
386
386
|
table.add_column("Status", style="blue")
|
|
387
387
|
table.add_column("Models", style="magenta")
|
|
388
388
|
|
|
389
|
-
for
|
|
389
|
+
for worker in workers:
|
|
390
390
|
table.add_row(
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
str(len(
|
|
391
|
+
worker.get("name", "unknown"),
|
|
392
|
+
worker.get("cluster", "unknown"),
|
|
393
|
+
worker.get("device", "unknown"),
|
|
394
|
+
worker.get("status", "unknown"),
|
|
395
|
+
str(len(worker.get("models", []))),
|
|
396
396
|
)
|
|
397
397
|
|
|
398
398
|
console.print(table)
|
|
399
399
|
else:
|
|
400
|
-
console.print("[yellow]No
|
|
401
|
-
console.print("Start a
|
|
400
|
+
console.print("[yellow]No workers found[/yellow]")
|
|
401
|
+
console.print("Start a worker with: hanzo node worker start")
|
|
402
402
|
|
|
403
403
|
except Exception as e:
|
|
404
404
|
console.print(f"[red]Error: {e}[/red]")
|
|
405
405
|
|
|
406
406
|
|
|
407
|
-
@
|
|
407
|
+
@worker_group.command(name="info")
|
|
408
408
|
@click.argument("name")
|
|
409
409
|
@click.pass_context
|
|
410
|
-
async def
|
|
411
|
-
"""Show detailed
|
|
410
|
+
async def worker_info(ctx, name: str):
|
|
411
|
+
"""Show detailed worker information."""
|
|
412
412
|
try:
|
|
413
413
|
from hanzo_cluster import HanzoNode
|
|
414
414
|
except ImportError:
|
|
415
415
|
console.print("[red]Error:[/red] hanzo-cluster not installed")
|
|
416
416
|
return
|
|
417
417
|
|
|
418
|
-
|
|
418
|
+
worker = HanzoNode(name=name)
|
|
419
419
|
|
|
420
420
|
try:
|
|
421
|
-
info = await
|
|
421
|
+
info = await worker.info()
|
|
422
422
|
|
|
423
|
-
console.print(f"[cyan]
|
|
424
|
-
console.print(f"
|
|
423
|
+
console.print(f"[cyan]Worker: {name}[/cyan]")
|
|
424
|
+
console.print(f" Node: {info.get('cluster', 'unknown')}")
|
|
425
425
|
console.print(f" Status: {info.get('status', 'unknown')}")
|
|
426
426
|
console.print(f" Device: {info.get('device', 'unknown')}")
|
|
427
427
|
|
|
@@ -456,4 +456,4 @@ async def node_info(ctx, name: str):
|
|
|
456
456
|
console.print(f" Peers: {len(peers)}")
|
|
457
457
|
|
|
458
458
|
except Exception as e:
|
|
459
|
-
console.print(f"[red]Error: {e}[/red]")
|
|
459
|
+
console.print(f"[red]Error: {e}[/red]")
|
hanzo/commands/repl.py
CHANGED
|
@@ -167,8 +167,11 @@ def exec(ctx, command: tuple, model: str):
|
|
|
167
167
|
|
|
168
168
|
asyncio.run(run())
|
|
169
169
|
|
|
170
|
-
except ImportError:
|
|
171
|
-
console.print("[red]Error:[/red]
|
|
170
|
+
except ImportError as e:
|
|
171
|
+
console.print(f"[red]Import Error:[/red] {e}")
|
|
172
|
+
console.print(
|
|
173
|
+
"[yellow]Note:[/yellow] hanzo-repl may not be installed correctly"
|
|
174
|
+
)
|
|
172
175
|
except Exception as e:
|
|
173
176
|
console.print(f"[red]Error: {e}[/red]")
|
|
174
177
|
|