diff --git a/docs/architecture/Architecture.md b/docs/architecture/Architecture.md new file mode 100644 index 0000000000..25e9a65723 --- /dev/null +++ b/docs/architecture/Architecture.md @@ -0,0 +1,14 @@ + +# System Architecture Overview + +This is a high-level overview of the system architecture. The system is divided into two main components: the frontend and the backend. The frontend is responsible for handling user interactions and displaying the results. The backend is responsible for handling the business logic and executing the agents. + +![system_architecture.svg](system_architecture.svg) + +This Overview is simplified to show the main components and their interactions. For a more detailed view of the backend architecture, see the [Backend Architecture](#backend-architecture) section. + +# Backend Architecture + +*__Disclaimer__: The backend architecture is a work in progress and is subject to change. The following diagram shows the current architecture of the backend based on the commit that is shown in the footer of the diagram.* + +![backend_architecture.svg](backend_architecture.svg) \ No newline at end of file diff --git a/docs/architecture/backend_architecture.png b/docs/architecture/backend_architecture.png new file mode 100644 index 0000000000..2cc41a3e67 Binary files /dev/null and b/docs/architecture/backend_architecture.png differ diff --git a/docs/architecture/backend_architecture.puml b/docs/architecture/backend_architecture.puml new file mode 100644 index 0000000000..70545ce5d7 --- /dev/null +++ b/docs/architecture/backend_architecture.puml @@ -0,0 +1,222 @@ +@startuml opendevin +!pragma useIntermediatePackages false + +class opendevin.action.agent.AgentEchoAction { + content: str + runnable: bool + action: str +} +class opendevin.action.agent.AgentFinishAction { + runnable: bool + action: str +} +class opendevin.observation.AgentMessageObservation { + role: str + observation: str +} +class opendevin.action.agent.AgentRecallAction { + query: str + action: str +} +class opendevin.observation.AgentRecallObservation { + memories: List[str] + role: str + observation: str +} +class opendevin.action.agent.AgentSummarizeAction { + summary: str + action: str +} +class opendevin.action.agent.AgentThinkAction { + thought: str + runnable: bool + action: str +} +class opendevin.action.base.ExecutableAction { +} +class opendevin.action.base.NotExecutableAction { +} +class opendevin.observation.Observation { + content: str +} +class opendevin.action.base.Action { +} +class opendevin.action.base.NullAction { + action: str +} +class opendevin.action.bash.CmdKillAction { + id: int + action: str +} +class opendevin.action.bash.CmdRunAction { + command: str + background: bool + action: str +} +class opendevin.action.browse.BrowseURLAction { + url: str + action: str +} +class opendevin.observation.BrowserOutputObservation { + url: str + status_code: int + error: bool + observation: str +} +class opendevin.action.fileop.FileReadAction { + path: str + action: str +} +class opendevin.observation.FileReadObservation { + path: str + observation: str +} +class opendevin.action.fileop.FileWriteAction { + path: str + contents: str + action: str +} +class opendevin.observation.FileWriteObservation { + path: str + observation: str +} +class opendevin.action.tasks.AddTaskAction { + parent: str + goal: str + subtasks: list + action: str +} +class opendevin.action.tasks.ModifyTaskAction { + id: str + state: str + action: str +} +abstract class opendevin.agent.Agent { + _registry: Dict[str, Type[Agent]] {static} + llm: LLM + _complete: None +} +class opendevin.llm.llm.LLM { + model: None + api_key: None + base_url: None + _debug_dir: None + _debug_idx: None + _debug_id: None + _completion: None +} +class opendevin.controller.agent_controller.AgentController { + agent: Agent + max_iterations: int + workdir: str + command_manager: CommandManager + state: State + plan: Plan + callbacks: List[Callable] +} +class opendevin.observation.AgentErrorObservation { + observation: str +} +class opendevin.controller.command_manager.CommandManager { + directory: None + shell: None +} +class opendevin.observation.NullObservation { + observation: str +} +class opendevin.plan.Plan { + main_goal: str {static} + task: Task {static} + main_goal: str + task: None +} +class opendevin.state.State { + plan: Plan + iteration: int + background_commands_obs: List[CmdOutputObservation] + history: List[Tuple[Action, Observation]] + updated_info: List[Tuple[Action, Observation]] +} +class opendevin.observation.CmdOutputObservation { + command_id: int + command: str + exit_code: int + observation: str +} +class opendevin.sandbox.sandbox.DockerInteractive { + background_commands: Dict[int, BackgroundCommand] {static} + instance_id: None + instance_id: None + workspace_dir: None + workspace_dir: None + workspace_dir: None + timeout: int + container_image: None + container_name: None +} +class opendevin.observation.UserMessageObservation { + role: str + observation: str +} +class opendevin.plan.Task { + id: str {static} + goal: str {static} + parent: Task | None {static} + subtasks: List[Task] {static} + id: None + id: None + parent: None + goal: str + subtasks: None +} + +class opendevin.server.session.Session { + websocket: None + controller: Optional[AgentController] + agent: Optional[Agent] + agent_task: None +} + +opendevin.action.base.ExecutableAction <|-- opendevin.action.agent.AgentEchoAction +opendevin.action.base.NotExecutableAction <|-- opendevin.action.agent.AgentFinishAction +opendevin.observation.Observation <|-- opendevin.observation.AgentMessageObservation +opendevin.action.base.ExecutableAction <|-- opendevin.action.agent.AgentRecallAction +opendevin.observation.Observation <|-- opendevin.observation.AgentRecallObservation +opendevin.action.base.NotExecutableAction <|-- opendevin.action.agent.AgentSummarizeAction +opendevin.action.base.NotExecutableAction <|-- opendevin.action.agent.AgentThinkAction +opendevin.action.base.Action <|-- opendevin.action.base.ExecutableAction +opendevin.action.base.Action <|-- opendevin.action.base.NotExecutableAction +opendevin.action.base.NotExecutableAction <|-- opendevin.action.base.NullAction +opendevin.action.base.ExecutableAction <|-- opendevin.action.bash.CmdKillAction +opendevin.action.base.ExecutableAction <|-- opendevin.action.bash.CmdRunAction +opendevin.action.base.ExecutableAction <|-- opendevin.action.browse.BrowseURLAction +opendevin.observation.Observation <|-- opendevin.observation.BrowserOutputObservation +opendevin.action.base.ExecutableAction <|-- opendevin.action.fileop.FileReadAction +opendevin.observation.Observation <|-- opendevin.observation.FileReadObservation +opendevin.action.base.ExecutableAction <|-- opendevin.action.fileop.FileWriteAction +opendevin.observation.Observation <|-- opendevin.observation.FileWriteObservation +opendevin.action.base.NotExecutableAction <|-- opendevin.action.tasks.AddTaskAction +opendevin.action.base.NotExecutableAction <|-- opendevin.action.tasks.ModifyTaskAction +opendevin.agent.Agent *-- opendevin.agent.Agent +opendevin.agent.Agent *-- opendevin.llm.llm.LLM +opendevin.controller.agent_controller.AgentController *-- opendevin.agent.Agent +opendevin.observation.Observation <|-- opendevin.observation.AgentErrorObservation +opendevin.observation.Observation <|-- opendevin.observation.NullObservation +opendevin.plan.Plan *-- opendevin.plan.Task +opendevin.state.State *-- opendevin.plan.Plan +opendevin.state.State *-- opendevin.observation.CmdOutputObservation +opendevin.state.State *-- opendevin.action.base.Action +opendevin.state.State *-- opendevin.observation.Observation +opendevin.observation.Observation <|-- opendevin.observation.CmdOutputObservation +opendevin.sandbox.sandbox.DockerInteractive *-- opendevin.sandbox.sandbox.BackgroundCommand +opendevin.observation.Observation <|-- opendevin.observation.UserMessageObservation +opendevin.plan.Task *-- opendevin.plan.Task +opendevin.server.session.Session *-- opendevin.controller.agent_controller.AgentController +opendevin.server.session.Session *-- opendevin.agent.Agent +opendevin.controller.agent_controller.AgentController -> opendevin.state.State +opendevin.controller.agent_controller.AgentController -> opendevin.plan.Plan +opendevin.controller.agent_controller.AgentController -> opendevin.controller.command_manager.CommandManager +opendevin.controller.command_manager.CommandManager -> opendevin.sandbox.sandbox.DockerInteractive + +footer Based on f3fda42; Generated by //py2puml// +@enduml \ No newline at end of file diff --git a/docs/architecture/backend_architecture.svg b/docs/architecture/backend_architecture.svg new file mode 100644 index 0000000000..6a088d30f3 --- /dev/null +++ b/docs/architecture/backend_architecture.svg @@ -0,0 +1 @@ +opendevinactionagentbasebashbrowsefileoptasksobservationagentllm.llmcontrolleragent_controllercommand_managerplanstatesandbox.sandboxserver.sessionAgentEchoActioncontent: strrunnable: boolaction: strAgentFinishActionrunnable: boolaction: strAgentRecallActionquery: straction: strAgentSummarizeActionsummary: straction: strAgentThinkActionthought: strrunnable: boolaction: strExecutableActionNotExecutableActionActionNullActionaction: strCmdKillActionid: intaction: strCmdRunActioncommand: strbackground: boolaction: strBrowseURLActionurl: straction: strFileReadActionpath: straction: strFileWriteActionpath: strcontents: straction: strAddTaskActionparent: strgoal: strsubtasks: listaction: strModifyTaskActionid: strstate: straction: strAgentMessageObservationrole: strobservation: strAgentRecallObservationmemories: List[str]role: strobservation: strObservationcontent: strBrowserOutputObservationurl: strstatus_code: interror: boolobservation: strFileReadObservationpath: strobservation: strFileWriteObservationpath: strobservation: strAgentErrorObservationobservation: strNullObservationobservation: strCmdOutputObservationcommand_id: intcommand: strexit_code: intobservation: strUserMessageObservationrole: strobservation: strAgent_registry: Dict[str, Type[Agent]]llm: LLM_complete: NoneLLMmodel: Noneapi_key: Nonebase_url: None_debug_dir: None_debug_idx: None_debug_id: None_completion: NoneAgentControlleragent: Agentmax_iterations: intworkdir: strcommand_manager: CommandManagerstate: Stateplan: Plancallbacks: List[Callable]CommandManagerdirectory: Noneshell: NonePlanmain_goal: strtask: Taskmain_goal: strtask: NoneTaskid: strgoal: strparent: Task | Nonesubtasks: List[Task]id: Noneid: Noneparent: Nonegoal: strsubtasks: NoneStateplan: Planiteration: intbackground_commands_obs: List[CmdOutputObservation]history: List[Tuple[Action, Observation]]updated_info: List[Tuple[Action, Observation]]DockerInteractivebackground_commands: Dict[int, BackgroundCommand]instance_id: Noneinstance_id: Noneworkspace_dir: Noneworkspace_dir: Noneworkspace_dir: Nonetimeout: intcontainer_image: Nonecontainer_name: NoneBackgroundCommandSessionwebsocket: Nonecontroller: Optional[AgentController]agent: Optional[Agent]agent_task: NoneBased on f3fda42; Generated bypy2puml \ No newline at end of file diff --git a/docs/architecture/system_architecture.png b/docs/architecture/system_architecture.png new file mode 100644 index 0000000000..42c05b1d4a Binary files /dev/null and b/docs/architecture/system_architecture.png differ diff --git a/docs/architecture/system_architecture.puml b/docs/architecture/system_architecture.puml new file mode 100644 index 0000000000..a3711af04a --- /dev/null +++ b/docs/architecture/system_architecture.puml @@ -0,0 +1,67 @@ +@startuml "System Architecture" + + +node frontend as frontend{ + + component App + + package components{ + + component Terminal + + component ChatInterface + + component BannerSettings + + } + + package services{ + component chatService + + component settingsService + + chatService -[hidden]u-> settingsService + } + + package socket + + App -> Terminal + App -> ChatInterface + App -> BannerSettings + ChatInterface -> chatService + BannerSettings -> settingsService + Terminal -> socket + chatService -d-> socket + settingsService -d-> socket + services -[hidden]d-> socket + + Terminal -[hidden]u-> ChatInterface + ChatInterface -[hidden]u-> BannerSettings + + + + interface "HTTP (:3001)" as HTTP + HTTP - App + +} + +node backend{ + package server as serverpackage{ + component Server + + 'defined in server/server.py, port is defined at startup with uvicorn + interface "Client WS\n(:3000/ws)" as client_socket + client_socket - Server + + + } + node AgentController{ + + } + Server -d-> AgentController +} + + +socket -d-> client_socket: connects to \n VITE_TERMINAL_WS_URL + +@enduml diff --git a/docs/architecture/system_architecture.svg b/docs/architecture/system_architecture.svg new file mode 100644 index 0000000000..95375acbd9 --- /dev/null +++ b/docs/architecture/system_architecture.svg @@ -0,0 +1 @@ +frontendcomponentsservicesbackendserverAppsocketHTTP (:3001)TerminalChatInterfaceBannerSettingschatServicesettingsServiceServerClient WS(:3000/ws)AgentControllerconnects toVITE_TERMINAL_WS_URL \ No newline at end of file