openhands-agent-server 1.10.0__py3-none-any.whl → 1.11.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openhands/agent_server/__main__.py +50 -0
- openhands/agent_server/bash_router.py +9 -0
- openhands/agent_server/bash_service.py +6 -0
- openhands/agent_server/conversation_service.py +10 -2
- openhands/agent_server/docker/Dockerfile +2 -0
- openhands/agent_server/docker/build.py +4 -0
- {openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/METADATA +1 -1
- {openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/RECORD +11 -11
- {openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/WHEEL +0 -0
- {openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/entry_points.txt +0 -0
- {openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/top_level.txt +0 -0
|
@@ -2,6 +2,7 @@ import argparse
|
|
|
2
2
|
import atexit
|
|
3
3
|
import faulthandler
|
|
4
4
|
import signal
|
|
5
|
+
import sys
|
|
5
6
|
from types import FrameType
|
|
6
7
|
|
|
7
8
|
import uvicorn
|
|
@@ -14,6 +15,43 @@ from openhands.sdk.logger import DEBUG, get_logger
|
|
|
14
15
|
logger = get_logger(__name__)
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def check_browser():
|
|
19
|
+
"""Check if browser functionality can render about:blank."""
|
|
20
|
+
executor = None
|
|
21
|
+
try:
|
|
22
|
+
# Register tools to ensure browser tools are available
|
|
23
|
+
from openhands.tools.preset.default import register_default_tools
|
|
24
|
+
|
|
25
|
+
register_default_tools(enable_browser=True)
|
|
26
|
+
|
|
27
|
+
# Import browser components
|
|
28
|
+
from openhands.tools.browser_use.definition import BrowserNavigateAction
|
|
29
|
+
from openhands.tools.browser_use.impl import BrowserToolExecutor
|
|
30
|
+
|
|
31
|
+
# Create executor
|
|
32
|
+
executor = BrowserToolExecutor(headless=True, session_timeout_minutes=2)
|
|
33
|
+
|
|
34
|
+
# Try to navigate to about:blank
|
|
35
|
+
action = BrowserNavigateAction(url="about:blank")
|
|
36
|
+
result = executor(action)
|
|
37
|
+
|
|
38
|
+
# Check if the operation was successful
|
|
39
|
+
if result.is_error:
|
|
40
|
+
print(f"Browser check failed: {str(result.content)}")
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
print("Browser check passed: Successfully rendered about:blank")
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
except Exception as e:
|
|
47
|
+
print(f"Browser check failed: {e}")
|
|
48
|
+
return False
|
|
49
|
+
finally:
|
|
50
|
+
# Ensure cleanup happens even if an error occurs
|
|
51
|
+
if executor is not None:
|
|
52
|
+
executor.close()
|
|
53
|
+
|
|
54
|
+
|
|
17
55
|
class LoggingServer(uvicorn.Server):
|
|
18
56
|
"""Custom uvicorn Server that logs signal handling events.
|
|
19
57
|
|
|
@@ -67,9 +105,21 @@ def main() -> None:
|
|
|
67
105
|
action="store_true",
|
|
68
106
|
help="Enable auto-reload (disabled by default)",
|
|
69
107
|
)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"--check-browser",
|
|
110
|
+
action="store_true",
|
|
111
|
+
help="Check if browser functionality works and exit",
|
|
112
|
+
)
|
|
70
113
|
|
|
71
114
|
args = parser.parse_args()
|
|
72
115
|
|
|
116
|
+
# Handle browser check
|
|
117
|
+
if args.check_browser:
|
|
118
|
+
if check_browser():
|
|
119
|
+
sys.exit(0)
|
|
120
|
+
else:
|
|
121
|
+
sys.exit(1)
|
|
122
|
+
|
|
73
123
|
print(f"🙌 Starting OpenHands Agent Server on {args.host}:{args.port}")
|
|
74
124
|
print(f"📖 API docs will be available at http://{args.host}:{args.port}/docs")
|
|
75
125
|
print(f"🔄 Auto-reload: {'enabled' if args.reload else 'disabled'}")
|
|
@@ -36,6 +36,14 @@ async def search_bash_events(
|
|
|
36
36
|
command_id__eq: UUID | None = None,
|
|
37
37
|
timestamp__gte: datetime | None = None,
|
|
38
38
|
timestamp__lt: datetime | None = None,
|
|
39
|
+
order__gt: Annotated[
|
|
40
|
+
int | None,
|
|
41
|
+
Query(
|
|
42
|
+
title="Filter to events with order greater than this value",
|
|
43
|
+
description="Only returns BashOutput events with order > this value. "
|
|
44
|
+
"Useful for polling to fetch only new events since the last poll.",
|
|
45
|
+
),
|
|
46
|
+
] = None,
|
|
39
47
|
sort_order: BashEventSortOrder = BashEventSortOrder.TIMESTAMP,
|
|
40
48
|
page_id: Annotated[
|
|
41
49
|
str | None,
|
|
@@ -55,6 +63,7 @@ async def search_bash_events(
|
|
|
55
63
|
command_id__eq=command_id__eq,
|
|
56
64
|
timestamp__gte=timestamp__gte,
|
|
57
65
|
timestamp__lt=timestamp__lt,
|
|
66
|
+
order__gt=order__gt,
|
|
58
67
|
sort_order=sort_order,
|
|
59
68
|
page_id=page_id,
|
|
60
69
|
limit=limit,
|
|
@@ -104,6 +104,7 @@ class BashEventService:
|
|
|
104
104
|
command_id__eq: UUID | None = None,
|
|
105
105
|
timestamp__gte: datetime | None = None,
|
|
106
106
|
timestamp__lt: datetime | None = None,
|
|
107
|
+
order__gt: int | None = None,
|
|
107
108
|
sort_order: BashEventSortOrder = BashEventSortOrder.TIMESTAMP,
|
|
108
109
|
page_id: str | None = None,
|
|
109
110
|
limit: int = 100,
|
|
@@ -168,6 +169,11 @@ class BashEventService:
|
|
|
168
169
|
for file_path in page_files:
|
|
169
170
|
event = self._load_event_from_file(file_path)
|
|
170
171
|
if event is not None:
|
|
172
|
+
# Filter by order if specified (only applies to BashOutput events)
|
|
173
|
+
if order__gt is not None:
|
|
174
|
+
event_order = getattr(event, "order", None)
|
|
175
|
+
if event_order is not None and event_order <= order__gt:
|
|
176
|
+
continue
|
|
171
177
|
page_events.append(event)
|
|
172
178
|
|
|
173
179
|
return BashEventPage(items=page_events, next_page_id=next_page_id)
|
|
@@ -34,8 +34,11 @@ logger = logging.getLogger(__name__)
|
|
|
34
34
|
def _compose_conversation_info(
|
|
35
35
|
stored: StoredConversation, state: ConversationState
|
|
36
36
|
) -> ConversationInfo:
|
|
37
|
+
# Use mode='json' so SecretStr in nested structures (e.g. LookupSecret.headers,
|
|
38
|
+
# agent.agent_context.secrets) serialize to strings. Without it, validation
|
|
39
|
+
# fails because ConversationInfo expects dict[str, str] but receives SecretStr.
|
|
37
40
|
return ConversationInfo(
|
|
38
|
-
**state.model_dump(),
|
|
41
|
+
**state.model_dump(mode="json"),
|
|
39
42
|
title=stored.title,
|
|
40
43
|
metrics=stored.metrics,
|
|
41
44
|
created_at=stored.created_at,
|
|
@@ -241,9 +244,14 @@ class ConversationService:
|
|
|
241
244
|
# 1. Fetch and load plugins on first run()/send_message()
|
|
242
245
|
# 2. Resolve refs to commit SHAs for deterministic resume
|
|
243
246
|
# 3. Merge plugin skills/MCP/hooks into the agent
|
|
247
|
+
#
|
|
248
|
+
# Use mode='json' so SecretStr in nested structures (e.g. LookupSecret.headers)
|
|
249
|
+
# serialize to plain strings. Pass expose_secrets=True so StaticSecret values
|
|
250
|
+
# are preserved through the round-trip; the dict is only used in-process to
|
|
251
|
+
# construct StoredConversation, not sent over the network.
|
|
244
252
|
stored = StoredConversation(
|
|
245
253
|
id=conversation_id,
|
|
246
|
-
**request.model_dump(),
|
|
254
|
+
**request.model_dump(mode="json", context={"expose_secrets": True}),
|
|
247
255
|
)
|
|
248
256
|
event_service = await self._start_event_service(stored)
|
|
249
257
|
initial_message = request.initial_message
|
|
@@ -333,6 +333,8 @@ _DEFAULT_PACKAGE_VERSION = _package_version()
|
|
|
333
333
|
|
|
334
334
|
|
|
335
335
|
class BuildOptions(BaseModel):
|
|
336
|
+
# NOTE: Using Python 3.12 due to PyInstaller+libtmux compatibility issue
|
|
337
|
+
# with Python 3.13. See issue #1886 for details.
|
|
336
338
|
base_image: str = Field(default="nikolaik/python-nodejs:python3.12-nodejs22")
|
|
337
339
|
custom_tags: str = Field(
|
|
338
340
|
default="", description="Comma-separated list of custom tags."
|
|
@@ -662,6 +664,8 @@ def main(argv: list[str]) -> int:
|
|
|
662
664
|
)
|
|
663
665
|
parser.add_argument(
|
|
664
666
|
"--base-image",
|
|
667
|
+
# NOTE: Using Python 3.12 due to PyInstaller+libtmux compatibility issue
|
|
668
|
+
# with Python 3.13. See issue #1886.
|
|
665
669
|
default=_env("BASE_IMAGE", "nikolaik/python-nodejs:python3.12-nodejs22"),
|
|
666
670
|
help="Base image to use (default from $BASE_IMAGE).",
|
|
667
671
|
)
|
{openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openhands-agent-server
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11.1
|
|
4
4
|
Summary: OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent
|
|
5
5
|
Project-URL: Source, https://github.com/OpenHands/software-agent-sdk
|
|
6
6
|
Project-URL: Homepage, https://github.com/OpenHands/software-agent-sdk
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
openhands/agent_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
openhands/agent_server/__main__.py,sha256=
|
|
2
|
+
openhands/agent_server/__main__.py,sha256=fR8lCTQSBOpEKNizotOoV4YdkjeHZqnbvP2kCkzlEDM,5174
|
|
3
3
|
openhands/agent_server/api.py,sha256=LqU4BWXc4VQ29sIiABZykznSMJ_dUQEOHixxeLBTuGY,12009
|
|
4
|
-
openhands/agent_server/bash_router.py,sha256=
|
|
5
|
-
openhands/agent_server/bash_service.py,sha256=
|
|
4
|
+
openhands/agent_server/bash_router.py,sha256=zlIjz2qleafBE5F7xrdIyCquBLHzEfsrKHyyx5XUIko,3704
|
|
5
|
+
openhands/agent_server/bash_service.py,sha256=sErWct5NP5XEtI3P0EwMBF9AW-vKT02ayEIILoO09VQ,14503
|
|
6
6
|
openhands/agent_server/config.py,sha256=EKxVV0QyD3KLLtFxNuUextxJplLW_zZ32nPFhli6ozA,6403
|
|
7
7
|
openhands/agent_server/conversation_router.py,sha256=lz-dnfPXrVBiGZ9GhYqfteCWJ4pq7AcnWqxsKWwCfc0,11178
|
|
8
|
-
openhands/agent_server/conversation_service.py,sha256=
|
|
8
|
+
openhands/agent_server/conversation_service.py,sha256=PHdBWgRDvqjVKIrj2X6AnDUkw04qKcIdXbHeXo56_VQ,28093
|
|
9
9
|
openhands/agent_server/dependencies.py,sha256=H3zyOc8uthpXseB3E7rWNccKIj7PlyfcgCYwFvmFq4c,2629
|
|
10
10
|
openhands/agent_server/desktop_router.py,sha256=OaCmevO33eUo3jTwiXBmQ3uT3ONu4-tqgBfYpZWrHSA,1349
|
|
11
11
|
openhands/agent_server/desktop_service.py,sha256=GnLrQd2rqlRXBCNPbCXOZEfAXa42y9GNyFAQRjVE7y8,7603
|
|
@@ -29,13 +29,13 @@ openhands/agent_server/tool_router.py,sha256=vM_9UKUzfChLK9B9Z3DL4VtKNdDw4w635kn
|
|
|
29
29
|
openhands/agent_server/utils.py,sha256=ajivE_kGCJ9qUhF9H3Qu7DUKg7uDvDQk16JcO3XntEs,1926
|
|
30
30
|
openhands/agent_server/vscode_router.py,sha256=tPmXzN6teuqMa1jvKS4Q3aWpk9p9wsp4LleKoDvkYGs,2133
|
|
31
31
|
openhands/agent_server/vscode_service.py,sha256=te7PWP0eedV7JTlLrBnCujg1dPYMmYZRvbIkxKPavgw,7685
|
|
32
|
-
openhands/agent_server/docker/Dockerfile,sha256=
|
|
33
|
-
openhands/agent_server/docker/build.py,sha256=
|
|
32
|
+
openhands/agent_server/docker/Dockerfile,sha256=jdTs0jPSnWC5t6N97qHyyne6zddfpsquhv34OeenUnM,10846
|
|
33
|
+
openhands/agent_server/docker/build.py,sha256=hZJ3T73E8eAsoRgTUi61sqorRAPdxXBlOQFatWEcwKQ,28445
|
|
34
34
|
openhands/agent_server/docker/wallpaper.svg,sha256=FR2g_b5mzz0x5EvRTKO93ASnWPagAyeS9RI3vRQBAsw,11532
|
|
35
35
|
openhands/agent_server/vscode_extensions/openhands-settings/extension.js,sha256=xoCKZ6YXlzlTWnTC52HuzX0sn9s77Vma-47WgEibO88,858
|
|
36
36
|
openhands/agent_server/vscode_extensions/openhands-settings/package.json,sha256=eCkuBBYEVArEjpp7c_m0H207OCLEygZhBLUEkeFNWOg,289
|
|
37
|
-
openhands_agent_server-1.
|
|
38
|
-
openhands_agent_server-1.
|
|
39
|
-
openhands_agent_server-1.
|
|
40
|
-
openhands_agent_server-1.
|
|
41
|
-
openhands_agent_server-1.
|
|
37
|
+
openhands_agent_server-1.11.1.dist-info/METADATA,sha256=MrHo9DLo_xm0WBWBTBEfk1Wf-9g81sA-2pjkm45sMvA,749
|
|
38
|
+
openhands_agent_server-1.11.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
39
|
+
openhands_agent_server-1.11.1.dist-info/entry_points.txt,sha256=uLQzPhqDqe85Dy9DvPiBE2CeqkwCryggr1Ty_mq65NA,70
|
|
40
|
+
openhands_agent_server-1.11.1.dist-info/top_level.txt,sha256=jHgVu9I0Blam8BXFgedoGKfglPF8XvW1TsJFIjcgP4E,10
|
|
41
|
+
openhands_agent_server-1.11.1.dist-info/RECORD,,
|
|
File without changes
|
{openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{openhands_agent_server-1.10.0.dist-info → openhands_agent_server-1.11.1.dist-info}/top_level.txt
RENAMED
|
File without changes
|