Improve stop button message for better user experience (#9860)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Graham Neubig
2025-08-05 21:53:40 -04:00
committed by GitHub
parent 238ae611f6
commit 1c66347803
4 changed files with 104 additions and 27 deletions

View File

@@ -82,8 +82,12 @@ from openhands.storage.files import FileStore
TRAFFIC_CONTROL_REMINDER = (
"Please click on resume button if you'd like to continue, or start a new task."
)
ERROR_ACTION_NOT_EXECUTED_ID = 'AGENT_ERROR$ERROR_ACTION_NOT_EXECUTED'
ERROR_ACTION_NOT_EXECUTED = 'The action has not been executed. This may have occurred because the user pressed the stop button, or because the runtime system crashed and restarted due to resource constraints. Any previously established system state, dependencies, or environment variables may have been lost.'
ERROR_ACTION_NOT_EXECUTED_STOPPED_ID = 'AGENT_ERROR$ERROR_ACTION_NOT_EXECUTED_STOPPED'
ERROR_ACTION_NOT_EXECUTED_ERROR_ID = 'AGENT_ERROR$ERROR_ACTION_NOT_EXECUTED_ERROR'
ERROR_ACTION_NOT_EXECUTED_STOPPED = (
'Stop button pressed. The action has not been executed.'
)
ERROR_ACTION_NOT_EXECUTED_ERROR = 'The action has not been executed due to a runtime error. The runtime system may have crashed and restarted due to resource constraints. Any previously established system state, dependencies, or environment variables may have been lost.'
class AgentController:
@@ -552,9 +556,17 @@ class AgentController:
# make a new ErrorObservation with the tool call metadata
if not found_observation:
# Use different messages and IDs based on whether the agent was stopped by user or due to error
if self.state.agent_state == AgentState.STOPPED:
error_content = ERROR_ACTION_NOT_EXECUTED_STOPPED
error_id = ERROR_ACTION_NOT_EXECUTED_STOPPED_ID
else: # AgentState.ERROR
error_content = ERROR_ACTION_NOT_EXECUTED_ERROR
error_id = ERROR_ACTION_NOT_EXECUTED_ERROR_ID
obs = ErrorObservation(
content=ERROR_ACTION_NOT_EXECUTED,
error_id=ERROR_ACTION_NOT_EXECUTED_ID,
content=error_content,
error_id=error_id,
)
obs.tool_call_metadata = self._pending_action.tool_call_metadata
obs._cause = self._pending_action.id # type: ignore[attr-defined]
@@ -580,14 +592,17 @@ class AgentController:
if new_state == self.state.agent_state:
return
# Store old state for control limits check
old_state = self.state.agent_state
# Update agent state BEFORE calling _reset() so _reset() sees the correct state
self.state.agent_state = new_state
if new_state in (AgentState.STOPPED, AgentState.ERROR):
self._reset()
# User is allowing to check control limits and expand them if applicable
if (
self.state.agent_state == AgentState.ERROR
and new_state == AgentState.RUNNING
):
if old_state == AgentState.ERROR and new_state == AgentState.RUNNING:
self.state_tracker.maybe_increase_control_flags_limits(self.headless_mode)
if self._pending_action is not None and (
@@ -603,8 +618,6 @@ class AgentController:
self._pending_action._id = None # type: ignore[attr-defined]
self.event_stream.add_event(self._pending_action, EventSource.AGENT)
self.state.agent_state = new_state
# Create observation with reason field if it's an error state
reason = ''
if new_state == AgentState.ERROR: