hanzo 0.2.2__py3-none-any.whl → 0.2.5__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/__init__.py CHANGED
@@ -1,95 +1,6 @@
1
- """Hanzo AI - Complete AI Infrastructure Platform SDK.
1
+ """Hanzo - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime."""
2
2
 
3
- This is the main Hanzo SDK that provides:
4
- - Router for LLM gateway (replaces litellm)
5
- - MCP (Model Context Protocol) server and tools
6
- - Agent runtime and orchestration
7
- - Memory systems
8
- - Network capabilities
3
+ __version__ = "0.2.5"
4
+ __all__ = ["main", "cli"]
9
5
 
10
- CLI access is provided via the hanzo-cli package.
11
- """
12
-
13
- __version__ = "0.2.2"
14
-
15
- # Core exports
16
- __all__ = [
17
- # Version
18
- "__version__",
19
-
20
- # Router (primary LLM interface - replaces litellm)
21
- "router",
22
- "Router",
23
- "completion",
24
- "acompletion",
25
- "embedding",
26
- "aembedding",
27
-
28
- # MCP
29
- "mcp",
30
- "MCPServer",
31
- "Tool",
32
-
33
- # Agents
34
- "Agent",
35
- "Network",
36
- "AgentTool",
37
-
38
- # Memory
39
- "Memory",
40
- "MemoryKV",
41
- "MemoryVector",
42
-
43
- # Core SDK
44
- "Client",
45
- "AsyncClient",
46
- ]
47
-
48
- # Export router as the primary LLM interface (replaces litellm)
49
- try:
50
- from . import router
51
- from .router import Router, completion, acompletion, embedding, aembedding
52
- # Make router the default for LLM operations
53
- llm = router # Compatibility alias
54
- except ImportError:
55
- router = None
56
- Router = None
57
- completion = None
58
- acompletion = None
59
- embedding = None
60
- aembedding = None
61
- llm = None
62
-
63
- # Export MCP capabilities
64
- try:
65
- import hanzo_mcp as mcp
66
- from hanzo_mcp import Tool
67
- from hanzo_mcp.server import MCPServer
68
- except ImportError:
69
- mcp = None
70
- Tool = None
71
- MCPServer = None
72
-
73
- # Export agent components
74
- try:
75
- from hanzo_agents import Agent, Network
76
- from hanzo_agents.core.tool import Tool as AgentTool
77
- except ImportError:
78
- Agent = None
79
- Network = None
80
- AgentTool = None
81
-
82
- # Export memory systems
83
- try:
84
- from hanzo_memory import Memory, MemoryKV, MemoryVector
85
- except ImportError:
86
- Memory = None
87
- MemoryKV = None
88
- MemoryVector = None
89
-
90
- # Export main SDK client
91
- try:
92
- from hanzoai import Client, AsyncClient
93
- except ImportError:
94
- Client = None
95
- AsyncClient = None
6
+ from .cli import main, cli
hanzo/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ """Entry point for python -m hanzo_cli."""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
hanzo/cli.py CHANGED
@@ -1,18 +1,242 @@
1
- """Main CLI entry point for Hanzo AI."""
1
+ """Main CLI entry point for Hanzo."""
2
2
 
3
+ import asyncio
3
4
  import sys
5
+ from typing import Optional
6
+
4
7
  import click
