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.
- pi_durable/__init__.py +320 -0
- pi_durable/context.py +328 -0
- pi_durable/delta.py +269 -0
- pi_durable/documents.py +366 -0
- pi_durable/entries.py +66 -0
- pi_durable/env/__init__.py +408 -0
- pi_durable/env/decode.py +48 -0
- pi_durable/env/line_scan.py +190 -0
- pi_durable/env/posix.py +1547 -0
- pi_durable/errors.py +89 -0
- pi_durable/harness/__init__.py +1 -0
- pi_durable/harness/agent.py +344 -0
- pi_durable/harness/compaction.py +673 -0
- pi_durable/harness/context.py +515 -0
- pi_durable/harness/define.py +111 -0
- pi_durable/harness/events.py +766 -0
- pi_durable/harness/generation.py +1079 -0
- pi_durable/harness/harness.py +570 -0
- pi_durable/harness/inbox.py +255 -0
- pi_durable/harness/live.py +374 -0
- pi_durable/harness/output.py +467 -0
- pi_durable/harness/prompt.py +288 -0
- pi_durable/harness/provider.py +78 -0
- pi_durable/harness/registry.py +136 -0
- pi_durable/harness/scheduler.py +1977 -0
- pi_durable/harness/submissions.py +357 -0
- pi_durable/harness/task_graph.py +334 -0
- pi_durable/harness/tool.py +1365 -0
- pi_durable/harness/types.py +772 -0
- pi_durable/harness/usage.py +88 -0
- pi_durable/harness/util.py +204 -0
- pi_durable/harness/validation.py +460 -0
- pi_durable/harness/view.py +324 -0
- pi_durable/ids.py +63 -0
- pi_durable/json.py +186 -0
- pi_durable/providers/__init__.py +362 -0
- pi_durable/providers/anthropic.py +603 -0
- pi_durable/providers/base.py +97 -0
- pi_durable/providers/json_parse.py +117 -0
- pi_durable/providers/openai.py +574 -0
- pi_durable/providers/request.py +35 -0
- pi_durable/providers/retry.py +127 -0
- pi_durable/providers/stream.py +183 -0
- pi_durable/providers/transcript.py +224 -0
- pi_durable/providers/usage.py +58 -0
- pi_durable/py.typed +0 -0
- pi_durable/search.py +115 -0
- pi_durable/session/__init__.py +5 -0
- pi_durable/session/drafts.py +762 -0
- pi_durable/session/forks.py +109 -0
- pi_durable/session/observation.py +374 -0
- pi_durable/session/session.py +1193 -0
- pi_durable/session/transaction.py +1088 -0
- pi_durable/storage/__init__.py +5 -0
- pi_durable/storage/jsonl/__init__.py +15 -0
- pi_durable/storage/jsonl/storage.py +958 -0
- pi_durable/storage/memory.py +889 -0
- pi_durable/storage/scan.py +57 -0
- pi_durable/storage/sqlite/__init__.py +26 -0
- pi_durable/storage/sqlite/database.py +62 -0
- pi_durable/storage/sqlite/migrations.py +191 -0
- pi_durable/storage/sqlite/posix.py +314 -0
- pi_durable/storage/sqlite/schema.py +97 -0
- pi_durable/storage/sqlite/storage.py +1130 -0
- pi_durable/tasks.py +89 -0
- pi_durable/testing/__init__.py +41 -0
- pi_durable/testing/assertions.py +44 -0
- pi_durable/testing/env_conformance.py +828 -0
- pi_durable/testing/runner.py +64 -0
- pi_durable/testing/storage_conformance.py +2008 -0
- pi_durable/testing/types.py +99 -0
- pi_durable/tool_search/__init__.py +159 -0
- pi_durable/tools/__init__.py +81 -0
- pi_durable/tools/_values.py +43 -0
- pi_durable/tools/bash.py +250 -0
- pi_durable/tools/edit.py +214 -0
- pi_durable/tools/edit_diff.py +452 -0
- pi_durable/tools/env.py +19 -0
- pi_durable/tools/file_mutation_queue.py +68 -0
- pi_durable/tools/image.py +248 -0
- pi_durable/tools/image_processor.py +77 -0
- pi_durable/tools/path_utils.py +111 -0
- pi_durable/tools/read.py +506 -0
- pi_durable/tools/write.py +71 -0
- pi_durable/truncate.py +185 -0
- pi_durable/types.py +1297 -0
- pi_durable_python-1.3.0.dist-info/METADATA +276 -0
- pi_durable_python-1.3.0.dist-info/RECORD +90 -0
- pi_durable_python-1.3.0.dist-info/WHEEL +4 -0
- 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,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.
|