pi-durable-python 1.3.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.
Files changed (90) hide show
  1. pi_durable/__init__.py +320 -0
  2. pi_durable/context.py +328 -0
  3. pi_durable/delta.py +269 -0
  4. pi_durable/documents.py +366 -0
  5. pi_durable/entries.py +66 -0
  6. pi_durable/env/__init__.py +408 -0
  7. pi_durable/env/decode.py +48 -0
  8. pi_durable/env/line_scan.py +190 -0
  9. pi_durable/env/posix.py +1547 -0
  10. pi_durable/errors.py +89 -0
  11. pi_durable/harness/__init__.py +1 -0
  12. pi_durable/harness/agent.py +344 -0
  13. pi_durable/harness/compaction.py +673 -0
  14. pi_durable/harness/context.py +515 -0
  15. pi_durable/harness/define.py +111 -0
  16. pi_durable/harness/events.py +766 -0
  17. pi_durable/harness/generation.py +1079 -0
  18. pi_durable/harness/harness.py +570 -0
  19. pi_durable/harness/inbox.py +255 -0
  20. pi_durable/harness/live.py +374 -0
  21. pi_durable/harness/output.py +467 -0
  22. pi_durable/harness/prompt.py +288 -0
  23. pi_durable/harness/provider.py +78 -0
  24. pi_durable/harness/registry.py +136 -0
  25. pi_durable/harness/scheduler.py +1977 -0
  26. pi_durable/harness/submissions.py +357 -0
  27. pi_durable/harness/task_graph.py +334 -0
  28. pi_durable/harness/tool.py +1365 -0
  29. pi_durable/harness/types.py +772 -0
  30. pi_durable/harness/usage.py +88 -0
  31. pi_durable/harness/util.py +204 -0
  32. pi_durable/harness/validation.py +460 -0
  33. pi_durable/harness/view.py +324 -0
  34. pi_durable/ids.py +63 -0
  35. pi_durable/json.py +186 -0
  36. pi_durable/providers/__init__.py +362 -0
  37. pi_durable/providers/anthropic.py +603 -0
  38. pi_durable/providers/base.py +97 -0
  39. pi_durable/providers/json_parse.py +117 -0
  40. pi_durable/providers/openai.py +574 -0
  41. pi_durable/providers/request.py +35 -0
  42. pi_durable/providers/retry.py +127 -0
  43. pi_durable/providers/stream.py +183 -0
  44. pi_durable/providers/transcript.py +224 -0
  45. pi_durable/providers/usage.py +58 -0
  46. pi_durable/py.typed +0 -0
  47. pi_durable/search.py +115 -0
  48. pi_durable/session/__init__.py +5 -0
  49. pi_durable/session/drafts.py +762 -0
  50. pi_durable/session/forks.py +109 -0
  51. pi_durable/session/observation.py +374 -0
  52. pi_durable/session/session.py +1193 -0
  53. pi_durable/session/transaction.py +1088 -0
  54. pi_durable/storage/__init__.py +5 -0
  55. pi_durable/storage/jsonl/__init__.py +15 -0
  56. pi_durable/storage/jsonl/storage.py +958 -0
  57. pi_durable/storage/memory.py +889 -0
  58. pi_durable/storage/scan.py +57 -0
  59. pi_durable/storage/sqlite/__init__.py +26 -0
  60. pi_durable/storage/sqlite/database.py +62 -0
  61. pi_durable/storage/sqlite/migrations.py +191 -0
  62. pi_durable/storage/sqlite/posix.py +314 -0
  63. pi_durable/storage/sqlite/schema.py +97 -0
  64. pi_durable/storage/sqlite/storage.py +1130 -0
  65. pi_durable/tasks.py +89 -0
  66. pi_durable/testing/__init__.py +41 -0
  67. pi_durable/testing/assertions.py +44 -0
  68. pi_durable/testing/env_conformance.py +828 -0
  69. pi_durable/testing/runner.py +64 -0
  70. pi_durable/testing/storage_conformance.py +2008 -0
  71. pi_durable/testing/types.py +99 -0
  72. pi_durable/tool_search/__init__.py +159 -0
  73. pi_durable/tools/__init__.py +81 -0
  74. pi_durable/tools/_values.py +43 -0
  75. pi_durable/tools/bash.py +250 -0
  76. pi_durable/tools/edit.py +214 -0
  77. pi_durable/tools/edit_diff.py +452 -0
  78. pi_durable/tools/env.py +19 -0
  79. pi_durable/tools/file_mutation_queue.py +68 -0
  80. pi_durable/tools/image.py +248 -0
  81. pi_durable/tools/image_processor.py +77 -0
  82. pi_durable/tools/path_utils.py +111 -0
  83. pi_durable/tools/read.py +506 -0
  84. pi_durable/tools/write.py +71 -0
  85. pi_durable/truncate.py +185 -0
  86. pi_durable/types.py +1297 -0
  87. pi_durable_python-1.3.0.dist-info/METADATA +276 -0
  88. pi_durable_python-1.3.0.dist-info/RECORD +90 -0
  89. pi_durable_python-1.3.0.dist-info/WHEEL +4 -0
  90. pi_durable_python-1.3.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.5
