Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import json
from collections.abc import Sequence
from datetime import UTC, datetime
from enum import Enum
from enum import StrEnum
from pathlib import Path
from typing import Any

Expand All @@ -27,7 +27,7 @@
# --- Enums and Models ---


class LogLevel(str, Enum):
class LogLevel(StrEnum):
"""Log level for entries."""

DEBUG = "debug"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ a = Analysis(
*collect_data_files("fastmcp"),
*collect_data_files("mcp"),
*collect_data_files("fakeredis"), # Required for commands.json used by fakeredis ACL
*collect_data_files("binaryornot"), # Required for binaryornot.data signatures at runtime
*get_fakeredis_data(), # Ensure fakeredis/model/ directory structure exists

# OpenHands SDK prompt templates (adjusted for shallow namespace layout)
Expand Down
6 changes: 3 additions & 3 deletions openhands-agent-server/openhands/agent_server/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from abc import ABC
from datetime import datetime
from enum import Enum
from enum import Enum, StrEnum
from typing import Any
from uuid import UUID, uuid4

Expand Down Expand Up @@ -51,7 +51,7 @@ class ServerErrorEvent(Event):
detail: str = Field(description="Details about the error")


class ConversationSortOrder(str, Enum):
class ConversationSortOrder(StrEnum):
"""Enum for conversation sorting options."""

CREATED_AT = "CREATED_AT"
Expand All @@ -60,7 +60,7 @@ class ConversationSortOrder(str, Enum):
UPDATED_AT_DESC = "UPDATED_AT_DESC"


class EventSortOrder(str, Enum):
class EventSortOrder(StrEnum):
"""Enum for event sorting options."""

TIMESTAMP = "TIMESTAMP"
Expand Down
4 changes: 2 additions & 2 deletions openhands-sdk/openhands/sdk/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,8 @@ def _execute_actions(
batch.emit(on_event)
batch.finalize(
on_event=on_event,
check_iterative_refinement=lambda ae: (
self._check_iterative_refinement(conversation, ae)
check_iterative_refinement=lambda ae: self._check_iterative_refinement(
conversation, ae
),
mark_finished=lambda: setattr(
state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
)
from openhands.sdk.event.conversation_error import ConversationErrorEvent
from openhands.sdk.hooks import HookConfig, HookEventProcessor, create_hook_callback
from openhands.sdk.io import LocalFileStore
from openhands.sdk.io import FileStore, LocalFileStore
from openhands.sdk.llm import LLM, Message, TextContent
from openhands.sdk.llm.llm_profile_store import LLMProfileStore
from openhands.sdk.llm.llm_registry import LLMRegistry
Expand Down Expand Up @@ -108,6 +108,7 @@ def __init__(
delete_on_close: bool = True,
cipher: Cipher | None = None,
tags: dict[str, str] | None = None,
file_store: FileStore | None = None,
**_: object,
):
"""Initialize the conversation.
Expand Down Expand Up @@ -188,6 +189,7 @@ def __init__(
stuck_detection=stuck_detection,
cipher=cipher,
tags=tags,
file_store=file_store,
)

self._pin_prompt_cache_key()
Expand Down
32 changes: 20 additions & 12 deletions openhands-sdk/openhands/sdk/conversation/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import json
from collections.abc import Callable, Sequence
from contextlib import AbstractContextManager
from enum import Enum
from enum import StrEnum
from pathlib import Path
from typing import Any, Self

Expand Down Expand Up @@ -43,7 +43,7 @@
logger = get_logger(__name__)


class ConversationExecutionStatus(str, Enum):
class ConversationExecutionStatus(StrEnum):
"""Enum representing the current execution state of the conversation."""

IDLE = "idle" # Conversation is ready to receive tasks
Expand Down Expand Up @@ -282,6 +282,7 @@ def create(
stuck_detection: bool = True,
cipher: Cipher | None = None,
tags: dict[str, str] | None = None,
file_store: FileStore | None = None,
Comment thread
StatPan marked this conversation as resolved.
) -> "ConversationState":
"""Create a new conversation state or resume from persistence.

Expand Down Expand Up @@ -311,6 +312,12 @@ def create(
are redacted (lost) on serialization.
tags: Optional key-value tags for the conversation. Keys must be
lowercase alphanumeric, values up to 256 characters.
file_store: Optional pre-configured FileStore for event
persistence. When provided, ``persistence_dir`` is **not**
used for EventLog storage (the supplied store takes
precedence). Note that ``persistence_dir`` is still read
for ``env_observation_persistence_dir`` — pass both if you
need observation persistence alongside a custom store.

Returns:
ConversationState ready for use
Expand All @@ -319,16 +326,17 @@ def create(
ValueError: If conversation ID or tools mismatch on restore
ValidationError: If agent or other fields fail Pydantic validation
"""
if persistence_dir:
file_store = LocalFileStore(
persistence_dir, cache_limit_size=max_iterations
)
else:
logger.warning(
"No persistence_dir provided; falling back to InMemoryFileStore. "
"EventLog data will not persist across requests."
)
file_store = InMemoryFileStore()
if file_store is None:
if persistence_dir:
file_store = LocalFileStore(
persistence_dir, cache_limit_size=max_iterations
)
else:
logger.warning(
"No persistence_dir provided; falling back to InMemoryFileStore. "
"EventLog data will not persist across requests."
)
file_store = InMemoryFileStore()

try:
base_text = file_store.read(BASE_STATE)
Expand Down
4 changes: 2 additions & 2 deletions openhands-sdk/openhands/sdk/hooks/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json
import logging
import re
from enum import Enum
from enum import StrEnum
from pathlib import Path
from typing import Any

Expand Down Expand Up @@ -36,7 +36,7 @@ def _pascal_to_snake(name: str) -> str:
)


class HookType(str, Enum):
class HookType(StrEnum):
"""Types of hooks that can be executed."""

COMMAND = "command" # Shell command executed via subprocess
Expand Down
6 changes: 3 additions & 3 deletions openhands-sdk/openhands/sdk/hooks/types.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""Hook event types and data structures."""

from enum import Enum
from enum import StrEnum
from typing import Any

from pydantic import BaseModel, Field


class HookEventType(str, Enum):
class HookEventType(StrEnum):
"""Types of hook events that can trigger hooks."""

PRE_TOOL_USE = "PreToolUse"
Expand All @@ -32,7 +32,7 @@ class HookEvent(BaseModel):
model_config = {"use_enum_values": True}


class HookDecision(str, Enum):
class HookDecision(StrEnum):
"""Decisions a hook can make about an operation."""

ALLOW = "allow"
Expand Down
12 changes: 11 additions & 1 deletion openhands-sdk/openhands/sdk/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,14 @@
from .memory import InMemoryFileStore


__all__ = ["LocalFileStore", "FileStore", "InMemoryFileStore"]
try:
from .postgresql import PostgreSQLFileStore

__all__ = [
"LocalFileStore",
"FileStore",
"InMemoryFileStore",
"PostgreSQLFileStore",
]
except ImportError:
__all__ = ["LocalFileStore", "FileStore", "InMemoryFileStore"]
Loading
Loading