Przeglądaj źródła

CodeActAgent: Fix delegate history (#2672)

Boxuan Li 1 rok temu
rodzic
commit
7766a3283e

+ 4 - 8
agenthub/codeact_agent/codeact_agent.py

@@ -10,15 +10,14 @@ from opendevin.controller.agent import Agent
 from opendevin.controller.state.state import State
 from opendevin.events.action import (
     Action,
+    AgentDelegateAction,
     AgentFinishAction,
-    BrowseInteractiveAction,
     CmdRunAction,
     IPythonRunCellAction,
     MessageAction,
 )
 from opendevin.events.observation import (
     AgentDelegateObservation,
-    BrowserOutputObservation,
     CmdOutputObservation,
     IPythonRunCellObservation,
 )
@@ -38,8 +37,8 @@ def action_to_str(action: Action) -> str:
         return f'{action.thought}\n<execute_bash>\n{action.command}\n</execute_bash>'
     elif isinstance(action, IPythonRunCellAction):
         return f'{action.thought}\n<execute_ipython>\n{action.code}\n</execute_ipython>'
-    elif isinstance(action, BrowseInteractiveAction):
-        return f'{action.thought}\n<execute_browse>\n{action.browser_actions}\n</execute_browse>'
+    elif isinstance(action, AgentDelegateAction):
+        return f'{action.thought}\n<execute_browse>\n{action.inputs["task"]}\n</execute_browse>'
     elif isinstance(action, MessageAction):
         return action.content
     return ''
@@ -47,7 +46,7 @@ def action_to_str(action: Action) -> str:
 
 def get_action_message(action: Action) -> dict[str, str] | None:
     if (
-        isinstance(action, BrowseInteractiveAction)
+        isinstance(action, AgentDelegateAction)
         or isinstance(action, CmdRunAction)
         or isinstance(action, IPythonRunCellAction)
         or isinstance(action, MessageAction)
@@ -78,9 +77,6 @@ def get_observation_message(obs) -> dict[str, str] | None:
         content = '\n'.join(splitted)
         content = truncate_observation(content)
         return {'role': 'user', 'content': content}
-    elif isinstance(obs, BrowserOutputObservation):
-        content = 'OBSERVATION:\n' + truncate_observation(obs.content)
-        return {'role': 'user', 'content': content}
     elif isinstance(obs, AgentDelegateObservation):
         content = 'OBSERVATION:\n' + truncate_observation(str(obs.outputs))
         return {'role': 'user', 'content': content}

+ 4 - 0
opendevin/controller/agent.py

@@ -72,6 +72,10 @@ class Agent(ABC):
         """
         self._complete = False
 
+    @property
+    def name(self):
+        return self.__class__.__name__
+
     @classmethod
     def register(cls, name: str, agent_cls: Type['Agent']):
         """

+ 9 - 7
opendevin/controller/agent_controller.py

@@ -195,7 +195,7 @@ class AgentController:
 
     async def set_agent_state_to(self, new_state: AgentState):
         logger.info(
-            f'[Agent Controller {self.id}] Setting agent({type(self.agent).__name__}) state from {self.state.agent_state} to {new_state}'
+            f'[Agent Controller {self.id}] Setting agent({self.agent.name}) state from {self.state.agent_state} to {new_state}'
         )
 
         if new_state == self.state.agent_state:
@@ -280,19 +280,21 @@ class AgentController:
                 # close delegate controller: we must close the delegate controller before adding new events
                 await self.delegate.close()
 
-                # clean up delegate status
-                self.delegate = None
-                self.delegateAction = None
-
                 # update delegate result observation
                 # TODO: replace this with AI-generated summary (#2395)
                 formatted_output = ', '.join(
                     f'{key}: {value}' for key, value in outputs.items()
                 )
-                content = f'Delegate agent finishes task with {formatted_output}'
+                content = (
+                    f'{self.delegate.agent.name} finishes task with {formatted_output}'
+                )
                 obs: Observation = AgentDelegateObservation(
                     outputs=outputs, content=content
                 )
+
+                # clean up delegate status
+                self.delegate = None
+                self.delegateAction = None
                 await self.event_stream.add_event(obs, EventSource.AGENT)
             return
 
@@ -300,7 +302,7 @@ class AgentController:
             raise MaxCharsExceedError(self.state.num_of_chars, self.max_chars)
 
         logger.info(
-            f'{type(self.agent).__name__} LEVEL {self.state.delegate_level} STEP {self.state.iteration}',
+            f'{self.agent.name} LEVEL {self.state.delegate_level} STEP {self.state.iteration}',
             extra={'msg_type': 'STEP'},
         )
         if self.state.iteration >= self.state.max_iterations:

+ 7 - 0
tests/integration/mock/CodeActAgent/test_browse_internet/prompt_005.log

@@ -332,6 +332,13 @@ Browse localhost:8000, and tell me the ultimate answer to life. Do not ask me fo
 
 ----------
 
+
+<execute_browse>
+Sure! Let me browse the server's homepage at http://localhost:8000 and find the ultimate answer to life.. I should start with: Get the content on "http://localhost:8000"
+</execute_browse>
+
+----------
+
 OBSERVATION:
 {'content': 'The answer to life, the universe, and everything is: OpenDevin is all you need!'}
 

+ 1 - 1
tests/integration/mock/ManagerAgent/test_edits/prompt_006.log

@@ -70,7 +70,7 @@ as well as observations you've made. This only includes the MOST RECENT
 actions and observations--more may have happened before that.
 They are time-ordered, with your most recent action at the bottom.
 
-[[{"source": "user", "action": "message", "args": {"content": "Fix typos in bad.txt. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "TypoFixerAgent", "inputs": {"task": "Fix typos in bad.txt"}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "Delegate agent finishes task with summary: {'file': 'bad.txt', 'typos_fixed': [{'original': 'typoo', 'corrected': 'typo'}, {'original': 'mor', 'corrected': 'more'}]}", "extras": {"outputs": {"summary": {"file": "bad.txt", "typos_fixed": [{"original": "typoo", "corrected": "typo"}, {"original": "mor", "corrected": "more"}]}}}}]]
+[[{"source": "user", "action": "message", "args": {"content": "Fix typos in bad.txt. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "TypoFixerAgent", "inputs": {"task": "Fix typos in bad.txt"}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "TypoFixerAgent finishes task with summary: {'file': 'bad.txt', 'typos_fixed': [{'original': 'typoo', 'corrected': 'typo'}, {'original': 'mor', 'corrected': 'more'}]}", "extras": {"outputs": {"summary": {"file": "bad.txt", "typos_fixed": [{"original": "typoo", "corrected": "typo"}, {"original": "mor", "corrected": "more"}]}}}}]]
 
 If the last item in the history is an error, you should try to fix it. If you
 cannot fix it, call the `reject` action.

+ 1 - 1
tests/integration/mock/ManagerAgent/test_simple_task_rejection/prompt_006.log

@@ -70,7 +70,7 @@ as well as observations you've made. This only includes the MOST RECENT
 actions and observations--more may have happened before that.
 They are time-ordered, with your most recent action at the bottom.
 
-[[{"source": "user", "action": "message", "args": {"content": "Write a git commit message for the current staging area. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "CommitWriterAgent", "inputs": {}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "Delegate agent finishes task with reason: Not a valid git repository.", "extras": {"outputs": {"reason": "Not a valid git repository."}}}]]
+[[{"source": "user", "action": "message", "args": {"content": "Write a git commit message for the current staging area. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "CommitWriterAgent", "inputs": {}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "CommitWriterAgent finishes task with reason: Not a valid git repository.", "extras": {"outputs": {"reason": "Not a valid git repository."}}}]]
 
 If the last item in the history is an error, you should try to fix it. If you
 cannot fix it, call the `reject` action.