feat: Implement actual AI chat functionality in hanzo dev

- Add real OpenAI and Anthropic API integration
- Implement proper chat_with_agents method that actually works
- Add fallback to direct API calls when network orchestrator unavailable
- Include openai and anthropic as dependencies
- Pass orchestrator_model to MultiClaudeOrchestrator
- Bump version to 0.3.13 for critical fix release

BREAKING: Chat now requires API keys (OPENAI_API_KEY or ANTHROPIC_API_KEY)
This commit is contained in:
2025-08-19 03:39:12 -05:00
parent b7646446b6
commit 83be37796e
3 changed files with 97 additions and 13 deletions
+3 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "hanzo"
version = "0.3.12"
version = "0.3.13"
description = "Hanzo AI - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime"
authors = [
{name = "Hanzo AI", email = "[email protected]"},
@@ -13,6 +13,8 @@ dependencies = [
"httpx>=0.23.0",
"pydantic>=2.0.0",
"pyyaml>=6.0",
"openai>=1.0.0",
"anthropic>=0.25.0",
]
readme = "README.md"
requires-python = ">= 3.10"
+1 -1
View File
@@ -26,7 +26,7 @@ from .utils.output import console
from .interactive.repl import HanzoREPL
# Version
__version__ = "0.2.10"
__version__ = "0.3.13"
@click.group(invoke_without_command=True)
+93 -11
View File
@@ -856,18 +856,97 @@ Examples:
async def chat_with_agents(self, message: str):
"""Send message to AI agents for natural chat."""
# For now, echo back to show it's working
console.print(f"[cyan]AI:[/cyan] I received your message: '{message}'")
console.print("[dim]Note: Agent integration in progress. Using echo mode.[/dim]")
try:
# Show thinking indicator
console.print("[dim]Thinking...[/dim]")
# Check if we have a network orchestrator with actual AI
if hasattr(self.orchestrator, 'execute_with_network'):
# Use the network orchestrator (GPT-4, GPT-5, etc.)
result = await self.orchestrator.execute_with_network(
task=message,
context={"mode": "chat", "interactive": True}
)
if result.get("output"):
console.print(f"[cyan]AI:[/cyan] {result['output']}")
elif result.get("error"):
console.print(f"[red]Error:[/red] {result['error']}")
else:
console.print("[yellow]No response from agent[/yellow]")
elif hasattr(self.orchestrator, 'execute_with_critique'):
# Use multi-Claude orchestrator
result = await self.orchestrator.execute_with_critique(message)
if result.get("output"):
console.print(f"[cyan]AI:[/cyan] {result['output']}")
else:
console.print("[yellow]No response from agent[/yellow]")
else:
# Fallback to direct API call if available
await self._direct_api_chat(message)
except Exception as e:
console.print(f"[red]Error connecting to AI: {e}[/red]")
console.print("[yellow]Make sure you have API keys configured:[/yellow]")
console.print(" • OPENAI_API_KEY for GPT models")
console.print(" • ANTHROPIC_API_KEY for Claude")
console.print(" • Or use --orchestrator local:llama3.2 for local models")
async def _direct_api_chat(self, message: str):
"""Direct API chat fallback when network orchestrator isn't available."""
import os
# TODO: Integrate with actual agents
# context = AgentContext(
# task=message,
# goal="Respond helpfully",
# constraints=[],
# success_criteria=[]
# )
# await self.orchestrator.execute_task(context)
# Try OpenAI first
if os.getenv("OPENAI_API_KEY"):
try:
from openai import AsyncOpenAI
client = AsyncOpenAI()
response = await client.chat.completions.create(
model=self.orchestrator.orchestrator_model or "gpt-4",
messages=[
{"role": "system", "content": "You are a helpful AI coding assistant."},
{"role": "user", "content": message}
],
temperature=0.7,
max_tokens=2000
)
if response.choices:
console.print(f"[cyan]AI:[/cyan] {response.choices[0].message.content}")
return
except Exception as e:
console.print(f"[yellow]OpenAI error: {e}[/yellow]")
# Try Anthropic
if os.getenv("ANTHROPIC_API_KEY"):
try:
from anthropic import AsyncAnthropic
client = AsyncAnthropic()
response = await client.messages.create(
model="claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": message}],
max_tokens=2000
)
if response.content:
console.print(f"[cyan]AI:[/cyan] {response.content[0].text}")
return
except Exception as e:
console.print(f"[yellow]Anthropic error: {e}[/yellow]")
# No API keys available
console.print("[red]No AI API keys configured![/red]")
console.print("Set one of these environment variables:")
console.print(" • export OPENAI_API_KEY=sk-...")
console.print(" • export ANTHROPIC_API_KEY=sk-ant-...")
console.print("Or use local models with: hanzo dev --orchestrator local:llama3.2")
async def handle_memory_command(self, command: str):
"""Handle memory/context commands starting with #."""
@@ -974,6 +1053,7 @@ async def run_dev_orchestrator(**kwargs):
enable_networking=network_mode,
enable_guardrails=guardrails,
console=console_obj,
orchestrator_model=orchestrator_model,
)
# Initialize instances
@@ -1578,6 +1658,7 @@ class MultiClaudeOrchestrator(HanzoDevOrchestrator):
enable_networking: bool,
enable_guardrails: bool,
console: Console,
orchestrator_model: str = "gpt-4",
):
super().__init__(workspace_dir, claude_path)
self.num_instances = num_instances
@@ -1585,6 +1666,7 @@ class MultiClaudeOrchestrator(HanzoDevOrchestrator):
self.enable_networking = enable_networking
self.enable_guardrails = enable_guardrails
self.console = console
self.orchestrator_model = orchestrator_model # Add this for chat interface
# Store multiple Claude instances
self.claude_instances = []