from aiohttp import web import json import asyncio from ..web_agent import WebAgent from ..web_io_buffer import WebIOBuffer from .util import wrap_async class Api: def __init__(self, app: web.Application, agent: WebAgent, io_buffer: WebIOBuffer): self._app = app self._agent = agent self._io_buffer = io_buffer self._init_routes() def _init_routes(self): """Initialize REST API and WebSocket routes.""" self._app.router.add_post("/api/inference/{llm}", self._run_inference) self._app.router.add_post("/api/approve/{llm}", self._approve_response) self._app.router.add_post("/api/context", self._modify_context) self._app.router.add_post("/api/input", self._send_input) self._app.router.add_post("/api/clear", self._clear_output) self._app.router.add_get("/api/output/{llm}", self._get_output) self._app.router.add_get("/api/llms", self._get_llms) @property def app(self): return self._app async def _run_inference(self, request: web.Request) -> web.Response: """Start inference on specified LLM.""" llm_name = request.match_info["llm"] try: await asyncio.get_event_loop().run_in_executor(None, self._agent.run_inference, llm_name) return web.Response(status=200) except (ValueError, RuntimeError) as e: return web.Response(status=400, text=str(e)) async def _approve_response(self, request: web.Request) -> web.Response: """Approve response from specified LLM.""" llm_name = request.match_info["llm"] data = await request.json() response = data.get("response") if not response: return web.Response(status=400, text="Missing response in request body") try: self._agent.approve_response(llm_name, response) return web.Response(status=200) except ValueError as e: return web.Response(status=400, text=str(e)) async def _modify_context(self, request: web.Request) -> web.Response: """Modify the current context.""" data = await request.json() context = data.get("context") if not context: return web.Response(status=400, text="Missing context in request body") self._agent.modify_context(context) return web.Response(status=200) async def _send_input(self, request: web.Request) -> web.Response: """Send input to the IO buffer.""" data = await request.json() input_text = data.get("input") if not input_text: return web.Response(status=400, text="Missing input in request body") self._io_buffer.append_stdin(input_text) return web.Response(status=200) async def _clear_output(self, request: web.Request) -> web.Response: """Clear the stdout buffer.""" self._io_buffer.clear_stdout() return web.Response(status=200) async def _get_output(self, request: web.Request) -> web.Response: """Get complete output for specified LLM.""" llm_name = request.match_info["llm"] try: output = self._agent.get_output(llm_name) return web.Response( text=json.dumps({"output": output}), content_type="application/json" ) except ValueError as e: return web.Response(status=400, text=str(e)) async def _get_llms(self, request: web.Request) -> web.Response: """Get all LLMs and their current states.""" states = self._agent.llms return web.Response( text=json.dumps({ name: state.name for name, state in states.items() }), content_type="application/json" )