hanzo 0.3.6__py3-none-any.whl → 0.3.7__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/commands/tools.py CHANGED
@@ -1,13 +1,10 @@
1
1
  """Tools management commands."""
2
2
 
3
- import asyncio
4
- from typing import List, Optional
5
-
6
3
  import click
7
4
  from rich.table import Table
8
5
  from rich.syntax import Syntax
9
6
 
10
- from ..utils.output import console, handle_errors
7
+ from ..utils.output import console
11
8
 
12
9
 
13
10
  @click.group(name="tools")
@@ -28,23 +25,22 @@ async def list_tools(ctx, category: str, installed: bool):
28
25
  console.print("[red]Error:[/red] hanzo-tools not installed")
29
26
  console.print("Install with: pip install hanzo[tools]")
30
27
  return
31
-
28
+
32
29
  registry = get_tool_registry()
33
-
30
+
34
31
  with console.status("Loading tools..."):
35
32
  try:
36
33
  tools = await registry.list_tools(
37
- category=category,
38
- installed_only=installed
34
+ category=category, installed_only=installed
39
35
  )
40
36
  except Exception as e:
41
37
  console.print(f"[red]Failed to load tools: {e}[/red]")
42
38
  return
43
-
39
+
44
40
  if not tools:
45
41
  console.print("[yellow]No tools found[/yellow]")
46
42
  return
47
-
43
+
48
44
  # Group by category
49
45
  categories = {}
50
46
  for tool in tools:
@@ -52,7 +48,7 @@ async def list_tools(ctx, category: str, installed: bool):
52
48
  if cat not in categories:
53
49
  categories[cat] = []
54
50
  categories[cat].append(tool)
55
-
51
+
56
52
  # Display tools
57
53
  for cat, cat_tools in sorted(categories.items()):
58
54
  table = Table(title=f"{cat.title()} Tools")
@@ -60,15 +56,15 @@ async def list_tools(ctx, category: str, installed: bool):
60
56
  table.add_column("Version", style="green")
61
57
  table.add_column("Description", style="white")
62
58
  table.add_column("Status", style="yellow")
63
-
59
+
64
60
  for tool in sorted(cat_tools, key=lambda t: t["name"]):
65
61
  table.add_row(
66
62
  tool["name"],
67
63
  tool.get("version", "latest"),
68
64
  tool.get("description", ""),
69
- "installed" if tool.get("installed") else "available"
65
+ "installed" if tool.get("installed") else "available",
70
66
  )
71
-
67
+
72
68
  console.print(table)
73
69
  if len(categories) > 1:
74
70
  console.print()
@@ -85,25 +81,24 @@ async def install(ctx, tool_name: str, version: str):
85
81
  except ImportError:
86
82
  console.print("[red]Error:[/red] hanzo-tools not installed")
87
83
  return
88
-
84
+
89
85
  registry = get_tool_registry()
90
-
86
+
91
87
  with console.status(f"Installing {tool_name}..."):
92
88
  try:
93
- result = await registry.install_tool(
94
- name=tool_name,
95
- version=version
89
+ result = await registry.install_tool(name=tool_name, version=version)
90
+
91
+ console.print(
92
+ f"[green]✓[/green] Installed {tool_name} v{result['version']}"
96
93
  )
97
-
98
- console.print(f"[green]✓[/green] Installed {tool_name} v{result['version']}")
99
-
94
+
100
95
  if deps := result.get("dependencies_installed"):
101
96
  console.print(f" Dependencies: {', '.join(deps)}")
102
-
97
+
103
98
  if config := result.get("post_install_message"):
104
99
  console.print(f"\n[yellow]Configuration:[/yellow]")
105
100
  console.print(config)
106
-
101
+
107
102
  except Exception as e:
108
103
  console.print(f"[red]Failed to install {tool_name}: {e}[/red]")
109
104
 
@@ -118,9 +113,9 @@ async def uninstall(ctx, tool_name: str):
118
113
  except ImportError:
119
114
  console.print("[red]Error:[/red] hanzo-tools not installed")
120
115
  return
121
-
116
+
122
117
  registry = get_tool_registry()
123
-
118
+
124
119
  if click.confirm(f"Uninstall {tool_name}?"):
125
120
  with console.status(f"Uninstalling {tool_name}..."):
126
121
  try:
@@ -141,20 +136,17 @@ async def update(ctx, tool_name: str, version: str):
141
136
  except ImportError:
142
137
  console.print("[red]Error:[/red] hanzo-tools not installed")
143
138
  return
144
-
139
+
145
140
  registry = get_tool_registry()
146
-
141
+
147
142
  with console.status(f"Updating {tool_name}..."):
148
143
  try:
149
- result = await registry.update_tool(
150
- name=tool_name,
151
- version=version
152
- )
153
-
144
+ result = await registry.update_tool(name=tool_name, version=version)
145
+
154
146
  console.print(f"[green]✓[/green] Updated {tool_name}")
155
147
  console.print(f" Previous: v{result['previous_version']}")
156
148
  console.print(f" Current: v{result['current_version']}")
157
-
149
+
158
150
  except Exception as e:
159
151
  console.print(f"[red]Failed to update {tool_name}: {e}[/red]")
160
152
 
@@ -169,35 +161,35 @@ async def info(ctx, tool_name: str):
169
161
  except ImportError:
170
162
  console.print("[red]Error:[/red] hanzo-tools not installed")
171
163
  return
172
-
164
+
173
165
  registry = get_tool_registry()
174
-
166
+
175
167
  with console.status(f"Loading {tool_name} info..."):
176
168
  try:
177
169
  info = await registry.get_tool_info(tool_name)
178
170
  except Exception as e:
179
171
  console.print(f"[red]Failed to get info: {e}[/red]")
180
172
  return
181
-
173
+
182
174
  console.print(f"[cyan]{info['name']}[/cyan]")
183
175
  console.print(f" Version: {info['version']}")
184
176
  console.print(f" Category: {info['category']}")
185
177
  console.print(f" Author: {info.get('author', 'Unknown')}")
186
178
  console.print(f" License: {info.get('license', 'Unknown')}")
187
-
179
+
188
180
  if desc := info.get("description"):
189
181
  console.print(f"\n{desc}")
190
-
182
+
191
183
  if features := info.get("features"):
192
184
  console.print("\n[cyan]Features:[/cyan]")
193
185
  for feature in features:
194
186
  console.print(f" • {feature}")
195
-
187
+
196
188
  if deps := info.get("dependencies"):
197
189
  console.print("\n[cyan]Dependencies:[/cyan]")
198
190
  for dep in deps:
199
191
  console.print(f" • {dep}")
200
-
192
+
201
193
  if usage := info.get("usage_example"):
202
194
  console.print("\n[cyan]Usage Example:[/cyan]")
203
195
  syntax = Syntax(usage, "python", theme="monokai", line_numbers=False)
@@ -216,7 +208,7 @@ async def run(ctx, tool_name: str, args: tuple, json: bool):
216
208
  except ImportError:
217
209
  console.print("[red]Error:[/red] hanzo-tools not installed")
218
210
  return
219
-
211
+
220
212
  # Parse arguments
221
213
  tool_args = {}
222
214
  for arg in args:
@@ -227,16 +219,12 @@ async def run(ctx, tool_name: str, args: tuple, json: bool):
227
219
  console.print(f"[red]Invalid argument format: {arg}[/red]")
228
220
  console.print("Use: key=value")
229
221
  return
230
-
222
+
231
223
  with console.status(f"Running {tool_name}..."):
232
224
  try:
233
- result = await run_tool(
234
- name=tool_name,
235
- args=tool_args
236
- )
237
-
225
+ result = await run_tool(name=tool_name, args=tool_args)
226
+
238
227
  if json:
239
- import json as json_lib
240
228
  console.print_json(data=result)
241
229
  else:
242
230
  if isinstance(result, str):
@@ -246,7 +234,7 @@ async def run(ctx, tool_name: str, args: tuple, json: bool):
246
234
  console.print(f"{key}: {value}")
247
235
  else:
248
236
  console.print(result)
249
-
237
+
250
238
  except Exception as e:
251
239
  console.print(f"[red]Tool execution failed: {e}[/red]")
252
240
 
@@ -261,40 +249,40 @@ async def upgrade(ctx, check: bool):
261
249
  except ImportError:
262
250
  console.print("[red]Error:[/red] hanzo-tools not installed")
263
251
  return
264
-
252
+
265
253
  registry = get_tool_registry()
266
-
254
+
267
255
  with console.status("Checking for updates..."):
268
256
  try:
269
257
  updates = await registry.check_updates()
270
258
  except Exception as e:
271
259
  console.print(f"[red]Failed to check updates: {e}[/red]")
272
260
  return
273
-
261
+
274
262
  if not updates:
275
263
  console.print("[green]✓[/green] All tools are up to date")
276
264
  return
277
-
265
+
278
266
  # Show available updates
279
267
  table = Table(title="Available Updates")
280
268
  table.add_column("Tool", style="cyan")
281
269
  table.add_column("Current", style="yellow")
282
270
  table.add_column("Latest", style="green")
283
271
  table.add_column("Changes", style="white")
284
-
272
+
285
273
  for update in updates:
286
274
  table.add_row(
287
275
  update["name"],
288
276
  update["current_version"],
289
277
  update["latest_version"],
290
- update.get("changelog_summary", "")
278
+ update.get("changelog_summary", ""),
291
279
  )
292
-
280
+
293
281
  console.print(table)
294
-
282
+
295
283
  if check:
296
284
  return
297
-
285
+
298
286
  # Perform updates
299
287
  if click.confirm(f"Update {len(updates)} tools?"):
300
288
  for update in updates:
@@ -317,19 +305,16 @@ async def create(ctx, name: str, template: str):
317
305
  except ImportError:
318
306
  console.print("[red]Error:[/red] hanzo-tools not installed")
319
307
  return
320
-
308
+
321
309
  with console.status(f"Creating tool '{name}'..."):
322
310
  try:
323
- path = await create_tool_template(
324
- name=name,
325
- template=template or "basic"
326
- )
327
-
311
+ path = await create_tool_template(name=name, template=template or "basic")
312
+
328
313
  console.print(f"[green]✓[/green] Created tool template at: {path}")
329
314
  console.print("\nNext steps:")
330
315
  console.print("1. Edit the tool implementation")
331
316
  console.print("2. Test with: hanzo tools run {name}")
332
317
  console.print("3. Package with: hanzo tools package {name}")
333
-
318
+
334
319
  except Exception as e:
335
- console.print(f"[red]Failed to create tool: {e}[/red]")
320
+ console.print(f"[red]Failed to create tool: {e}[/red]")
@@ -1,3 +1,3 @@
1
1
  """Interactive modules for Hanzo CLI."""
2
2
 
3
- __all__ = ["repl", "dashboard"]
3
+ __all__ = ["repl", "dashboard"]
@@ -1,62 +1,51 @@
1
1
  """Dashboard interface for Hanzo CLI."""
2
2
 
3
- from typing import Optional
4
-
5
- from rich.console import Console
6
- from rich.layout import Layout
7
- from rich.panel import Panel
8
- from rich.table import Table
9
3
  from rich.live import Live
10
4
  from rich.text import Text
5
+ from rich.panel import Panel
6
+ from rich.table import Table
7
+ from rich.layout import Layout
8
+ from rich.console import Console
11
9
 
12
10
 
13
11
  def run_dashboard(refresh_rate: float = 1.0):
14
12
  """Run the interactive dashboard."""
15
13
  console = Console()
16
-
14
+
17
15
  layout = Layout()
18
16
  layout.split_column(
19
17
  Layout(name="header", size=3),
20
18
  Layout(name="body"),
21
- Layout(name="footer", size=3)
19
+ Layout(name="footer", size=3),
22
20
  )
23
-
21
+
24
22
  layout["header"].update(
25
23
  Panel(
26
24
  Text("Hanzo AI Dashboard", style="bold cyan", justify="center"),
27
- border_style="cyan"
25
+ border_style="cyan",
28
26
  )
29
27
  )
30
-
31
- layout["body"].split_row(
32
- Layout(name="left"),
33
- Layout(name="right")
34
- )
35
-
36
- layout["left"].split_column(
37
- Layout(name="cluster", size=10),
38
- Layout(name="agents")
39
- )
40
-
41
- layout["right"].split_column(
42
- Layout(name="jobs", size=15),
43
- Layout(name="logs")
44
- )
45
-
28
+
29
+ layout["body"].split_row(Layout(name="left"), Layout(name="right"))
30
+
31
+ layout["left"].split_column(Layout(name="cluster", size=10), Layout(name="agents"))
32
+
33
+ layout["right"].split_column(Layout(name="jobs", size=15), Layout(name="logs"))
34
+
46
35
  def get_cluster_panel() -> Panel:
47
36
  """Get cluster status panel."""
48
37
  table = Table(show_header=False, box=None)
49
38
  table.add_column("Key", style="cyan")
50
39
  table.add_column("Value", style="white")
51
-
40
+
52
41
  # Mock data - would be real in production
53
42
  table.add_row("Status", "[green]Running[/green]")
54
43
  table.add_row("Nodes", "3")
55
44
  table.add_row("Models", "llama-3.2-3b, gpt-4")
56
45
  table.add_row("Port", "8000")
57
-
46
+
58
47
  return Panel(table, title="Cluster", border_style="green")
59
-
48
+
60
49
  def get_agents_panel() -> Panel:
61
50
  """Get agents panel."""
62
51
  table = Table()
@@ -64,28 +53,28 @@ def run_dashboard(refresh_rate: float = 1.0):
64
53
  table.add_column("Name", style="green")
65
54
  table.add_column("Status", style="yellow")
66
55
  table.add_column("Jobs", style="magenta")
67
-
56
+
68
57
  # Mock data
69
58
  table.add_row("a1b2", "researcher", "idle", "42")
70
59
  table.add_row("c3d4", "coder", "busy", "17")
71
60
  table.add_row("e5f6", "analyst", "idle", "23")
72
-
61
+
73
62
  return Panel(table, title="Agents", border_style="blue")
74
-
63
+
75
64
  def get_jobs_panel() -> Panel:
76
65
  """Get jobs panel."""
77
66
  table = Table()
78
67
  table.add_column("ID", style="cyan", width=8)
79
68
  table.add_column("Type", style="green")
80
69
  table.add_column("Status", style="yellow")
81
-
70
+
82
71
  # Mock data
83
72
  table.add_row("j001", "chat", "complete")
84
73
  table.add_row("j002", "analysis", "running")
85
74
  table.add_row("j003", "search", "queued")
86
-
75
+
87
76
  return Panel(table, title="Recent Jobs", border_style="yellow")
88
-
77
+
89
78
  def get_logs_panel() -> Panel:
90
79
  """Get logs panel."""
91
80
  logs = """[dim]2024-01-20 10:15:23[/dim] Agent started: researcher
@@ -93,33 +82,34 @@ def run_dashboard(refresh_rate: float = 1.0):
93
82
  [dim]2024-01-20 10:15:25[/dim] Model loaded: llama-3.2-3b
94
83
  [dim]2024-01-20 10:15:26[/dim] Network peer connected: node-2
95
84
  [dim]2024-01-20 10:15:27[/dim] Job j001 completed (2.3s)"""
96
-
85
+
97
86
  return Panel(logs, title="Logs", border_style="dim")
98
-
87
+
99
88
  layout["footer"].update(
100
89
  Panel(
101
90
  "[bold]Q[/bold] Quit [bold]R[/bold] Refresh [bold]C[/bold] Clear",
102
- border_style="dim"
91
+ border_style="dim",
103
92
  )
104
93
  )
105
-
94
+
106
95
  # Update panels
107
96
  layout["cluster"].update(get_cluster_panel())
108
97
  layout["agents"].update(get_agents_panel())
109
98
  layout["jobs"].update(get_jobs_panel())
110
99
  layout["logs"].update(get_logs_panel())
111
-
100
+
112
101
  try:
113
- with Live(layout, refresh_per_second=1/refresh_rate, screen=True):
102
+ with Live(layout, refresh_per_second=1 / refresh_rate, screen=True):
114
103
  while True:
115
104
  import time
105
+
116
106
  time.sleep(refresh_rate)
117
-
107
+
118
108
  # Update dynamic panels
119
109
  layout["cluster"].update(get_cluster_panel())
120
110
  layout["agents"].update(get_agents_panel())
121
111
  layout["jobs"].update(get_jobs_panel())
122
112
  layout["logs"].update(get_logs_panel())
123
-
113
+
124
114
  except KeyboardInterrupt:
125
- console.print("\n[yellow]Dashboard closed[/yellow]")
115
+ console.print("\n[yellow]Dashboard closed[/yellow]")
hanzo/interactive/repl.py CHANGED
@@ -1,20 +1,19 @@
1
1
  """Interactive REPL for Hanzo CLI."""
2
2
 
3
- import asyncio
3
+ from typing import Optional
4
4
  from pathlib import Path
5
- from typing import Dict, Any, Optional
6
5
 
6
+ from rich.console import Console
7
+ from rich.markdown import Markdown
7
8
  from prompt_toolkit import PromptSession
8
9
  from prompt_toolkit.history import FileHistory
9
- from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
10
10
  from prompt_toolkit.completion import WordCompleter
11
- from rich.console import Console
12
- from rich.markdown import Markdown
11
+ from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
13
12
 
14
13
 
15
14
  class HanzoREPL:
16
15
  """Interactive REPL for Hanzo CLI."""
17
-
16
+
18
17
  def __init__(self, console: Optional[Console] = None):
19
18
  self.console = console or Console()
20
19
  self.session = PromptSession(
@@ -29,47 +28,46 @@ class HanzoREPL:
29
28
  "status": self.show_status,
30
29
  }
31
30
  self.running = False
32
-
31
+
33
32
  async def run(self):
34
33
  """Run the REPL."""
35
34
  self.running = True
36
35
  # Don't print welcome message here since it's already printed in cli.py
37
-
36
+
38
37
  # Set up command completer
39
38
  completer = WordCompleter(
40
39
  list(self.commands.keys()) + ["chat", "agent", "cluster", "mcp", "network"],
41
- ignore_case=True
40
+ ignore_case=True,
42
41
  )
43
-
42
+
44
43
  while self.running:
45
44
  try:
46
45
  # Get input
47
46
  command = await self.session.prompt_async(
48
- "hanzo> ",
49
- completer=completer
47
+ "hanzo> ", completer=completer
50
48
  )
51
-
49
+
52
50
  if not command.strip():
53
51
  continue
54
-
52
+
55
53
  # Parse command
56
54
  parts = command.strip().split(maxsplit=1)
57
55
  cmd = parts[0].lower()
58
56
  args = parts[1] if len(parts) > 1 else ""
59
-
57
+
60
58
  # Execute command
61
59
  if cmd in self.commands:
62
60
  await self.commands[cmd](args)
63
61
  else:
64
62
  await self.execute_command(cmd, args)
65
-
63
+
66
64
  except KeyboardInterrupt:
67
65
  continue
68
66
  except EOFError:
69
67
  break
70
68
  except Exception as e:
71
69
  self.console.print(f"[red]Error: {e}[/red]")
72
-
70
+
73
71
  async def show_help(self, args: str = ""):
74
72
  """Show help message."""
75
73
  help_text = """
@@ -103,16 +101,16 @@ hanzo> mcp run read_file --arg path=README.md
103
101
  - Use Ctrl+R for reverse search
104
102
  """
105
103
  self.console.print(Markdown(help_text))
106
-
104
+
107
105
  def exit_repl(self, args: str = ""):
108
106
  """Exit the REPL."""
109
107
  self.running = False
110
108
  self.console.print("\n[yellow]Goodbye![/yellow]")
111
-
109
+
112
110
  def clear_screen(self, args: str = ""):
113
111
  """Clear the screen."""
114
112
  self.console.clear()
115
-
113
+
116
114
  async def show_status(self, args: str = ""):
117
115
  """Show system status."""
118
116
  status = {
@@ -120,35 +118,38 @@ hanzo> mcp run read_file --arg path=README.md
120
118
  "agents": await self.count_agents(),
121
119
  "auth": self.check_auth_status(),
122
120
  }
123
-
121
+
124
122
  self.console.print("[cyan]System Status:[/cyan]")
125
123
  self.console.print(f" Cluster: {status['cluster']}")
126
124
  self.console.print(f" Agents: {status['agents']}")
127
125
  self.console.print(f" Auth: {status['auth']}")
128
-
126
+
129
127
  async def execute_command(self, cmd: str, args: str):
130
128
  """Execute a CLI command."""
131
129
  # Import here to avoid circular imports
132
- from .. import cli
133
- import click
134
130
  import sys
135
-
131
+
132
+ import click
133
+
134
+ from .. import cli
135
+
136
136
  # Build command line
137
137
  argv = [cmd]
138
138
  if args:
139
139
  import shlex
140
+
140
141
  argv.extend(shlex.split(args))
141
-
142
+
142
143
  # Create a new context
143
144
  try:
144
145
  # Save original argv
145
146
  orig_argv = sys.argv
146
147
  sys.argv = ["hanzo"] + argv
147
-
148
+
148
149
  # Execute command
149
150
  ctx = click.Context(cli.cli)
150
151
  cli.cli.invoke(ctx)
151
-
152
+
152
153
  except SystemExit:
153
154
  # Catch exit from commands
154
155
  pass
@@ -157,28 +158,30 @@ hanzo> mcp run read_file --arg path=README.md
157
158
  finally:
158
159
  # Restore argv
159
160
  sys.argv = orig_argv
160
-
161
+
161
162
  async def check_cluster_status(self) -> str:
162
163
  """Check if cluster is running."""
163
164
  try:
164
165
  import httpx
166
+
165
167
  async with httpx.AsyncClient() as client:
166
168
  response = await client.get("http://localhost:8000/health", timeout=1.0)
167
169
  return "running" if response.status_code == 200 else "not responding"
168
170
  except:
169
171
  return "not running"
170
-
172
+
171
173
  async def count_agents(self) -> int:
172
174
  """Count running agents."""
173
175
  # This would check actual agent status
174
176
  return 0
175
-
177
+
176
178
  def check_auth_status(self) -> str:
177
179
  """Check authentication status."""
178
180
  import os
181
+
179
182
  if os.environ.get("HANZO_API_KEY"):
180
183
  return "authenticated (API key)"
181
184
  elif (Path.home() / ".hanzo" / "auth.json").exists():
182
185
  return "authenticated (saved)"
183
186
  else:
184
- return "not authenticated"
187
+ return "not authenticated"
hanzo/mcp_server.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """MCP server entry point for hanzo/mcp command."""
2
2
 
3
3
  import sys
4
+
4
5
  import click
5
6
 
6
7
 
@@ -8,11 +9,15 @@ def main():
8
9
  """Start the Hanzo MCP server."""
9
10
  try:
10
11
  from hanzo_mcp.server import main as mcp_main
12
+
11
13
  mcp_main()
12
14
  except ImportError:
13
- click.echo("Error: hanzo-mcp is not installed. Please run: pip install hanzo[mcp] or pip install hanzo[all]", err=True)
15
+ click.echo(
16
+ "Error: hanzo-mcp is not installed. Please run: pip install hanzo[mcp] or pip install hanzo[all]",
17
+ err=True,
18
+ )
14
19
  sys.exit(1)
15
20
 
16
21
 
17
22
  if __name__ == "__main__":
18
- main()
23
+ main()