mvp-factory-openhands/test-scripts/openhands-sdk-wrapper-v2.py

203 lines
5.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
OpenHands SDK Wrapper for n8n Integration (V2 - Uses VENV)
Usage: python3 /home/bam/openhands-sdk-wrapper-v2.py "task description"
This wrapper uses the SDK venv to ensure all dependencies are available.
"""
import sys
import os
import json
import argparse
import subprocess
from datetime import datetime
from pathlib import Path
def run_openhands_task(task, workspace="/home/bam", verbose=True):
"""
Execute an OpenHands task using the SDK
Args:
task: Task description string
workspace: Working directory path
verbose: Print detailed logs
Returns:
dict: Results including success status and output
"""
results = {
'success': False,
'task': task,
'workspace': workspace,
'timestamp': datetime.now().isoformat(),
'error': None,
'files_created': [],
'stdout': '',
'stderr': ''
}
try:
if verbose:
print(f"🚀 Starting OpenHands SDK execution...")
print(f"📋 Task: {task}")
print(f"📁 Workspace: {workspace}")
print("-" * 50)
# Create workspace directory if it doesn't exist
workspace_path = Path(workspace)
workspace_path.mkdir(parents=True, exist_ok=True)
# Prepare the actual SDK script to run in venv
sdk_script = '''
import sys
import os
from pathlib import Path
# Add SDK to path
sys.path.insert(0, '/tmp/software-agent-sdk/openhands-sdk')
# Load environment
env_file = '/home/bam/openhands/.env'
if os.path.exists(env_file):
with open(env_file, 'r') as f:
for line in f:
line = line.strip()
if line and '=' in line and not line.startswith('#'):
key, value = line.split('=', 1)
os.environ[key] = value
from openhands.sdk import LLM, Agent, Conversation
# Configure LLM
api_key = os.getenv('MINIMAX_API_KEY')
if not api_key:
print("ERROR: MINIMAX_API_KEY not found")
sys.exit(1)
llm = LLM(
model="openai/MiniMax-M2",
api_key=api_key,
base_url="https://api.minimax.io/v1"
)
# Create agent
agent = Agent(llm=llm)
# Start conversation
workspace = sys.argv[1] if len(sys.argv) > 1 else '/home/bam'
conversation = Conversation(agent=agent, workspace=workspace)
# Send and run task
task = sys.argv[2] if len(sys.argv) > 2 else ''
conversation.send_message(task)
conversation.run()
# List files created
files = []
if os.path.exists(workspace):
for item in os.listdir(workspace):
item_path = os.path.join(workspace, item)
if os.path.isfile(item_path) and not item.startswith('.'):
files.append(item)
print("SUCCESS")
print("Files created: " + str(files))
'''
# Write the SDK script to a temp file
import tempfile
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
f.write(sdk_script)
temp_script = f.name
# Execute using the venv Python
venv_python = '/tmp/software-agent-sdk/.venv/bin/python3'
cmd = [venv_python, temp_script, str(workspace_path), task]
if verbose:
print("⏳ Running SDK in venv...")
process = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300
)
# Clean up temp file
os.unlink(temp_script)
# Parse output
results['stdout'] = process.stdout
results['stderr'] = process.stderr
if process.returncode == 0:
# Check if output contains "SUCCESS"
if "SUCCESS" in process.stdout:
results['success'] = True
# Extract files list
for line in process.stdout.split('\n'):
if 'Files created:' in line:
try:
files_str = line.split('Files created:')[1].strip()
results['files_created'] = eval(files_str)
except:
pass
if verbose:
print("✅ Task completed successfully!")
if results['files_created']:
print(f"📄 Files created: {results['files_created']}")
else:
results['error'] = process.stderr or "Unknown error"
if verbose:
print(f"❌ Task failed: {results['error']}")
except subprocess.TimeoutExpired:
results['error'] = "Timeout: Task took too long (>5 minutes)"
if verbose:
print("❌ Task timed out")
except Exception as e:
results['error'] = str(e)
if verbose:
print(f"❌ Task failed: {e}")
return results
def main():
"""Main entry point for the wrapper script"""
parser = argparse.ArgumentParser(description='OpenHands SDK Wrapper for n8n (V2)')
parser.add_argument('task', help='Task description to execute')
parser.add_argument('--workspace', default='/home/bam', help='Working directory')
parser.add_argument('--quiet', action='store_true', help='Suppress verbose output')
parser.add_argument('--json', action='store_true', help='Output results as JSON')
args = parser.parse_args()
# Run the task
results = run_openhands_task(
task=args.task,
workspace=args.workspace,
verbose=not args.quiet
)
# Output results
if args.json:
print(json.dumps(results, indent=2))
else:
if results['success']:
print("SUCCESS")
if results['files_created']:
print(f"Files created: {', '.join(results['files_created'])}")
else:
print("FAILED")
if results['error']:
print(f"Error: {results['error']}")
# Exit with appropriate code
sys.exit(0 if results['success'] else 1)
if __name__ == "__main__":
main()