mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
fix: Improve AI tool detection and fallback handling
- Fix Hanzo Node detection to verify chat endpoint actually works - Skip Hanzo Node if /v1/chat/completions returns 404 - Add proper fallback chain when primary tool fails - Show helpful error messages and suggest working alternatives - agent will be used when Hanzo Node isn't functional
This commit is contained in:
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Hanzo Package Publishing Script
|
||||
# Version 0.2.5
|
||||
|
||||
set -e
|
||||
|
||||
echo "=================================="
|
||||
echo "Hanzo Package Publishing"
|
||||
echo "Version: 0.2.5"
|
||||
echo "=================================="
|
||||
echo
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "pyproject.toml" ]; then
|
||||
echo "Error: pyproject.toml not found. Please run from pkg/hanzo directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean previous builds
|
||||
echo "Cleaning previous builds..."
|
||||
rm -rf dist/ build/ *.egg-info 2>/dev/null || true
|
||||
|
||||
# Build the package
|
||||
echo "Building distribution packages..."
|
||||
python -m build
|
||||
|
||||
# Check the build
|
||||
echo
|
||||
echo "Build complete. Contents:"
|
||||
ls -la dist/
|
||||
|
||||
# Test the package (optional)
|
||||
echo
|
||||
read -p "Do you want to test the package locally before uploading? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Creating test virtual environment..."
|
||||
python -m venv test_env
|
||||
source test_env/bin/activate
|
||||
pip install dist/hanzo-0.2.5-py3-none-any.whl
|
||||
echo "Testing hanzo command..."
|
||||
hanzo --version
|
||||
deactivate
|
||||
rm -rf test_env
|
||||
echo "Test successful!"
|
||||
fi
|
||||
|
||||
# Upload to TestPyPI first (optional)
|
||||
echo
|
||||
read -p "Do you want to upload to TestPyPI first? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Uploading to TestPyPI..."
|
||||
python -m twine upload --repository testpypi dist/*
|
||||
echo
|
||||
echo "Package uploaded to TestPyPI."
|
||||
echo "Test with: pip install --index-url https://test.pypi.org/simple/ hanzo"
|
||||
echo
|
||||
read -p "Continue to PyPI? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Stopping here. Package is on TestPyPI."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Upload to PyPI
|
||||
echo
|
||||
echo "Uploading to PyPI..."
|
||||
echo "You will be prompted for your PyPI credentials or API token."
|
||||
echo
|
||||
python -m twine upload dist/*
|
||||
|
||||
echo
|
||||
echo "=================================="
|
||||
echo "Package published successfully!"
|
||||
echo "Install with: pip install hanzo"
|
||||
echo "Current version: 0.2.5"
|
||||
echo "=================================="
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "hanzo"
|
||||
version = "0.3.28"
|
||||
version = "0.3.29"
|
||||
description = "Hanzo AI - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime"
|
||||
authors = [
|
||||
{name = "Hanzo AI", email = "[email protected]"},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Hanzo - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime."""
|
||||
|
||||
__version__ = "0.3.28"
|
||||
__version__ = "0.3.29"
|
||||
__all__ = ["main", "cli", "__version__"]
|
||||
|
||||
from .cli import cli, main
|
||||
|
||||
@@ -645,8 +645,25 @@ class EnhancedHanzoREPL:
|
||||
if success:
|
||||
self.console.print(output)
|
||||
else:
|
||||
# Fallback to regular model
|
||||
self.console.print(f"[yellow]{self.current_tool.display_name} failed, trying cloud model...[/yellow]")
|
||||
# Show error and try fallback
|
||||
self.console.print(f"[red]Error: {output}[/red]")
|
||||
|
||||
# Try to find next available tool
|
||||
if self.tool_detector and self.tool_detector.detected_tools:
|
||||
for fallback_tool in self.tool_detector.detected_tools:
|
||||
if fallback_tool != self.current_tool:
|
||||
self.console.print(f"[yellow]Trying {fallback_tool.display_name}...[/yellow]")
|
||||
success, output = self.tool_detector.execute_with_tool(fallback_tool, message)
|
||||
if success:
|
||||
self.console.print(output)
|
||||
# Suggest switching to working tool
|
||||
self.console.print(f"\n[dim]Tip: Switch to {fallback_tool.display_name} with /model {fallback_tool.name}[/dim]")
|
||||
return
|
||||
else:
|
||||
self.console.print(f"[red]{fallback_tool.display_name} also failed[/red]")
|
||||
|
||||
# Final fallback to cloud model
|
||||
self.console.print(f"[yellow]Falling back to cloud model...[/yellow]")
|
||||
await self.execute_command("ask", f"--cloud --model gpt-3.5-turbo {message}")
|
||||
else:
|
||||
# Use regular model through hanzo ask
|
||||
|
||||
@@ -170,22 +170,46 @@ class ToolDetector:
|
||||
try:
|
||||
response = httpx.get(tool.api_endpoint, timeout=1.0)
|
||||
if response.status_code == 200:
|
||||
tool.detected = True
|
||||
tool.version = "Running"
|
||||
|
||||
# Special handling for Hanzo services
|
||||
# For Hanzo Node, verify it can actually handle chat completions
|
||||
if tool.name == "hanzod":
|
||||
# Check if models are loaded
|
||||
try:
|
||||
models_response = httpx.get("http://localhost:8000/models", timeout=1.0)
|
||||
if models_response.status_code == 200:
|
||||
models = models_response.json()
|
||||
if models:
|
||||
tool.version = f"Running ({len(models)} models)"
|
||||
# Check if the chat completions endpoint works
|
||||
test_response = httpx.post(
|
||||
"http://localhost:8000/v1/chat/completions",
|
||||
json={
|
||||
"messages": [{"role": "user", "content": "test"}],
|
||||
"model": "test",
|
||||
"max_tokens": 1
|
||||
},
|
||||
timeout=2.0
|
||||
)
|
||||
# Only mark as detected if we get a valid response or specific error
|
||||
# 404 means the endpoint doesn't exist
|
||||
if test_response.status_code == 404:
|
||||
return False
|
||||
|
||||
tool.detected = True
|
||||
tool.version = "Running (Local AI)"
|
||||
|
||||
# Try to get model info
|
||||
try:
|
||||
models_response = httpx.get("http://localhost:8000/v1/models", timeout=1.0)
|
||||
if models_response.status_code == 200:
|
||||
models = models_response.json().get("data", [])
|
||||
if models:
|
||||
tool.version = f"Running ({len(models)} models)"
|
||||
except:
|
||||
pass
|
||||
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
|
||||
return True
|
||||
# If chat endpoint doesn't work, node isn't useful
|
||||
return False
|
||||
else:
|
||||
# For other services, just check health endpoint
|
||||
tool.detected = True
|
||||
tool.version = "Running"
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -318,12 +342,13 @@ class ToolDetector:
|
||||
try:
|
||||
# Special handling for Hanzo services
|
||||
if tool.name == "hanzod":
|
||||
# Use the local API directly
|
||||
# Use the local API directly with correct endpoint
|
||||
try:
|
||||
response = httpx.post(
|
||||
"http://localhost:8000/chat/completions",
|
||||
"http://localhost:8000/v1/chat/completions",
|
||||
json={
|
||||
"messages": [{"role": "user", "content": prompt}],
|
||||
"model": "default", # Use default model
|
||||
"stream": False
|
||||
},
|
||||
timeout=30.0
|
||||
@@ -331,6 +356,8 @@ class ToolDetector:
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
return True, result.get("choices", [{}])[0].get("message", {}).get("content", "")
|
||||
else:
|
||||
return False, f"Hanzo Node returned {response.status_code}: {response.text}"
|
||||
except Exception as e:
|
||||
return False, f"Hanzo Node error: {e}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user