from aiohttp import web import asyncio from .auto_approver import AutoApprover from .config import Config from .iteration_logger import IterationLogger from .llm_engine.hf_llm_engine import HfLlmEngine from .llm_engine.local_llm_engine import LocalLlmEngine from .llm_engine.mistral_llm_engine import MistralLlmEngine from .llm_engine.openai_llm_engine import OpenAILlmEngine from .llm_engine.qwq_llm_engine import QwQLlmEngine from .response_parser import ResponseParser from .system_metrics import SystemMetrics from .web.api import Api from .web.static import Static from .web.websockts import Websockets from .web_agent import WebAgent from .web_io_buffer import WebIOBuffer from .working_memory import WorkingMemory from .xml_validator import XMLValidator class Main: @classmethod async def create(cls, config: Config): self = cls() self._config = config self._system_prompt = self._config.system_prompt.read_text() self._action_schema = self._config.action_schema.read_text() # Initialize LLM engines based on config self._llms = {} if config.local_enabled: self._llms['local'] = LocalLlmEngine( config.local_model, config.local_temperature, config.local_token_limit, config.local_api_key, ) if config.openai_enabled: self._llms['openai'] = OpenAILlmEngine( config.openai_model, config.openai_temperature, config.openai_token_limit, config.openai_api_key, ) if config.hf_enabled: self._llms['hf'] = HfLlmEngine( config.hf_model, config.hf_temperature, config.hf_api_key, ) if config.mistral_enabled: self._llms['mistral'] = MistralLlmEngine( config.mistral_model, config.mistral_temperature, config.mistral_token_limit, config.mistral_api_key, ) if config.qwq_enabled: self._llms['qwq'] = QwQLlmEngine( config.qwq_model, config.qwq_temperature, config.qwq_token_limit, config.hf_api_key, ) if not self._llms: raise ValueError("No LLM engines enabled in configuration") self._io_buffer = WebIOBuffer() self._working_memory = WorkingMemory() self._agent = WebAgent( system_prompt=self._system_prompt, action_schema=self._action_schema, working_memory=self._working_memory, metrics=SystemMetrics(), llms=self._llms, validator=XMLValidator(self._action_schema), parser=ResponseParser(config.work_dir, self._io_buffer), iteration_logger=IterationLogger(self._config.iterations_dir, self._system_prompt, self._action_schema), ) self._auto_approver = AutoApprover(self._agent) self._app = web.Application() self._api = Api(config.work_dir, self._app, self._agent, self._io_buffer, self._working_memory, self._auto_approver) self._websockets = Websockets(self._app, self._agent, self._io_buffer, self._auto_approver, self._working_memory) self._static = Static(self._app, self._config) return self @property def app(self): return self._app async def _serve_index(self, request: web.Request) -> web.Response: """Serve the React application HTML for any unmatched routes.""" index_path = self._config.static_files / "index.html" if not index_path.exists(): raise web.HTTPNotFound() with open(index_path, "r") as f: html_content = f.read() return web.Response( text=html_content, content_type="text/html" ) def main(): loop = asyncio.new_event_loop() config = Config() main_instance = loop.run_until_complete(Main.create(config)) print(f"Web server started at http://localhost:{config.port}") web.run_app(main_instance.app, loop=loop, host=config.host, port=config.port) return 0