OpenHands/openhands/app_server/app_conversation/app_conversation_models.py
Hiep Le 36cf4e161a
fix(backend): ensure microagents are loaded for V1 conversations (#11772)
Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
2025-11-19 18:54:08 +07:00

162 lines
5.4 KiB
Python

from datetime import datetime
from enum import Enum
from uuid import uuid4
from pydantic import BaseModel, Field
from openhands.agent_server.models import SendMessageRequest
from openhands.agent_server.utils import OpenHandsUUID, utc_now
from openhands.app_server.event_callback.event_callback_models import (
EventCallbackProcessor,
)
from openhands.app_server.sandbox.sandbox_models import SandboxStatus
from openhands.integrations.service_types import ProviderType
from openhands.sdk.conversation.state import ConversationExecutionStatus
from openhands.sdk.llm import MetricsSnapshot
from openhands.storage.data_models.conversation_metadata import ConversationTrigger
class AgentType(Enum):
"""Agent type for conversation."""
DEFAULT = 'default'
PLAN = 'plan'
class AppConversationInfo(BaseModel):
"""Conversation info which does not contain status."""
id: OpenHandsUUID = Field(default_factory=uuid4)
created_by_user_id: str | None
sandbox_id: str
selected_repository: str | None = None
selected_branch: str | None = None
git_provider: ProviderType | None = None
title: str | None = None
trigger: ConversationTrigger | None = None
pr_number: list[int] = Field(default_factory=list)
llm_model: str | None = None
metrics: MetricsSnapshot | None = None
parent_conversation_id: OpenHandsUUID | None = None
sub_conversation_ids: list[OpenHandsUUID] = Field(default_factory=list)
created_at: datetime = Field(default_factory=utc_now)
updated_at: datetime = Field(default_factory=utc_now)
class AppConversationSortOrder(Enum):
CREATED_AT = 'CREATED_AT'
CREATED_AT_DESC = 'CREATED_AT_DESC'
UPDATED_AT = 'UPDATED_AT'
UPDATED_AT_DESC = 'UPDATED_AT_DESC'
TITLE = 'TITLE'
TITLE_DESC = 'TITLE_DESC'
class AppConversationInfoPage(BaseModel):
items: list[AppConversationInfo]
next_page_id: str | None = None
class AppConversation(AppConversationInfo): # type: ignore
sandbox_status: SandboxStatus = Field(
default=SandboxStatus.MISSING,
description='Current sandbox status. Will be MISSING if the sandbox does not exist.',
)
execution_status: ConversationExecutionStatus | None = Field(
default=None,
description='Current agent status. Will be None if the sandbox_status is not RUNNING',
)
conversation_url: str | None = Field(
default=None, description='The URL where the conversation may be accessed'
)
session_api_key: str | None = Field(
default=None, description='The Session Api Key for REST operations.'
)
# JSON fields for complex data types
pr_number: list[int] = Field(default_factory=list)
metrics: MetricsSnapshot | None = Field(default=None)
class AppConversationPage(BaseModel):
items: list[AppConversation]
next_page_id: str | None = None
class AppConversationStartRequest(BaseModel):
"""Start conversation request object.
Although a user can go directly to the sandbox and start conversations, they
would need to manually supply required startup parameters such as LLM key. Starting
from the app server copies these from the user info.
"""
sandbox_id: str | None = Field(default=None)
initial_message: SendMessageRequest | None = None
processors: list[EventCallbackProcessor] | None = Field(default=None)
llm_model: str | None = None
# Git parameters
selected_repository: str | None = None
selected_branch: str | None = None
git_provider: ProviderType | None = None
title: str | None = None
trigger: ConversationTrigger | None = None
pr_number: list[int] = Field(default_factory=list)
parent_conversation_id: OpenHandsUUID | None = None
agent_type: AgentType = Field(default=AgentType.DEFAULT)
class AppConversationStartTaskStatus(Enum):
WORKING = 'WORKING'
WAITING_FOR_SANDBOX = 'WAITING_FOR_SANDBOX'
PREPARING_REPOSITORY = 'PREPARING_REPOSITORY'
RUNNING_SETUP_SCRIPT = 'RUNNING_SETUP_SCRIPT'
SETTING_UP_GIT_HOOKS = 'SETTING_UP_GIT_HOOKS'
SETTING_UP_SKILLS = 'SETTING_UP_SKILLS'
STARTING_CONVERSATION = 'STARTING_CONVERSATION'
READY = 'READY'
ERROR = 'ERROR'
class AppConversationStartTaskSortOrder(Enum):
CREATED_AT = 'CREATED_AT'
CREATED_AT_DESC = 'CREATED_AT_DESC'
UPDATED_AT = 'UPDATED_AT'
UPDATED_AT_DESC = 'UPDATED_AT_DESC'
class AppConversationStartTask(BaseModel):
"""Object describing the start process for an app conversation.
Because starting an app conversation can be slow (And can involve starting a sandbox),
we kick off a background task for it. Once the conversation is started, the app_conversation_id
is populated."""
id: OpenHandsUUID = Field(default_factory=uuid4)
created_by_user_id: str | None
status: AppConversationStartTaskStatus = AppConversationStartTaskStatus.WORKING
detail: str | None = None
app_conversation_id: OpenHandsUUID | None = Field(
default=None, description='The id of the app_conversation, if READY'
)
sandbox_id: str | None = Field(
default=None, description='The id of the sandbox, if READY'
)
agent_server_url: str | None = Field(
default=None, description='The agent server url, if READY'
)
request: AppConversationStartRequest
created_at: datetime = Field(default_factory=utc_now)
updated_at: datetime = Field(default_factory=utc_now)
class AppConversationStartTaskPage(BaseModel):
items: list[AppConversationStartTask]
next_page_id: str | None = None