Bumped Software Agent SDK and fixed V1 Delete (#11768)

This commit is contained in:
Tim O'Farrell 2025-11-18 15:52:23 +00:00 committed by GitHub
parent f5611c2188
commit 84c62c4f23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 107 additions and 14 deletions

28
enterprise/poetry.lock generated
View File

@ -5829,6 +5829,7 @@ files = [
{file = "openhands_agent_server-1.1.0-py3-none-any.whl", hash = "sha256:59a856883df23488c0723e47655ef21649a321fcd4709a25a4690866eff6ac88"},
{file = "openhands_agent_server-1.1.0.tar.gz", hash = "sha256:e39bebd39afd45cfcfd765005e7c4e5409e46678bd7612ae20bae79f7057b935"},
]
develop = false
[package.dependencies]
aiosqlite = ">=0.19"
@ -5841,9 +5842,16 @@ uvicorn = ">=0.31.1"
websockets = ">=12"
wsproto = ">=1.2.0"
[package.source]
type = "git"
url = "https://github.com/OpenHands/agent-sdk.git"
reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
resolved_reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
subdirectory = "openhands-agent-server"
[[package]]
name = "openhands-ai"
version = "0.0.0-post.5525+0b6631523"
version = "0.0.0-post.5576+ed2ac6040"
description = "OpenHands: Code Less, Make More"
optional = false
python-versions = "^3.12,<3.14"
@ -5860,6 +5868,7 @@ bashlex = "^0.18"
boto3 = "*"
browsergym-core = "0.13.3"
deprecated = "*"
deprecation = "^2.1.0"
dirhash = "*"
docker = "*"
fastapi = "*"
@ -5951,8 +5960,10 @@ files = [
{file = "openhands_sdk-1.1.0-py3-none-any.whl", hash = "sha256:4a984ce1687a48cf99a67fdf3d37b116f8b2840743d4807810b5024af6a1d57e"},
{file = "openhands_sdk-1.1.0.tar.gz", hash = "sha256:855e0d8f3657205e4119e50520c17e65b3358b1a923f7a051a82512a54bf426c"},
]
develop = false
[package.dependencies]
deprecation = ">=2.1.0"
fastmcp = ">=2.11.3"
httpx = ">=0.27.0"
litellm = ">=1.77.7.dev9"
@ -5966,6 +5977,13 @@ websockets = ">=12"
[package.extras]
boto3 = ["boto3 (>=1.35.0)"]
[package.source]
type = "git"
url = "https://github.com/OpenHands/agent-sdk.git"
reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
resolved_reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
subdirectory = "openhands-sdk"
[[package]]
name = "openhands-tools"
version = "1.1.0"
@ -5977,6 +5995,7 @@ files = [
{file = "openhands_tools-1.1.0-py3-none-any.whl", hash = "sha256:767d6746f05edade49263aa24450a037485a3dc23379f56917ef19aad22033f9"},
{file = "openhands_tools-1.1.0.tar.gz", hash = "sha256:c2fadaa4f4e16e9a3df5781ea847565dcae7171584f09ef7c0e1d97c8dfc83f6"},
]
develop = false
[package.dependencies]
bashlex = ">=0.18"
@ -5988,6 +6007,13 @@ libtmux = ">=0.46.2"
openhands-sdk = "*"
pydantic = ">=2.11.7"
[package.source]
type = "git"
url = "https://github.com/OpenHands/agent-sdk.git"
reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
resolved_reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
subdirectory = "openhands-tools"
[[package]]
name = "openpyxl"
version = "3.1.5"

View File

@ -113,10 +113,10 @@ class TestConversationRunner:
agent.finish_on_step = 1
convo = Conversation(agent)
# Set security analyzer using the new API to enable confirmation mode
convo.set_security_analyzer(MagicMock())
convo.state.execution_status = (
ConversationExecutionStatus.WAITING_FOR_CONFIRMATION
)
@ -127,7 +127,7 @@ class TestConversationRunner:
cr, '_handle_confirmation_request', return_value=confirmation
) as mock_confirmation_request:
cr.process_message(message=None)
mock_confirmation_request.assert_called_once()
assert agent.step_count == expected_run_calls
assert convo.state.execution_status == final_status

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:4e2ecd8-python'
AGENT_SERVER_IMAGE = 'ghcr.io/openhands/agent-server:15f565b-python'
class SandboxSpecService(ABC):

View File

