openhands-sdk 1.5.0__py3-none-any.whl → 1.7.2__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.
Files changed (56) hide show
  1. openhands/sdk/__init__.py +9 -1
  2. openhands/sdk/agent/agent.py +35 -12
  3. openhands/sdk/agent/base.py +53 -7
  4. openhands/sdk/agent/prompts/model_specific/anthropic_claude.j2 +3 -0
  5. openhands/sdk/agent/prompts/model_specific/google_gemini.j2 +1 -0
  6. openhands/sdk/agent/prompts/model_specific/openai_gpt/gpt-5-codex.j2 +2 -0
  7. openhands/sdk/agent/prompts/model_specific/openai_gpt/gpt-5.j2 +3 -0
  8. openhands/sdk/agent/prompts/self_documentation.j2 +15 -0
  9. openhands/sdk/agent/prompts/system_prompt.j2 +29 -1
  10. openhands/sdk/agent/utils.py +18 -4
  11. openhands/sdk/context/__init__.py +2 -0
  12. openhands/sdk/context/agent_context.py +42 -10
  13. openhands/sdk/context/condenser/base.py +11 -6
  14. openhands/sdk/context/condenser/llm_summarizing_condenser.py +169 -20
  15. openhands/sdk/context/condenser/no_op_condenser.py +2 -1
  16. openhands/sdk/context/condenser/pipeline_condenser.py +10 -9
  17. openhands/sdk/context/condenser/utils.py +149 -0
  18. openhands/sdk/context/prompts/prompt.py +40 -2
  19. openhands/sdk/context/prompts/templates/system_message_suffix.j2 +3 -3
  20. openhands/sdk/context/skills/__init__.py +2 -0
  21. openhands/sdk/context/skills/skill.py +152 -1
  22. openhands/sdk/context/view.py +287 -27
  23. openhands/sdk/conversation/base.py +17 -0
  24. openhands/sdk/conversation/conversation.py +19 -0
  25. openhands/sdk/conversation/exceptions.py +29 -4
  26. openhands/sdk/conversation/impl/local_conversation.py +126 -9
  27. openhands/sdk/conversation/impl/remote_conversation.py +152 -3
  28. openhands/sdk/conversation/state.py +42 -1
  29. openhands/sdk/conversation/stuck_detector.py +81 -45
  30. openhands/sdk/conversation/types.py +30 -0
  31. openhands/sdk/event/llm_convertible/system.py +16 -20
  32. openhands/sdk/hooks/__init__.py +30 -0
  33. openhands/sdk/hooks/config.py +180 -0
  34. openhands/sdk/hooks/conversation_hooks.py +227 -0
  35. openhands/sdk/hooks/executor.py +155 -0
  36. openhands/sdk/hooks/manager.py +170 -0
  37. openhands/sdk/hooks/types.py +40 -0
  38. openhands/sdk/io/cache.py +85 -0
  39. openhands/sdk/io/local.py +39 -2
  40. openhands/sdk/llm/llm.py +3 -2
  41. openhands/sdk/llm/message.py +4 -3
  42. openhands/sdk/llm/mixins/fn_call_converter.py +61 -16
  43. openhands/sdk/llm/mixins/non_native_fc.py +5 -1
  44. openhands/sdk/llm/utils/model_features.py +64 -24
  45. openhands/sdk/llm/utils/model_prompt_spec.py +98 -0
  46. openhands/sdk/llm/utils/verified_models.py +6 -4
  47. openhands/sdk/logger/logger.py +1 -1
  48. openhands/sdk/tool/schema.py +10 -0
  49. openhands/sdk/tool/tool.py +2 -2
  50. openhands/sdk/utils/async_executor.py +76 -67
  51. openhands/sdk/utils/models.py +1 -1
  52. openhands/sdk/utils/paging.py +63 -0
  53. {openhands_sdk-1.5.0.dist-info → openhands_sdk-1.7.2.dist-info}/METADATA +3 -3
  54. {openhands_sdk-1.5.0.dist-info → openhands_sdk-1.7.2.dist-info}/RECORD +56 -41
  55. {openhands_sdk-1.5.0.dist-info → openhands_sdk-1.7.2.dist-info}/WHEEL +0 -0
  56. {openhands_sdk-1.5.0.dist-info → openhands_sdk-1.7.2.dist-info}/top_level.txt +0 -0
@@ -1,88 +1,72 @@
1
- """Reusable async-to-sync execution utility."""
2
-
3
- import asyncio
1
+ import atexit
4
2
  import inspect
5
3
  import threading
4
+ import weakref
6
5
  from collections.abc import Callable
7
6
  from typing import Any
8
7
 
8
+ import anyio
9
+ from anyio.from_thread import start_blocking_portal
10
+
11
+ from openhands.sdk.logger import get_logger
12
+
13
+
14
+ logger = get_logger(__name__)
15
+
9
16
 
10
17
  class AsyncExecutor:
11
18
  """
12
- Manages a background event loop for executing async code from sync contexts.
13
-
14
- This provides a robust async-to-sync bridge with proper resource management,
15
- timeout support, and thread safety.
19
+ Thin wrapper around AnyIO's BlockingPortal to execute async code
20
+ from synchronous contexts with proper resource and timeout handling.
16
21
  """
17
22
 
18
- _lock: threading.Lock
19
-
20
23
  def __init__(self):
21
- self._loop: asyncio.AbstractEventLoop | None = None
22
- self._thread: threading.Thread | None = None
24
+ self._portal = None
25
+ self._portal_cm = None
23
26
  self._lock = threading.Lock()
27
+ self._atexit_registered = False
24
28
 
25
- def _ensure_loop(self) -> asyncio.AbstractEventLoop:
26
- """Ensure the background event loop is running."""
29
+ def _ensure_portal(self):
27
30
  with self._lock:
