Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions examples/01_standalone_sdk/04_confirmation_mode_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
from pydantic import SecretStr

from openhands.sdk import LLM, BaseConversation, Conversation
from openhands.sdk.conversation.state import AgentExecutionStatus, ConversationState
from openhands.sdk.conversation.state import (
ConversationExecutionStatus,
ConversationState,
)
from openhands.sdk.security.confirmation_policy import AlwaysConfirm, NeverConfirm
from openhands.tools.preset.default import get_default_agent

Expand Down Expand Up @@ -56,10 +59,10 @@ def run_until_finished(conversation: BaseConversation, confirmer: Callable) -> N
on reject, call reject_pending_actions().
Preserves original error if agent waits but no actions exist.
"""
while conversation.state.agent_status != AgentExecutionStatus.FINISHED:
while conversation.state.execution_status != ConversationExecutionStatus.FINISHED:
if (
conversation.state.agent_status
== AgentExecutionStatus.WAITING_FOR_CONFIRMATION
conversation.state.execution_status
== ConversationExecutionStatus.WAITING_FOR_CONFIRMATION
):
pending = ConversationState.get_unmatched_actions(conversation.state.events)
if not pending:
Expand Down
8 changes: 4 additions & 4 deletions examples/01_standalone_sdk/09_pause_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Agent,
Conversation,
)
from openhands.sdk.conversation.state import AgentExecutionStatus
from openhands.sdk.conversation.state import ConversationExecutionStatus
from openhands.sdk.tool import Tool, register_tool
from openhands.tools.execute_bash import BashTool
from openhands.tools.file_editor import FileEditorTool
Expand Down Expand Up @@ -54,8 +54,8 @@
try:
# Main loop - similar to the user's sample script
while (
conversation.state.agent_status != AgentExecutionStatus.FINISHED
and conversation.state.agent_status != AgentExecutionStatus.PAUSED
conversation.state.execution_status != ConversationExecutionStatus.FINISHED
and conversation.state.execution_status != ConversationExecutionStatus.PAUSED
):
# Send encouraging messages periodically
conversation.send_message("keep going! you can do it!")
Expand All @@ -65,4 +65,4 @@

thread.join()

print(f"Agent status: {conversation.state.agent_status}")
print(f"Agent status: {conversation.state.execution_status}")
11 changes: 7 additions & 4 deletions examples/01_standalone_sdk/16_llm_security_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
from pydantic import SecretStr

from openhands.sdk import LLM, Agent, BaseConversation, Conversation
from openhands.sdk.conversation.state import AgentExecutionStatus, ConversationState
from openhands.sdk.conversation.state import (
ConversationExecutionStatus,
ConversationState,
)
from openhands.sdk.security.confirmation_policy import ConfirmRisky
from openhands.sdk.security.llm_analyzer import LLMSecurityAnalyzer
from openhands.sdk.tool import Tool, register_tool
Expand Down Expand Up @@ -69,10 +72,10 @@ def run_until_finished_with_security(
* On reject: conversation.reject_pending_actions(...).
- If WAITING but no pending actions: print warning and set IDLE (matches original).
"""
while conversation.state.agent_status != AgentExecutionStatus.FINISHED:
while conversation.state.execution_status != ConversationExecutionStatus.FINISHED:
if (
conversation.state.agent_status
== AgentExecutionStatus.WAITING_FOR_CONFIRMATION
conversation.state.execution_status
== ConversationExecutionStatus.WAITING_FOR_CONFIRMATION
):
pending = ConversationState.get_unmatched_actions(conversation.state.events)
if not pending:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def event_callback(event):
conversation.run()

logger.info("✅ First task completed!")
logger.info(f"Agent status: {conversation.state.agent_status}")
logger.info(f"Agent status: {conversation.state.execution_status}")

