python-durable 0.2.0__tar.gz → 0.2.1__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.
- {python_durable-0.2.0 → python_durable-0.2.1}/PKG-INFO +1 -1
- {python_durable-0.2.0 → python_durable-0.2.1}/pyproject.toml +1 -1
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/pydantic_ai.py +16 -2
- {python_durable-0.2.0 → python_durable-0.2.1}/tests/test_pydantic_ai.py +16 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/.github/workflows/publish.yml +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/.gitignore +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/LICENSE +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/README.md +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/examples/approval.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/examples/examples.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/examples/in_memory_example.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/examples/pydantic_ai_example.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/examples/redis_example.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/__init__.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/backoff.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/context.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/redis_store.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/store.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/src/durable/workflow.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/tests/__init__.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/tests/test_durable.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/tests/test_redis_store.py +0 -0
- {python_durable-0.2.0 → python_durable-0.2.1}/tests/test_signals.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-durable
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Lightweight workflow durability for Python — make any async workflow resumable after crashes with just a decorator.
|
|
5
5
|
Project-URL: Repository, https://github.com/WillemDeGroef/python-durable
|
|
6
6
|
Author: Willem
|
|
@@ -69,6 +69,20 @@ def _deserialize_messages(data: list[dict]) -> list[Any]:
|
|
|
69
69
|
return result
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
def _serialize_run_result(result: Any) -> dict:
|
|
73
|
+
"""Convert an agent RunResult to a JSON-serializable dict."""
|
|
74
|
+
output = result.output
|
|
75
|
+
# If output is a pydantic model, convert to dict
|
|
76
|
+
if hasattr(output, "model_dump"):
|
|
77
|
+
output = output.model_dump(mode="json")
|
|
78
|
+
data: dict[str, Any] = {"output": output}
|
|
79
|
+
try:
|
|
80
|
+
data["all_messages"] = _serialize_messages(result.all_messages())
|
|
81
|
+
except Exception:
|
|
82
|
+
data["all_messages"] = []
|
|
83
|
+
return data
|
|
84
|
+
|
|
85
|
+
|
|
72
86
|
def _run_id_for_agent(agent_name: str, prompt: str, run_id: str | None) -> str:
|
|
73
87
|
"""Generate a deterministic run ID from the agent name and prompt."""
|
|
74
88
|
if run_id:
|
|
@@ -207,7 +221,7 @@ class DurableAgent(Generic[AgentDepsT, OutputT]):
|
|
|
207
221
|
step_id="agent-run",
|
|
208
222
|
**kwargs,
|
|
209
223
|
)
|
|
210
|
-
return result
|
|
224
|
+
return _AgentRunResult(result)
|
|
211
225
|
|
|
212
226
|
async def _do_model_request(
|
|
213
227
|
self,
|
|
@@ -225,7 +239,7 @@ class DurableAgent(Generic[AgentDepsT, OutputT]):
|
|
|
225
239
|
run_kwargs.update(kwargs)
|
|
226
240
|
|
|
227
241
|
result = await self.agent.run(prompt, **run_kwargs)
|
|
228
|
-
return
|
|
242
|
+
return _serialize_run_result(result)
|
|
229
243
|
|
|
230
244
|
async def _do_tool_call(
|
|
231
245
|
self,
|
|
@@ -326,3 +326,19 @@ class TestIntegration:
|
|
|
326
326
|
r2 = await durable.run("What is 6*7?", run_id="calc-1")
|
|
327
327
|
assert r2.output == "42"
|
|
328
328
|
assert agent.run.call_count == 1
|
|
329
|
+
|
|
330
|
+
async def test_durable_agent_with_sqlite_store(self, tmp_path):
|
|
331
|
+
"""Ensure agent results are JSON-serializable for SQLiteStore."""
|
|
332
|
+
db_path = str(tmp_path / "test.db")
|
|
333
|
+
wf = Workflow("test-sqlite", db=db_path)
|
|
334
|
+
|
|
335
|
+
agent, _ = _mock_agent(output="serialized ok")
|
|
336
|
+
durable = DurableAgent(agent, wf, name="sqlite-agent")
|
|
337
|
+
|
|
338
|
+
r1 = await durable.run("Test prompt", run_id="sqlite-1")
|
|
339
|
+
assert r1.output == "serialized ok"
|
|
340
|
+
assert agent.run.call_count == 1
|
|
341
|
+
|
|
342
|
+
r2 = await durable.run("Test prompt", run_id="sqlite-1")
|
|
343
|
+
assert r2.output == "serialized ok"
|
|
344
|
+
assert agent.run.call_count == 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|