28
- if self._loop is not None:
29
- return self._loop
30
-
31
- loop = asyncio.new_event_loop()
32
-
33
- def _runner():
34
- asyncio.set_event_loop(loop)
35
- loop.run_forever()
36
-
37
- t = threading.Thread(target=_runner, daemon=True, name="AsyncExecutor")
38
- t.start()
39
-
40
- # Wait for loop to start
41
- while not loop.is_running():
42
- pass
43
-
44
- self._loop = loop
45
- self._thread = t
46
- return loop
47
-
48
- def _shutdown_loop(self) -> None:
49
- """Shutdown the background event loop."""
50
- with self._lock:
51
- loop, t = self._loop, self._thread
52
- self._loop = None
53
- self._thread = None
54
-
55
- if loop and loop.is_running():
56
- try:
57
- loop.call_soon_threadsafe(loop.stop)
58
- except RuntimeError:
59
- pass
60
- if t and t.is_alive():
61
- t.join(timeout=1.0)
31
+ if self._portal is None:
32
+ self._portal_cm = start_blocking_portal()
33
+ self._portal = self._portal_cm.__enter__()
34
+ # Register atexit handler to ensure cleanup on interpreter shutdown
35
+ if not self._atexit_registered:
36
+ # Use weakref to avoid keeping the executor alive
37
+ weak_self = weakref.ref(self)
38
+
39
+ def cleanup():
40
+ executor = weak_self()
41
+ if executor is not None:
42
+ try:
43
+ executor.close()
44
+ except Exception:
45
+ pass
46
+
47
+ atexit.register(cleanup)
48
+ self._atexit_registered = True
49
+ return self._portal
62
50
 
63
51
  def run_async(
64
52
  self,
65
53
  awaitable_or_fn: Callable[..., Any] | Any,
66
54
  *args,
67
- timeout: float = 300.0,
55
+ timeout: float | None = None,
68
56
  **kwargs,
69
57
  ) -> Any:
70
58
  """
71
- Run a coroutine or async function on the background loop from sync code.
59
+ Run a coroutine or async function from sync code.
72
60
 
73
61
  Args:
74
- awaitable_or_fn: Coroutine or async function to execute
75
- *args: Arguments to pass to the function
76
- timeout: Timeout in seconds (default: 300)
77
- **kwargs: Keyword arguments to pass to the function
78
-
79
- Returns:
80
- The result of the async operation
81
-
82
- Raises:
83
- TypeError: If awaitable_or_fn is not a coroutine or async function
84
- asyncio.TimeoutError: If the operation times out
62
+ awaitable_or_fn: coroutine or async function
63
+ *args: positional arguments (only used if awaitable_or_fn is a function)
64
+ timeout: optional timeout in seconds
65
+ **kwargs: keyword arguments (only used if awaitable_or_fn is a function)
85
66
  """
67
+ portal = self._ensure_portal()
68
+
69
+ # Construct coroutine
86
70
  if inspect.iscoroutine(awaitable_or_fn):
87
71
  coro = awaitable_or_fn
88
72
  elif inspect.iscoroutinefunction(awaitable_or_fn):
@@ -90,17 +74,42 @@ class AsyncExecutor:
90
74
  else:
91
75
  raise TypeError("run_async expects a coroutine or async function")
92
76
 
93
- loop = self._ensure_loop()
94
- fut = asyncio.run_coroutine_threadsafe(coro, loop)
95
- return fut.result(timeout)
77
+ # Apply timeout by wrapping in an async function with fail_after
78
+ if timeout is not None:
79
+
80
+ async def _with_timeout():
81
+ with anyio.fail_after(timeout):
82
+ return await coro
83
+
84
+ return portal.call(_with_timeout)
85
+ else:
86
+
87
+ async def _execute():
88
+ return await coro
89
+
90
+ return portal.call(_execute)
96
91
 
97
92
  def close(self):
98
- """Close the async executor and cleanup resources."""
99
- self._shutdown_loop()
93
+ with self._lock:
94
+ portal_cm = self._portal_cm
95
+ self._portal_cm = None
96
+ self._portal = None
97
+
98
+ if portal_cm is not None:
99
+ try:
100
+ portal_cm.__exit__(None, None, None)
101
+ except Exception as e:
102
+ logger.warning(f"Error closing BlockingPortal: {e}")
103
+
104
+ def __enter__(self):
105
+ return self
106
+
107
+ def __exit__(self, exc_type, exc_val, exc_tb):
108
+ self.close()
109
+ return False
100
110
 
101
111
  def __del__(self):
102
- """Cleanup on deletion."""
103
112
  try:
104
113
  self.close()
105
114
  except Exception:
106
- pass # Ignore cleanup errors during deletion
115
+ pass
@@ -146,7 +146,7 @@ class OpenHandsModel(BaseModel):
146
146
  # duplicate fields are produced by model_dump_json which does not appear
147
147
  # in model_dump
148
148
  kwargs["mode"] = "json"
149
- return json.dumps(self.model_dump(**kwargs))
149
+ return json.dumps(self.model_dump(**kwargs), ensure_ascii=False)
150
150
 
151
151
  def __init_subclass__(cls, **kwargs):
