Refactor actions and observations (#1479)

* refactor actions and events

* remove type_key

* remove stream

* move import

* move import

* fix NullObs

* reorder imports

* fix lint

* fix dataclasses

* remove blank fields

* fix nullobs

* fix sidebar labels

* fix test compilation

* switch to asdict

* lint

* fix whitespace

* fix executable

* delint

* fix run

* remove NotImplementeds

* fix path prefix

* remove null files

* add debug

* add more debug info

* fix dataclass on null

* remove debug

* revert sandbox

* fix merge issues

* fix tyeps

* Update opendevin/events/action/browse.py
This commit is contained in:
Robert Brennan 2024-05-02 11:44:54 -04:00 committed by GitHub
parent f19333aa6e
commit ce7c7eaae4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 489 additions and 236 deletions

View File

@ -1,14 +1,14 @@
from typing import List
from opendevin.action import (
from opendevin.agent import Agent
from opendevin.events.action import (
Action,
AgentThinkAction,
FileReadAction,
FileWriteAction,
)
from opendevin.agent import Agent
from opendevin.events.observation import Observation
from opendevin.llm.llm import LLM
from opendevin.observation import Observation
from opendevin.state import State
from .parser import parse_command

View File

@ -1,6 +1,6 @@
import re
from opendevin.action import (
from opendevin.events.action import (
Action,
AgentEchoAction,
AgentFinishAction,

View File

@ -2,7 +2,8 @@ import re
from typing import List, Mapping
from agenthub.codeact_agent.prompt import EXAMPLES, SYSTEM_MESSAGE
from opendevin.action import (
from opendevin.agent import Agent
from opendevin.events.action import (
Action,
AgentEchoAction,
AgentFinishAction,
@ -11,14 +12,13 @@ from opendevin.action import (
IPythonRunCellAction,
NullAction,
)
from opendevin.agent import Agent
from opendevin.llm.llm import LLM
from opendevin.observation import (
from opendevin.events.observation import (
AgentMessageObservation,
CmdOutputObservation,
IPythonRunCellObservation,
UserMessageObservation,
)
from opendevin.llm.llm import LLM
from opendevin.sandbox.plugins import (
JupyterRequirement,
PluginRequirement,

View File

@ -1,9 +1,9 @@
from typing import List
from opendevin.action import Action, AgentDelegateAction, AgentFinishAction
from opendevin.agent import Agent
from opendevin.events.action import Action, AgentDelegateAction, AgentFinishAction
from opendevin.events.observation import AgentDelegateObservation
from opendevin.llm.llm import LLM
from opendevin.observation import AgentDelegateObservation
from opendevin.state import State

View File

@ -1,7 +1,8 @@
import time
from typing import List, TypedDict
from opendevin.action import (
from opendevin.agent import Agent
from opendevin.events.action import (
Action,
AddTaskAction,
AgentFinishAction,
@ -13,9 +14,7 @@ from opendevin.action import (
FileWriteAction,
ModifyTaskAction,
)
from opendevin.agent import Agent
from opendevin.llm.llm import LLM
from opendevin.observation import (
from opendevin.events.observation import (
AgentRecallObservation,
CmdOutputObservation,
FileReadObservation,
@ -23,6 +22,7 @@ from opendevin.observation import (
NullObservation,
Observation,
)
from opendevin.llm.llm import LLM
from opendevin.state import State
"""

View File

@ -3,8 +3,8 @@ from typing import Dict, List
from jinja2 import BaseLoader, Environment
from opendevin.action import Action, action_from_dict
from opendevin.agent import Agent
from opendevin.events.action import Action, action_from_dict
from opendevin.exceptions import LLMOutputError
from opendevin.llm.llm import LLM
from opendevin.state import State

View File

@ -3,7 +3,8 @@ from typing import List
import agenthub.monologue_agent.utils.prompts as prompts
from agenthub.monologue_agent.utils.monologue import Monologue
from opendevin import config
from opendevin.action import (
from opendevin.agent import Agent
from opendevin.events.action import (
Action,
AgentRecallAction,
AgentThinkAction,
@ -14,10 +15,7 @@ from opendevin.action import (
GitHubPushAction,
NullAction,
)
from opendevin.agent import Agent
from opendevin.exceptions import AgentNoInstructionError
from opendevin.llm.llm import LLM
from opendevin.observation import (
from opendevin.events.observation import (
AgentRecallObservation,
BrowserOutputObservation,
CmdOutputObservation,
@ -25,6 +23,8 @@ from opendevin.observation import (
NullObservation,
Observation,
)
from opendevin.exceptions import AgentNoInstructionError
from opendevin.llm.llm import LLM
from opendevin.schema import ActionType
from opendevin.schema.config import ConfigType
from opendevin.state import State

View File

@ -3,14 +3,14 @@ from json import JSONDecodeError
from typing import List
from opendevin import config
from opendevin.action import (
from opendevin.events.action import (
Action,
action_from_dict,
)
from opendevin.exceptions import LLMOutputError
from opendevin.observation import (
from opendevin.events.observation import (
CmdOutputObservation,
)
from opendevin.exceptions import LLMOutputError
from opendevin.schema.config import ConfigType
from . import json

View File

@ -1,7 +1,7 @@
from typing import List
from opendevin.action import Action, AgentFinishAction
from opendevin.agent import Agent
from opendevin.events.action import Action, AgentFinishAction
from opendevin.llm.llm import LLM
from opendevin.state import State

View File

@ -1,7 +1,7 @@
import json
from typing import Dict, List, Tuple, Type
from opendevin.action import (
from opendevin.events.action import (
Action,
AddTaskAction,
AgentFinishAction,
@ -17,11 +17,11 @@ from opendevin.action import (
NullAction,
action_from_dict,
)
from opendevin.logger import opendevin_logger as logger
from opendevin.observation import (
from opendevin.events.observation import (
NullObservation,
Observation,
)
from opendevin.logger import opendevin_logger as logger
from opendevin.plan import Plan
from opendevin.schema import ActionType

View File

@ -0,0 +1,9 @@
---
sidebar_label: action
title: opendevin.events.action
---
#### ACTION\_TYPE\_TO\_CLASS
type: ignore[attr-defined]

View File

@ -0,0 +1,14 @@
---
sidebar_label: empty
title: opendevin.events.action.empty
---
## NullAction Objects
```python
@dataclass
class NullAction(Action)
```
An action that does nothing.

View File

@ -0,0 +1,16 @@
---
sidebar_label: files
title: opendevin.events.action.files
---
## FileReadAction Objects
```python
@dataclass
class FileReadAction(Action)
```
Reads a file from a given path.
Can be set to read specific lines using start and end
Default lines 0:-1 (whole file)

View File

@ -0,0 +1,46 @@
---
sidebar_label: github
title: opendevin.events.action.github
---
## GitHubPushAction Objects
```python
@dataclass
class GitHubPushAction(Action)
```
This pushes the current branch to github.
To use this, you need to set the GITHUB_TOKEN environment variable.
The agent will return a message with a URL that you can click to make a pull
request.
**Attributes**:
- `owner` - The owner of the source repo
- `repo` - The name of the source repo
- `branch` - The branch to push
- `action` - The action identifier
## GitHubSendPRAction Objects
```python
@dataclass
class GitHubSendPRAction(Action)
```
An action to send a github PR.
To use this, you need to set the GITHUB_TOKEN environment variable.
**Attributes**:
- `owner` - The owner of the source repo
- `repo` - The name of the source repo
- `title` - The title of the PR
- `head` - The branch to send the PR from
- `head_repo` - The repo to send the PR from
- `base` - The branch to send the PR to
- `body` - The body of the PR

View File

@ -0,0 +1,14 @@
---
sidebar_label: tasks
title: opendevin.events.action.tasks
---
## TaskStateChangedAction Objects
```python
@dataclass
class TaskStateChangedAction(Action)
```
Fake action, just to notify the client that a task state has changed.

View File

@ -0,0 +1,9 @@
---
sidebar_label: observation
title: opendevin.events.observation
---
#### OBSERVATION\_TYPE\_TO\_CLASS
type: ignore[attr-defined]

View File

@ -0,0 +1,14 @@
---
sidebar_label: browse
title: opendevin.events.observation.browse
---
## BrowserOutputObservation Objects
```python
@dataclass
class BrowserOutputObservation(Observation)
```
This data class represents the output of a browser.

View File

@ -0,0 +1,23 @@
---
sidebar_label: commands
title: opendevin.events.observation.commands
---
## CmdOutputObservation Objects
```python
@dataclass
class CmdOutputObservation(Observation)
```
This data class represents the output of a command.
## IPythonRunCellObservation Objects
```python
@dataclass
class IPythonRunCellObservation(Observation)
```
This data class represents the output of a IPythonRunCellAction.

View File

@ -0,0 +1,14 @@
---
sidebar_label: delegate
title: opendevin.events.observation.delegate
---
## AgentDelegateObservation Objects
```python
@dataclass
class AgentDelegateObservation(Observation)
```
This data class represents the result from delegating to another agent

View File

@ -0,0 +1,15 @@
---
sidebar_label: empty
title: opendevin.events.observation.empty
---
## NullObservation Objects
```python
@dataclass
class NullObservation(Observation)
```
This data class represents a null observation.
This is used when the produced action is NOT executable.

View File

@ -0,0 +1,14 @@
---
sidebar_label: error
title: opendevin.events.observation.error
---
## AgentErrorObservation Objects
```python
@dataclass
class AgentErrorObservation(Observation)
```
This data class represents an error encountered by the agent.

View File

@ -0,0 +1,23 @@
---
sidebar_label: files
title: opendevin.events.observation.files
---
## FileReadObservation Objects
```python
@dataclass
class FileReadObservation(Observation)
```
This data class represents the content of a file.
## FileWriteObservation Objects
```python
@dataclass
class FileWriteObservation(Observation)
```
This data class represents a file write operation

View File

@ -0,0 +1,23 @@
---
sidebar_label: message
title: opendevin.events.observation.message
---
## UserMessageObservation Objects
```python
@dataclass
class UserMessageObservation(Observation)
```
This data class represents a message sent by the user.
## AgentMessageObservation Objects
```python
@dataclass
class AgentMessageObservation(Observation)
```
This data class represents a message sent by the agent.

View File

@ -0,0 +1,20 @@
---
sidebar_label: observation
title: opendevin.events.observation.observation
---
## Observation Objects
```python
@dataclass
class Observation(Event)
```
#### to\_memory
```python
def to_memory() -> dict
```
Converts the observation to a dictionary.

View File

@ -0,0 +1,14 @@
---
sidebar_label: recall
title: opendevin.events.observation.recall
---
## AgentRecallObservation Objects
```python
@dataclass
class AgentRecallObservation(Observation)
```
This data class represents a list of memories recalled by the agent.

View File

@ -1,61 +0,0 @@
from dataclasses import asdict, dataclass
from typing import TYPE_CHECKING
from opendevin.schema import ActionType
if TYPE_CHECKING:
from opendevin.controller import AgentController
from opendevin.observation import Observation
@dataclass
class Action:
async def run(self, controller: 'AgentController') -> 'Observation':
raise NotImplementedError
def to_memory(self):
d = asdict(self)
try:
v = d.pop('action')
except KeyError:
raise NotImplementedError(f'{self=} does not have action attribute set')
return {'action': v, 'args': d}
def to_dict(self):
d = self.to_memory()
d['message'] = self.message
return d
@property
def executable(self) -> bool:
raise NotImplementedError
@property
def message(self) -> str:
raise NotImplementedError
@dataclass
class ExecutableAction(Action):
@property
def executable(self) -> bool:
return True
@dataclass
class NotExecutableAction(Action):
@property
def executable(self) -> bool:
return False
@dataclass
class NullAction(NotExecutableAction):
"""An action that does nothing.
"""
action: str = ActionType.NULL
@property
def message(self) -> str:
return 'No action'

View File

@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Dict, List, Type
if TYPE_CHECKING:
from opendevin.action import Action
from opendevin.events.action import Action
from opendevin.state import State
from opendevin.exceptions import AgentAlreadyRegisteredError, AgentNotRegisteredError
from opendevin.llm.llm import LLM

View File

@ -1,13 +1,12 @@
from typing import List
from opendevin import config
from opendevin.action import (
from opendevin.events.action import (
Action,
)
from opendevin.observation import (
from opendevin.events.observation import (
AgentErrorObservation,
CmdOutputObservation,
NullObservation,
Observation,
)
from opendevin.sandbox import DockerExecBox, DockerSSHBox, E2BBox, LocalBox, Sandbox
@ -43,9 +42,6 @@ class ActionManager:
self.sandbox.init_plugins(plugins)
async def run_action(self, action: Action, agent_controller) -> Observation:
observation: Observation = NullObservation('')
if not action.executable:
return observation
observation = await action.run(agent_controller)
return observation

View File

@ -3,14 +3,23 @@ from typing import Callable, List, Type
from agenthub.codeact_agent.codeact_agent import CodeActAgent
from opendevin import config
from opendevin.action import (
from opendevin.agent import Agent
from opendevin.controller.action_manager import ActionManager
from opendevin.events.action import (
Action,
AgentDelegateAction,
AgentFinishAction,
AgentTalkAction,
NullAction,
TaskStateChangedAction,
)
from opendevin.events.observation import (
AgentDelegateObservation,
AgentErrorObservation,
NullObservation,
Observation,
UserMessageObservation,
)
from opendevin.action.tasks import TaskStateChangedAction
from opendevin.agent import Agent
from opendevin.browser.browser_env import BrowserEnv
from opendevin.controller.action_manager import ActionManager
@ -21,13 +30,6 @@ from opendevin.exceptions import (
MaxCharsExceedError,
)
from opendevin.logger import opendevin_logger as logger
from opendevin.observation import (
AgentDelegateObservation,
AgentErrorObservation,
NullObservation,
Observation,
UserMessageObservation,
)
from opendevin.plan import Plan
from opendevin.sandbox import DockerSSHBox
from opendevin.schema import TaskState

View File

View File

@ -1,4 +1,7 @@
from ..exceptions import AgentMalformedActionError
from opendevin.exceptions import AgentMalformedActionError
from .action import Action
from .agent import (
AgentDelegateAction,
AgentEchoAction,
@ -8,12 +11,12 @@ from .agent import (
AgentTalkAction,
AgentThinkAction,
)
from .base import Action, NullAction
from .bash import CmdKillAction, CmdRunAction, IPythonRunCellAction
from .browse import BrowseURLAction
from .fileop import FileReadAction, FileWriteAction
from .commands import CmdKillAction, CmdRunAction, IPythonRunCellAction
from .empty import NullAction
from .files import FileReadAction, FileWriteAction
from .github import GitHubPushAction
from .tasks import AddTaskAction, ModifyTaskAction
from .tasks import AddTaskAction, ModifyTaskAction, TaskStateChangedAction
actions = (
CmdKillAction,
@ -29,6 +32,7 @@ actions = (
AgentDelegateAction,
AddTaskAction,
ModifyTaskAction,
TaskStateChangedAction,
GitHubPushAction,
)
@ -71,5 +75,6 @@ __all__ = [
'AgentSummarizeAction',
'AddTaskAction',
'ModifyTaskAction',
'TaskStateChangedAction',
'IPythonRunCellAction'
]

View File

@ -0,0 +1,22 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING
from opendevin.events.event import Event
from opendevin.events.observation import NullObservation, Observation
if TYPE_CHECKING:
from opendevin.controller import AgentController
@dataclass
class Action(Event):
async def run(self, controller: 'AgentController') -> 'Observation':
return NullObservation('')
def to_memory(self):
d = super().to_memory()
try:
v = d.pop('action')
except KeyError:
raise NotImplementedError(f'{self=} does not have action attribute set')
return {'action': v, 'args': d}

View File

@ -1,7 +1,7 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Dict
from opendevin.observation import (
from opendevin.events.observation import (
AgentMessageObservation,
AgentRecallObservation,
NullObservation,
@ -9,14 +9,14 @@ from opendevin.observation import (
)
from opendevin.schema import ActionType
from .base import ExecutableAction, NotExecutableAction
from .action import Action
if TYPE_CHECKING:
from opendevin.controller import AgentController
@dataclass
class AgentRecallAction(ExecutableAction):
class AgentRecallAction(Action):
query: str
thought: str = ''
action: str = ActionType.RECALL
@ -33,24 +33,21 @@ class AgentRecallAction(ExecutableAction):
@dataclass
class AgentThinkAction(NotExecutableAction):
class AgentThinkAction(Action):
thought: str
action: str = ActionType.THINK
async def run(self, controller: 'AgentController') -> 'Observation':
raise NotImplementedError
@property
def message(self) -> str:
return self.thought
@dataclass
class AgentTalkAction(NotExecutableAction):
class AgentTalkAction(Action):
content: str
action: str = ActionType.TALK
async def run(self, controller: 'AgentController') -> 'Observation':
async def run(self, controller: 'AgentController') -> Observation:
raise NotImplementedError
@property
@ -62,11 +59,11 @@ class AgentTalkAction(NotExecutableAction):
@dataclass
class AgentEchoAction(ExecutableAction):
class AgentEchoAction(Action):
content: str
action: str = 'echo'
async def run(self, controller: 'AgentController') -> 'Observation':
async def run(self, controller: 'AgentController') -> Observation:
return AgentMessageObservation(self.content)
@property
@ -75,7 +72,7 @@ class AgentEchoAction(ExecutableAction):
@dataclass
class AgentSummarizeAction(NotExecutableAction):
class AgentSummarizeAction(Action):
summary: str
action: str = ActionType.SUMMARIZE
@ -85,27 +82,24 @@ class AgentSummarizeAction(NotExecutableAction):
@dataclass
class AgentFinishAction(NotExecutableAction):
class AgentFinishAction(Action):
outputs: Dict = field(default_factory=dict)
thought: str = ''
action: str = ActionType.FINISH
async def run(self, controller: 'AgentController') -> 'Observation':
raise NotImplementedError
@property
def message(self) -> str:
return "All done! What's next on the agenda?"
@dataclass
class AgentDelegateAction(ExecutableAction):
class AgentDelegateAction(Action):
agent: str
inputs: dict
thought: str = ''
action: str = ActionType.DELEGATE
async def run(self, controller: 'AgentController') -> 'Observation':
async def run(self, controller: 'AgentController') -> Observation:
await controller.start_delegate(self)
return NullObservation('')

View File

@ -2,17 +2,18 @@ import os
from dataclasses import dataclass
from typing import TYPE_CHECKING
from opendevin.observation import BrowserOutputObservation
from opendevin.events.observation import BrowserOutputObservation
from opendevin.schema import ActionType
from .base import ExecutableAction
from .action import Action
if TYPE_CHECKING:
from opendevin.controller import AgentController
@dataclass
class BrowseURLAction(ExecutableAction):
class BrowseURLAction(Action):
url: str
thought: str = ''
action: str = ActionType.BROWSE

View File

@ -6,17 +6,17 @@ from typing import TYPE_CHECKING
from opendevin import config
from opendevin.schema import ActionType, ConfigType
from .base import ExecutableAction
from .action import Action
if TYPE_CHECKING:
from opendevin.controller import AgentController
from opendevin.observation import CmdOutputObservation, Observation
from opendevin.events.observation import CmdOutputObservation, Observation
from opendevin.observation import IPythonRunCellObservation
from opendevin.events.observation import IPythonRunCellObservation
@dataclass
class CmdRunAction(ExecutableAction):
class CmdRunAction(Action):
command: str
background: bool = False
thought: str = ''
@ -38,7 +38,7 @@ class CmdRunAction(ExecutableAction):
@dataclass
class CmdKillAction(ExecutableAction):
class CmdKillAction(Action):
id: int
thought: str = ''
action: str = ActionType.KILL
@ -55,7 +55,7 @@ class CmdKillAction(ExecutableAction):
@dataclass
class IPythonRunCellAction(ExecutableAction):
class IPythonRunCellAction(Action):
code: str
thought: str = ''
action: str = ActionType.RUN_IPYTHON

View File

@ -0,0 +1,16 @@
from dataclasses import dataclass
from opendevin.schema import ActionType
from .action import Action
@dataclass
class NullAction(Action):
"""An action that does nothing.
"""
action: str = ActionType.NULL
@property
def message(self) -> str:
return 'No action'

View File

@ -3,7 +3,7 @@ from dataclasses import dataclass
from pathlib import Path
from opendevin import config
from opendevin.observation import (
from opendevin.events.observation import (
AgentErrorObservation,
FileReadObservation,
FileWriteObservation,
@ -13,7 +13,7 @@ from opendevin.sandbox import E2BBox
from opendevin.schema import ActionType
from opendevin.schema.config import ConfigType
from .base import ExecutableAction
from .action import Action
def resolve_path(file_path, working_directory):
@ -41,7 +41,7 @@ def resolve_path(file_path, working_directory):
@dataclass
class FileReadAction(ExecutableAction):
class FileReadAction(Action):
"""
Reads a file from a given path.
Can be set to read specific lines using start and end
@ -95,7 +95,7 @@ class FileReadAction(ExecutableAction):
@dataclass
class FileWriteAction(ExecutableAction):
class FileWriteAction(Action):
path: str
content: str
start: int = 0

View File

@ -6,20 +6,23 @@ from typing import TYPE_CHECKING
import requests
from opendevin import config
from opendevin.observation import AgentErrorObservation, Observation
from opendevin.observation.message import AgentMessageObservation
from opendevin.observation.run import CmdOutputObservation
from opendevin.events.observation import (
AgentErrorObservation,
AgentMessageObservation,
CmdOutputObservation,
Observation,
)
from opendevin.schema import ActionType
from opendevin.schema.config import ConfigType
from .base import ExecutableAction
from .action import Action
if TYPE_CHECKING:
from opendevin.controller import AgentController
@dataclass
class GitHubPushAction(ExecutableAction):
class GitHubPushAction(Action):
"""This pushes the current branch to github.
To use this, you need to set the GITHUB_TOKEN environment variable.
@ -85,7 +88,7 @@ class GitHubPushAction(ExecutableAction):
@dataclass
class GitHubSendPRAction(ExecutableAction):
class GitHubSendPRAction(Action):
"""An action to send a github PR.
To use this, you need to set the GITHUB_TOKEN environment variable.

View File

@ -1,17 +1,17 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING
from opendevin.observation import NullObservation
from opendevin.events.observation import NullObservation
from opendevin.schema import ActionType
from .base import ExecutableAction, NotExecutableAction
from .action import Action
if TYPE_CHECKING:
from opendevin.controller import AgentController
@dataclass
class AddTaskAction(ExecutableAction):
class AddTaskAction(Action):
parent: str
goal: str
subtasks: list = field(default_factory=list)
@ -29,7 +29,7 @@ class AddTaskAction(ExecutableAction):
@dataclass
class ModifyTaskAction(ExecutableAction):
class ModifyTaskAction(Action):
id: str
state: str
thought: str = ''
@ -46,7 +46,7 @@ class ModifyTaskAction(ExecutableAction):
@dataclass
class TaskStateChangedAction(NotExecutableAction):
class TaskStateChangedAction(Action):
"""Fake action, just to notify the client that a task state has changed."""
task_state: str
thought: str = ''

16
opendevin/events/event.py Normal file
View File

@ -0,0 +1,16 @@
from dataclasses import asdict, dataclass
@dataclass
class Event:
def to_memory(self):
return asdict(self)
def to_dict(self):
d = self.to_memory()
d['message'] = self.message
return d
@property
def message(self) -> str:
return self.message

View File

@ -1,11 +1,12 @@
from .base import NullObservation, Observation
from .browse import BrowserOutputObservation
from .commands import CmdOutputObservation, IPythonRunCellObservation
from .delegate import AgentDelegateObservation
from .empty import NullObservation
from .error import AgentErrorObservation
from .files import FileReadObservation, FileWriteObservation
from .message import AgentMessageObservation, UserMessageObservation
from .observation import Observation
from .recall import AgentRecallObservation
from .run import CmdOutputObservation, IPythonRunCellObservation
observations = (
CmdOutputObservation,

View File

@ -2,7 +2,7 @@ from dataclasses import dataclass, field
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass

View File

@ -2,7 +2,7 @@ from dataclasses import dataclass
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass

View File

@ -2,14 +2,13 @@ from dataclasses import dataclass
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass
class AgentDelegateObservation(Observation):
"""
This data class represents a delegate observation.
This is used when the produced action is NOT executable.
This data class represents the result from delegating to another agent
"""
outputs: dict

View File

@ -0,0 +1,19 @@
from dataclasses import dataclass
from opendevin.schema import ObservationType
from .observation import Observation
@dataclass
class NullObservation(Observation):
"""
This data class represents a null observation.
This is used when the produced action is NOT executable.
"""
observation: str = ObservationType.NULL
@property
def message(self) -> str:
return 'No observation'

View File

@ -2,7 +2,7 @@ from dataclasses import dataclass
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass

View File

@ -2,7 +2,7 @@ from dataclasses import dataclass
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass

View File

@ -2,7 +2,7 @@ from dataclasses import dataclass
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass

View File

@ -0,0 +1,19 @@
from dataclasses import dataclass
from opendevin.events.event import Event
@dataclass
class Observation(Event):
content: str
def to_memory(self) -> dict:
"""Converts the observation to a dictionary."""
extras = super().to_memory()
content = extras.pop('content', '')
observation = extras.pop('observation', '')
return {
'observation': observation,
'content': content,
'extras': extras,
}

View File

@ -3,7 +3,7 @@ from typing import List
from opendevin.schema import ObservationType
from .base import Observation
from .observation import Observation
@dataclass

View File

@ -1,52 +0,0 @@
import copy
from dataclasses import dataclass
from opendevin.schema import ObservationType
@dataclass
class Observation:
"""
This data class represents an observation of the environment.
"""
content: str
def __str__(self) -> str:
return self.content
def to_dict(self) -> dict:
"""Converts the observation to a dictionary and adds user message."""
memory_dict = self.to_memory()
memory_dict['message'] = self.message
return memory_dict
def to_memory(self) -> dict:
"""Converts the observation to a dictionary."""
extras = copy.deepcopy(self.__dict__)
content = extras.pop('content', '')
observation = extras.pop('observation', '')
return {
'observation': observation,
'content': content,
'extras': extras,
}
@property
def message(self) -> str:
"""Returns a message describing the observation."""
return ''
@dataclass
class NullObservation(Observation):
"""
This data class represents a null observation.
This is used when the produced action is NOT executable.
"""
observation: str = ObservationType.NULL
@property
def message(self) -> str:
return ''

View File

@ -2,15 +2,19 @@ import asyncio
from typing import Dict, List, Optional
from opendevin import config
from opendevin.action import (
from opendevin.agent import Agent
from opendevin.controller import AgentController
from opendevin.events.action import (
Action,
NullAction,
)
from opendevin.agent import Agent
from opendevin.controller import AgentController
from opendevin.events.observation import (
NullObservation,
Observation,
UserMessageObservation,
)
from opendevin.llm.llm import LLM
from opendevin.logger import opendevin_logger as logger
from opendevin.observation import NullObservation, Observation, UserMessageObservation
from opendevin.schema import ActionType, ConfigType, TaskState, TaskStateAction
from opendevin.server.session import session_manager

View File

@ -1,10 +1,10 @@
from dataclasses import dataclass, field
from typing import Dict, List, Tuple
from opendevin.action import (
from opendevin.events.action import (
Action,
)
from opendevin.observation import (
from opendevin.events.observation import (
CmdOutputObservation,
Observation,
)

View File

@ -3,25 +3,26 @@ from pathlib import Path
import pytest
from opendevin import config
from opendevin.action import fileop
from opendevin.events.action import files
from opendevin.schema import ConfigType
SANDBOX_PATH_PREFIX = '/workspace'
def test_resolve_path():
assert fileop.resolve_path('test.txt', '/workspace') == Path(config.get(ConfigType.WORKSPACE_BASE)) / 'test.txt'
assert fileop.resolve_path('subdir/test.txt', '/workspace') == \
assert files.resolve_path('test.txt', '/workspace') == Path(config.get(ConfigType.WORKSPACE_BASE)) / 'test.txt'
assert files.resolve_path('subdir/test.txt', '/workspace') == \
Path(config.get(ConfigType.WORKSPACE_BASE)) / 'subdir' / 'test.txt'
assert fileop.resolve_path(Path(fileop.SANDBOX_PATH_PREFIX) / 'test.txt', '/workspace') == \
assert files.resolve_path(Path(SANDBOX_PATH_PREFIX) / 'test.txt', '/workspace') == \
Path(config.get(ConfigType.WORKSPACE_BASE)) / 'test.txt'
assert fileop.resolve_path(Path(fileop.SANDBOX_PATH_PREFIX) / 'subdir' / 'test.txt',
assert files.resolve_path(Path(SANDBOX_PATH_PREFIX) / 'subdir' / 'test.txt',
'/workspace') == Path(config.get(ConfigType.WORKSPACE_BASE)) / 'subdir' / 'test.txt'
assert fileop.resolve_path(Path(fileop.SANDBOX_PATH_PREFIX) / 'subdir' / '..' / 'test.txt',
assert files.resolve_path(Path(SANDBOX_PATH_PREFIX) / 'subdir' / '..' / 'test.txt',
'/workspace') == Path(config.get(ConfigType.WORKSPACE_BASE)) / 'test.txt'
with pytest.raises(PermissionError):
fileop.resolve_path(Path(fileop.SANDBOX_PATH_PREFIX) / '..' / 'test.txt', '/workspace')
files.resolve_path(Path(SANDBOX_PATH_PREFIX) / '..' / 'test.txt', '/workspace')
with pytest.raises(PermissionError):
fileop.resolve_path(Path('..') / 'test.txt', '/workspace')
files.resolve_path(Path('..') / 'test.txt', '/workspace')
with pytest.raises(PermissionError):
fileop.resolve_path(Path('/') / 'test.txt', '/workspace')
assert fileop.resolve_path('test.txt', '/workspace/test') == \
files.resolve_path(Path('/') / 'test.txt', '/workspace')
assert files.resolve_path('test.txt', '/workspace/test') == \
Path(config.get(ConfigType.WORKSPACE_BASE)) / 'test' / 'test.txt'

View File

@ -5,12 +5,12 @@ import pytest
from agenthub.dummy_agent.agent import DummyAgent
from opendevin import config
from opendevin.action.github import GitHubPushAction, GitHubSendPRAction
from opendevin.controller.agent_controller import AgentController
from opendevin.events.action.github import GitHubPushAction, GitHubSendPRAction
from opendevin.events.observation.commands import CmdOutputObservation
from opendevin.events.observation.error import AgentErrorObservation
from opendevin.events.observation.message import AgentMessageObservation
from opendevin.llm.llm import LLM
from opendevin.observation.error import AgentErrorObservation
from opendevin.observation.message import AgentMessageObservation
from opendevin.observation.run import CmdOutputObservation
from opendevin.schema.config import ConfigType

View File

@ -1,4 +1,4 @@
from opendevin.action import (
from opendevin.events.action import (
Action,
AddTaskAction,
AgentFinishAction,

View File

@ -1,4 +1,4 @@
from opendevin.observation import (
from opendevin.events.observation import (
CmdOutputObservation,
Observation,
observation_from_dict,