5
- from importlib import import_module
8
+ from rich.console import Console
9
+
10
+ from .commands import agent, auth, chat, cluster, config, mcp, miner, network, repl, tools
11
+ from .interactive.repl import HanzoREPL
12
+ from .utils.output import console
13
+
14
+ # Version
15
+ __version__ = "0.2.5"
16
+
17
+
18
+ @click.group(invoke_without_command=True)
19
+ @click.version_option(version=__version__, prog_name="hanzo")
20
+ @click.option("--verbose", "-v", is_flag=True, help="Verbose output")
21
+ @click.option("--json", is_flag=True, help="JSON output format")
22
+ @click.option("--config", "-c", type=click.Path(), help="Config file path")
23
+ @click.pass_context
24
+ def cli(ctx, verbose: bool, json: bool, config: Optional[str]):
25
+ """Hanzo AI - Unified CLI for local, private, and free AI.
26
+
27
+ Run without arguments to enter interactive mode.
28
+ """
29
+ # Ensure context object exists
30
+ ctx.ensure_object(dict)
31
+ ctx.obj["verbose"] = verbose
32
+ ctx.obj["json"] = json
33
+ ctx.obj["config"] = config
34
+ ctx.obj["console"] = console
35
+
36
+ # If no subcommand, enter interactive mode or start compute node
37
+ if ctx.invoked_subcommand is None:
38
+ # Check if we should start as a compute node
39
+ import os
40
+ if os.environ.get("HANZO_COMPUTE_NODE") == "1":
41
+ # Start as a compute node
42
+ from .commands import network
43
+ asyncio.run(start_compute_node(ctx))
44
+ else:
45
+ # Enter interactive REPL mode
46
+ console.print("[bold cyan]Hanzo AI - Interactive Mode[/bold cyan]")
47
+ console.print("Type 'help' for commands, 'exit' to quit\n")
48
+ try:
49
+ repl = HanzoREPL(console=console)
50
+ asyncio.run(repl.run())
51
+ except KeyboardInterrupt:
52
+ console.print("\n[yellow]Interrupted[/yellow]")
53
+ except EOFError:
54
+ console.print("\n[yellow]Goodbye![/yellow]")
55
+
56
+
57
+ # Register command groups
58
+ cli.add_command(agent.agent_group)
59
+ cli.add_command(auth.auth_group)
60
+ cli.add_command(cluster.cluster_group)
61
+ cli.add_command(mcp.mcp_group)
62
+ cli.add_command(miner.miner_group)
63
+ cli.add_command(chat.chat_command)
64
+ cli.add_command(repl.repl_group)
65
+ cli.add_command(tools.tools_group)
66
+ cli.add_command(network.network_group)
67
+ cli.add_command(config.config_group)
68
+
69
+
70
+ # Quick aliases
71
+ @cli.command()
72
+ @click.argument("prompt", nargs=-1, required=True)
73
+ @click.option("--model", "-m", default="llama-3.2-3b", help="Model to use")
74
+ @click.option("--local/--cloud", default=True, help="Use local or cloud model")
75
+ @click.pass_context
76
+ def ask(ctx, prompt: tuple, model: str, local: bool):
77
+ """Quick question to AI (alias for 'hanzo chat --once')."""
78
+ prompt_text = " ".join(prompt)
79
+ asyncio.run(chat.ask_once(ctx, prompt_text, model, local))
80
+
81
+
82
+ @cli.command()
83
+ @click.option("--name", "-n", default="hanzo-local", help="Cluster name")
84
+ @click.option("--port", "-p", default=8000, help="API port")
85
+ @click.pass_context
86
+ def serve(ctx, name: str, port: int):
87
+ """Start local AI cluster (alias for 'hanzo cluster start')."""
88
+ asyncio.run(cluster.start_cluster(ctx, name, port))
89
+
90
+
91
+ @cli.command()
92
+ @click.option("--name", "-n", help="Node name (auto-generated if not provided)")
93
+ @click.option("--port", "-p", default=52415, help="Node port (default: 52415 for hanzo/net)")
94
+ @click.option("--network", default="local", help="Network to join (mainnet/testnet/local)")
95
+ @click.option("--models", "-m", multiple=True, help="Models to serve (e.g., llama-3.2-3b)")
96
+ @click.option("--max-jobs", type=int, default=10, help="Max concurrent jobs")
97
+ @click.pass_context
98
+ def node(ctx, name: str, port: int, network: str, models: tuple, max_jobs: int):
99
+ """Start as a compute node for the Hanzo network using hanzo/net."""
100
+ asyncio.run(start_compute_node(ctx, name, port, network, models, max_jobs))
101
+
102
+
103
+ async def start_compute_node(ctx, name: str = None, port: int = 52415,
104
+ network: str = "mainnet", models: tuple = None,
105
+ max_jobs: int = 10):
106
+ """Start this instance as a compute node using hanzo/net."""
107
+ console = ctx.obj.get("console", Console())
108
+
109
+ console.print("[bold cyan]Starting Hanzo Net Compute Node[/bold cyan]")
110
+ console.print(f"Network: {network}")
111
+ console.print(f"Port: {port}")
112
+
113
+ try:
114
+ import subprocess
115
+ import sys
116
+ import os
117
+
118
+ # Check if hanzo/net is available
119
+ net_path = "/Users/z/work/hanzo/net"
120
+ if not os.path.exists(net_path):
121
+ # Try to find net in the Python environment
122
+ try:
123
+ import net
124
+ # net is installed as a package
125
+ console.print("[green]✓[/green] Using installed hanzo/net")
126
+
127
+ # Run net directly
128
+ from net.main import run as net_run
129
+
130
+ # Set up environment for net
131
+ if models:
132
+ os.environ["NET_MODELS"] = ",".join(models)
133
+ if name:
134
+ os.environ["NET_NODE_NAME"] = name
135
+
136
+ console.print(f"\n[green]✓[/green] Node initialized")
137
+ console.print(f" Port: {port}")
138
+ console.print(f" Models: {', '.join(models) if models else 'auto-detect'}")
139
+ console.print("\n[bold green]Hanzo Net is running![/bold green]")
140
+ console.print("WebUI: http://localhost:52415")
141
+ console.print("API: http://localhost:52415/v1/chat/completions")
142
+ console.print("\nPress Ctrl+C to stop\n")
143
+
144
+ # Run net
145
+ await net_run()
146
+
147
+ except ImportError:
148
+ # net not installed, try to run from source
149
+ console.print("[yellow]hanzo/net not installed, checking for source...[/yellow]")
150
+
151
+ if os.path.exists(net_path):
152
+ console.print(f"[green]✓[/green] Found hanzo/net at {net_path}")
153
+
154
+ # Add net to Python path
155
+ sys.path.insert(0, os.path.join(net_path, "src"))
156
+
157
+ # Import and run net
158
+ from net.main import run as net_run
159
+
160
+ console.print(f"\n[green]✓[/green] Starting net node")
161
+ console.print(f" Port: {port}")
162
+ console.print(f" Models: {', '.join(models) if models else 'auto-detect'}")
163
+ console.print("\n[bold green]Hanzo Net is running![/bold green]")
164
+ console.print("WebUI: http://localhost:52415")
165
+ console.print("API: http://localhost:52415/v1/chat/completions")
166
+ console.print("\nPress Ctrl+C to stop\n")
167
+
168
+ # Run net
169
+ await net_run()
170
+ else:
171
+ console.print("[red]Error:[/red] hanzo/net not found")
172
+ console.print("\nInstall hanzo/net:")
173
+ console.print(" git clone https://github.com/hanzoai/net.git")
174
+ console.print(" cd net && pip install -e .")
175
+ return
176
+ else:
177
+ # Run from source directory
178
+ console.print(f"[green]✓[/green] Using hanzo/net from {net_path}")
179
+
180
+ # Change to net directory and run
181
+ original_cwd = os.getcwd()
182
+ try:
183
+ os.chdir(net_path)
184
+
185
+ # Set up environment
186
+ env = os.environ.copy()
187
+ if models:
188
+ env["NET_MODELS"] = ",".join(models)
189
+ if name:
190
+ env["NET_NODE_NAME"] = name
191
+
192
+ console.print(f"\n[green]✓[/green] Starting net node")
193
+ console.print(f" Port: {port}")
194
+ console.print(f" Models: {', '.join(models) if models else 'auto-detect'}")
195
+ console.print("\n[bold green]Hanzo Net is running![/bold green]")
196
+ console.print("WebUI: http://localhost:52415")
197
+ console.print("API: http://localhost:52415/v1/chat/completions")
198
+ console.print("\nPress Ctrl+C to stop\n")
199
+
200
+ # Add src to path and run net
201
+ env["PYTHONPATH"] = os.path.join(net_path, "src") + ":" + env.get("PYTHONPATH", "")
202
+
203
+ # Run net command
204
+ process = subprocess.run(
205
+ [sys.executable, "-c", "from net.main import run; run()"],
206
+ env=env,
207
+ check=False
208
+ )
209
+
210
+ if process.returncode != 0 and process.returncode != -2: # -2 is Ctrl+C
211
+ console.print(f"[red]Net exited with code {process.returncode}[/red]")
212
+
213
+ finally:
214
+ os.chdir(original_cwd)
215
+
216
+ except KeyboardInterrupt:
217
+ console.print("\n[yellow]Shutting down node...[/yellow]")
218
+ console.print("[green]✓[/green] Node stopped")
219
+ except Exception as e:
220
+ console.print(f"[red]Error starting compute node: {e}[/red]")
221
+
222
+
223
+ @cli.command()
224
+ @click.pass_context
225
+ def dashboard(ctx):
226
+ """Open interactive dashboard."""
227
+ from .interactive.dashboard import run_dashboard
228
+ run_dashboard()
6
229
 