152
152
  """
@@ -0,0 +1,63 @@
1
+ """Pagination utilities for iterating over paginated search results."""
2
+
3
+ from collections.abc import AsyncGenerator, Awaitable, Callable
4
+ from typing import Any, Protocol
5
+
6
+
7
+ class PageProtocol[T](Protocol):
8
+ """Protocol for page objects returned by search functions.
9
+
10
+ All page objects should have:
11
+ - items: A list of items of type T
12
+ - next_page_id: Optional string for pagination
13
+ """
14
+
15
+ items: list[T]
16
+ next_page_id: str | None
17
+
18
+
19
+ async def page_iterator[T](
20
+ search_func: Callable[..., Awaitable[PageProtocol[T]]],
21
+ *args: Any,
22
+ **kwargs: Any,
23
+ ) -> AsyncGenerator[T, None]:
24
+ """
25
+ Iterate over items from paginated search results.
26
+
27
+ This utility function handles pagination automatically by calling the search
28
+ function repeatedly with updated page_id parameters until all pages are
29
+ exhausted.
30
+
31
+ Args:
32
+ search_func: An async function that returns a PageProtocol[T] object
33
+ with 'items' and 'next_page_id' attributes
34
+ *args: Positional arguments to pass to the search function
35
+ **kwargs: Keyword arguments to pass to the search function
36
+
37
+ Yields:
38
+ Individual items of type T from each page
39
+
40
+ Example:
41
+ async for event in page_iterator(event_service.search_events, limit=50):
42
+ await send_event(event, websocket)
43
+
44
+ async for conversation in page_iterator(
45
+ conversation_service.search_conversations,
46
+ execution_status=ConversationExecutionStatus.RUNNING
47
+ ):
48
+ print(conversation.title)
49
+ """
50
+ page_id = kwargs.pop("page_id", None)
51
+
52
+ while True:
53
+ # Call the search function with current page_id
54
+ page = await search_func(*args, page_id=page_id, **kwargs)
55
+
56
+ # Yield each item from the current page
57
+ for item in page.items:
58
+ yield item
59
+
60
+ # Check if there are more pages
61
+ page_id = page.next_page_id
62
+ if not page_id:
63
+ break
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openhands-sdk
3
- Version: 1.5.0
3
+ Version: 1.7.2
4
4
  Summary: OpenHands SDK - Core functionality for building AI agents
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: deprecation>=2.1.0
7
7
  Requires-Dist: fastmcp>=2.11.3
8
8
  Requires-Dist: httpx>=0.27.0
9
- Requires-Dist: litellm>=1.80.7
9
+ Requires-Dist: litellm>=1.80.10
10
10
  Requires-Dist: pydantic>=2.11.7
11
11
  Requires-Dist: python-frontmatter>=1.1.0
12
12
  Requires-Dist: python-json-logger>=3.3.0
13
13
  Requires-Dist: tenacity>=9.1.2
14
14
  Requires-Dist: websockets>=12
15
- Requires-Dist: lmnr>=0.7.20
15
+ Requires-Dist: lmnr>=0.7.24
16
16
  Provides-Extra: boto3
17
17
  Requires-Dist: boto3>=1.35.0; extra == "boto3"
@@ -1,56 +1,62 @@
1
- openhands/sdk/__init__.py,sha256=SsB5acHhWvF6e3FlbR72PzZHH9ByJiXc7vnwxBPqmhw,2374
1
+ openhands/sdk/__init__.py,sha256=QCJNFOXO4WsOlr3DELNxwMuIKPt_-81VZXjfbXhDw5I,2535
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=OCR7JJytiiTHLuFwU3XjMtJx11Y2Io-DamdbMa2mf60,23760
5
- openhands/sdk/agent/base.py,sha256=HmZ_wNXdbsStqxjgkylGFm9B0pkp-0MCjmFTyh_XenM,15780
6
- openhands/sdk/agent/utils.py,sha256=alYsAQ611XQ_94ogJacYD22BLbgSJjzd3Xex_b9KuC4,7418
4
+ openhands/sdk/agent/agent.py,sha256=jTpAcBehUvH6cjat9hT7BBQm3BtWscB8gcOKOzLgJI8,24749
5
+ openhands/sdk/agent/base.py,sha256=YY7j4FBrtt7krz7PH4N7brWF46HN0dsbuwhyaIsaMr4,17953
6
+ openhands/sdk/agent/utils.py,sha256=TpANm_Vj4Ku-36T_SD1-u9Y9l86t1RcPU7QVaUh3qU0,8157
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
9
9
  openhands/sdk/agent/prompts/security_policy.j2,sha256=K56d2aaZ88DI-y2DsMSDaiZRTTnkkzuBLjbzXfKHGA8,993
10
10
  openhands/sdk/agent/prompts/security_risk_assessment.j2,sha256=7o1tk6MIQpVD7sAES-sBhw4ckYLGQydzYnjjNitP5iY,1196
11
- openhands/sdk/agent/prompts/system_prompt.j2,sha256=-emgmh86xJCU8W5Vbsp1zRORWaT0EGegKL13WVYJyBM,8136
11
+ openhands/sdk/agent/prompts/self_documentation.j2,sha256=Q0nLryVYnGg8Qk056-3tW2WJ2rwBijC5iqJByEdGAT0,1063
12
+ openhands/sdk/agent/prompts/system_prompt.j2,sha256=4sIK8BvwBZI9D_WN3O2TQEDBGa_c1Tlgmj6XMuW2_dA,9071
12
13
  openhands/sdk/agent/prompts/system_prompt_interactive.j2,sha256=AW3rGuqu82BqbS1XMXVO4Fp-Apa8DPYZV3_nQYkzVtM,1388
13
14
  openhands/sdk/agent/prompts/system_prompt_long_horizon.j2,sha256=_oOHRIer_FSuRrBOSOPpe5Ueo9KgSTba5SPoHHpghCI,2995
14
15
  openhands/sdk/agent/prompts/system_prompt_planning.j2,sha256=wh01KX7yzeUSn5PtG3Ij0keRM6vmQuZZM6I0Fod4DK4,2934
15
16
  openhands/sdk/agent/prompts/system_prompt_tech_philosophy.j2,sha256=Yq9H7hHen2-tNsfBq9RlAWpyWsVRpjHhzmziZv8JHs8,5005
16
- openhands/sdk/context/__init__.py,sha256=dsOiCbO-eizN7HiGn_ZSSgH-EE841ygwalMzWz9GbVY,557
17
- openhands/sdk/context/agent_context.py,sha256=CFJRTk0QHcHLB5nL9pKaXiKpVU2UwFNZdYf9p8TArs4,9318
18
- openhands/sdk/context/view.py,sha256=j8R4r1PSKFUJR_G4qDyI8ToqyHbWtU0YRKDBm8LJm4I,9260
17
+ openhands/sdk/agent/prompts/model_specific/anthropic_claude.j2,sha256=Cf4vXqlwoh94hOsLqcuIeMailgkrbGLF9vv0wHt4eEM,379
18
+ openhands/sdk/agent/prompts/model_specific/google_gemini.j2,sha256=DvGy_9yuqeyKJ8GDF_qVpQz4ri-rSCRl1awqPE1ImSs,219
19
+ openhands/sdk/agent/prompts/model_specific/openai_gpt/gpt-5-codex.j2,sha256=5iJvfBq3okP0yBVmQe9unB4gZx22_C3Yp_GyWtfColU,312
20
+ openhands/sdk/agent/prompts/model_specific/openai_gpt/gpt-5.j2,sha256=iMnSKjg2nrFoRUCkNMlGLoMmNWv_9bzK7D82dkJZCbQ,466
21
+ openhands/sdk/context/__init__.py,sha256=r2YtpZMVFIIaKYVh2yjicTXYPURGhIUUdbliaLYbnnA,609
22
+ openhands/sdk/context/agent_context.py,sha256=BlnGNpzQ3urWTmxDV_E5I-m8ZmRlolFgTint0T96QSU,10662
23
+ openhands/sdk/context/view.py,sha256=kHhEqyLfUEcXGfG9vOSPRImQGzqkDvtjsgL5BwmcGsU,20487
19
24
  openhands/sdk/context/condenser/__init__.py,sha256=o3O5wEOUak7mzJ3EzY4s6pjUwA_Q5EzLvgNSFM46d50,490
20
- openhands/sdk/context/condenser/base.py,sha256=fp1WxZGslE1luwmzFmablZ9Q3h_F7ErBJfCAh6HKpRI,3659
21
- openhands/sdk/context/condenser/llm_summarizing_condenser.py,sha256=Qjmaa_3cwDYDKXbMW1xRddkNHFaHDq2hFNbEKyvxEl8,3449
22
- openhands/sdk/context/condenser/no_op_condenser.py,sha256=s1tOAe71OyXpN6aOROGVnyW7FLplbbpBUo22hOtm3fg,394
23
- openhands/sdk/context/condenser/pipeline_condenser.py,sha256=rBHrPtffc_AWiH12yEfuYHCS2sExK0LP-xIb_ji9PO0,1939
25
+ openhands/sdk/context/condenser/base.py,sha256=lA1OAwSVIXU1GCfvD5_NE5U6hNCYJGuE3G5BaqIPnFM,4007
26
+ openhands/sdk/context/condenser/llm_summarizing_condenser.py,sha256=sh1ZHM50s3-suuDm0XrQbiQ8M-OG1MjlBUygWBq1Nk0,9121
27
+ openhands/sdk/context/condenser/no_op_condenser.py,sha256=T87bTtJw4dqlOIZZZ4R_JFPXeSymDqlbsZtH6ng7N1E,474
28
+ openhands/sdk/context/condenser/pipeline_condenser.py,sha256=wkbEA6R8u8u3Wi1AQmx1AKF9hQ25dLSeKuvB56N1Ohc,2145
29
+ openhands/sdk/context/condenser/utils.py,sha256=kI4oechGeozHRTFPcq6UVbGgLL-6msR3D2-4fPssFVU,5599
24
30
  openhands/sdk/context/condenser/prompts/summarizing_prompt.j2,sha256=J7uwQAsrrZdliYRJt9wKg9pYlXaa9sNze4ipMRkeqnQ,2157
25
31
  openhands/sdk/context/prompts/__init__.py,sha256=wC1Qiak4RHY3YS0TuZRmhFGAJ7Vc6CLwvQ4KQJB5o84,104
26
- openhands/sdk/context/prompts/prompt.py,sha256=a2eCR4QSYzgdDxcGkGVktKerAOk-SCb8odTABQHilJE,2684
32
+ openhands/sdk/context/prompts/prompt.py,sha256=8ZV9C0lg9Lnw7lF5zLnLTF9nL6gTnW5vGIw1YxtRQBU,3724
27
33
  openhands/sdk/context/prompts/templates/ask_agent_template.j2,sha256=VRKWdF2VTJ_Tyway_Wexp8_KlNgAkME94eZelbbsEZI,212
28
34
  openhands/sdk/context/prompts/templates/skill_knowledge_info.j2,sha256=3yNxEEbScAU1w60ix7Ph91wr6p8mjwT-3EGkkZkWT9Q,261
29
- openhands/sdk/context/prompts/templates/system_message_suffix.j2,sha256=YZYYX6XgclDa6GPmJAUjN2UxKlmqCp1gaL61IQzMtDY,2100
30
- openhands/sdk/context/skills/__init__.py,sha256=5YmyufIWoLvoUYtcZE_xI4sOtcCs70-CHrblnzavWWY,593
35
+ openhands/sdk/context/prompts/templates/system_message_suffix.j2,sha256=_UYK1BZrZaO5BQKO99b_nbs_cyEhO9RdZcGaBqYwmc0,2180
36
+ openhands/sdk/context/skills/__init__.py,sha256=yGLI8A3JHIvipjdZ7ClcbU5Q-vqWQHsZWxNQeoSTW8g,645
31
37
  openhands/sdk/context/skills/exceptions.py,sha256=tVBSbXTXG32nb1TebVAuzbNNHvn8GScpSM1bHCnQzvY,305
32
- openhands/sdk/context/skills/skill.py,sha256=iJpJWiXLHhxd7tmdPo1HcIDqa4emAYkQHgN7KvkQcl0,20407
38
+ openhands/sdk/context/skills/skill.py,sha256=MjPRYEiGyXVgO1cfhM4UkVgfR9VmJv-Y1BDgN6sXS98,25976
33
39
  openhands/sdk/context/skills/trigger.py,sha256=ZGaDmMpJghnAEuTTYX6UepsA5nX1CSz83zK1Ox46vMk,756
34
40
  openhands/sdk/context/skills/types.py,sha256=qdakWgfs_88I_cnmVhO5bl3C3s11GvCydq7Q-V53kCI,1662
35
41
  openhands/sdk/conversation/__init__.py,sha256=1-xh49S2KJhtAjkHDaDHU28UWhfQLl3CeFlo179gr00,1402
36
- openhands/sdk/conversation/base.py,sha256=3qUc4_PjrT1IztBX7EJKuypvRVWRIbMmIQ3Fc2lvspI,8308
37
- openhands/sdk/conversation/conversation.py,sha256=bmgjOmPnznJFgEyOguzqUwwLamEEtmPf_YNSLnsUmWM,5253
42
+ openhands/sdk/conversation/base.py,sha256=sVpfqtyTVi7_d8rzI_gemZGHusVrNy9S_yNJmTGMEq8,8964
43
+ openhands/sdk/conversation/conversation.py,sha256=KN4mqYqrzc5LWksliDmRV-wNg1FdF0IVyaopOKeajas,6079
38
44
  openhands/sdk/conversation/conversation_stats.py,sha256=ZlQ99kgG5YVCrZ4rqJlq63JaiInxX8jqv-q5lS7RN68,3038
39
45
  openhands/sdk/conversation/event_store.py,sha256=he-bwP823s5zAIdua_0ZgkkHQCJoAqbtV2SN0hibX30,5207
40
46
  openhands/sdk/conversation/events_list_base.py,sha256=n_YvgbhBPOPDbw4Kp68J0EKFM39vg95ng09GMfTz29s,505
41
- openhands/sdk/conversation/exceptions.py,sha256=C3pN3MJJIYdhcMHMqtOmVkR1BhVe3pfxBhxzQ6FVBjc,804
47
+ openhands/sdk/conversation/exceptions.py,sha256=9XkDVj2Q1PbB9GAIPLQ03M-r0r94ZRY1PmKZpSTDCY8,1757
42
48
  openhands/sdk/conversation/fifo_lock.py,sha256=nY5RsobNvVXBbAzwjqIxyQwPUh0AzffbTZw4PewhTTI,4240
43
49
  openhands/sdk/conversation/persistence_const.py,sha256=om3pOQa5sGK8t_NUYb3Tz-7sKeu531gaS1e7iCaqWmo,218
44
50
  openhands/sdk/conversation/response_utils.py,sha256=rPlC3cDSmoQte6NZ0kK6h6-9ho5cbF8jEw-DiyEhgIM,1548
45
51
  openhands/sdk/conversation/secret_registry.py,sha256=6fY1zRxb55rC4uIMFcR0lDssIyyjaPh9pCWGqDikrek,4446
46
52
  openhands/sdk/conversation/serialization_diff.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- openhands/sdk/conversation/state.py,sha256=EpP_0MAWv14gEIBvIlpdIxtxLCzN1n2mgzSzQNRpCY8,13046
48
- openhands/sdk/conversation/stuck_detector.py,sha256=PZF0HWC6G0SUud_U3hiv5r4AqfJJMw5-ookEWVOY5sY,10866
53
+ openhands/sdk/conversation/state.py,sha256=vq9t8mu9eTmFm77K0fPZvrhhGmj6eaTmSQD6xu_3d3U,14760
54
+ openhands/sdk/conversation/stuck_detector.py,sha256=4UNU7Bh9M2yrw3RavMzZeFGQ5RutqavkckW3exFPqQw,11673
49
55
  openhands/sdk/conversation/title_utils.py,sha256=j40-dP-Oes-mhU2xUC7fCC8cB0wkMdbbDJU7WLHiVIo,7063
50
- openhands/sdk/conversation/types.py,sha256=CMCCJz6fSfWgaAgWXeorEDC8VSXyyplyiMlpcueszT8,423
56
+ openhands/sdk/conversation/types.py,sha256=q_yc3VNc8r3cdmvPXzpj7HvdLeDqv-37hCgOWMU65a4,1507
51
57
  openhands/sdk/conversation/impl/__init__.py,sha256=DmDFyNR4RU8eiMocKf2j9eBQomipP-rrJgU1LoVWTDA,220
52
- openhands/sdk/conversation/impl/local_conversation.py,sha256=R0iTc1oCaOBiBUH3Ei7RNO1JMS_7nEuBlCr3ILUosU0,22594
53
- openhands/sdk/conversation/impl/remote_conversation.py,sha256=9_yCDHO5KKODYHVzUt0mJnsSVcDE6Tv3TJvGULilcyE,28536
58
+ openhands/sdk/conversation/impl/local_conversation.py,sha256=YZUwl0-uRa0aR29qJWon7nt4Ul2M1V0R_1mtJUBSfyE,27599
59
+ openhands/sdk/conversation/impl/remote_conversation.py,sha256=WDa_BAhcTJ-gYeBiVwTarOuUogCdVEFlZIfcU2WPwhI,34432
54
60
  openhands/sdk/conversation/visualizer/__init__.py,sha256=0LXpKlt2eJcrqP1z6jQP_nLx23V8ErnQkKYSxvUp0_A,275
55
61
  openhands/sdk/conversation/visualizer/base.py,sha256=77DdRdHAPSESxRCYyRRSOK7ROBlljscxogkFFr4YgM0,2323
56
62
  openhands/sdk/conversation/visualizer/default.py,sha256=k-3-l1j8H_EOEn_pfzsUczcc4JDhQni7AUQZgZ2TpB4,11885
@@ -73,28 +79,35 @@ openhands/sdk/event/llm_convertible/__init__.py,sha256=04kTm2F3M8oGpkBbePb35R1jp
73
79
  openhands/sdk/event/llm_convertible/action.py,sha256=EY55De2QFtsHN9a5vDYmIY3jZGucjj6LuJj5BjIvXKo,5485
74
80
  openhands/sdk/event/llm_convertible/message.py,sha256=yeEI2zy3IuOu2fAyCkr8fhdn6qwiLcgR4MYAot4CGpw,5048
75
81
  openhands/sdk/event/llm_convertible/observation.py,sha256=LF09On5eI9Cadb_yK4bhh_-pvnf5onsr-MzayL0r0h0,5045
76
- openhands/sdk/event/llm_convertible/system.py,sha256=_jfRDKb-WK9pow3nDS0g7aev_FAx1VxLFpvFfxjyyHc,2592
82
+ openhands/sdk/event/llm_convertible/system.py,sha256=iGyizThTd8lxekgHK7E-4Z5xTF_Zb7_y7J9zAitL7lI,2332
77
83
  openhands/sdk/git/exceptions.py,sha256=T3_jdOzilK39y1_ilMQ3Z3RSkxHJZafUoZTzOiuGji0,991
78
84
  openhands/sdk/git/git_changes.py,sha256=RQwva8j5mq09WoTrmNcZMBHrGUzn0CPYilW6k1kJCD0,8339
79
85
  openhands/sdk/git/git_diff.py,sha256=osaSys05wp9i-_KqfcYEHhNFzzU0B2qCn9vChfRPL0g,3820
80
86
  openhands/sdk/git/models.py,sha256=himUK-g49iQHMBfJlVr4tTUOXQhudJUR-vcntTeFkPM,349
81
87
  openhands/sdk/git/utils.py,sha256=Ep0DEFGs3hon9cX166RxtJCLQqbA-JXcKo2kNGGHhoA,6338
88
+ openhands/sdk/hooks/__init__.py,sha256=J2ZO0Ajnw6IDbrDuA1BtXlzoGkSIZ3VcF0Haihgd8pE,854
89
+ openhands/sdk/hooks/config.py,sha256=QeUA2joRglX-fXazoSXpZLrKpQO9jwW7htNQ_D5WtFU,5964
90
+ openhands/sdk/hooks/conversation_hooks.py,sha256=j8Ok16kuHn-0EVP9IKOBfReirBZ8ZDlmI1G5lC_KZxA,8741
91
+ openhands/sdk/hooks/executor.py,sha256=K-nE92r_6dsNV_ISEhoqIyxGvYzD9wgwSyHFM456NX4,5016
92
+ openhands/sdk/hooks/manager.py,sha256=woce5tBGaygQvKL_p3K77Xq9K8QMwsbZYjEmDCGHoIY,5864
93
+ openhands/sdk/hooks/types.py,sha256=ZQp2_HVvOWI9YQPZInFJ0QdhpKo4UxGmq4YLYz9zfOY,1066
82
94
  openhands/sdk/io/__init__.py,sha256=6pXTWP03Wn5S7b6fOT0g3PYn-qSoEGGdrrwBqALYGA4,165
83
95
  openhands/sdk/io/base.py,sha256=kAcX0chfCswakiieJlKiHWoJgL3zOtaQauRqMPNYfW8,1355
84
- openhands/sdk/io/local.py,sha256=H1wjnBS0EkBJxEatWqNpteL1bPBHoetcnhrIeou4uEY,2991
96
+ openhands/sdk/io/cache.py,sha256=TZD9Px-WK303WGjm5nin9n3TCKGiAJ-PIqrM5MFeg5c,2908
97
+ openhands/sdk/io/local.py,sha256=IhU4OLP3-S8UCCWTm_xqw7XDYgeYms77b6I_FhZq0iU,4232
85
98
  openhands/sdk/io/memory.py,sha256=XIsdXsSyF-PzoYVmvJuO7Vtz-k3D5jMOFoZ5gHw8tbA,1712
86
99
  openhands/sdk/llm/__init__.py,sha256=k8UneyfoDUMe0lSP4GSlYzrL2Fe3MkDUKpSg2OIDi_I,1206
87
- openhands/sdk/llm/llm.py,sha256=Xd0NsCjn59bYVdgUih31JyBiEebKOJmPYMhYWdYLve0,44677
100
+ openhands/sdk/llm/llm.py,sha256=bvUoK9e0qH6yhT3JmB1TjeH-aYJWunVL4t9EoPMoJnY,44706
88
101
  openhands/sdk/llm/llm_registry.py,sha256=DL9yqSbAM7OBkzdIChLuxG2qk_oElW2tC2xem6mq0F8,3530
89
102
  openhands/sdk/llm/llm_response.py,sha256=DaBVBkij4Sz-RsYhRb3UUcvJCTzCBcOYQ9IhFwN4ukI,1988
90
- openhands/sdk/llm/message.py,sha256=zVcmHL4z99Bm0_qHz0hhtDh8a9r8Y1GtcfCgL5yBsME,25429
103
+ openhands/sdk/llm/message.py,sha256=Tw7sIw5A-rZqIH8dPI0UnoXf0KuPB8tURcJMQyv9JZg,25507
91
104
  openhands/sdk/llm/streaming.py,sha256=tFJ7B0AjJ-e8Xv13DTtc2FdrsLRUCG8wxQex8fDlOp4,214
92
105
  openhands/sdk/llm/exceptions/__init__.py,sha256=6iMJah2nS6BboU06HqgAM2JT6aykCWY8muoUwaaJpR8,1144
93
106
  openhands/sdk/llm/exceptions/classifier.py,sha256=pu5fVNubUrB3eXV1i5W7m4-D4Ik2Z-fGe1ba2t0SSc4,1456
94
107
  openhands/sdk/llm/exceptions/mapping.py,sha256=D68duh85HPONw5P0Mv4e8Ji-ubi6qWEb2d9FkOKf8cA,1656
95
108
  openhands/sdk/llm/exceptions/types.py,sha256=IfyRtfH5eJrsLOlp6Fz76CiCKjx1ukmXciIcLBjworU,2781
96
- openhands/sdk/llm/mixins/fn_call_converter.py,sha256=G5u0cNGLBscog7Vt0c7Xjo5uLsvyleBlk12Mq0wTQTM,46310
97
- openhands/sdk/llm/mixins/non_native_fc.py,sha256=ymPELReJtFsBJCweEpfx2njyd6NCG9mj9AoDPPLFAqc,3250
109
+ openhands/sdk/llm/mixins/fn_call_converter.py,sha256=xlYywDHYMhVQyd_CiTuoY1JHaqpEIEjsZknCJN_hFFE,48528
110
+ openhands/sdk/llm/mixins/non_native_fc.py,sha256=KL2-rCh9uNz5WDskP7rc2uv1xOzZWgvffWqPaGbYvtw,3408
98
111
  openhands/sdk/llm/options/__init__.py,sha256=EntvOWC5kwDoTMXXMkYuoWMQ13hD8YtC9CEMCtnKj7o,54
99
112
  openhands/sdk/llm/options/chat_options.py,sha256=YrQrMKUj9Sb0ZdzJMoB11PwD7hzdLBDGrOMWfgZQ10s,3452
100
113
  openhands/sdk/llm/options/common.py,sha256=qFcPuZF_c4rmH1bgGG8Qp6TJ4YWpv9IFzfLZRRiik9M,580
@@ -104,14 +117,15 @@ openhands/sdk/llm/router/base.py,sha256=9mUUpv-zgT6HVKmJ87Q5e5VncoKi8hHd9aP8j9cJ
104
117
  openhands/sdk/llm/router/impl/multimodal.py,sha256=uKFVm7b3Jr0xCC1lvP-cVn-fIkTv24-pK3xKlOJahz4,3034
105
118
  openhands/sdk/llm/router/impl/random.py,sha256=oBHoFTBMa9OeDyg-rV4siLCkN6rKYL0uDlZMEseB3ro,656
106
119
  openhands/sdk/llm/utils/metrics.py,sha256=4zD0Hkc9Oc4qcDcVZUX13RyggyObshUbz4Ik9W1uIw4,11592
107
- openhands/sdk/llm/utils/model_features.py,sha256=JMGShnYBplGL6O6f19YC2EqI3dIviNN_58TFbflBnlA,4607
120
+ openhands/sdk/llm/utils/model_features.py,sha256=eBy6w61oBD9yG-4VtRTgZyvOQ4ubOOkJZv5UIQ3Hu4Q,6134
108
121
  openhands/sdk/llm/utils/model_info.py,sha256=1mFYA7OcEyUB6k1doao8_w1XT7UMM_DAm57HcTpKkLw,2628
122
+ openhands/sdk/llm/utils/model_prompt_spec.py,sha256=onw9-y7x0aJS8IOjNzeqhdvcFNwK1l_s0XgurWlnj5o,2587
109
123
  openhands/sdk/llm/utils/retry_mixin.py,sha256=M-hXp8EwP1FjNN6tgHiv133BtUQgRr9Kz_ZWxeAJLGA,4765
110
124
  openhands/sdk/llm/utils/telemetry.py,sha256=_csSRWg80djE27QN9Mg3palVTP-LJ7BbttOaHQYykZU,13970
111
125
  openhands/sdk/llm/utils/unverified_models.py,sha256=SmYrX_WxXOJBanTviztqy1xPjOcLY4i3qvwNBEga_Dk,4797
112
- openhands/sdk/llm/utils/verified_models.py,sha256=2DpRJJY8CJrsV4y6ZWrwrzllqniBQ6avNEtqNDsHr3A,1432
126
+ openhands/sdk/llm/utils/verified_models.py,sha256=4rUtUdRaVx0ZR6V1WsaWAMlgO7SkDdG4yoVgXHj689U,1462
113
127
  openhands/sdk/logger/__init__.py,sha256=vZvFDYfW01Y8Act3tveMs3XxTysJlt4HeT-n6X_ujYk,330
114
- openhands/sdk/logger/logger.py,sha256=kSpeol92dKesm24ZxVyYbtAxeYccmuFZJw3qNO9X-t4,6513
128
+ openhands/sdk/logger/logger.py,sha256=en8SHzFC2baohQmqbgE8t0mvV_xMZQrILEycOzdAZL0,6511
115
129
  openhands/sdk/logger/rolling.py,sha256=E6oy0asgmOhZHoWlSCw0QK1PKnS6kvtxjoWLAsqlGvs,3440
116
130
  openhands/sdk/mcp/__init__.py,sha256=-wQbZ405PjVRCBtSfirp4jsiRohd7IJAyAdicZ-M8Ok,588
117
131
  openhands/sdk/mcp/client.py,sha256=CLkFImydorlT_RBTE5UxvRNGMlc-uO3wvupoDzB5E20,2420
@@ -131,21 +145,22 @@ openhands/sdk/security/llm_analyzer.py,sha256=wb7VNJjzlKkimh1mR2wpn6LSqBdo3GZJqh
131
145
  openhands/sdk/security/risk.py,sha256=4I1zPCQa-PLlez7so8IYqY8bSvqHrxu-hzbix7GrxIE,3497
132
146
  openhands/sdk/tool/__init__.py,sha256=Fpcy_I5CYC8lDf2KNLj7LJg9YpoDObbacMFOvM9fI5g,692
133
147
  openhands/sdk/tool/registry.py,sha256=x5j8DwOjH3YJijhXe_3nRPsSr1A2sDPpNhxCuvFrHK0,5456
134
- openhands/sdk/tool/schema.py,sha256=PdQbkzPER-Z9B-eKPMr16M8ap27gghszq1xSHH5DGZQ,9114
148
+ openhands/sdk/tool/schema.py,sha256=w8J3UQtdE3vgh_8jRVXLzGYPOhmPn9n-YHBAnxt79Y0,9500
135
149
  openhands/sdk/tool/spec.py,sha256=EbtWasVhwjLKNJywHubbwfYqfgXnZbU4QE6XUOLhsdk,1221
136
- openhands/sdk/tool/tool.py,sha256=tcAno2EEXF-Ta8icgSbX_0mQDuuBDmQ5CugnEINHqwk,17798
150
+ openhands/sdk/tool/tool.py,sha256=UrsUiBmywGXtCKlGCxSF650wSx9kX76RpaTs6U3Jb5w,17796
137
151
  openhands/sdk/tool/builtins/__init__.py,sha256=30MfENomH9JBPwKs03Xwgny09dDUOt3FSIQ3egRJKhM,729
138
152
  openhands/sdk/tool/builtins/finish.py,sha256=pPv_bKDOQE4sUK9lNh1H1lDaxavHozjOwLCIuYrb424,3136
139
153
  openhands/sdk/tool/builtins/think.py,sha256=Jp8CBHJZwrtNuVCLrxKlVwb9HeQ1lZB56PCYMxW3wWk,4050
140
154
  openhands/sdk/utils/__init__.py,sha256=81qUukQiVDos57kbtZfFGZ3i0zX-t1eSI0J8UZN4fP4,448
141
- openhands/sdk/utils/async_executor.py,sha256=3DshvClrloM904NpsVxxAIlAPTU5kpb2ydufuM6SrtM,3168
155
+ openhands/sdk/utils/async_executor.py,sha256=1MjdhO9zgcwZSmPDJrqaha4XCGnnON9duxlOU3Kl6CI,3408
142
156
  openhands/sdk/utils/async_utils.py,sha256=LN_kg1YwHwDfZlwiVkNQPiYMcJVoiuATkDy3nOQlT64,1187
143
157
  openhands/sdk/utils/cipher.py,sha256=YgumKR7mVdXuyoy0MAhcOXwRu7VUF3xFnTKNQPDQMjo,2363
144
158
  openhands/sdk/utils/command.py,sha256=iqTdFL9tPQ0gyq5w_HOMXSSHg1nowtrWwJBeDL87lZs,2480
145
159
  openhands/sdk/utils/deprecation.py,sha256=7XwepMKTwBLaqS-4rdJupKxNZkepV0Mrru3uTQukS0k,5114
146
160
  openhands/sdk/utils/github.py,sha256=l-_LQKw820dA_U8NmDdmaReAPhgMAWqfH1oRMi1q5OA,1638
147
161
  openhands/sdk/utils/json.py,sha256=hHAA7i7NCJrQhb5WWSsoT0nvmJUi0koyBdbviFrfdcM,1384
148
- openhands/sdk/utils/models.py,sha256=tOTGa4O1vHZgHvOp2mNv5V4hM3fBSM6Sswv-0oYVyJQ,20676
162
+ openhands/sdk/utils/models.py,sha256=kQn1-pLBv44tMBAdMSicV7hb5AKpmMQp7NTim1N_Au4,20696
163
+ openhands/sdk/utils/paging.py,sha256=pgSQTe8_pArNjW8jwIyB3XKK04cf4knRHZbgrJrCm8Y,1962
149
164
  openhands/sdk/utils/pydantic_diff.py,sha256=vOy4M1XKKDkCzp7RXBvnibvPYWL8fNEDtWNUn_-N1yg,2732
150
165
  openhands/sdk/utils/pydantic_secrets.py,sha256=B9njRdijnqO4g-GDCWRsWd-TZc5GTjMncDEPMFP_aUE,2186
151
166
  openhands/sdk/utils/truncate.py,sha256=LYRA45CBR7daSC03gs80nu7PYdROh943_niOpaoquKU,4390
@@ -159,7 +174,7 @@ openhands/sdk/workspace/remote/__init__.py,sha256=eKkj6NOESMUBGDVC6_L2Wfuc4K6G-m
159
174
  openhands/sdk/workspace/remote/async_remote_workspace.py,sha256=ftv1Vdx4mmM3AjygJpemMJGvhaQel7ORxdQVk12z4ZE,5061
160
175
  openhands/sdk/workspace/remote/base.py,sha256=72C9MZV7ch5n6oHNvFMo6irW7b6Le8n4gk3yFuc0798,5605
161
176
  openhands/sdk/workspace/remote/remote_workspace_mixin.py,sha256=CzHfnLUIra5sgPkP9kcggb1vHGOPpYQzLsHvGO2rRt0,10963
162
- openhands_sdk-1.5.0.dist-info/METADATA,sha256=IVPCCDK7mDlhvBwwHXT2lp53I9IcyIcInnOZlcaxIYg,545
163
- openhands_sdk-1.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
164
- openhands_sdk-1.5.0.dist-info/top_level.txt,sha256=jHgVu9I0Blam8BXFgedoGKfglPF8XvW1TsJFIjcgP4E,10
165
- openhands_sdk-1.5.0.dist-info/RECORD,,
177
+ openhands_sdk-1.7.2.dist-info/METADATA,sha256=GeeFJNWEfr8EivjstoimTNGD6TTfQhKAGTfKz1SFXbo,546
178
+ openhands_sdk-1.7.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
179
+ openhands_sdk-1.7.2.dist-info/top_level.txt,sha256=jHgVu9I0Blam8BXFgedoGKfglPF8XvW1TsJFIjcgP4E,10
180
+ openhands_sdk-1.7.2.dist-info/RECORD,,