More updates of agent_status to execution_status (#11642)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Tim O'Farrell
2025-11-05 12:19:34 -07:00
committed by GitHub
parent 5a8f08b4ef
commit d99c7827d8
18 changed files with 666 additions and 157 deletions

View File

@@ -11,7 +11,7 @@ from openhands.app_server.event_callback.event_callback_models import (
)
from openhands.app_server.sandbox.sandbox_models import SandboxStatus
from openhands.integrations.service_types import ProviderType
from openhands.sdk.conversation.state import AgentExecutionStatus
from openhands.sdk.conversation.state import ConversationExecutionStatus
from openhands.sdk.llm import MetricsSnapshot
from openhands.storage.data_models.conversation_metadata import ConversationTrigger
@@ -57,7 +57,7 @@ class AppConversation(AppConversationInfo): # type: ignore
default=SandboxStatus.MISSING,
description='Current sandbox status. Will be MISSING if the sandbox does not exist.',
)
agent_status: AgentExecutionStatus | None = Field(
execution_status: ConversationExecutionStatus | None = Field(
default=None,
description='Current agent status. Will be None if the sandbox_status is not RUNNING',
)

View File

@@ -222,7 +222,7 @@ class LiveStatusAppConversationService(GitAppConversationService):
app_conversation_info = AppConversationInfo(
id=info.id,
# TODO: As of writing, StartConversationRequest from AgentServer does not have a title
title=f'Conversation {info.id}',
title=f'Conversation {info.id.hex}',
sandbox_id=sandbox.id,
created_by_user_id=user_id,
llm_model=start_conversation_request.agent.llm.model,
@@ -337,7 +337,9 @@ class LiveStatusAppConversationService(GitAppConversationService):
if app_conversation_info is None:
return None
sandbox_status = sandbox.status if sandbox else SandboxStatus.MISSING
agent_status = conversation_info.agent_status if conversation_info else None
execution_status = (
conversation_info.execution_status if conversation_info else None
)
conversation_url = None
session_api_key = None
if sandbox and sandbox.exposed_urls:
@@ -356,7 +358,7 @@ class LiveStatusAppConversationService(GitAppConversationService):
return AppConversation(
**app_conversation_info.model_dump(),
sandbox_status=sandbox_status,
agent_status=agent_status,
execution_status=execution_status,
conversation_url=conversation_url,
session_api_key=session_api_key,
)

View File

@@ -1,13 +1,16 @@
"""Event Callback router for OpenHands Server."""
import asyncio
import importlib
import logging
import pkgutil
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import APIKeyHeader
from jwt import InvalidTokenError
from openhands import tools # type: ignore[attr-defined]
from openhands.agent_server.models import ConversationInfo, Success
from openhands.app_server.app_conversation.app_conversation_info_service import (
AppConversationInfoService,
@@ -97,8 +100,7 @@ async def on_conversation_update(
app_conversation_info = AppConversationInfo(
id=conversation_info.id,
# TODO: As of writing, ConversationInfo from AgentServer does not have a title
title=existing.title or f'Conversation {conversation_info.id}',
title=existing.title or f'Conversation {conversation_info.id.hex}',
sandbox_id=sandbox_info.id,
created_by_user_id=sandbox_info.created_by_user_id,
llm_model=conversation_info.agent.llm.model,
@@ -186,3 +188,16 @@ async def _run_callbacks_in_bg_and_close(
# We don't use asynio.gather here because callbacks must be run in sequence.
for event in events:
await event_callback_service.execute_callbacks(conversation_id, event)
def _import_all_tools():
"""We need to import all tools so that they are available for deserialization in webhooks."""
for _, name, is_pkg in pkgutil.walk_packages(tools.__path__, tools.__name__ + '.'):
if is_pkg: # Check if it's a subpackage
try:
importlib.import_module(name)
except ImportError as e:
_logger.error(f"Warning: Could not import subpackage '{name}': {e}")
_import_all_tools()

View File

@@ -11,7 +11,7 @@ from openhands.sdk.utils.models import DiscriminatedUnionMixin
# The version of the agent server to use for deployments.
# Typically this will be the same as the values from the pyproject.toml
AGENT_SERVER_IMAGE = 'ghcr.io/openhands/agent-server:23c8436-python'
AGENT_SERVER_IMAGE = 'ghcr.io/openhands/agent-server:d5995c3-python'
class SandboxSpecService(ABC):

View File

@@ -50,7 +50,7 @@ from openhands.integrations.service_types import (
)
from openhands.runtime import get_runtime_cls
from openhands.runtime.runtime_status import RuntimeStatus
from openhands.sdk.conversation.state import AgentExecutionStatus
from openhands.sdk.conversation.state import ConversationExecutionStatus
from openhands.server.data_models.agent_loop_info import AgentLoopInfo
from openhands.server.data_models.conversation_info import ConversationInfo
from openhands.server.data_models.conversation_info_result_set import (
@@ -1387,16 +1387,16 @@ def _to_conversation_info(app_conversation: AppConversation) -> ConversationInfo
if conversation_status == ConversationStatus.RUNNING:
runtime_status_mapping = {
AgentExecutionStatus.ERROR: RuntimeStatus.ERROR,
AgentExecutionStatus.IDLE: RuntimeStatus.READY,
AgentExecutionStatus.RUNNING: RuntimeStatus.READY,
AgentExecutionStatus.PAUSED: RuntimeStatus.READY,
AgentExecutionStatus.WAITING_FOR_CONFIRMATION: RuntimeStatus.READY,
AgentExecutionStatus.FINISHED: RuntimeStatus.READY,
AgentExecutionStatus.STUCK: RuntimeStatus.ERROR,
ConversationExecutionStatus.ERROR: RuntimeStatus.ERROR,
ConversationExecutionStatus.IDLE: RuntimeStatus.READY,
ConversationExecutionStatus.RUNNING: RuntimeStatus.READY,
ConversationExecutionStatus.PAUSED: RuntimeStatus.READY,
ConversationExecutionStatus.WAITING_FOR_CONFIRMATION: RuntimeStatus.READY,
ConversationExecutionStatus.FINISHED: RuntimeStatus.READY,
ConversationExecutionStatus.STUCK: RuntimeStatus.ERROR,
}
runtime_status = runtime_status_mapping.get(
app_conversation.agent_status, RuntimeStatus.ERROR
app_conversation.execution_status, RuntimeStatus.ERROR
)
else:
runtime_status = None