# Wait for events to stop coming (no events for 2 seconds)
logger.info("⏳ Waiting for events to stop...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def event_callback(event) -> None:
logger.info("🚀 Running conversation...")
conversation.run()
logger.info("✅ First task completed!")
logger.info(f"Agent status: {conversation.state.agent_status}")
logger.info(f"Agent status: {conversation.state.execution_status}")

# Wait for events to settle (no events for 2 seconds)
logger.info("⏳ Waiting for events to stop...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
UpdateSecretsRequest,
)
from openhands.sdk import LLM, Agent, TextContent, Tool
from openhands.sdk.conversation.state import AgentExecutionStatus
from openhands.sdk.conversation.state import ConversationExecutionStatus
from openhands.sdk.workspace import LocalWorkspace


Expand Down Expand Up @@ -66,8 +66,8 @@ async def search_conversations(
Query(title="The max number of results in the page", gt=0, lte=100),
] = 100,
status: Annotated[
AgentExecutionStatus | None,
Query(title="Optional filter by agent execution status"),
ConversationExecutionStatus | None,
Query(title="Optional filter by conversation execution status"),
] = None,
sort_order: Annotated[
ConversationSortOrder,
Expand All @@ -86,8 +86,8 @@ async def search_conversations(
@conversation_router.get("/count")
async def count_conversations(
status: Annotated[
AgentExecutionStatus | None,
Query(title="Optional filter by agent execution status"),
ConversationExecutionStatus | None,
Query(title="Optional filter by conversation execution status"),
] = None,
conversation_service: ConversationService = Depends(get_conversation_service),
) -> int:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
from openhands.agent_server.server_details_router import update_last_execution_time
from openhands.agent_server.utils import utc_now
from openhands.sdk import LLM, Event, Message
from openhands.sdk.conversation.state import AgentExecutionStatus, ConversationState
from openhands.sdk.conversation.state import (
ConversationExecutionStatus,
ConversationState,
)


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -67,7 +70,7 @@ async def search_conversations(
self,
page_id: str | None = None,
limit: int = 100,
agent_status: AgentExecutionStatus | None = None,
execution_status: ConversationExecutionStatus | None = None,
sort_order: ConversationSortOrder = ConversationSortOrder.CREATED_AT_DESC,
) -> ConversationPage:
if self._event_services is None:
Expand All @@ -80,8 +83,8 @@ async def search_conversations(
conversation_info = _compose_conversation_info(event_service.stored, state)
# Apply status filter if provided
if (
agent_status is not None
and conversation_info.agent_status != agent_status
execution_status is not None
and conversation_info.execution_status != execution_status
):
continue

Expand Down Expand Up @@ -122,7 +125,7 @@ async def search_conversations(

async def count_conversations(
self,
agent_status: AgentExecutionStatus | None = None,
execution_status: ConversationExecutionStatus | None = None,
) -> int:
"""Count conversations matching the given filters."""
if self._event_services is None:
Expand All @@ -133,7 +136,10 @@ async def count_conversations(
state = await event_service.get_state()

# Apply status filter if provided
if agent_status is not None and state.agent_status != agent_status:
if (
execution_status is not None
and state.execution_status != execution_status
):
continue

count += 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
from openhands.sdk import LLM, Agent, Event, Message, get_logger
from openhands.sdk.conversation.impl.local_conversation import LocalConversation
from openhands.sdk.conversation.secrets_manager import SecretValue
from openhands.sdk.conversation.state import AgentExecutionStatus, ConversationState
from openhands.sdk.conversation.state import (
ConversationExecutionStatus,
ConversationState,
)
from openhands.sdk.event.conversation_state import ConversationStateUpdateEvent
from openhands.sdk.security.confirmation_policy import ConfirmationPolicyBase
from openhands.sdk.utils.async_utils import AsyncCallbackWrapper
Expand Down Expand Up @@ -148,7 +151,7 @@ async def send_message(self, message: Message, run: bool = False):
await loop.run_in_executor(None, self._conversation.send_message, message)
if run:
with self._conversation.state as state:
run = state.agent_status != AgentExecutionStatus.RUNNING
run = state.execution_status != ConversationExecutionStatus.RUNNING
if run:
loop.run_in_executor(None, self._conversation.run)

Expand Down
7 changes: 5 additions & 2 deletions openhands-agent-server/openhands/agent_server/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
from openhands.agent_server.utils import utc_now
from openhands.sdk import LLM, AgentBase, Event, ImageContent, Message, TextContent
from openhands.sdk.conversation.secret_source import SecretSource
from openhands.sdk.conversation.state import AgentExecutionStatus, ConversationState
from openhands.sdk.conversation.state import (
ConversationExecutionStatus,
ConversationState,
)
from openhands.sdk.llm.utils.metrics import MetricsSnapshot
from openhands.sdk.security.confirmation_policy import (
ConfirmationPolicyBase,
Expand Down Expand Up @@ -129,7 +132,7 @@ class ConversationPage(BaseModel):

class ConversationResponse(BaseModel):
conversation_id: str
state: AgentExecutionStatus
state: ConversationExecutionStatus


class ConfirmationResponseRequest(BaseModel):
Expand Down
10 changes: 6 additions & 4 deletions openhands-sdk/openhands/sdk/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from openhands.sdk.agent.base import AgentBase
from openhands.sdk.context.view import View
from openhands.sdk.conversation import ConversationCallbackType, ConversationState
from openhands.sdk.conversation.state import AgentExecutionStatus
from openhands.sdk.conversation.state import ConversationExecutionStatus
from openhands.sdk.event import (
ActionEvent,
AgentErrorEvent,
Expand Down Expand Up @@ -251,7 +251,7 @@ def step(

else:
logger.info("LLM produced a message response - awaits user input")
state.agent_status = AgentExecutionStatus.FINISHED
state.execution_status = ConversationExecutionStatus.FINISHED
msg_event = MessageEvent(
source="agent",
llm_message=message,
Expand Down Expand Up @@ -294,7 +294,9 @@ def _requires_user_confirmation(

# Grab the confirmation policy from the state and pass in the risks.
if any(state.confirmation_policy.should_confirm(risk) for risk in risks):
state.agent_status = AgentExecutionStatus.WAITING_FOR_CONFIRMATION
state.execution_status = (
ConversationExecutionStatus.WAITING_FOR_CONFIRMATION
)
return True

return False
Expand Down Expand Up @@ -439,5 +441,5 @@ def _execute_action_event(

# Set conversation state
if tool.name == FinishTool.name:
state.agent_status = AgentExecutionStatus.FINISHED
state.execution_status = ConversationExecutionStatus.FINISHED
return obs_event
2 changes: 1 addition & 1 deletion openhands-sdk/openhands/sdk/agent/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def step(
2. Executing the tool
3. Updating the conversation state with
LLM calls (role="assistant") and tool results (role="tool")
4.1 If conversation is finished, set state.agent_status to FINISHED
4.1 If conversation is finished, set state.execution_status to FINISHED
4.2 Otherwise, just return, Conversation will kick off the next step

NOTE: state will be mutated in-place.
Expand Down
6 changes: 3 additions & 3 deletions openhands-sdk/openhands/sdk/conversation/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

if TYPE_CHECKING:
from openhands.sdk.agent.base import AgentBase
from openhands.sdk.conversation.state import AgentExecutionStatus
from openhands.sdk.conversation.state import ConversationExecutionStatus


class ConversationStateProtocol(Protocol):
Expand All @@ -35,8 +35,8 @@ def events(self) -> EventsListBase:
...

@property
def agent_status(self) -> "AgentExecutionStatus":
"""The current agent execution status."""
def execution_status(self) -> "ConversationExecutionStatus":
"""The current conversation execution status."""
...

@property
Expand Down
Loading
Loading