diff --git a/openhands/agenthub/codeact_agent/codeact_agent.py b/openhands/agenthub/codeact_agent/codeact_agent.py index ecb756781abe..974839e568cf 100644 --- a/openhands/agenthub/codeact_agent/codeact_agent.py +++ b/openhands/agenthub/codeact_agent/codeact_agent.py @@ -433,26 +433,6 @@ def _get_messages(self, state: State) -> list[Message]: ], ) ] - example_message = self.prompt_manager.get_example_user_message() - if example_message: - messages.append( - Message( - role='user', - content=[TextContent(text=example_message)], - cache_prompt=self.llm.is_caching_prompt_active(), - ) - ) - - # Repository and runtime info - additional_info = self.prompt_manager.get_additional_info() - if self.config.enable_prompt_extensions and additional_info: - # only add these if prompt extension is enabled - messages.append( - Message( - role='user', - content=[TextContent(text=additional_info)], - ) - ) pending_tool_call_action_messages: dict[str, Message] = {} tool_call_id_to_message: dict[str, Message] = {} @@ -460,6 +440,7 @@ def _get_messages(self, state: State) -> list[Message]: # Condense the events from the state. events = self.condenser.condensed_history(state) + is_first_message_handled = False for event in events: # create a regular message from an event if isinstance(event, Action): @@ -501,11 +482,20 @@ def _get_messages(self, state: State) -> list[Message]: for response_id in _response_ids_to_remove: pending_tool_call_action_messages.pop(response_id) - for message in messages_to_add: - if message: - if message.role == 'user': - self.prompt_manager.enhance_message(message) - messages.append(message) + for msg in messages_to_add: + if msg: + if msg.role == 'user' and not is_first_message_handled: + is_first_message_handled = True + # compose the first user message with examples or repo/runtime info + self.prompt_manager.enhance_first_user_message( + msg, self.config.enable_prompt_extensions + ) + + # enhance the user message with additional context based on keywords matched + if msg.role == 'user': + self.prompt_manager.enhance_message(msg) + + messages.append(msg) if self.llm.is_caching_prompt_active(): # NOTE: this is only needed for anthropic @@ -513,7 +503,7 @@ def _get_messages(self, state: State) -> list[Message]: # https://github.com/anthropics/anthropic-quickstarts/blob/8f734fd08c425c6ec91ddd613af04ff87d70c5a0/computer-use-demo/computer_use_demo/loop.py#L241-L262 breakpoints_remaining = 3 # remaining 1 for system/tool for message in reversed(messages): - if message.role == 'user' or message.role == 'tool': + if message.role in ('user', 'tool'): if breakpoints_remaining > 0: message.content[ -1 diff --git a/openhands/utils/prompt.py b/openhands/utils/prompt.py index 1ffd4b8f117b..d1c1f2ddd343 100644 --- a/openhands/utils/prompt.py +++ b/openhands/utils/prompt.py @@ -205,6 +205,30 @@ def enhance_message(self, message: Message) -> None: micro_text += '\n' message.content.append(TextContent(text=micro_text)) + def enhance_first_user_message( + self, + message: Message, + enable_prompt_extensions: bool, + ) -> None: + """ + Add example_message and additional_info into the first user message. + """ + # Get additional info, if enabled + additional_info = None + if enable_prompt_extensions: + additional_info = self.get_additional_info() or None + + # And insert the new content at the start of the list + if additional_info: + message.content.insert(0, TextContent(text=additional_info)) + + # Fetch the sample user text, if any + example_message = self.get_example_user_message() or None + + # And insert it at the start + if example_message: + message.content.insert(0, TextContent(text=example_message)) + def add_turns_left_reminder(self, messages: list[Message], state: State) -> None: latest_user_message = next( islice(