2
+ Name: pi-durable-python
3
+ Version: 1.3.0
4
+ Summary: Python port of @earendil-works/pi-durable v1.3.0
5
+ Project-URL: Repository, https://github.com/arpesenti/pi-durable-python
6
+ Project-URL: Upstream, https://github.com/earendil-works/pi/tree/main/packages/durable
7
+ Author: Armando Pesenti Gritti
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,conversations,durable-execution,pi,port,tasks
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: 3.15
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.11
22
+ Provides-Extra: all
23
+ Requires-Dist: anthropic>=0.46; extra == 'all'
24
+ Requires-Dist: jsonschema>=4.20; extra == 'all'
25
+ Requires-Dist: openai>=1.70; extra == 'all'
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.46; extra == 'anthropic'
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
31
+ Requires-Dist: pytest>=8; extra == 'dev'
32
+ Requires-Dist: ruff>=0.6; extra == 'dev'
33
+ Provides-Extra: openai
34
+ Requires-Dist: openai>=1.70; extra == 'openai'
35
+ Provides-Extra: schema
36
+ Requires-Dist: jsonschema>=4.20; extra == 'schema'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # pi-durable-python
40
+
41
+ A Python port of [`@earendil-works/pi-durable`](https://github.com/earendil-works/pi/tree/v1.3.0/packages/durable)
42
+ **v1.3.0**: durable conversations, tasks, and documents for agents, on `asyncio`.
43
+
44
+ The process can die at any point. A run, a tool round, a compaction, or an inbox placement only
45
+ happens after the state it depends on is committed, so a restart resumes from what storage holds
46
+ rather than from what memory held.
47
+
48
+ - **Durable by construction.** Every effect is sandwiched between committed state: tasks re-enter
49
+ their checkpoint, submissions survive a crash, documents version as they change.
50
+ - **Small core.** The base install has no runtime dependencies, and the memory, SQLite, and JSONL
51
+ storage backends all ship in it. Model adapters and JSON Schema validation are separate extras.
52
+ - **Composable.** A `Session` is the kernel; the `Harness` adds conversations, submissions,
53
+ scheduling, compaction, extensions, and hooks on top of it.
54
+ - **Parity, not resemblance.** This is a mechanical translation of the v1.3.0 source held to its
55
+ semantics and persisted record shapes. [`PARITY.md`](./PARITY.md) is the contract.
56
+
57
+ ## Requirements
58
+
59
+ - **Python.** CPython 3.11 or newer. The verified set is 3.11, 3.12, 3.13, 3.14, and 3.15 on Linux
60
+ and macOS, plus the 3.14t and 3.15t free-threaded builds; the classifiers list the plain CPython
61
+ versions 3.11 through 3.15.
62
+ - **Free-threaded parity.** The suite passes on builds with the GIL disabled, so the code does not
63
+ depend on it. Nothing claims thread safety: do not share one `Session` or `Storage` between
64
+ threads. Concurrent `asyncio` tasks are the supported concurrency.
65
+ - **Dependencies.** The core package has no runtime dependencies. The `openai` and `anthropic`
66
+ extras carry their SDKs, and `schema` carries `jsonschema`.
67
+
68
+ ## Install
69
+
70
+ ```console
71
+ pip install pi-durable-python
72
+ ```
73
+
74
+ Extras are independent; install only the ones you use:
75
+
76
+ | Extra | Adds | Install |
77
+ | --- | --- | --- |
78
+ | `openai` | OpenAI Chat Completions adapter (`AsyncOpenAI`) | `pip install "pi-durable-python[openai]"` |
79
+ | `anthropic` | Anthropic Messages adapter (`AsyncAnthropic`) | `pip install "pi-durable-python[anthropic]"` |
80
+ | `schema` | JSON Schema validation for structured output and tool arguments | `pip install "pi-durable-python[schema]"` |
81
+ | `all` | Everything in `openai`, `anthropic`, and `schema` | `pip install "pi-durable-python[all]"` |
82
+ | `dev` | pytest, pytest-asyncio, ruff, and mypy | `pip install "pi-durable-python[dev]"` |
83
+
84
+ From a checkout, `uv sync --extra dev` or
85
+ `python -m pip install -e ".[dev,openai,anthropic,schema]"` matches CI.
86
+
87
+ ## Quick start
88
+
89
+ ### A durable session and a document
90
+
91
+ A `Session` is the only writer: every change goes through `commit`, and readers see committed
92
+ state. Documents are typed JSON records, defined once and used as tokens.
93
+
94
+ <!-- example -->
95
+ ```python
96
+ import asyncio
97
+
98
+ from pi_durable import MemoryStorage, create_session, define_doc
99
+ from pi_durable.context import BACKGROUND_CONTEXT
100
+
101
+ # Define once: the kind, version, scope, and initial value migrate and materialize the document.
102
+ CounterDoc = define_doc(
103
+ {"kind": "demo.counter", "version": 1, "scope": "session", "initial": lambda: {"count": 0}}
104
+ )
105
+
106
+
107
+ async def main() -> None:
108
+ session = create_session(MemoryStorage())
109
+
110
+ async def bump(tx):
111
+ counter = await tx.doc(CounterDoc) # a draft, materialized only if the commit lands
112
+ counter.count += 1
113
+
114
+ await session.commit(bump, BACKGROUND_CONTEXT)
115
+
116
+ async def bump_again(tx):
117
+ (await tx.doc(CounterDoc)).count += 1
118
+
119
+ await session.commit(bump_again, BACKGROUND_CONTEXT)
120
+
121
+ snapshot = await session.snapshot(CounterDoc, BACKGROUND_CONTEXT)
122
+ print(snapshot) # {'count': 2}
123
+
124
+ await session.close(BACKGROUND_CONTEXT)
125
+
126
+
127
+ asyncio.run(main())
128
+ ```
129
+
130
+ Snapshots, document states, and watches are disposable reads: `snapshot()` copies the committed
131
+ value, `document_state()` subscribes to later commits, and `watch_doc()` delivers every committed
132
+ frame. `MemoryStorage` is the reference backend; SQLite and JSONL live in
133
+ `pi_durable.storage.sqlite` and `pi_durable.storage.jsonl`.
134
+
135
+ ### A conversation
136
+
137
+ The `Harness` adds conversations on top of a `Session`. A submission is the only entry point: it is
138
+ admitted to the inbox, placed as an entry, and settled once a run answers it. Passive writes (such
139
+ as seeding a transcript) need no model at all.
140
+
141
+ <!-- example -->
142
+ ```python
143
+ import asyncio
144
+
145
+ from pi_durable import Harness, MemoryStorage, UserEntry, create_registry
146
+ from pi_durable.context import BACKGROUND_CONTEXT
147
+
148
+
149
+ async def main() -> None:
150
+ harness = await Harness.open(
151
+ MemoryStorage(), {"models": {}, "registry": create_registry()}, BACKGROUND_CONTEXT
152
+ )
153
+ try:
154
+ conversation = await harness.root(BACKGROUND_CONTEXT)
155
+ await conversation.submit(
156
+ {
157
+ "type": "write",
158
+ "entry": {
159
+ "kind": UserEntry.kind,
160
+ "model": [{"role": "user", "content": "hello", "timestamp": 0}],
161
+ },
162
+ },
163
+ BACKGROUND_CONTEXT,
164
+ )
165
+
166
+ view = await conversation.context(BACKGROUND_CONTEXT)
167
+ print([message["role"] for message in view["messages"]]) # ['user']
168
+
169
+ state = await conversation.view_state(BACKGROUND_CONTEXT)
170
+ print([entry["kind"] for entry in state.value["entries"]]) # ['pi.user']
171
+ state.dispose()
172
+ finally:
173
+ await harness.close(BACKGROUND_CONTEXT)
174
+
175
+
176
+ asyncio.run(main())
177
+ ```
178
+
179
+ ### Answering with a model
180
+
181
+ The provider adapters implement the `Models` protocol, so the core never imports an SDK. A model
182
+ reference in an agent change uses the persisted camelCase spelling. Opening a `Harness` starts it
183
+ paused, and admitting a submission resumes scheduling, so a host can restore state before work
184
+ begins.
185
+
186
+ ```python
187
+ import asyncio
188
+
189
+ from pi_durable import Harness, MemoryStorage, Model, create_registry
190
+ from pi_durable.context import BACKGROUND_CONTEXT
191
+ from pi_durable.providers.openai import OpenAIModels
192
+
193
+
194
+ async def main() -> None:
195
+ model = Model(provider="openai", model_id="gpt-4.1", context_window=1_000_000, max_tokens=32_768)
196
+ models = OpenAIModels([model]) # reads OPENAI_API_KEY, or pass api_key=...
197
+ harness = await Harness.open(
198
+ MemoryStorage(), {"models": models, "registry": create_registry()}, BACKGROUND_CONTEXT
199
+ )
200
+ try:
201
+ conversation = await harness.root(
202
+ BACKGROUND_CONTEXT,
203
+ {"agent": {"model": {"provider": "openai", "modelId": "gpt-4.1"}}},
204
+ )
205
+ submission = await conversation.submit(
206
+ {"type": "input", "content": "Explain durable execution in one sentence."},
207
+ BACKGROUND_CONTEXT,
208
+ )
209
+ settled = await submission.wait(BACKGROUND_CONTEXT)
210
+ print(settled["status"]) # 'done' or 'unanswered'
211
+ finally:
212
+ await harness.close(BACKGROUND_CONTEXT)
213
+
214
+
215
+ asyncio.run(main())
216
+ ```
217
+
218
+ The answer is an entry, not a return value: `settled["answer"]` names the assistant entry, which the
219
+ conversation view and the entry scan both expose. This snippet needs credentials, so the test suite
220
+ does not run it; README examples that run offline carry an `<!-- example -->` marker and are
221
+ executed by `tests/test_release_docs.py`.
222
+
223
+ ## API at a glance
224
+
225
+ | Module | Holds |
226
+ | --- | --- |
227
+ | `pi_durable` | Root export: `Session`/`create_session`, `Harness`, entry tokens, document and task definitions, errors, provider protocol, `MemoryStorage`, and the built-in task types. |
228
+ | `pi_durable.env` | The `ExecutionEnv` contract, the POSIX backend, output truncation, and line scanning. |
229
+ | `pi_durable.harness` | Conversations, submissions and the inbox, the scheduler, agents and the registry, extensions and hooks, tools, generation, compaction, usage, the conversation view, the agent event stream, and the task graph. |
230
+ | `pi_durable.providers` | The `Model` catalog entry, the `Models` protocol, transcript and request helpers, retry and overflow classifiers, and the OpenAI/Anthropic adapters (`pi_durable.providers.openai`, `pi_durable.providers.anthropic`). |
231
+ | `pi_durable.session` | The Session kernel, the transaction API, document drafts, forks, and observation. |
232
+ | `pi_durable.storage` | The reference memory backend (`pi_durable.storage.memory`), SQLite (`pi_durable.storage.sqlite`), and JSONL (`pi_durable.storage.jsonl`). |
233
+ | `pi_durable.testing` | Storage and environment conformance suites, plus assertions for writing your own backend. |
234
+ | `pi_durable.tool_search` | BM25 deferred-tool discovery for large tool sets. |
235
+ | `pi_durable.tools` | The built-in coding tools: `read`, `write`, `edit`, and `bash`. |
236
+
237
+ The [usage guide](./docs/usage.md) walks through documents, tasks, the Harness, providers, storage
238
+ backends, and extensions with runnable examples. The normative details are in the
239
+ [vendored 1.3.0 specification](./docs/upstream/spec-1.3.0.md); the parity matrix is
240
+ [`PARITY.md`](./PARITY.md), and the [audit report](./docs/parity-report.md) lists the translated
241
+ suites and the remaining explicit deviations.
242
+
243
+ ## Stability and versioning
244
+
245
+ - **Lockstep.** The package version tracks the upstream release it translates: 1.3.0 here is
246
+ `@earendil-works/pi-durable` v1.3.0 (tag `v1.3.0`, commit
247
+ `71023aec1546d6d677a65669c5665c0927ce0dd0`). Adopting a later upstream release is a version bump,
248
+ not a routine sync.
249
+ - **Parity is semantics and persisted shapes.** Python names follow PEP 8 while classes stay
250
+ PascalCase and persisted JSON keeps camelCase, so a stored record round-trips as the specification
251
+ describes. Cross-language storage interoperability is incidental, not a contract; see
252
+ [ADR 0001](./docs/adr/0001-parity-baseline-and-boundary.md).
253
+ - **Stable surface.** The modules in the table above, the names exported from them, and the
254
+ specification sections they implement. `AgentEventStream` is experimental, as upstream says.
255
+ - **Excluded.** Code Mode, the image implementation (the `ImageProcessor` protocol remains),
256
+ Cloudflare adapters, PowerShell, Windows support, and the benchmark helpers. [`PARITY.md`](./PARITY.md)
257
+ marks every exclusion.
258
+
259
+ ## Development
260
+
261
+ ```console
262
+ uv sync --extra dev,openai,anthropic,schema
263
+ uv run ruff check src tests
264
+ uv run mypy
265
+ uv run pytest
266
+ ```
267
+
268
+ CI runs the suite on Linux and macOS for Python 3.11–3.15 and the two free-threaded builds, builds
269
+ and installs the sdist and wheel in fresh environments, then installs each extra from the wheel to
270
+ prove the extras resolve and stay independent. [`docs/release.md`](./docs/release.md) records the
271
+ full release steps: verify, build, tag, publish.
272
+
273
+ ## License
274
+
275
+ MIT. The vendored v1.3.0 specification is MIT, copyright (c) 2025 Mario Zechner; see
276
+ [`docs/upstream/LICENSE`](./docs/upstream/LICENSE).
@@ -0,0 +1,90 @@
1
+ pi_durable/__init__.py,sha256=mkkC_RQFE0dopGWCo6jPAoUTNLwOePkxOzrfn2X4ZB0,7648
2
+ pi_durable/context.py,sha256=1vGEdRsE_6_hgQTmDQGgf9BpWs6425ZU40x0cG4-kTo,9747
3
+ pi_durable/delta.py,sha256=SAh27NvqkZZTKnCkGkDiTIqQNMQqhjykV7BuU_VwLe0,9136
4
+ pi_durable/documents.py,sha256=EH3v8gyC482hHpazA9m8VqSJgK6wKChHNep-Rux0ijY,12933
5
+ pi_durable/entries.py,sha256=sw10JTd849TtQMX1c_YqbmV37te2Q9o2QsDb4RKTT34,2414
6
+ pi_durable/errors.py,sha256=tsrMKUQTZCTyh4kU7ACXN-pOYcHpKodv7eXT64rR5Rk,2848
7
+ pi_durable/ids.py,sha256=DV6xBL_OxjfCb3pAO00uiT7s5cX5vBGJ1bgMrAP1GQs,1969
8
+ pi_durable/json.py,sha256=NV7D6ZyI4lownPLwWgS6ygHvAUb6V-02hNIhLmWFkKE,6120
9
+ pi_durable/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ pi_durable/search.py,sha256=vAkwzMKp871AvJBY7WGO_525QC1FDyFEVujhM920DtA,3550
11
+ pi_durable/tasks.py,sha256=6VPlXQOdIvx4rC0dxmKi2qWeC1HGiSJwh6TOgABt6Is,2759
12
+ pi_durable/truncate.py,sha256=49DT7g9tWRZQgxyZar-zZ5s6faN2zUQXT6zG0vM9mHw,5461
13
+ pi_durable/types.py,sha256=Jq_P-lJm31vXNVmabv-IdS3l4vcs4-bQK_erMPNuMns,36687
14
+ pi_durable/env/__init__.py,sha256=h4VEbhjodYkqgJjQ_XGYACNVhYcmG_aE5LS1wAmcfGQ,10946
15
+ pi_durable/env/decode.py,sha256=18F-hHNjWqjxfWRsrr14HR2FUni_QwD0pFru7P9OR_c,1663
16
+ pi_durable/env/line_scan.py,sha256=e9vivHY4LUb3A8HkcFbA_6M3k8CIBcOtZd6bixkXgXc,6733
17
+ pi_durable/env/posix.py,sha256=z5bwb7wVGAb7zJdOZFrZ22QtgNwwffYFWBkfiD389h8,56850
18
+ pi_durable/harness/__init__.py,sha256=O3dclZ8or9XqZNPazD82sFdwZmH2mpd1rJMDmPz4UVQ,29
19
+ pi_durable/harness/agent.py,sha256=q2v7Xvp2-fPcFLtmMGs8YJIAr-3kw_Yk5k0w_1gDrgs,11833
20
+ pi_durable/harness/compaction.py,sha256=REdvYBGvmKJoTMuy8e0iR6XUajcAW6leWzp8EIfTTyk,24717
21
+ pi_durable/harness/context.py,sha256=CRiIiT70qTpUB8fhQGNVdsVbamEp1o5Wfky-EdZJOLI,17585
22
+ pi_durable/harness/define.py,sha256=LcYmVI654sPGzFUPV6ZOR9kl1dEiCD_RZPFD5sy323o,3561
23
+ pi_durable/harness/events.py,sha256=K6dUGkOFRdB1IetO_H_K8yFuJiA5enJ4XB3WClkBwyE,28141
24
+ pi_durable/harness/generation.py,sha256=RFAxj-7jR6JTmwwY0hAcD1GwL3DHv6YID5eN1wTWV2E,39576
25
+ pi_durable/harness/harness.py,sha256=E5_X1u5nVBSPsu8X9MS1u6iDNerF-zkWoZUMVlveS_k,22479
26
+ pi_durable/harness/inbox.py,sha256=ptowY8M2m-oZnTHWWKamMZzxqaAHWrst1IwtDW54Glk,8380
27
+ pi_durable/harness/live.py,sha256=LYEIvIiezgnVEaNrwNl3rjo4nVwj1AQKkCpVd4NWJpo,11462
28
+ pi_durable/harness/output.py,sha256=8N8jNAav2g040sxc6UNgWFtDqloXCb3i2C30XPZSPCU,16467
29
+ pi_durable/harness/prompt.py,sha256=0NdX9acYyOMfRXKWiziieADjzW_uMVxyRzUZp6aVchQ,9801
30
+ pi_durable/harness/provider.py,sha256=GqcJYOnhhQ9tIJB9jxh5tEWZC4vpQ_gZxnmxXtBFbcY,2412
31
+ pi_durable/harness/registry.py,sha256=vXErM_5viI2gus4hC08zgOR3bm5v2EJ7XNR-mRIEmcM,4610
32
+ pi_durable/harness/scheduler.py,sha256=A13ACVx7Xxdcab06kN4gzRKZ3CPXsK3Ad4t5sS2sLDE,80296
33
+ pi_durable/harness/submissions.py,sha256=cQN41fRfD875DyHPkNPFyI6VPXQH5PKhHC2U_3hEcm4,12752
34
+ pi_durable/harness/task_graph.py,sha256=_eH9tIKZTrXtf8CcR7GvTi7liOTI9EyWmpRjTQ9Akfo,10891
35
+ pi_durable/harness/tool.py,sha256=-_cattqt1xb2KcqZy0fWMw_6-XOdklY-072QGFiJYVc,51344
36
+ pi_durable/harness/types.py,sha256=3Eie8ly5TEF97BTM82xYGb_2MFazMLM3Seaeitl1Bm4,22556
37
+ pi_durable/harness/usage.py,sha256=wiQ0At1lhErXXj1eEae4MpdsRnbijITRBQz3vc-jmgM,3183
38
+ pi_durable/harness/util.py,sha256=r1xWxlyJst99tuGRpde8-R-ZsiNYCAjztLRY1B6QhGg,6742
39
+ pi_durable/harness/validation.py,sha256=kdD8-wR2bloltVww3ZGP2zgqidnGI80nf5EvCh2ygwU,18903
40
+ pi_durable/harness/view.py,sha256=DTgcljzYvNs9UuPcBopb4fdEMAFV91qquUmuJRZ5jMI,11608
41
+ pi_durable/providers/__init__.py,sha256=QV-VBDbQCqo6_aAQ6zyNp9DGqbGetxBDZRzGlQOgut0,12304
42
+ pi_durable/providers/anthropic.py,sha256=vz366Ts0i_-NWu0sclFi47szUKYWDdLu7F00ors45rU,24736
43
+ pi_durable/providers/base.py,sha256=2Ejvms2GPARMWkpnLI2tjaC6FNmwZlFhcWWygcJN7Hs,3072
44
+ pi_durable/providers/json_parse.py,sha256=Mbr46kojsbm0PQkobNwZFSnkX3w0h_CKJ3xB51nV8E8,3660
45
+ pi_durable/providers/openai.py,sha256=ztJLf_7yapADlPTPVUnnr3yTw2zV0WsJQmj5xuDtJDs,21876
46
+ pi_durable/providers/request.py,sha256=0ozS6WQIMnjE_8vUctJzqsmzx3ZcsgT-_TCdlu5trlc,1091
47
+ pi_durable/providers/retry.py,sha256=wOqXVHZLf7CWlCgWU-FJ6xCWSp-_1B4DzYuxdLxxJ94,4161
48
+ pi_durable/providers/stream.py,sha256=OGvhgrf__ixhU_QfBsV1OHDcO_c723henZpWOH7MCRA,6558
49
+ pi_durable/providers/transcript.py,sha256=h0S4xv6H0Vyi6l6byl6CetcUi7Lzu8gHRvVvuVWNN9g,8505
50
+ pi_durable/providers/usage.py,sha256=Rsqg8rQbwYskRwQhq5zMzTqxynn3JWAODalDS4f6a6A,1972
51
+ pi_durable/session/__init__.py,sha256=pPI6XLnp12vWdD2NzH3_GB-N6LLehWdAwIZ8GU56Ixs,157
52
+ pi_durable/session/drafts.py,sha256=9LQzsihdwLO0-7vpSDiGAqL9tvcnSsRqjYd0K4jNlRU,25621
53
+ pi_durable/session/forks.py,sha256=XIPfd9RMbmnhOI5KyCXZMmU78Hnxma320bqGYhUvn5w,3492
54
+ pi_durable/session/observation.py,sha256=ImcNNE7aOixh3lEk6koIFZ9EAkauq_CU1Q3MXTfvKns,12752
55
+ pi_durable/session/session.py,sha256=0UnxPkMRvjOTc9mDFkdSccK1Ii6JtJo49sWeCJe-Mj0,44868
56
+ pi_durable/session/transaction.py,sha256=t1x-a45jocEi3237YcaCk_tnk7Y3nT_AFNCI49za43k,43289
57
+ pi_durable/storage/__init__.py,sha256=J-2_1Q1xim1xTub9QSYAJocwgc7MOlZ5rv3fDZaPopk,134
58
+ pi_durable/storage/memory.py,sha256=8be-R20ypBi17nrrtT2LS1_UWLA5nmjfwtGH2bYehCg,37616
59
+ pi_durable/storage/scan.py,sha256=FPLPt7r8Fj500FlADk1b-NyVJYdyOhxjW6Df6OOU03U,1952
60
+ pi_durable/storage/jsonl/__init__.py,sha256=Zl-sPADIbaQ-7N4W5KYdVZJWJOCMWttXtH9Hd7eGoOI,278
61
+ pi_durable/storage/jsonl/storage.py,sha256=JdxHB6a512i-69K0EzdtXqOhkn5XbYu3JsnJAXdkMuQ,37965
62
+ pi_durable/storage/sqlite/__init__.py,sha256=cZlC-55GCFTw0kmVdNW1xU44Skrnd0tapawsiHZm9Nw,714
63
+ pi_durable/storage/sqlite/database.py,sha256=POVqSb4zQKc6U1MTySuhIcLYHdieb87rpNPU4Uy3h-E,2888
64
+ pi_durable/storage/sqlite/migrations.py,sha256=XqnGszUs7f9HiYT3Li_CNuql8Fe8fOq3TO36j4_PyS0,8407
65
+ pi_durable/storage/sqlite/posix.py,sha256=Cs_WdgnL4YSLXINWcK5aoPL3LhES8_Xjm4wBAOH1nBY,10826
66
+ pi_durable/storage/sqlite/schema.py,sha256=9WpOEBPeIRjJs5ybDD1jlYDqaY0FF_rWJW4GRQZP-FA,3306
67
+ pi_durable/storage/sqlite/storage.py,sha256=1fHhQWFpPLTMtE0F0OUOyZZ9QJmyvUqhuoASKwMIDJE,44786
68
+ pi_durable/testing/__init__.py,sha256=HEFSZe8chLqsla94jBz_SxWK_YnOtGPTSxcuDGJQtYc,1319
69
+ pi_durable/testing/assertions.py,sha256=GguUZRZnDvApXK8bcwCLF8a5l5ZJazBWluE8_v9QUSQ,1611
70
+ pi_durable/testing/env_conformance.py,sha256=pAqqd8PDTl9w2bNOJP27p6pD_y6R1GBcVuPrlqBDMTA,34343
71
+ pi_durable/testing/runner.py,sha256=WM-cr5pq2SPvwh8uwmnBCOwSspYdwJOJuVoVHQelq_Y,1777
72
+ pi_durable/testing/storage_conformance.py,sha256=XUbSOQvf4XiGew_q6yjSRZ5YSBTOhT43fepaIrk1ca4,81478
73
+ pi_durable/testing/types.py,sha256=ZKN_N2Z7ZolUAieRZmHXx00tHC6f0OXrkftImEdBumI,3008
74
+ pi_durable/tool_search/__init__.py,sha256=iPLeu10cfRmg51qBRRszekry9IWGjBSwNSuttMLpIIE,5760
75
+ pi_durable/tools/__init__.py,sha256=iq4x7uQeOEXODesNs0dM5pqHdwQ512FTojiL16_lFtM,2093
76
+ pi_durable/tools/_values.py,sha256=kDFm03Zk6-6FVD_gqc3uHo1-bVQyhk2XIZ2r2VYY9BE,1299
77
+ pi_durable/tools/bash.py,sha256=_KJqHcQvGBEkMS2p3BeUjZwwaXZKDOM7Y09RdvSXuCE,8563
78
+ pi_durable/tools/edit.py,sha256=otmVeayyWtfTCWWcKu4HSVAZWGH7wGJPwGZFxojjhEk,7777
79
+ pi_durable/tools/edit_diff.py,sha256=4Q4MxkXT7cHFV5ndnweFxYKAwVNjEEue1nm7pxHcjRs,16958
80
+ pi_durable/tools/env.py,sha256=7f54EL-l8YsbC0u_J4MuA4pYKI5WLzf5EDqrqFcjqSY,462
81
+ pi_durable/tools/file_mutation_queue.py,sha256=YKTbP2XCW0h4URmFUwMaqcy04VKpHMHOj1fvqDyGzEA,2340
82
+ pi_durable/tools/image.py,sha256=rbdcIkeaDYr_nSyX1N0i3gIRgi6C-D_i-hGJeWXww-E,8481
83
+ pi_durable/tools/image_processor.py,sha256=ESQViVL6BC7RF_qk3R3e4EiLpdS9h0JfwwjFOKEkA8Q,2070
84
+ pi_durable/tools/path_utils.py,sha256=8BbCUW9xnSJvXxYOBYdz3waOmnDhxM9_eXpCeRth0_g,4000
85
+ pi_durable/tools/read.py,sha256=a1rdYwWajU-PUIowko1bpdT07yocAsPS-V48-WrNPHE,18895
86
+ pi_durable/tools/write.py,sha256=XmmRqne2Y8R1jh9ZB0tBh5IPFZw87QsWx7UWjkkPJPw,2357
87
+ pi_durable_python-1.3.0.dist-info/METADATA,sha256=e9qad4McIb-bszu5pDSZRj9kDWeZxX-yaLrpgJKOwn0,12324
88
+ pi_durable_python-1.3.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
89
+ pi_durable_python-1.3.0.dist-info/licenses/LICENSE,sha256=v4jh9TtVqmIw9d9G92RUgEsx0Ekb5hPuPVqAZOE2Tek,1079
90
+ pi_durable_python-1.3.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Armando Pesenti Gritti
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.