hanzo 0.3.10__tar.gz → 0.3.11__tar.gz
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-0.3.10 → hanzo-0.3.11}/PKG-INFO +2 -5
- {hanzo-0.3.10 → hanzo-0.3.11}/pyproject.toml +2 -5
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/cli.py +86 -9
- {hanzo-0.3.10 → hanzo-0.3.11}/.gitignore +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/README.md +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/__init__.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/__main__.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/__init__.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/agent.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/auth.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/chat.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/cluster.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/config.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/mcp.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/miner.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/network.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/repl.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/commands/tools.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/interactive/__init__.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/interactive/dashboard.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/interactive/repl.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/mcp_server.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/repl.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/router/__init__.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/utils/__init__.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/utils/config.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/utils/net_check.py +0 -0
- {hanzo-0.3.10 → hanzo-0.3.11}/src/hanzo/utils/output.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hanzo
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.11
|
|
4
4
|
Summary: Hanzo AI - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime
|
|
5
5
|
Project-URL: Homepage, https://hanzo.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/hanzoai/python-sdk
|
|
@@ -14,16 +14,13 @@ Classifier: Intended Audience :: Developers
|
|
|
14
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
20
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.10
|
|
25
23
|
Requires-Dist: click>=8.1.0
|
|
26
|
-
Requires-Dist: hanzo-net>=0.1.12
|
|
27
24
|
Requires-Dist: httpx>=0.23.0
|
|
28
25
|
Requires-Dist: prompt-toolkit>=3.0.0
|
|
29
26
|
Requires-Dist: pydantic>=2.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "hanzo"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.11"
|
|
4
4
|
description = "Hanzo AI - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Hanzo AI", email = "dev@hanzo.ai"},
|
|
@@ -13,10 +13,9 @@ dependencies = [
|
|
|
13
13
|
"httpx>=0.23.0",
|
|
14
14
|
"pydantic>=2.0.0",
|
|
15
15
|
"pyyaml>=6.0",
|
|
16
|
-
"hanzo-net>=0.1.12",
|
|
17
16
|
]
|
|
18
17
|
readme = "README.md"
|
|
19
|
-
requires-python = ">= 3.
|
|
18
|
+
requires-python = ">= 3.10"
|
|
20
19
|
keywords = ["ai", "cli", "hanzo", "agents", "llm", "mcp", "local-ai", "private-ai"]
|
|
21
20
|
classifiers = [
|
|
22
21
|
"Development Status :: 4 - Beta",
|
|
@@ -25,8 +24,6 @@ classifiers = [
|
|
|
25
24
|
"License :: OSI Approved :: Apache Software License",
|
|
26
25
|
"Operating System :: OS Independent",
|
|
27
26
|
"Programming Language :: Python :: 3",
|
|
28
|
-
"Programming Language :: Python :: 3.8",
|
|
29
|
-
"Programming Language :: Python :: 3.9",
|
|
30
27
|
"Programming Language :: Python :: 3.10",
|
|
31
28
|
"Programming Language :: Python :: 3.11",
|
|
32
29
|
"Programming Language :: Python :: 3.12",
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
import asyncio
|
|
5
|
+
import signal
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
5
8
|
from typing import Optional
|
|
6
9
|
|
|
7
10
|
import click
|
|
@@ -115,7 +118,11 @@ def serve(ctx, name: str, port: int):
|
|
|
115
118
|
@click.pass_context
|
|
116
119
|
def net(ctx, name: str, port: int, network: str, models: tuple, max_jobs: int):
|
|
117
120
|
"""Start the Hanzo Network distributed AI compute node."""
|
|
118
|
-
|
|
121
|
+
try:
|
|
122
|
+
asyncio.run(start_compute_node(ctx, name, port, network, models, max_jobs))
|
|
123
|
+
except KeyboardInterrupt:
|
|
124
|
+
# Already handled in start_compute_node
|
|
125
|
+
pass
|
|
119
126
|
|
|
120
127
|
|
|
121
128
|
@cli.command()
|
|
@@ -133,7 +140,11 @@ def net(ctx, name: str, port: int, network: str, models: tuple, max_jobs: int):
|
|
|
133
140
|
@click.pass_context
|
|
134
141
|
def node(ctx, name: str, port: int, network: str, models: tuple, max_jobs: int):
|
|
135
142
|
"""Alias for 'hanzo net' - Start as a compute node for the Hanzo network."""
|
|
136
|
-
|
|
143
|
+
try:
|
|
144
|
+
asyncio.run(start_compute_node(ctx, name, port, network, models, max_jobs))
|
|
145
|
+
except KeyboardInterrupt:
|
|
146
|
+
# Already handled in start_compute_node
|
|
147
|
+
pass
|
|
137
148
|
|
|
138
149
|
|
|
139
150
|
async def start_compute_node(
|
|
@@ -204,8 +215,40 @@ async def start_compute_node(
|
|
|
204
215
|
console.print("API: http://localhost:52415/v1/chat/completions")
|
|
205
216
|
console.print("\nPress Ctrl+C to stop\n")
|
|
206
217
|
|
|
207
|
-
#
|
|
208
|
-
|
|
218
|
+
# Set up signal handlers for async version
|
|
219
|
+
stop_event = asyncio.Event()
|
|
220
|
+
|
|
221
|
+
def async_signal_handler(signum, frame):
|
|
222
|
+
console.print("\n[yellow]Stopping hanzo net...[/yellow]")
|
|
223
|
+
stop_event.set()
|
|
224
|
+
|
|
225
|
+
signal.signal(signal.SIGINT, async_signal_handler)
|
|
226
|
+
signal.signal(signal.SIGTERM, async_signal_handler)
|
|
227
|
+
|
|
228
|
+
# Run net with proper signal handling
|
|
229
|
+
try:
|
|
230
|
+
net_task = asyncio.create_task(net_run())
|
|
231
|
+
stop_task = asyncio.create_task(stop_event.wait())
|
|
232
|
+
|
|
233
|
+
# Wait for either net to complete or stop signal
|
|
234
|
+
done, pending = await asyncio.wait(
|
|
235
|
+
[net_task, stop_task],
|
|
236
|
+
return_when=asyncio.FIRST_COMPLETED
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
# Cancel pending tasks
|
|
240
|
+
for task in pending:
|
|
241
|
+
task.cancel()
|
|
242
|
+
try:
|
|
243
|
+
await task
|
|
244
|
+
except asyncio.CancelledError:
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
# Check if we stopped due to signal
|
|
248
|
+
if stop_task in done:
|
|
249
|
+
console.print("[green]✓[/green] Node stopped gracefully")
|
|
250
|
+
except asyncio.CancelledError:
|
|
251
|
+
console.print("[yellow]Cancelled[/yellow]")
|
|
209
252
|
finally:
|
|
210
253
|
sys.argv = original_argv
|
|
211
254
|
else:
|
|
@@ -252,12 +295,46 @@ async def start_compute_node(
|
|
|
252
295
|
if models:
|
|
253
296
|
cmd_args.extend(["--default-model", models[0]])
|
|
254
297
|
|
|
255
|
-
# Run net command with detected python
|
|
256
|
-
process
|
|
257
|
-
|
|
258
|
-
|
|
298
|
+
# Run net command with detected python in a more signal-friendly way
|
|
299
|
+
# Create new process group for better signal handling
|
|
300
|
+
process = subprocess.Popen(
|
|
301
|
+
cmd_args,
|
|
302
|
+
env=env,
|
|
303
|
+
preexec_fn=os.setsid if hasattr(os, 'setsid') else None
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# Set up signal handlers to forward to subprocess group
|
|
307
|
+
def signal_handler(signum, frame):
|
|
308
|
+
if process.poll() is None: # Process is still running
|
|
309
|
+
console.print("\n[yellow]Stopping hanzo net...[/yellow]")
|
|
310
|
+
try:
|
|
311
|
+
# Send signal to entire process group
|
|
312
|
+
if hasattr(os, 'killpg'):
|
|
313
|
+
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
|
|
314
|
+
else:
|
|
315
|
+
process.terminate()
|
|
316
|
+
process.wait(timeout=5) # Wait up to 5 seconds
|
|
317
|
+
except subprocess.TimeoutExpired:
|
|
318
|
+
console.print("[yellow]Force stopping...[/yellow]")
|
|
319
|
+
if hasattr(os, 'killpg'):
|
|
320
|
+
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
|
321
|
+
else:
|
|
322
|
+
process.kill()
|
|
323
|
+
process.wait()
|
|
324
|
+
except ProcessLookupError:
|
|
325
|
+
pass # Process already terminated
|
|
326
|
+
raise KeyboardInterrupt
|
|
327
|
+
|
|
328
|
+
# Register signal handlers
|
|
329
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
330
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
331
|
+
|
|
332
|
+
# Wait for process to complete
|
|
333
|
+
returncode = process.wait()
|
|
334
|
+
|
|
335
|
+
if returncode != 0 and returncode != -2: # -2 is Ctrl+C
|
|
259
336
|
console.print(
|
|
260
|
-
f"[red]Net exited with code {
|
|
337
|
+
f"[red]Net exited with code {returncode}[/red]"
|
|
261
338
|
)
|
|
262
339
|
|
|
263
340
|
finally:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|