harness-sdk-python 0.4.5__tar.gz → 0.6.0__tar.gz
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.
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/PKG-INFO +2 -2
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/README.md +1 -1
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/pyproject.toml +1 -1
- harness_sdk_python-0.6.0/src/harness_sdk/__init__.py +4 -0
- harness_sdk_python-0.6.0/src/harness_sdk/linear_thread.py +52 -0
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/src/harness_sdk/run_manager.py +187 -116
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/run_helpers.py +63 -9
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_batches.py +3 -3
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_branch_anchor.py +2 -2
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_edit_dispatched.py +5 -5
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_edit_reload.py +8 -8
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_enqueue.py +9 -9
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_facade.py +3 -3
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_input_required.py +57 -39
- harness_sdk_python-0.6.0/tests/test_linear_thread.py +122 -0
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_meta.py +18 -18
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_outcomes.py +8 -14
- harness_sdk_python-0.6.0/tests/test_prepare_hooks.py +167 -0
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_rewind_during_run.py +8 -8
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_run_leaf.py +54 -49
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_settle.py +9 -20
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_steer.py +6 -6
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_stop_continue.py +81 -12
- harness_sdk_python-0.4.5/src/harness_sdk/__init__.py +0 -3
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/.gitignore +0 -0
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/src/harness_sdk/fenced_postgres.py +0 -0
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_fenced_postgres.py +0 -0
- {harness_sdk_python-0.4.5 → harness_sdk_python-0.6.0}/tests/test_placement.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: harness-sdk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: RunManager: the harness-sdk runs subsystem for Python Statewire hosts
|
|
5
5
|
Project-URL: Repository, https://github.com/assistant-ui/harness-sdk
|
|
6
6
|
License-Expression: MIT
|
|
@@ -23,7 +23,7 @@ class MyHost(Statewire):
|
|
|
23
23
|
self.runs = RunManager(
|
|
24
24
|
state=self.state,
|
|
25
25
|
start=self._start,
|
|
26
|
-
|
|
26
|
+
thread=self._thread,
|
|
27
27
|
create_task=self.create_task,
|
|
28
28
|
capabilities=("rewind",),
|
|
29
29
|
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Callable
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True)
|
|
6
|
+
class LinearThread:
|
|
7
|
+
_messages: Callable[[], list[dict[str, Any]]]
|
|
8
|
+
_role: Callable[[dict[str, Any]], str]
|
|
9
|
+
|
|
10
|
+
async def get_message_meta(self, message_id: str | None) -> dict[str, Any] | None:
|
|
11
|
+
items = self._messages()
|
|
12
|
+
if message_id is None:
|
|
13
|
+
return {"isLeaf": not items}
|
|
14
|
+
for index, message in enumerate(items):
|
|
15
|
+
if message.get("id") == message_id:
|
|
16
|
+
return {
|
|
17
|
+
"parentId": items[index - 1].get("id") if index > 0 else None,
|
|
18
|
+
"role": self._role(message),
|
|
19
|
+
"isLeaf": index == len(items) - 1,
|
|
20
|
+
"onActiveBranch": True,
|
|
21
|
+
}
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
async def get_leaf_message_id(self) -> str | None:
|
|
25
|
+
items = self._messages()
|
|
26
|
+
return items[-1].get("id") if items else None
|
|
27
|
+
|
|
28
|
+
async def get_message_child_id(self, parent_id: str) -> str | None:
|
|
29
|
+
"""The id of the first non-tool message after parent_id; None when parent_id is unknown or only tools follow."""
|
|
30
|
+
items = self._messages()
|
|
31
|
+
index = next(
|
|
32
|
+
(i for i, m in enumerate(items) if m.get("id") == parent_id), None
|
|
33
|
+
)
|
|
34
|
+
if index is None:
|
|
35
|
+
return None
|
|
36
|
+
for message in items[index + 1 :]:
|
|
37
|
+
if message.get("type") != "tool":
|
|
38
|
+
return message.get("id")
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def linear_thread(
|
|
43
|
+
*,
|
|
44
|
+
messages: Callable[[], list[dict[str, Any]]],
|
|
45
|
+
role: Callable[[dict[str, Any]], str],
|
|
46
|
+
) -> LinearThread:
|
|
47
|
+
"""RunManager thread projection over a linear message list: ``messages`` returns the current list, ``role`` maps a message to its role."""
|
|
48
|
+
if not callable(messages):
|
|
49
|
+
raise TypeError("messages must be callable")
|
|
50
|
+
if not callable(role):
|
|
51
|
+
raise TypeError("role must be callable")
|
|
52
|
+
return LinearThread(messages, role)
|