7
230
 
8
231
  def main():
9
- """Main entry point for hanzo command - delegates to hanzo-cli."""
232
+ """Main entry point."""
10
233
  try:
11
- # Import and run hanzo_cli
12
- from hanzo_cli.cli import main as cli_main
13
- cli_main()
14
- except ImportError:
15
- click.echo("Error: hanzo-cli is not installed. Please run: pip install hanzo[all]", err=True)
234
+ cli(auto_envvar_prefix="HANZO")
235
+ except KeyboardInterrupt:
236
+ console.print("\n[yellow]Interrupted by user[/yellow]")
237
+ sys.exit(0)
238
+ except Exception as e:
239
+ console.print(f"[red]Error: {e}[/red]")
16
240
  sys.exit(1)
17
241
 
18
242
 
@@ -0,0 +1,3 @@
1
+ """Command modules for Hanzo CLI."""
2
+
3
+ __all__ = ["agent", "auth", "chat", "cluster", "config", "mcp", "miner", "network", "repl", "tools"]
@@ -0,0 +1,112 @@
1
+ """Agent management commands."""
2
+
3
+ import asyncio
4
+ from typing import List, Optional
5
+
6
+ import click
7
+ from rich.table import Table
8
+
9
+ from ..utils.output import console, handle_errors
10
+
11
+
12
+ @click.group(name="agent")
13
+ def agent_group():
14
+ """Manage AI agents."""
15
+ pass
16
+
17
+
18
+ @agent_group.command()
19
+ @click.option("--name", "-n", required=True, help="Agent name")
20
+ @click.option("--model", "-m", default="llama-3.2-3b", help="Model to use")
21
+ @click.option("--description", "-d", help="Agent description")
22
+ @click.option("--local/--cloud", default=True, help="Use local or cloud model")
23
+ @click.pass_context
24
+ @handle_errors
25
+ async def create(ctx, name: str, model: str, description: Optional[str], local: bool):
26
+ """Create a new agent."""
27
+ try:
28
+ from hanzoai.agents import create_agent
29
+ except ImportError:
30
+ console.print("[red]Error:[/red] hanzo-agents not installed")
31
+ console.print("Install with: pip install hanzo[agents]")
32
+ return
33
+
34
+ base_url = "http://localhost:8000" if local else None
35
+
36
+ with console.status(f"Creating agent '{name}'..."):
37
+ agent = create_agent(
38
+ name=name,
39
+ model=model,
40
+ base_url=base_url
41
+ )
42
+
43
+ console.print(f"[green]✓[/green] Created agent: {name}")
44
+ console.print(f" Model: {model}")
45
+ console.print(f" Mode: {'local' if local else 'cloud'}")
46
+
47
+
48
+ @agent_group.command()
49
+ @click.pass_context
50
+ def list(ctx):
51
+ """List available agents."""
52
+ # TODO: Connect to agent registry
53
+ table = Table(title="Available Agents")
54
+ table.add_column("Name", style="cyan", no_wrap=True)
55
+ table.add_column("Model", style="green")
56
+ table.add_column("Status", style="yellow")
57
+ table.add_column("Description")
58
+
59
+ # Mock data for now
60
+ agents = [
61
+ ("helper", "llama-3.2-3b", "active", "General purpose assistant"),
62
+ ("coder", "codellama-7b", "idle", "Code generation specialist"),
63
+ ("researcher", "llama-3.2-3b", "idle", "Research and analysis"),
64
+ ]
65
+
66
+ for name, model, status, desc in agents:
67
+ table.add_row(name, model, status, desc)
68
+
69
+ console.print(table)
70
+
71
+
72
+ @agent_group.command()
73
+ @click.argument("agents", nargs=-1, required=True)
74
+ @click.option("--task", "-t", required=True, help="Task to execute")
75
+ @click.option("--parallel", "-p", is_flag=True, help="Run agents in parallel")
76
+ @click.option("--timeout", type=int, help="Timeout in seconds")
77
+ @click.pass_context
78
+ @handle_errors
79
+ async def run(ctx, agents: tuple, task: str, parallel: bool, timeout: Optional[int]):
80
+ """Run a task with specified agents."""
81
+ try:
82
+ from hanzoai.agents import create_network
83
+ except ImportError:
84
+ console.print("[red]Error:[/red] hanzo-agents not installed")
85
+ console.print("Install with: pip install hanzo[agents]")
86
+ return
87
+
88
+ agent_list = list(agents)
89
+
90
+ with console.status(f"Running task with {len(agent_list)} agents..."):
91
+ # Create network with agents
92
+ network = create_network(agents=agent_list)
93
+
94
+ # Run task
95
+ result = await asyncio.wait_for(
96
+ network.run(task),
97
+ timeout=timeout
98
+ ) if timeout else await network.run(task)
99
+
100
+ console.print("[green]Task completed![/green]")
101
+ console.print(result)
102
+
103
+
104
+ @agent_group.command()
105
+ @click.argument("agent")
106
+ @click.pass_context
107
+ def delete(ctx, agent: str):
108
+ """Delete an agent."""
109
+ if click.confirm(f"Delete agent '{agent}'?"):
110
+ console.print(f"[yellow]Deleted agent: {agent}[/yellow]")
111
+ else:
112
+ console.print("Cancelled")