openhands-sdk 1.9.0__py3-none-any.whl → 1.10.0__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/sdk/agent/agent.py +54 -13
- openhands/sdk/agent/base.py +32 -45
- openhands/sdk/context/condenser/llm_summarizing_condenser.py +0 -23
- openhands/sdk/context/condenser/prompts/summarizing_prompt.j2 +1 -5
- openhands/sdk/context/view.py +108 -122
- openhands/sdk/conversation/__init__.py +2 -0
- openhands/sdk/conversation/conversation.py +13 -3
- openhands/sdk/conversation/exceptions.py +18 -0
- openhands/sdk/conversation/impl/local_conversation.py +192 -23
- openhands/sdk/conversation/impl/remote_conversation.py +141 -12
- openhands/sdk/critic/impl/api/critic.py +10 -7
- openhands/sdk/event/condenser.py +52 -2
- openhands/sdk/git/cached_repo.py +19 -0
- openhands/sdk/hooks/__init__.py +2 -0
- openhands/sdk/hooks/config.py +44 -4
- openhands/sdk/hooks/executor.py +2 -1
- openhands/sdk/llm/llm.py +47 -13
- openhands/sdk/llm/message.py +65 -27
- openhands/sdk/llm/options/chat_options.py +2 -1
- openhands/sdk/mcp/client.py +53 -6
- openhands/sdk/mcp/tool.py +24 -21
- openhands/sdk/mcp/utils.py +31 -23
- openhands/sdk/plugin/__init__.py +12 -1
- openhands/sdk/plugin/fetch.py +118 -14
- openhands/sdk/plugin/loader.py +111 -0
- openhands/sdk/plugin/plugin.py +155 -13
- openhands/sdk/plugin/types.py +163 -1
- openhands/sdk/utils/__init__.py +2 -0
- openhands/sdk/utils/async_utils.py +36 -1
- openhands/sdk/utils/command.py +28 -1
- {openhands_sdk-1.9.0.dist-info → openhands_sdk-1.10.0.dist-info}/METADATA +1 -1
- {openhands_sdk-1.9.0.dist-info → openhands_sdk-1.10.0.dist-info}/RECORD +34 -33
- {openhands_sdk-1.9.0.dist-info → openhands_sdk-1.10.0.dist-info}/WHEEL +1 -1
- {openhands_sdk-1.9.0.dist-info → openhands_sdk-1.10.0.dist-info}/top_level.txt +0 -0
openhands/sdk/plugin/types.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
import re
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
10
10
|
import frontmatter
|
|
11
11
|
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
@@ -15,6 +15,117 @@ from pydantic import BaseModel, Field, field_validator, model_validator
|
|
|
15
15
|
MARKETPLACE_MANIFEST_DIRS = [".plugin", ".claude-plugin"]
|
|
16
16
|
MARKETPLACE_MANIFEST_FILE = "marketplace.json"
|
|
17
17
|
|
|
18
|
+
|
|
19
|
+
class PluginSource(BaseModel):
|
|
20
|
+
"""Specification for a plugin to load.
|
|
21
|
+
|
|
22
|
+
This model describes where to find a plugin and is used by load_plugins()
|
|
23
|
+
to fetch and load plugins from various sources.
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
>>> # GitHub repository
|
|
27
|
+
>>> PluginSource(source="github:owner/repo", ref="v1.0.0")
|
|
28
|
+
|
|
29
|
+
>>> # Plugin from monorepo subdirectory
|
|
30
|
+
>>> PluginSource(
|
|
31
|
+
... source="github:owner/monorepo",
|
|
32
|
+
... repo_path="plugins/my-plugin"
|
|
33
|
+
... )
|
|
34
|
+
|
|
35
|
+
>>> # Local path
|
|
36
|
+
>>> PluginSource(source="/path/to/plugin")
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
source: str = Field(
|
|
40
|
+
description="Plugin source: 'github:owner/repo', any git URL, or local path"
|
|
41
|
+
)
|
|
42
|
+
ref: str | None = Field(
|
|
43
|
+
default=None,
|
|
44
|
+
description="Optional branch, tag, or commit (only for git sources)",
|
|
45
|
+
)
|
|
46
|
+
repo_path: str | None = Field(
|
|
47
|
+
default=None,
|
|
48
|
+
description=(
|
|
49
|
+
"Subdirectory path within the git repository "
|
|
50
|
+
"(e.g., 'plugins/my-plugin' for monorepos). "
|
|
51
|
+
"Only relevant for git sources, not local paths."
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@field_validator("repo_path")
|
|
56
|
+
@classmethod
|
|
57
|
+
def validate_repo_path(cls, v: str | None) -> str | None:
|
|
58
|
+
"""Validate repo_path is a safe relative path within the repository."""
|
|
59
|
+
if v is None:
|
|
60
|
+
return v
|
|
61
|
+
# Must be relative (no absolute paths)
|
|
62
|
+
if v.startswith("/"):
|
|
63
|
+
raise ValueError("repo_path must be relative, not absolute")
|
|
64
|
+
# No parent directory traversal
|
|
65
|
+
if ".." in Path(v).parts:
|
|
66
|
+
raise ValueError(
|
|
67
|
+
"repo_path cannot contain '..' (parent directory traversal)"
|
|
68
|
+
)
|
|
69
|
+
return v
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ResolvedPluginSource(BaseModel):
|
|
73
|
+
"""A plugin source with resolved ref (pinned to commit SHA).
|
|
74
|
+
|
|
75
|
+
Used for persistence to ensure deterministic behavior across pause/resume.
|
|
76
|
+
When a conversation is resumed, the resolved ref ensures we get exactly
|
|
77
|
+
the same plugin version that was used when the conversation started.
|
|
78
|
+
|
|
79
|
+
The resolved_ref is the actual commit SHA that was fetched, even if the
|
|
80
|
+
original ref was a branch name like 'main'. This prevents drift when
|
|
81
|
+
branches are updated between pause and resume.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
source: str = Field(
|
|
85
|
+
description="Plugin source: 'github:owner/repo', any git URL, or local path"
|
|
86
|
+
)
|
|
87
|
+
resolved_ref: str | None = Field(
|
|
88
|
+
default=None,
|
|
89
|
+
description=(
|
|
90
|
+
"Resolved commit SHA (for git sources). None for local paths. "
|
|
91
|
+
"This is the actual commit that was checked out, even if the "
|
|
92
|
+
"original ref was a branch name."
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
repo_path: str | None = Field(
|
|
96
|
+
default=None,
|
|
97
|
+
description="Subdirectory path within the git repository",
|
|
98
|
+
)
|
|
99
|
+
original_ref: str | None = Field(
|
|
100
|
+
default=None,
|
|
101
|
+
description="Original ref from PluginSource (for debugging/display)",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def from_plugin_source(
|
|
106
|
+
cls, plugin_source: PluginSource, resolved_ref: str | None
|
|
107
|
+
) -> ResolvedPluginSource:
|
|
108
|
+
"""Create a ResolvedPluginSource from a PluginSource and resolved ref."""
|
|
109
|
+
return cls(
|
|
110
|
+
source=plugin_source.source,
|
|
111
|
+
resolved_ref=resolved_ref,
|
|
112
|
+
repo_path=plugin_source.repo_path,
|
|
113
|
+
original_ref=plugin_source.ref,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def to_plugin_source(self) -> PluginSource:
|
|
117
|
+
"""Convert back to PluginSource using the resolved ref.
|
|
118
|
+
|
|
119
|
+
When loading from persistence, use the resolved_ref to ensure we get
|
|
120
|
+
the exact same version that was originally fetched.
|
|
121
|
+
"""
|
|
122
|
+
return PluginSource(
|
|
123
|
+
source=self.source,
|
|
124
|
+
ref=self.resolved_ref, # Use resolved SHA, not original ref
|
|
125
|
+
repo_path=self.repo_path,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
18
129
|
# Type aliases for marketplace plugin entry configurations
|
|
19
130
|
# These provide better documentation than dict[str, Any] while remaining flexible
|
|
20
131
|
|
|
@@ -35,6 +146,10 @@ type LspServersDict = dict[str, dict[str, Any]]
|
|
|
35
146
|
type HooksConfigDict = dict[str, Any]
|
|
36
147
|
|
|
37
148
|
|
|
149
|
+
if TYPE_CHECKING:
|
|
150
|
+
from openhands.sdk.context.skills import Skill
|
|
151
|
+
|
|
152
|
+
|
|
38
153
|
class PluginAuthor(BaseModel):
|
|
39
154
|
"""Author information for a plugin."""
|
|
40
155
|
|
|
@@ -250,6 +365,53 @@ class CommandDefinition(BaseModel):
|
|
|
250
365
|
metadata=metadata,
|
|
251
366
|
)
|
|
252
367
|
|
|
368
|
+
def to_skill(self, plugin_name: str) -> Skill:
|
|
369
|
+
"""Convert this command to a keyword-triggered Skill.
|
|
370
|
+
|
|
371
|
+
Creates a Skill with a KeywordTrigger using the Claude Code namespacing
|
|
372
|
+
format: /<plugin-name>:<command-name>
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
plugin_name: The name of the plugin this command belongs to.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
A Skill object with the command content and a KeywordTrigger.
|
|
379
|
+
|
|
380
|
+
Example:
|
|
381
|
+
For a plugin "city-weather" with command "now":
|
|
382
|
+
- Trigger keyword: "/city-weather:now"
|
|
383
|
+
- When user types "/city-weather:now Tokyo", the skill activates
|
|
384
|
+
"""
|
|
385
|
+
from openhands.sdk.context.skills import Skill
|
|
386
|
+
from openhands.sdk.context.skills.trigger import KeywordTrigger
|
|
387
|
+
|
|
388
|
+
# Build the trigger keyword in Claude Code namespace format
|
|
389
|
+
trigger_keyword = f"/{plugin_name}:{self.name}"
|
|
390
|
+
|
|
391
|
+
# Build skill content with $ARGUMENTS placeholder context
|
|
392
|
+
content_parts = []
|
|
393
|
+
if self.description:
|
|
394
|
+
content_parts.append(f"## {self.name}\n\n{self.description}\n")
|
|
395
|
+
|
|
396
|
+
if self.argument_hint:
|
|
397
|
+
content_parts.append(
|
|
398
|
+
f"**Arguments**: `$ARGUMENTS` - {self.argument_hint}\n"
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
if self.content:
|
|
402
|
+
content_parts.append(f"\n{self.content}")
|
|
403
|
+
|
|
404
|
+
skill_content = "\n".join(content_parts).strip()
|
|
405
|
+
|
|
406
|
+
return Skill(
|
|
407
|
+
name=f"{plugin_name}:{self.name}",
|
|
408
|
+
content=skill_content,
|
|
409
|
+
description=self.description or f"Command {self.name} from {plugin_name}",
|
|
410
|
+
trigger=KeywordTrigger(keywords=[trigger_keyword]),
|
|
411
|
+
source=self.source,
|
|
412
|
+
allowed_tools=self.allowed_tools if self.allowed_tools else None,
|
|
413
|
+
)
|
|
414
|
+
|
|
253
415
|
|
|
254
416
|
class MarketplaceOwner(BaseModel):
|
|
255
417
|
"""Owner information for a marketplace.
|
openhands/sdk/utils/__init__.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Utility functions for the OpenHands SDK."""
|
|
2
2
|
|
|
3
|
+
from .command import sanitized_env
|
|
3
4
|
from .deprecation import (
|
|
4
5
|
deprecated,
|
|
5
6
|
warn_deprecated,
|
|
@@ -19,4 +20,5 @@ __all__ = [
|
|
|
19
20
|
"deprecated",
|
|
20
21
|
"warn_deprecated",
|
|
21
22
|
"sanitize_openhands_mentions",
|
|
23
|
+
"sanitized_env",
|
|
22
24
|
]
|
|
@@ -5,7 +5,9 @@ of synchronous conversation handling.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import asyncio
|
|
8
|
+
import threading
|
|
8
9
|
from collections.abc import Callable, Coroutine
|
|
10
|
+
from concurrent.futures import Future
|
|
9
11
|
from typing import Any
|
|
10
12
|
|
|
11
13
|
from openhands.sdk.event.base import Event
|
|
@@ -21,10 +23,14 @@ class AsyncCallbackWrapper:
|
|
|
21
23
|
but internally executes an async callback in an event loop running in a
|
|
22
24
|
different thread. This allows async callbacks to be used in synchronous
|
|
23
25
|
conversation contexts.
|
|
26
|
+
|
|
27
|
+
Tracks pending futures to allow waiting for all callbacks to complete.
|
|
24
28
|
"""
|
|
25
29
|
|
|
26
30
|
async_callback: AsyncConversationCallback
|
|
27
31
|
loop: asyncio.AbstractEventLoop
|
|
32
|
+
_pending_futures: list[Future]
|
|
33
|
+
_lock: threading.Lock
|
|
28
34
|
|
|
29
35
|
def __init__(
|
|
30
36
|
self,
|
|
@@ -33,7 +39,36 @@ class AsyncCallbackWrapper:
|
|
|
33
39
|
):
|
|
34
40
|
self.async_callback = async_callback
|
|
35
41
|
self.loop = loop
|
|
42
|
+
self._pending_futures = []
|
|
43
|
+
self._lock = threading.Lock()
|
|
36
44
|
|
|
37
45
|
def __call__(self, event: Event):
|
|
38
46
|
if self.loop.is_running():
|
|
39
|
-
asyncio.run_coroutine_threadsafe(
|
|
47
|
+
future = asyncio.run_coroutine_threadsafe(
|
|
48
|
+
self.async_callback(event), self.loop
|
|
49
|
+
)
|
|
50
|
+
with self._lock:
|
|
51
|
+
# Clean up completed futures to avoid unbounded memory growth
|
|
52
|
+
self._pending_futures = [
|
|
53
|
+
f for f in self._pending_futures if not f.done()
|
|
54
|
+
]
|
|
55
|
+
self._pending_futures.append(future)
|
|
56
|
+
|
|
57
|
+
def wait_for_pending(self, timeout: float | None = None) -> None:
|
|
58
|
+
"""Wait for all pending callbacks to complete.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
timeout: Maximum time to wait in seconds. None means wait indefinitely.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
TimeoutError: If timeout is exceeded while waiting.
|
|
65
|
+
"""
|
|
66
|
+
with self._lock:
|
|
67
|
+
futures = list(self._pending_futures)
|
|
68
|
+
|
|
69
|
+
for future in futures:
|
|
70
|
+
try:
|
|
71
|
+
future.result(timeout=timeout)
|
|
72
|
+
except Exception:
|
|
73
|
+
# Exceptions in callbacks are already logged, ignore here
|
|
74
|
+
pass
|
openhands/sdk/utils/command.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import shlex
|
|
2
3
|
import subprocess
|
|
3
4
|
import sys
|
|
4
5
|
import threading
|
|
6
|
+
from collections.abc import Mapping
|
|
5
7
|
|
|
6
8
|
from openhands.sdk.logger import get_logger
|
|
7
9
|
|
|
@@ -9,6 +11,31 @@ from openhands.sdk.logger import get_logger
|
|
|
9
11
|
logger = get_logger(__name__)
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
def sanitized_env(
|
|
15
|
+
env: Mapping[str, str] | None = None,
|
|
16
|
+
) -> dict[str, str]:
|
|
17
|
+
"""Return a copy of *env* with sanitized values.
|
|
18
|
+
|
|
19
|
+
PyInstaller-based binaries rewrite ``LD_LIBRARY_PATH`` so their vendored
|
|
20
|
+
libraries win. This function restores the original value so that subprocess
|
|
21
|
+
will not use them.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
base_env: dict[str, str]
|
|
25
|
+
if env is None:
|
|
26
|
+
base_env = dict(os.environ)
|
|
27
|
+
else:
|
|
28
|
+
base_env = dict(env)
|
|
29
|
+
|
|
30
|
+
if "LD_LIBRARY_PATH_ORIG" in base_env:
|
|
31
|
+
origin = base_env["LD_LIBRARY_PATH_ORIG"]
|
|
32
|
+
if origin:
|
|
33
|
+
base_env["LD_LIBRARY_PATH"] = origin
|
|
34
|
+
else:
|
|
35
|
+
base_env.pop("LD_LIBRARY_PATH", None)
|
|
36
|
+
return base_env
|
|
37
|
+
|
|
38
|
+
|
|
12
39
|
def execute_command(
|
|
13
40
|
cmd: list[str] | str,
|
|
14
41
|
env: dict[str, str] | None = None,
|
|
@@ -29,7 +56,7 @@ def execute_command(
|
|
|
29
56
|
proc = subprocess.Popen(
|
|
30
57
|
cmd_to_run,
|
|
31
58
|
cwd=cwd,
|
|
32
|
-
env=env,
|
|
59
|
+
env=sanitized_env(env),
|
|
33
60
|
stdout=subprocess.PIPE,
|
|
34
61
|
stderr=subprocess.PIPE,
|
|
35
62
|
text=True,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openhands-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.0
|
|
4
4
|
Summary: OpenHands SDK - Core functionality for building AI agents
|
|
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,8 +1,8 @@
|
|
|
1
1
|
openhands/sdk/__init__.py,sha256=FNRcPyCbvwYGrbSCxox_UWIHK5JuyCLHCyPLPZRd5sA,2589
|
|
2
2
|
openhands/sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
openhands/sdk/agent/__init__.py,sha256=yOn1ZCgTTq2VJlTzKDSzmWVPli1siBzqV89vlEHCwOg,137
|
|
4
|
-
openhands/sdk/agent/agent.py,sha256=
|
|
5
|
-
openhands/sdk/agent/base.py,sha256=
|
|
4
|
+
openhands/sdk/agent/agent.py,sha256=BVbXw3L7V8sUuxtlBOjEg0t7ESJLY1kp6W8C3Qossf8,31020
|
|
5
|
+
openhands/sdk/agent/base.py,sha256=yo1uCd7Iyp7-CidkIKn5E05LwbRrABW1CxNK_cT6DMM,19313
|
|
6
6
|
openhands/sdk/agent/utils.py,sha256=AY_7VBFaJ2iorfh0MiS-mXaK6f8ONDejNcbkde_xTGg,8274
|
|
7
7
|
openhands/sdk/agent/prompts/in_context_learning_example.j2,sha256=MGB0dPUlh6pwLoR_dBK-M3e5dtETX6C6WNjPcPixZmU,5512
|
|
8
8
|
openhands/sdk/agent/prompts/in_context_learning_example_suffix.j2,sha256=k3Zwnd7Iq7kL4lo307RDuu1mxWXn6pSLsEdvKEXN3BU,164
|
|
@@ -20,14 +20,14 @@ openhands/sdk/agent/prompts/model_specific/openai_gpt/gpt-5-codex.j2,sha256=5iJv
|
|
|
20
20
|
openhands/sdk/agent/prompts/model_specific/openai_gpt/gpt-5.j2,sha256=iMnSKjg2nrFoRUCkNMlGLoMmNWv_9bzK7D82dkJZCbQ,466
|
|
21
21
|
openhands/sdk/context/__init__.py,sha256=r2YtpZMVFIIaKYVh2yjicTXYPURGhIUUdbliaLYbnnA,609
|
|
22
22
|
openhands/sdk/context/agent_context.py,sha256=TUQB-RBmkKvnwMLKvG9eOc5TVlRnDtBOSeoXRA28JoA,12425
|
|
23
|
-
openhands/sdk/context/view.py,sha256=
|
|
23
|
+
openhands/sdk/context/view.py,sha256=xSgwWiA7Omcz7bpXm_7-ANRlO590PjDAQvMggvr-sK0,19757
|
|
24
24
|
openhands/sdk/context/condenser/__init__.py,sha256=peHKPk51AujZhXvR2H0j1vBUJsCc8D6-OMHZ4Vk-pxU,568
|
|
25
25
|
openhands/sdk/context/condenser/base.py,sha256=4_heKNni0BW3Lib3WMVRpzm8G03opW6VcHH9M_mV-j0,5869
|
|
26
|
-
openhands/sdk/context/condenser/llm_summarizing_condenser.py,sha256=
|
|
26
|
+
openhands/sdk/context/condenser/llm_summarizing_condenser.py,sha256=5GPeICwDKSa5QWZ2mDGWDJXnxNBvSmZGV1hu4j6Q6r8,9836
|
|
27
27
|
openhands/sdk/context/condenser/no_op_condenser.py,sha256=T87bTtJw4dqlOIZZZ4R_JFPXeSymDqlbsZtH6ng7N1E,474
|
|
28
28
|
openhands/sdk/context/condenser/pipeline_condenser.py,sha256=wkbEA6R8u8u3Wi1AQmx1AKF9hQ25dLSeKuvB56N1Ohc,2145
|
|
29
29
|
openhands/sdk/context/condenser/utils.py,sha256=kI4oechGeozHRTFPcq6UVbGgLL-6msR3D2-4fPssFVU,5599
|
|
30
|
-
openhands/sdk/context/condenser/prompts/summarizing_prompt.j2,sha256=
|
|
30
|
+
openhands/sdk/context/condenser/prompts/summarizing_prompt.j2,sha256=iM_MRDY27i34qiZ0F6IsDxyePKpzxO3OEP5K1rA90_M,2081
|
|
31
31
|
openhands/sdk/context/prompts/__init__.py,sha256=wC1Qiak4RHY3YS0TuZRmhFGAJ7Vc6CLwvQ4KQJB5o84,104
|
|
32
32
|
openhands/sdk/context/prompts/prompt.py,sha256=8ZV9C0lg9Lnw7lF5zLnLTF9nL6gTnW5vGIw1YxtRQBU,3724
|
|
33
33
|
openhands/sdk/context/prompts/templates/ask_agent_template.j2,sha256=VRKWdF2VTJ_Tyway_Wexp8_KlNgAkME94eZelbbsEZI,212
|
|
@@ -39,13 +39,13 @@ openhands/sdk/context/skills/skill.py,sha256=s_krfMmqELS1YD24EZyU_vqUs-pmNUO1jZn
|
|
|
39
39
|
openhands/sdk/context/skills/trigger.py,sha256=ZGaDmMpJghnAEuTTYX6UepsA5nX1CSz83zK1Ox46vMk,756
|
|
40
40
|
openhands/sdk/context/skills/types.py,sha256=LvyCveHBSt2-g9Lbpr_eQMvOd4eEBjJb3irAWL-OzE0,1813
|
|
41
41
|
openhands/sdk/context/skills/utils.py,sha256=kpJjVz_BQGjFrgO8QpBwTAqHbAU8spD6crOLI_ollac,11870
|
|
42
|
-
openhands/sdk/conversation/__init__.py,sha256=
|
|
42
|
+
openhands/sdk/conversation/__init__.py,sha256=USxX0PTUI9ufA8CJ8iyDkIaKR5iFbDo3L9G5tBx3k94,1509
|
|
43
43
|
openhands/sdk/conversation/base.py,sha256=btRjqHk4FkAJjIAi34fgkNUml9R-0qfsDsJgomlN-kI,9143
|
|
44
|
-
openhands/sdk/conversation/conversation.py,sha256=
|
|
44
|
+
openhands/sdk/conversation/conversation.py,sha256=7wvXabfbb1iT1th8ntsjnduTdZSwM93yhdYz1wWKa4M,6449
|
|
45
45
|
openhands/sdk/conversation/conversation_stats.py,sha256=ZlQ99kgG5YVCrZ4rqJlq63JaiInxX8jqv-q5lS7RN68,3038
|
|
46
46
|
openhands/sdk/conversation/event_store.py,sha256=JZF6AibFezcIzEw4IQqKHG8T8s53SfD_LkZycsOH6xY,7992
|
|
47
47
|
openhands/sdk/conversation/events_list_base.py,sha256=n_YvgbhBPOPDbw4Kp68J0EKFM39vg95ng09GMfTz29s,505
|
|
48
|
-
openhands/sdk/conversation/exceptions.py,sha256=
|
|
48
|
+
openhands/sdk/conversation/exceptions.py,sha256=GHrPxo8QEVwA2OQUM0F5ksltLrSmap1C0alZXX6w048,2351
|
|
49
49
|
openhands/sdk/conversation/fifo_lock.py,sha256=nY5RsobNvVXBbAzwjqIxyQwPUh0AzffbTZw4PewhTTI,4240
|
|
50
50
|
openhands/sdk/conversation/persistence_const.py,sha256=om3pOQa5sGK8t_NUYb3Tz-7sKeu531gaS1e7iCaqWmo,218
|
|
51
51
|
openhands/sdk/conversation/response_utils.py,sha256=rPlC3cDSmoQte6NZ0kK6h6-9ho5cbF8jEw-DiyEhgIM,1548
|
|
@@ -56,8 +56,8 @@ openhands/sdk/conversation/stuck_detector.py,sha256=4UNU7Bh9M2yrw3RavMzZeFGQ5Rut
|
|
|
56
56
|
openhands/sdk/conversation/title_utils.py,sha256=j40-dP-Oes-mhU2xUC7fCC8cB0wkMdbbDJU7WLHiVIo,7063
|
|
57
57
|
openhands/sdk/conversation/types.py,sha256=q_yc3VNc8r3cdmvPXzpj7HvdLeDqv-37hCgOWMU65a4,1507
|
|
58
58
|
openhands/sdk/conversation/impl/__init__.py,sha256=DmDFyNR4RU8eiMocKf2j9eBQomipP-rrJgU1LoVWTDA,220
|
|
59
|
-
openhands/sdk/conversation/impl/local_conversation.py,sha256=
|
|
60
|
-
openhands/sdk/conversation/impl/remote_conversation.py,sha256=
|
|
59
|
+
openhands/sdk/conversation/impl/local_conversation.py,sha256=wqTmwB7TvNeB1wEosv93xcVH08h4TqGcht-xWSdTfsI,36930
|
|
60
|
+
openhands/sdk/conversation/impl/remote_conversation.py,sha256=E9JGKtELXWVRCVptgBnRD1M_1QaSc_m7QugvHQ8L5DY,43536
|
|
61
61
|
openhands/sdk/conversation/visualizer/__init__.py,sha256=0LXpKlt2eJcrqP1z6jQP_nLx23V8ErnQkKYSxvUp0_A,275
|
|
62
62
|
openhands/sdk/conversation/visualizer/base.py,sha256=oMg-JvQc34ebYdC3J9itHraoB2u3MdQ6E77AKiTmu30,3198
|
|
63
63
|
openhands/sdk/conversation/visualizer/default.py,sha256=k-3-l1j8H_EOEn_pfzsUczcc4JDhQni7AUQZgZ2TpB4,11885
|
|
@@ -71,11 +71,11 @@ openhands/sdk/critic/impl/pass_critic.py,sha256=kikTVZmve0DCTkQnhRutdUSff0OLbqH0
|
|
|
71
71
|
openhands/sdk/critic/impl/api/__init__.py,sha256=cgpLoVholRbE6YyCu4KUs0InG6LHcdBVAM1eq1ja8xQ,375
|
|
72
72
|
openhands/sdk/critic/impl/api/chat_template.py,sha256=qu5tJMi1Nuynp4FsV_MG_sAz4V6hpHactbxoGZGkAJE,7564
|
|
73
73
|
openhands/sdk/critic/impl/api/client.py,sha256=M43mM76EQY66ANfX2tIUeE_wvV6M5MdMYlbHDIqxQ34,10980
|
|
74
|
-
openhands/sdk/critic/impl/api/critic.py,sha256=
|
|
74
|
+
openhands/sdk/critic/impl/api/critic.py,sha256=F2fKcMUfjLsokRmjx6jck7oQTqJEws4lBL5a9W8JoN4,3437
|
|
75
75
|
openhands/sdk/critic/impl/api/taxonomy.py,sha256=dVM0t4x4H4a_vCkc4jl40agLR1PgQlW-V9NO6_wkhGo,6440
|
|
76
76
|
openhands/sdk/event/__init__.py,sha256=ir-jRVA0QjEbFuDzJOYRq2kXTgUHs8eJ7_skoCRNzr8,1141
|
|
77
77
|
openhands/sdk/event/base.py,sha256=QpQtYfYiZqaKWA-2xa4GEmk2qkUHKD6x-OIAk7SMnDs,5568
|
|
78
|
-
openhands/sdk/event/condenser.py,sha256=
|
|
78
|
+
openhands/sdk/event/condenser.py,sha256=5qDFFNutMry8KnLVh-Oq5b3TOoa3A-pnS9j7ZhacSR0,4681
|
|
79
79
|
openhands/sdk/event/conversation_error.py,sha256=73HDgrPDXba2_IMk3sMgk85_glkaKlZzEOk0afhm47Q,1392
|
|
80
80
|
openhands/sdk/event/conversation_state.py,sha256=V-ti5SLL5SL330sEOQgpy-U8tErVwZYG0iC3AqjTUwo,3650
|
|
81
81
|
openhands/sdk/event/llm_completion_log.py,sha256=VCxJiZBsn1F6TRV6fwvsPs6W9DpjghfIFmJJlGKztXg,1232
|
|
@@ -87,16 +87,16 @@ openhands/sdk/event/llm_convertible/action.py,sha256=WbLNQMS0DJFMRrDLOtqhBTjQ2T1
|
|
|
87
87
|
openhands/sdk/event/llm_convertible/message.py,sha256=I_chCsUuqBhc5INnNZUDsGa464TJYJBb7lLbOdHRFeM,5413
|
|
88
88
|
openhands/sdk/event/llm_convertible/observation.py,sha256=LF09On5eI9Cadb_yK4bhh_-pvnf5onsr-MzayL0r0h0,5045
|
|
89
89
|
openhands/sdk/event/llm_convertible/system.py,sha256=iGyizThTd8lxekgHK7E-4Z5xTF_Zb7_y7J9zAitL7lI,2332
|
|
90
|
-
openhands/sdk/git/cached_repo.py,sha256=
|
|
90
|
+
openhands/sdk/git/cached_repo.py,sha256=wI8hY6bfbzNR9dWhiiJu_T0I_hlFUuzam5T7D0HlJIU,16312
|
|
91
91
|
openhands/sdk/git/exceptions.py,sha256=T3_jdOzilK39y1_ilMQ3Z3RSkxHJZafUoZTzOiuGji0,991
|
|
92
92
|
openhands/sdk/git/git_changes.py,sha256=RQwva8j5mq09WoTrmNcZMBHrGUzn0CPYilW6k1kJCD0,8339
|
|
93
93
|
openhands/sdk/git/git_diff.py,sha256=osaSys05wp9i-_KqfcYEHhNFzzU0B2qCn9vChfRPL0g,3820
|
|
94
94
|
openhands/sdk/git/models.py,sha256=himUK-g49iQHMBfJlVr4tTUOXQhudJUR-vcntTeFkPM,349
|
|
95
95
|
openhands/sdk/git/utils.py,sha256=8wXm9UhqjuJEcjRUSkVK7V7XgxMnIMLgwh2ShbrpZfk,10691
|
|
96
|
-
openhands/sdk/hooks/__init__.py,sha256=
|
|
97
|
-
openhands/sdk/hooks/config.py,sha256=
|
|
96
|
+
openhands/sdk/hooks/__init__.py,sha256=eQ7nB7_5jKgm4OsbnR4-dSvyLo_uBBKrBKYofQy0fmQ,949
|
|
97
|
+
openhands/sdk/hooks/config.py,sha256=OwZ4DkAAvZwq6BxbbNnB4AmUfmkEyq3pkAUDQWvp5LI,10932
|
|
98
98
|
openhands/sdk/hooks/conversation_hooks.py,sha256=I62p4wrS2Jz3GatlNghUYY-57CnRrcxlvQawWFXU1-0,10629
|
|
99
|
-
openhands/sdk/hooks/executor.py,sha256=
|
|
99
|
+
openhands/sdk/hooks/executor.py,sha256=Ez7x-XTTtm5jT434OStLjHBUFEapqz_M-NY2hF0NAGc,5060
|
|
100
100
|
openhands/sdk/hooks/manager.py,sha256=woce5tBGaygQvKL_p3K77Xq9K8QMwsbZYjEmDCGHoIY,5864
|
|
101
101
|
openhands/sdk/hooks/types.py,sha256=ZQp2_HVvOWI9YQPZInFJ0QdhpKo4UxGmq4YLYz9zfOY,1066
|
|
102
102
|
openhands/sdk/io/__init__.py,sha256=6pXTWP03Wn5S7b6fOT0g3PYn-qSoEGGdrrwBqALYGA4,165
|
|
@@ -105,10 +105,10 @@ openhands/sdk/io/cache.py,sha256=TZD9Px-WK303WGjm5nin9n3TCKGiAJ-PIqrM5MFeg5c,290
|
|
|
105
105
|
openhands/sdk/io/local.py,sha256=5ZibVqYj7hV5gpgYr2SKq2aSsAL1m2JykhtmRyVKyf8,5189
|
|
106
106
|
openhands/sdk/io/memory.py,sha256=_GQ8WqilLJgdxtRccfVS653VDy1bo6CyZJDHGUQXEm8,2793
|
|
107
107
|
openhands/sdk/llm/__init__.py,sha256=k8UneyfoDUMe0lSP4GSlYzrL2Fe3MkDUKpSg2OIDi_I,1206
|
|
108
|
-
openhands/sdk/llm/llm.py,sha256=
|
|
108
|
+
openhands/sdk/llm/llm.py,sha256=V1zOje01vwlsVmtJIswvWWOP2firwM9sIZNxojqc_l0,45808
|
|
109
109
|
openhands/sdk/llm/llm_registry.py,sha256=DL9yqSbAM7OBkzdIChLuxG2qk_oElW2tC2xem6mq0F8,3530
|
|
110
110
|
openhands/sdk/llm/llm_response.py,sha256=DaBVBkij4Sz-RsYhRb3UUcvJCTzCBcOYQ9IhFwN4ukI,1988
|
|
111
|
-
openhands/sdk/llm/message.py,sha256=
|
|
111
|
+
openhands/sdk/llm/message.py,sha256=YK--c42j6Pb7wjUrPeIfiRRIt0w0pmJMHvGIZC3ugO4,27085
|
|
112
112
|
openhands/sdk/llm/streaming.py,sha256=tFJ7B0AjJ-e8Xv13DTtc2FdrsLRUCG8wxQex8fDlOp4,214
|
|
113
113
|
openhands/sdk/llm/exceptions/__init__.py,sha256=6iMJah2nS6BboU06HqgAM2JT6aykCWY8muoUwaaJpR8,1144
|
|
114
114
|
openhands/sdk/llm/exceptions/classifier.py,sha256=pu5fVNubUrB3eXV1i5W7m4-D4Ik2Z-fGe1ba2t0SSc4,1456
|
|
@@ -117,7 +117,7 @@ openhands/sdk/llm/exceptions/types.py,sha256=IfyRtfH5eJrsLOlp6Fz76CiCKjx1ukmXciI
|
|
|
117
117
|
openhands/sdk/llm/mixins/fn_call_converter.py,sha256=xlYywDHYMhVQyd_CiTuoY1JHaqpEIEjsZknCJN_hFFE,48528
|
|
118
118
|
openhands/sdk/llm/mixins/non_native_fc.py,sha256=KL2-rCh9uNz5WDskP7rc2uv1xOzZWgvffWqPaGbYvtw,3408
|
|
119
119
|
openhands/sdk/llm/options/__init__.py,sha256=EntvOWC5kwDoTMXXMkYuoWMQ13hD8YtC9CEMCtnKj7o,54
|
|
120
|
-
openhands/sdk/llm/options/chat_options.py,sha256=
|
|
120
|
+
openhands/sdk/llm/options/chat_options.py,sha256=9xB4I4DXBFirM0ZCrc8-KwW5eD07IAbYHglkJjTczuE,3784
|
|
121
121
|
openhands/sdk/llm/options/common.py,sha256=qFcPuZF_c4rmH1bgGG8Qp6TJ4YWpv9IFzfLZRRiik9M,580
|
|
122
122
|
openhands/sdk/llm/options/responses_options.py,sha256=1ff_06XcORneDQUjwrEM6tel9HLI9_veMcoKHYAKLG8,2302
|
|
123
123
|
openhands/sdk/llm/router/__init__.py,sha256=N8qldpGdLLCWZzn5Rz2y8AheSoCTQLGkLOBDCFNMJRA,261
|
|
@@ -136,18 +136,19 @@ openhands/sdk/logger/__init__.py,sha256=vZvFDYfW01Y8Act3tveMs3XxTysJlt4HeT-n6X_u
|
|
|
136
136
|
openhands/sdk/logger/logger.py,sha256=en8SHzFC2baohQmqbgE8t0mvV_xMZQrILEycOzdAZL0,6511
|
|
137
137
|
openhands/sdk/logger/rolling.py,sha256=E6oy0asgmOhZHoWlSCw0QK1PKnS6kvtxjoWLAsqlGvs,3440
|
|
138
138
|
openhands/sdk/mcp/__init__.py,sha256=-wQbZ405PjVRCBtSfirp4jsiRohd7IJAyAdicZ-M8Ok,588
|
|
139
|
-
openhands/sdk/mcp/client.py,sha256=
|
|
139
|
+
openhands/sdk/mcp/client.py,sha256=NTDTYTxedRDB0xkkMwT1_uN2ReV4SvLsURKNB8Ih0lg,3754
|
|
140
140
|
openhands/sdk/mcp/definition.py,sha256=vFLQeLW99fBzPGR7X7_1GzTmIHlSVAbmsg3elhhkp5U,3424
|
|
141
141
|
openhands/sdk/mcp/exceptions.py,sha256=N4g7Wju420TQJ7hmck1e5UblWbC_7Torb-UTFj1GN70,448
|
|
142
|
-
openhands/sdk/mcp/tool.py,sha256=
|
|
143
|
-
openhands/sdk/mcp/utils.py,sha256=
|
|
142
|
+
openhands/sdk/mcp/tool.py,sha256=c7Pzgm_n5iAT4TK4zAJsdiaLkvouzuHjdBK2N4R9N6M,10380
|
|
143
|
+
openhands/sdk/mcp/utils.py,sha256=Drm3D1SuNknwNa9yfqIVRzZhEXlqHj39LhLz0XbEF04,3081
|
|
144
144
|
openhands/sdk/observability/__init__.py,sha256=JKHDWoj01igaCUChdXgKmstESiMmbAK9CN5XzT2H7fo,122
|
|
145
145
|
openhands/sdk/observability/laminar.py,sha256=U2AbSWpPcUYdrzx__-BEg4LPW13f1l-Hk-V4qeBmE3k,5053
|
|
146
146
|
openhands/sdk/observability/utils.py,sha256=N0p8ACs2WKS1PyFPjiU-PPng6WsAe15ZpFViFAw1gO0,576
|
|
147
|
-
openhands/sdk/plugin/__init__.py,sha256=
|
|
148
|
-
openhands/sdk/plugin/fetch.py,sha256=
|
|
149
|
-
openhands/sdk/plugin/
|
|
150
|
-
openhands/sdk/plugin/
|
|
147
|
+
openhands/sdk/plugin/__init__.py,sha256=NFEu_uiWcJB1oyq7oz6nsVnbcApdyiNWdvZC7xs-l24,1252
|
|
148
|
+
openhands/sdk/plugin/fetch.py,sha256=bmuHYJl7LGPBJFLUk2-P_xoPfJPJM7oMfJiBURyb5nE,11263
|
|
149
|
+
openhands/sdk/plugin/loader.py,sha256=PcrCOn5WH_d5cf_qXEDopD2dLx7K0i3sErGuN_Xl35M,3767
|
|
150
|
+
openhands/sdk/plugin/plugin.py,sha256=_QrrLl6xjHxcF31jnsohjb6R3Sb6Q8IZwblSdzY8sPE,17851
|
|
151
|
+
openhands/sdk/plugin/types.py,sha256=hcpLaYz-sTJ7Dby1_BwTdm3Uq-UnIlHWHacjT0nXXyo,28581
|
|
151
152
|
openhands/sdk/secret/__init__.py,sha256=Y-M2WPfYLfVYZSFZGTf6MDOnjsL5SayETtA4t9X0gjw,348
|
|
152
153
|
openhands/sdk/secret/secrets.py,sha256=RFhyTBxwGgeYoojD56DtI_4CL43R8emo8WzvUH-8Z4w,3281
|
|
153
154
|
openhands/sdk/security/__init__.py,sha256=x2-a0fsImxSM2msHl7gV0fENWyZbpY7-HW_CBwNrPZY,89
|
|
@@ -163,11 +164,11 @@ openhands/sdk/tool/tool.py,sha256=9VV2aJtGeBmRn09oovRMtGafBC6UcAMWNSF1Uo2g6G0,19
|
|
|
163
164
|
openhands/sdk/tool/builtins/__init__.py,sha256=3F2NYhSkWOebKlNwRlwpoQD_rkxoT-pEx4AvAkMmJTs,911
|
|
164
165
|
openhands/sdk/tool/builtins/finish.py,sha256=pPv_bKDOQE4sUK9lNh1H1lDaxavHozjOwLCIuYrb424,3136
|
|
165
166
|
openhands/sdk/tool/builtins/think.py,sha256=Jp8CBHJZwrtNuVCLrxKlVwb9HeQ1lZB56PCYMxW3wWk,4050
|
|
166
|
-
openhands/sdk/utils/__init__.py,sha256=
|
|
167
|
+
openhands/sdk/utils/__init__.py,sha256=Y4lyjcci1-saGs7de-XbjFbKT93FYgrGp9HBNYPi7KI,504
|
|
167
168
|
openhands/sdk/utils/async_executor.py,sha256=1MjdhO9zgcwZSmPDJrqaha4XCGnnON9duxlOU3Kl6CI,3408
|
|
168
|
-
openhands/sdk/utils/async_utils.py,sha256=
|
|
169
|
+
openhands/sdk/utils/async_utils.py,sha256=0d_Z8hx0FaPcUkoJfYM2qoTk_cnaNnF6FmgKovvEjO8,2394
|
|
169
170
|
openhands/sdk/utils/cipher.py,sha256=YgumKR7mVdXuyoy0MAhcOXwRu7VUF3xFnTKNQPDQMjo,2363
|
|
170
|
-
openhands/sdk/utils/command.py,sha256=
|
|
171
|
+
openhands/sdk/utils/command.py,sha256=Z60BqN5PWo0-j88nwkTUdlF-vfidnqjKO0Jt73zJvXk,3238
|
|
171
172
|
openhands/sdk/utils/deprecation.py,sha256=7XwepMKTwBLaqS-4rdJupKxNZkepV0Mrru3uTQukS0k,5114
|
|
172
173
|
openhands/sdk/utils/github.py,sha256=l-_LQKw820dA_U8NmDdmaReAPhgMAWqfH1oRMi1q5OA,1638
|
|
173
174
|
openhands/sdk/utils/json.py,sha256=hHAA7i7NCJrQhb5WWSsoT0nvmJUi0koyBdbviFrfdcM,1384
|
|
@@ -186,7 +187,7 @@ openhands/sdk/workspace/remote/__init__.py,sha256=eKkj6NOESMUBGDVC6_L2Wfuc4K6G-m
|
|
|
186
187
|
openhands/sdk/workspace/remote/async_remote_workspace.py,sha256=MfnYoXvx_tZ7MKDGJCofnkYAJxfBKqNtM2Qprx3QQRk,5608
|
|
187
188
|
openhands/sdk/workspace/remote/base.py,sha256=t-qbouLxkAsPKvVblXWWHKixHsLFz4bw3l9LW_n9_6o,6152
|
|
188
189
|
openhands/sdk/workspace/remote/remote_workspace_mixin.py,sha256=CzHfnLUIra5sgPkP9kcggb1vHGOPpYQzLsHvGO2rRt0,10963
|
|
189
|
-
openhands_sdk-1.
|
|
190
|
-
openhands_sdk-1.
|
|
191
|
-
openhands_sdk-1.
|
|
192
|
-
openhands_sdk-1.
|
|
190
|
+
openhands_sdk-1.10.0.dist-info/METADATA,sha256=c60-7ef_Nqg959qhqZ9lCr8Dv2FMaD0xpICRop3QX-Q,859
|
|
191
|
+
openhands_sdk-1.10.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
192
|
+
openhands_sdk-1.10.0.dist-info/top_level.txt,sha256=jHgVu9I0Blam8BXFgedoGKfglPF8XvW1TsJFIjcgP4E,10
|
|
193
|
+
openhands_sdk-1.10.0.dist-info/RECORD,,
|
|
File without changes
|