@ -9,6 +9,7 @@ from datetime import datetime, timedelta, timezone
from typing import Annotated
import base62
import httpx
from fastapi import APIRouter, Depends, Query, Request, status
from fastapi.responses import JSONResponse
from jinja2 import Environment, FileSystemLoader
@ -28,10 +29,14 @@ from openhands.app_server.config import (
depends_app_conversation_info_service,
depends_app_conversation_service,
depends_db_session,
depends_httpx_client,
depends_sandbox_service,
)
from openhands.app_server.sandbox.sandbox_service import SandboxService
from openhands.app_server.services.db_session_injector import set_db_session_keep_open
from openhands.app_server.services.httpx_client_injector import (
set_httpx_client_keep_open,
)
from openhands.core.config.llm_config import LLMConfig
from openhands.core.config.mcp_config import MCPConfig
from openhands.core.logger import openhands_logger as logger
@ -105,6 +110,7 @@ app_conversation_service_dependency = depends_app_conversation_service()
app_conversation_info_service_dependency = depends_app_conversation_info_service()
sandbox_service_dependency = depends_sandbox_service()
db_session_dependency = depends_db_session()
httpx_client_dependency = depends_httpx_client()
def _filter_conversations_by_age(
@ -487,8 +493,11 @@ async def delete_conversation(
app_conversation_info_service: AppConversationInfoService = app_conversation_info_service_dependency,
sandbox_service: SandboxService = sandbox_service_dependency,
db_session: AsyncSession = db_session_dependency,
httpx_client: httpx.AsyncClient = httpx_client_dependency,
) -> bool:
set_db_session_keep_open(request.state, True)
set_httpx_client_keep_open(request.state, True)
# Try V1 conversation first
v1_result = await _try_delete_v1_conversation(
conversation_id,
@ -496,6 +505,7 @@ async def delete_conversation(
app_conversation_info_service,
sandbox_service,
db_session,
httpx_client,
)
if v1_result is not None:
return v1_result
@ -510,6 +520,7 @@ async def _try_delete_v1_conversation(
app_conversation_info_service: AppConversationInfoService,
sandbox_service: SandboxService,
db_session: AsyncSession,
httpx_client: httpx.AsyncClient,
) -> bool | None:
"""Try to delete a V1 conversation. Returns None if not a V1 conversation."""
result = None
@ -527,10 +538,17 @@ async def _try_delete_v1_conversation(
result = await app_conversation_service.delete_app_conversation(
app_conversation_info.id
)
# Manually commit so that the conversation will vanish from the list
await db_session.commit()
# Delete the sandbox in the background
asyncio.create_task(
_delete_sandbox_and_close_connection(
sandbox_service, app_conversation_info.sandbox_id, db_session
_delete_sandbox_and_close_connections(
sandbox_service,
app_conversation_info.sandbox_id,
db_session,
httpx_client,
)
)
except (ValueError, TypeError):
@ -543,14 +561,22 @@ async def _try_delete_v1_conversation(
return result
async def _delete_sandbox_and_close_connection(
sandbox_service: SandboxService, sandbox_id: str, db_session: AsyncSession
async def _delete_sandbox_and_close_connections(
sandbox_service: SandboxService,
sandbox_id: str,
db_session: AsyncSession,
httpx_client: httpx.AsyncClient,
):
try:
await sandbox_service.delete_sandbox(sandbox_id)
await db_session.commit()
finally:
await db_session.aclose()
await asyncio.gather(
*[
db_session.aclose(),
httpx_client.aclose(),
]
)
async def _delete_v0_conversation(conversation_id: str, user_id: str | None) -> bool:

42
poetry.lock generated
View File

@ -2408,6 +2408,21 @@ wrapt = ">=1.10,<2"
[package.extras]
dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version >= \"3.12\"", "tox"]
[[package]]
name = "deprecation"
version = "2.1.0"
description = "A library to handle automated deprecations"
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"},
{file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"},
]
[package.dependencies]
packaging = "*"
[[package]]
name = "dill"
version = "0.3.8"
@ -7338,6 +7353,7 @@ files = [
{file = "openhands_agent_server-1.1.0-py3-none-any.whl", hash = "sha256:59a856883df23488c0723e47655ef21649a321fcd4709a25a4690866eff6ac88"},
{file = "openhands_agent_server-1.1.0.tar.gz", hash = "sha256:e39bebd39afd45cfcfd765005e7c4e5409e46678bd7612ae20bae79f7057b935"},
]
develop = false
[package.dependencies]
aiosqlite = ">=0.19"
@ -7350,6 +7366,13 @@ uvicorn = ">=0.31.1"
websockets = ">=12"
wsproto = ">=1.2.0"
[package.source]
type = "git"
url = "https://github.com/OpenHands/agent-sdk.git"
reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
resolved_reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
subdirectory = "openhands-agent-server"
[[package]]
name = "openhands-sdk"
version = "1.1.0"
@ -7361,8 +7384,10 @@ files = [
{file = "openhands_sdk-1.1.0-py3-none-any.whl", hash = "sha256:4a984ce1687a48cf99a67fdf3d37b116f8b2840743d4807810b5024af6a1d57e"},
{file = "openhands_sdk-1.1.0.tar.gz", hash = "sha256:855e0d8f3657205e4119e50520c17e65b3358b1a923f7a051a82512a54bf426c"},
]
develop = false
[package.dependencies]
deprecation = ">=2.1.0"
fastmcp = ">=2.11.3"
httpx = ">=0.27.0"
litellm = ">=1.77.7.dev9"
@ -7376,6 +7401,13 @@ websockets = ">=12"
[package.extras]
boto3 = ["boto3 (>=1.35.0)"]
[package.source]
type = "git"
url = "https://github.com/OpenHands/agent-sdk.git"
reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
resolved_reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
subdirectory = "openhands-sdk"
[[package]]
name = "openhands-tools"
version = "1.1.0"
@ -7387,6 +7419,7 @@ files = [
{file = "openhands_tools-1.1.0-py3-none-any.whl", hash = "sha256:767d6746f05edade49263aa24450a037485a3dc23379f56917ef19aad22033f9"},
{file = "openhands_tools-1.1.0.tar.gz", hash = "sha256:c2fadaa4f4e16e9a3df5781ea847565dcae7171584f09ef7c0e1d97c8dfc83f6"},
]
develop = false
[package.dependencies]
bashlex = ">=0.18"
@ -7398,6 +7431,13 @@ libtmux = ">=0.46.2"
openhands-sdk = "*"
pydantic = ">=2.11.7"
[package.source]
type = "git"
url = "https://github.com/OpenHands/agent-sdk.git"
reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
resolved_reference = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d"
subdirectory = "openhands-tools"
[[package]]
name = "openpyxl"
version = "3.1.5"
@ -16729,4 +16769,4 @@ third-party-runtimes = ["daytona", "e2b-code-interpreter", "modal", "runloop-api
[metadata]
lock-version = "2.1"
python-versions = "^3.12,<3.14"
content-hash = "0fe5bab6aeb5ebce4588b30cfcf491af4cc9d9b9cd5160e67c8a055d9db276fc"
content-hash = "44c6c1f432337d216b70a6654fb0cd20410ddeb56485999859032aec53e90458"

View File

@ -113,9 +113,9 @@ e2b-code-interpreter = { version = "^2.0.0", optional = true }
pybase62 = "^1.0.0"
# V1 dependencies
#openhands-agent-server = { git = "https://github.com/OpenHands/agent-sdk.git", subdirectory = "openhands-agent-server", rev = "f3c0c19cd134fbda84e07f152897a6d61e1e46c5" }
#openhands-sdk = { git = "https://github.com/OpenHands/agent-sdk.git", subdirectory = "openhands-sdk", rev = "f3c0c19cd134fbda84e07f152897a6d61e1e46c5" }
#openhands-tools = { git = "https://github.com/OpenHands/agent-sdk.git", subdirectory = "openhands-tools", rev = "f3c0c19cd134fbda84e07f152897a6d61e1e46c5" }
#openhands-agent-server = { git = "https://github.com/OpenHands/agent-sdk.git", subdirectory = "openhands-agent-server", rev = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d" }
#openhands-sdk = { git = "https://github.com/OpenHands/agent-sdk.git", subdirectory = "openhands-sdk", rev = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d" }
#openhands-tools = { git = "https://github.com/OpenHands/agent-sdk.git", subdirectory = "openhands-tools", rev = "15f565b8ac38876e40dc05c08e2b04ccaae4a66d" }
openhands-sdk = "1.1.0"
openhands-agent-server = "1.1.0"
openhands-tools = "1.1.0"
@ -123,6 +123,7 @@ python-jose = { version = ">=3.3", extras = [ "cryptography" ] }
sqlalchemy = { extras = [ "asyncio" ], version = "^2.0.40" }
pg8000 = "^1.31.5"
asyncpg = "^0.30.0"
deprecation = "^2.1.0"
lmnr = "^0.7.20"
[tool.poetry.extras]