203 lines
5.8 KiB
Python
Executable File
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()
|