mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 13:52:43 +08:00
* server working with agent library * update readme * add messages to events * factor out steps * fix websocket messages * allow user to run arbitrary actions * allow user to run commands before a task is started * fix main.py * check JSON * handle errors in controller better * fix memory issue * better error handling and task cancellation * fix monologue len * fix imports * remove server from lint check * fix lint issues * fix lint errors
69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
import asyncio
|
|
|
|
from opendevin.lib.command_manager import CommandManager
|
|
from opendevin.lib.event import Event
|
|
|
|
def print_callback(event):
|
|
print(event.str_truncated(), flush=True)
|
|
|
|
class AgentController:
|
|
def __init__(self, agent, workdir, max_iterations=100, callbacks=[]):
|
|
self.agent = agent
|
|
self.max_iterations = max_iterations
|
|
self.background_commands = []
|
|
self.command_manager = CommandManager(workdir)
|
|
self.callbacks = callbacks
|
|
self.callbacks.append(self.agent.add_event)
|
|
self.callbacks.append(print_callback)
|
|
|
|
async def add_user_event(self, event: Event):
|
|
await self.handle_action(event)
|
|
|
|
async def start_loop(self, task):
|
|
try:
|
|
self.agent.instruction = task
|
|
for i in range(self.max_iterations):
|
|
print("STEP", i, flush=True)
|
|
done = await self.step()
|
|
if done:
|
|
print("FINISHED", flush=True)
|
|
break
|
|
except Exception as e:
|
|
print("Error in loop", e, flush=True)
|
|
pass
|
|
|
|
|
|
async def step(self) -> bool:
|
|
log_events = self.command_manager.get_background_events()
|
|
for event in log_events:
|
|
await self.run_callbacks(event)
|
|
|
|
try:
|
|
action_event = self.agent.step(self.command_manager)
|
|
except Exception as e:
|
|
action_event = Event('error', {'error': str(e)})
|
|
if action_event is None:
|
|
action_event = Event('error', {'error': "Agent did not return an event"})
|
|
|
|
await self.handle_action(action_event)
|
|
return action_event.action == 'finish'
|
|
|
|
async def handle_action(self, event: Event):
|
|
print("=== HANDLING EVENT ===", flush=True)
|
|
await self.run_callbacks(event)
|
|
print("--- EVENT OUTPUT ---", flush=True)
|
|
output_event = event.run(self)
|
|
await self.run_callbacks(output_event)
|
|
|
|
async def run_callbacks(self, event):
|
|
if event is None:
|
|
return
|
|
for callback in self.callbacks:
|
|
idx = self.callbacks.index(callback)
|
|
try:
|
|
callback(event)
|
|
except Exception as e:
|
|
print("Callback error:" + str(idx), e, flush=True)
|
|
pass
|
|
await asyncio.sleep(0.001) # Give back control for a tick, so we can await in callbacks
|