pi-agent-python-sdk 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.
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/CHANGELOG.md +26 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/PKG-INFO +94 -40
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/README.md +91 -37
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/pyproject.toml +3 -3
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_events.py +4 -2
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_launch.py +1 -1
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_observation.py +28 -6
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_runs.py +4 -4
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_transport.py +11 -2
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/client.py +27 -8
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/sync.py +10 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/types.py +41 -3
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/.gitignore +0 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/LICENSE +0 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/__init__.py +0 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_collections.py +0 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_usage.py +0 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/errors.py +0 -0
- {pi_agent_python_sdk-0.2.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/py.typed +0 -0
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.2.1
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Stop process observations without closing Pi, then drain buffered records;
|
|
10
|
+
report scoped stop, discard, overflow, and process termination separately.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Drain the ready queue in each blocking iterator transfer to avoid finite-burst
|
|
15
|
+
overflow caused by repeated partial transfers. Queue limits remain unchanged;
|
|
16
|
+
the additional batch is bounded by the same count and byte budgets.
|
|
17
|
+
- Allow sequential async stream iterator reuse while retaining concurrent-reader
|
|
18
|
+
and result-drain protections.
|
|
19
|
+
- Keep a healthy client usable after locally rejected, unsent input, without
|
|
20
|
+
relaxing ownership or cleanup for commands that may have reached Pi.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Update the tested Pi runtime to 0.86.0, retaining 0.85.1 as the minimum.
|
|
25
|
+
- Clarify Python interface choice, async event consumption, and structured-output
|
|
26
|
+
boundaries; demonstrate thinking, tool events, and unknown metadata.
|
|
27
|
+
- Describe system transcript messages, session usage entries, compaction system
|
|
28
|
+
snapshots, and model prompt-cache metadata in the wire annotations. Preserve
|
|
29
|
+
legacy optional fields and raw metadata; Pi still owns transcript and cache behavior.
|
|
30
|
+
|
|
5
31
|
## 0.2.0
|
|
6
32
|
|
|
7
33
|
### Breaking changes
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pi-agent-python-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Typed async and synchronous Python clients for Pi's agent RPC runtime
|
|
5
5
|
Project-URL: Homepage, https://github.com/cheenulabs/pi-agent-python-sdk
|
|
6
|
-
Project-URL: Documentation, https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.2.
|
|
6
|
+
Project-URL: Documentation, https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.2.1/docs
|
|
7
7
|
Project-URL: Issues, https://github.com/cheenulabs/pi-agent-python-sdk/issues
|
|
8
|
-
Project-URL: Changelog, https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
8
|
+
Project-URL: Changelog, https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/CHANGELOG.md
|
|
9
9
|
Author: cheenulabs
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
License-File: LICENSE
|
|
@@ -23,30 +23,60 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
# Pi Agent Python SDK
|
|
25
25
|
|
|
26
|
-
[][pypi]
|
|
27
27
|
[][metadata]
|
|
28
28
|
[][license]
|
|
29
29
|
|
|
30
|
-
**
|
|
30
|
+
**Use your installed Pi coding agent as a Python API. Stream responses,
|
|
31
|
+
continue conversations, and control sessions from Python.**
|
|
31
32
|
|
|
32
33
|
A community Python SDK for [Pi coding agent](https://github.com/earendil-works/pi).
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
its usual models, authentication, tools, extensions, skills, and configuration.
|
|
34
|
+
It starts Pi as a subprocess and exposes the same agent runtime through a typed
|
|
35
|
+
Python interface for RPC commands, streaming, and session control.
|
|
36
36
|
|
|
37
37
|
> Requires Python **3.11+** and a separate Pi installation. The tested protocol
|
|
38
|
-
> baseline is **Pi 0.
|
|
38
|
+
> baseline is **Pi 0.86.0**; see [compatibility][compatibility] for version and
|
|
39
39
|
> platform scope.
|
|
40
40
|
|
|
41
41
|
[Quick start](#quick-start) · [Streaming](#streaming) · [Async](#async-usage) ·
|
|
42
|
-
[Configuration](#configuration) · [
|
|
42
|
+
[Configuration](#configuration) · [Thinking](#models-and-thinking) ·
|
|
43
|
+
[RPC](#rpc-access) · [Documentation](#documentation)
|
|
44
|
+
|
|
45
|
+
## Why use this?
|
|
46
|
+
|
|
47
|
+
If you already use Pi from the terminal, this SDK lets you use the same agent
|
|
48
|
+
from Python code. Instead of managing a separate implementation, you can start Pi
|
|
49
|
+
in RPC mode and call it as a programmatic API from scripts, apps, services, or
|
|
50
|
+
background jobs.
|
|
51
|
+
|
|
52
|
+
This is useful when you want to:
|
|
53
|
+
|
|
54
|
+
- Add Pi-powered coding or reasoning to a Python application.
|
|
55
|
+
- Automate project analysis, refactors, or repository workflows.
|
|
56
|
+
- Build a service or CLI around Pi without reimplementing the agent runtime.
|
|
57
|
+
- Stream text, thinking, tool, and session events in Python.
|
|
58
|
+
- Reuse your existing Pi configuration, models, tools, and extensions.
|
|
59
|
+
|
|
60
|
+
The SDK keeps Pi's usual setup and model selection, while exposing a typed Python
|
|
61
|
+
interface for prompts, follow-ups, model control, and RPC access. It launches Pi
|
|
62
|
+
as a subprocess and communicates over its JSONL protocol; it does not attach to
|
|
63
|
+
an already-running interactive Pi terminal session.
|
|
64
|
+
|
|
65
|
+
## What you can do
|
|
66
|
+
|
|
67
|
+
- **Run and stream:** get a final answer or consume text, thinking, and tool events.
|
|
68
|
+
- **Keep a conversation:** send follow-up prompts, resume sessions, fork, or clone.
|
|
69
|
+
- **Control Pi:** select models, adjust thinking, steer work, compact context, and
|
|
70
|
+
call all 33 RPC commands in the pinned baseline.
|
|
71
|
+
- **Integrate with your application:** use sync or async clients, typed results,
|
|
72
|
+
raw event dictionaries, and extension UI callbacks.
|
|
43
73
|
|
|
44
74
|
## Quick start
|
|
45
75
|
|
|
46
76
|
Install Pi with Node.js **22.19.0 or newer**:
|
|
47
77
|
|
|
48
78
|
```sh
|
|
49
|
-
npm install -g @earendil-works/pi-coding-agent@0.
|
|
79
|
+
npm install -g @earendil-works/pi-coding-agent@0.86.0
|
|
50
80
|
pi --version
|
|
51
81
|
```
|
|
52
82
|
|
|
@@ -56,7 +86,7 @@ The SDK uses that configuration when it starts Pi.
|
|
|
56
86
|
Install the Python package from [PyPI][pypi]:
|
|
57
87
|
|
|
58
88
|
```sh
|
|
59
|
-
python -m pip install pi-agent-python-sdk==0.2.
|
|
89
|
+
python -m pip install pi-agent-python-sdk==0.2.1
|
|
60
90
|
```
|
|
61
91
|
|
|
62
92
|
The distribution is named `pi-agent-python-sdk`; import it as
|
|
@@ -87,15 +117,6 @@ with PiClient() as pi:
|
|
|
87
117
|
Pi keeps the conversation context. Each result contains only the messages and
|
|
88
118
|
answer from that call; a call with no assistant output has empty text.
|
|
89
119
|
|
|
90
|
-
## What you can do
|
|
91
|
-
|
|
92
|
-
- **Run and stream:** get a final answer or consume text, thinking, and tool events.
|
|
93
|
-
- **Keep a conversation:** send follow-up prompts, resume sessions, fork, or clone.
|
|
94
|
-
- **Control Pi:** select models, adjust thinking, steer work, compact context, and
|
|
95
|
-
call all 33 RPC commands in the pinned baseline.
|
|
96
|
-
- **Integrate with your application:** use sync or async clients, typed results,
|
|
97
|
-
raw event dictionaries, and extension UI callbacks.
|
|
98
|
-
|
|
99
120
|
## Streaming
|
|
100
121
|
|
|
101
122
|
```python
|
|
@@ -159,6 +180,38 @@ pass `extra_args=["--extension", "/absolute/path/to/your-extension.ts"]` to eith
|
|
|
159
180
|
client. See [using your own extensions][extensions]
|
|
160
181
|
for details and [extension UI][ui-example] for an interactive example.
|
|
161
182
|
|
|
183
|
+
## Models and thinking
|
|
184
|
+
|
|
185
|
+
The SDK uses Pi's configured model unless you pass `provider=` and `model=`.
|
|
186
|
+
Pi determines which thinking levels that model supports; query them before
|
|
187
|
+
choosing a level:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from pi_agent import PiClient
|
|
191
|
+
|
|
192
|
+
with PiClient() as pi:
|
|
193
|
+
levels = pi.get_available_thinking_levels()
|
|
194
|
+
print("Supported thinking levels:", levels)
|
|
195
|
+
if "high" in levels:
|
|
196
|
+
pi.set_thinking_level("high")
|
|
197
|
+
print("Effective thinking level:", pi.get_state()["thinkingLevel"])
|
|
198
|
+
|
|
199
|
+
result = pi.run("Analyse this project's architecture without changing files.")
|
|
200
|
+
print(result.text)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Set the model and thinking level before starting `run()` or `stream()`. Pi can
|
|
204
|
+
adjust unsupported level requests, so read `get_state()["thinkingLevel"]` for the
|
|
205
|
+
effective value. The setting applies to subsequent prompts in the current
|
|
206
|
+
session without changing global defaults. With `AsyncPiClient`, await the same
|
|
207
|
+
methods. See the [model and thinking commands][thinking-reference] for cycling
|
|
208
|
+
levels and other controls.
|
|
209
|
+
|
|
210
|
+
The thinking level controls Pi's reasoning setting. Thinking **output** is
|
|
211
|
+
separate: when Pi emits it, deltas are available in `event.raw` during streaming
|
|
212
|
+
and finalized thinking blocks in `result.messages`. `result.text` contains the
|
|
213
|
+
final assistant text, not thinking.
|
|
214
|
+
|
|
162
215
|
## RPC access
|
|
163
216
|
|
|
164
217
|
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
|
|
@@ -215,7 +268,7 @@ the [command reference][commands] for every method.
|
|
|
215
268
|
| [RPC structure][rpc] | How the Python client maps to Pi's protocol |
|
|
216
269
|
| [Compatibility][compatibility] | Runtime versions and platform validation |
|
|
217
270
|
| [Examples][examples] | Runnable sync, async, streaming, sessions, steering, and UI examples |
|
|
218
|
-
| [Release notes][release] | Changes included in 0.2.
|
|
271
|
+
| [Release notes][release] | Changes included in 0.2.1 |
|
|
219
272
|
|
|
220
273
|
Examples use your configured Pi and may make provider calls. Development checks
|
|
221
274
|
use an isolated local test provider; see [CONTRIBUTING.md][contributing] for
|
|
@@ -229,21 +282,22 @@ Maintainers: [protocol discovery][discovery] ·
|
|
|
229
282
|
[MIT][license]
|
|
230
283
|
|
|
231
284
|
[pypi]: https://pypi.org/project/pi-agent-python-sdk/
|
|
232
|
-
[release]: https://github.com/cheenulabs/pi-agent-python-sdk/releases/tag/v0.2.
|
|
233
|
-
[metadata]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
234
|
-
[license]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
235
|
-
[compatibility]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
236
|
-
[errors]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
237
|
-
[stream-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
238
|
-
[constructor-options]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
239
|
-
[extensions]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
240
|
-
[ui-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
241
|
-
[rpc]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
242
|
-
[commands]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
243
|
-
[
|
|
244
|
-
[
|
|
245
|
-
[
|
|
246
|
-
[
|
|
247
|
-
[
|
|
248
|
-
[
|
|
249
|
-
[
|
|
285
|
+
[release]: https://github.com/cheenulabs/pi-agent-python-sdk/releases/tag/v0.2.1
|
|
286
|
+
[metadata]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/pyproject.toml
|
|
287
|
+
[license]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/LICENSE
|
|
288
|
+
[compatibility]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/compatibility.md
|
|
289
|
+
[errors]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/errors.md
|
|
290
|
+
[stream-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/examples/stream.py
|
|
291
|
+
[constructor-options]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md#constructor-options
|
|
292
|
+
[extensions]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/usage.md#using-your-own-extensions
|
|
293
|
+
[ui-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/examples/ui.py
|
|
294
|
+
[rpc]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/rpc.md
|
|
295
|
+
[commands]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md#all-33-rpc-commands
|
|
296
|
+
[thinking-reference]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md#models-state-and-compaction
|
|
297
|
+
[usage]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/usage.md
|
|
298
|
+
[api]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md
|
|
299
|
+
[examples]: https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.2.1/examples
|
|
300
|
+
[contributing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/CONTRIBUTING.md
|
|
301
|
+
[discovery]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/discovery.md
|
|
302
|
+
[maintenance]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/maintenance.md
|
|
303
|
+
[releasing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/releasing.md
|
|
@@ -1,29 +1,59 @@
|
|
|
1
1
|
# Pi Agent Python SDK
|
|
2
2
|
|
|
3
|
-
[][pypi]
|
|
4
4
|
[][metadata]
|
|
5
5
|
[][license]
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**Use your installed Pi coding agent as a Python API. Stream responses,
|
|
8
|
+
continue conversations, and control sessions from Python.**
|
|
8
9
|
|
|
9
10
|
A community Python SDK for [Pi coding agent](https://github.com/earendil-works/pi).
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
its usual models, authentication, tools, extensions, skills, and configuration.
|
|
11
|
+
It starts Pi as a subprocess and exposes the same agent runtime through a typed
|
|
12
|
+
Python interface for RPC commands, streaming, and session control.
|
|
13
13
|
|
|
14
14
|
> Requires Python **3.11+** and a separate Pi installation. The tested protocol
|
|
15
|
-
> baseline is **Pi 0.
|
|
15
|
+
> baseline is **Pi 0.86.0**; see [compatibility][compatibility] for version and
|
|
16
16
|
> platform scope.
|
|
17
17
|
|
|
18
18
|
[Quick start](#quick-start) · [Streaming](#streaming) · [Async](#async-usage) ·
|
|
19
|
-
[Configuration](#configuration) · [
|
|
19
|
+
[Configuration](#configuration) · [Thinking](#models-and-thinking) ·
|
|
20
|
+
[RPC](#rpc-access) · [Documentation](#documentation)
|
|
21
|
+
|
|
22
|
+
## Why use this?
|
|
23
|
+
|
|
24
|
+
If you already use Pi from the terminal, this SDK lets you use the same agent
|
|
25
|
+
from Python code. Instead of managing a separate implementation, you can start Pi
|
|
26
|
+
in RPC mode and call it as a programmatic API from scripts, apps, services, or
|
|
27
|
+
background jobs.
|
|
28
|
+
|
|
29
|
+
This is useful when you want to:
|
|
30
|
+
|
|
31
|
+
- Add Pi-powered coding or reasoning to a Python application.
|
|
32
|
+
- Automate project analysis, refactors, or repository workflows.
|
|
33
|
+
- Build a service or CLI around Pi without reimplementing the agent runtime.
|
|
34
|
+
- Stream text, thinking, tool, and session events in Python.
|
|
35
|
+
- Reuse your existing Pi configuration, models, tools, and extensions.
|
|
36
|
+
|
|
37
|
+
The SDK keeps Pi's usual setup and model selection, while exposing a typed Python
|
|
38
|
+
interface for prompts, follow-ups, model control, and RPC access. It launches Pi
|
|
39
|
+
as a subprocess and communicates over its JSONL protocol; it does not attach to
|
|
40
|
+
an already-running interactive Pi terminal session.
|
|
41
|
+
|
|
42
|
+
## What you can do
|
|
43
|
+
|
|
44
|
+
- **Run and stream:** get a final answer or consume text, thinking, and tool events.
|
|
45
|
+
- **Keep a conversation:** send follow-up prompts, resume sessions, fork, or clone.
|
|
46
|
+
- **Control Pi:** select models, adjust thinking, steer work, compact context, and
|
|
47
|
+
call all 33 RPC commands in the pinned baseline.
|
|
48
|
+
- **Integrate with your application:** use sync or async clients, typed results,
|
|
49
|
+
raw event dictionaries, and extension UI callbacks.
|
|
20
50
|
|
|
21
51
|
## Quick start
|
|
22
52
|
|
|
23
53
|
Install Pi with Node.js **22.19.0 or newer**:
|
|
24
54
|
|
|
25
55
|
```sh
|
|
26
|
-
npm install -g @earendil-works/pi-coding-agent@0.
|
|
56
|
+
npm install -g @earendil-works/pi-coding-agent@0.86.0
|
|
27
57
|
pi --version
|
|
28
58
|
```
|
|
29
59
|
|
|
@@ -33,7 +63,7 @@ The SDK uses that configuration when it starts Pi.
|
|
|
33
63
|
Install the Python package from [PyPI][pypi]:
|
|
34
64
|
|
|
35
65
|
```sh
|
|
36
|
-
python -m pip install pi-agent-python-sdk==0.2.
|
|
66
|
+
python -m pip install pi-agent-python-sdk==0.2.1
|
|
37
67
|
```
|
|
38
68
|
|
|
39
69
|
The distribution is named `pi-agent-python-sdk`; import it as
|
|
@@ -64,15 +94,6 @@ with PiClient() as pi:
|
|
|
64
94
|
Pi keeps the conversation context. Each result contains only the messages and
|
|
65
95
|
answer from that call; a call with no assistant output has empty text.
|
|
66
96
|
|
|
67
|
-
## What you can do
|
|
68
|
-
|
|
69
|
-
- **Run and stream:** get a final answer or consume text, thinking, and tool events.
|
|
70
|
-
- **Keep a conversation:** send follow-up prompts, resume sessions, fork, or clone.
|
|
71
|
-
- **Control Pi:** select models, adjust thinking, steer work, compact context, and
|
|
72
|
-
call all 33 RPC commands in the pinned baseline.
|
|
73
|
-
- **Integrate with your application:** use sync or async clients, typed results,
|
|
74
|
-
raw event dictionaries, and extension UI callbacks.
|
|
75
|
-
|
|
76
97
|
## Streaming
|
|
77
98
|
|
|
78
99
|
```python
|
|
@@ -136,6 +157,38 @@ pass `extra_args=["--extension", "/absolute/path/to/your-extension.ts"]` to eith
|
|
|
136
157
|
client. See [using your own extensions][extensions]
|
|
137
158
|
for details and [extension UI][ui-example] for an interactive example.
|
|
138
159
|
|
|
160
|
+
## Models and thinking
|
|
161
|
+
|
|
162
|
+
The SDK uses Pi's configured model unless you pass `provider=` and `model=`.
|
|
163
|
+
Pi determines which thinking levels that model supports; query them before
|
|
164
|
+
choosing a level:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from pi_agent import PiClient
|
|
168
|
+
|
|
169
|
+
with PiClient() as pi:
|
|
170
|
+
levels = pi.get_available_thinking_levels()
|
|
171
|
+
print("Supported thinking levels:", levels)
|
|
172
|
+
if "high" in levels:
|
|
173
|
+
pi.set_thinking_level("high")
|
|
174
|
+
print("Effective thinking level:", pi.get_state()["thinkingLevel"])
|
|
175
|
+
|
|
176
|
+
result = pi.run("Analyse this project's architecture without changing files.")
|
|
177
|
+
print(result.text)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Set the model and thinking level before starting `run()` or `stream()`. Pi can
|
|
181
|
+
adjust unsupported level requests, so read `get_state()["thinkingLevel"]` for the
|
|
182
|
+
effective value. The setting applies to subsequent prompts in the current
|
|
183
|
+
session without changing global defaults. With `AsyncPiClient`, await the same
|
|
184
|
+
methods. See the [model and thinking commands][thinking-reference] for cycling
|
|
185
|
+
levels and other controls.
|
|
186
|
+
|
|
187
|
+
The thinking level controls Pi's reasoning setting. Thinking **output** is
|
|
188
|
+
separate: when Pi emits it, deltas are available in `event.raw` during streaming
|
|
189
|
+
and finalized thinking blocks in `result.messages`. `result.text` contains the
|
|
190
|
+
final assistant text, not thinking.
|
|
191
|
+
|
|
139
192
|
## RPC access
|
|
140
193
|
|
|
141
194
|
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
|
|
@@ -192,7 +245,7 @@ the [command reference][commands] for every method.
|
|
|
192
245
|
| [RPC structure][rpc] | How the Python client maps to Pi's protocol |
|
|
193
246
|
| [Compatibility][compatibility] | Runtime versions and platform validation |
|
|
194
247
|
| [Examples][examples] | Runnable sync, async, streaming, sessions, steering, and UI examples |
|
|
195
|
-
| [Release notes][release] | Changes included in 0.2.
|
|
248
|
+
| [Release notes][release] | Changes included in 0.2.1 |
|
|
196
249
|
|
|
197
250
|
Examples use your configured Pi and may make provider calls. Development checks
|
|
198
251
|
use an isolated local test provider; see [CONTRIBUTING.md][contributing] for
|
|
@@ -206,21 +259,22 @@ Maintainers: [protocol discovery][discovery] ·
|
|
|
206
259
|
[MIT][license]
|
|
207
260
|
|
|
208
261
|
[pypi]: https://pypi.org/project/pi-agent-python-sdk/
|
|
209
|
-
[release]: https://github.com/cheenulabs/pi-agent-python-sdk/releases/tag/v0.2.
|
|
210
|
-
[metadata]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
211
|
-
[license]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
212
|
-
[compatibility]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
213
|
-
[errors]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
214
|
-
[stream-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
215
|
-
[constructor-options]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
216
|
-
[extensions]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
217
|
-
[ui-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
218
|
-
[rpc]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
219
|
-
[commands]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
220
|
-
[
|
|
221
|
-
[
|
|
222
|
-
[
|
|
223
|
-
[
|
|
224
|
-
[
|
|
225
|
-
[
|
|
226
|
-
[
|
|
262
|
+
[release]: https://github.com/cheenulabs/pi-agent-python-sdk/releases/tag/v0.2.1
|
|
263
|
+
[metadata]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/pyproject.toml
|
|
264
|
+
[license]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/LICENSE
|
|
265
|
+
[compatibility]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/compatibility.md
|
|
266
|
+
[errors]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/errors.md
|
|
267
|
+
[stream-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/examples/stream.py
|
|
268
|
+
[constructor-options]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md#constructor-options
|
|
269
|
+
[extensions]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/usage.md#using-your-own-extensions
|
|
270
|
+
[ui-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/examples/ui.py
|
|
271
|
+
[rpc]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/rpc.md
|
|
272
|
+
[commands]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md#all-33-rpc-commands
|
|
273
|
+
[thinking-reference]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md#models-state-and-compaction
|
|
274
|
+
[usage]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/usage.md
|
|
275
|
+
[api]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/api.md
|
|
276
|
+
[examples]: https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.2.1/examples
|
|
277
|
+
[contributing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/CONTRIBUTING.md
|
|
278
|
+
[discovery]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/discovery.md
|
|
279
|
+
[maintenance]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/maintenance.md
|
|
280
|
+
[releasing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/docs/releasing.md
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pi-agent-python-sdk"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Typed async and synchronous Python clients for Pi's agent RPC runtime"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -26,9 +26,9 @@ dependencies = []
|
|
|
26
26
|
|
|
27
27
|
[project.urls]
|
|
28
28
|
Homepage = "https://github.com/cheenulabs/pi-agent-python-sdk"
|
|
29
|
-
Documentation = "https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.2.
|
|
29
|
+
Documentation = "https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.2.1/docs"
|
|
30
30
|
Issues = "https://github.com/cheenulabs/pi-agent-python-sdk/issues"
|
|
31
|
-
Changelog = "https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.
|
|
31
|
+
Changelog = "https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.2.1/CHANGELOG.md"
|
|
32
32
|
|
|
33
33
|
[dependency-groups]
|
|
34
34
|
dev = [
|
|
@@ -117,8 +117,10 @@ class _Subscription(Generic[T]):
|
|
|
117
117
|
async def _next_batch(self) -> list[T]:
|
|
118
118
|
records = [await self.__anext__()]
|
|
119
119
|
# Transfer only records already buffered; never wait to fill a batch.
|
|
120
|
-
#
|
|
121
|
-
|
|
120
|
+
# Drain the ready queue in one crossing so bridge latency does not leave
|
|
121
|
+
# a growing backlog. No await below: count and bytes stay within the
|
|
122
|
+
# existing queue budgets, including the first record just removed.
|
|
123
|
+
while self._records:
|
|
122
124
|
record = self._next_nowait()
|
|
123
125
|
assert record is not None
|
|
124
126
|
records.append(record)
|
|
@@ -13,7 +13,7 @@ from ._transport import _close_process_pipes, _wait_for_exit
|
|
|
13
13
|
from .errors import PiProcessError, PiVersionError
|
|
14
14
|
|
|
15
15
|
MINIMUM_PI_VERSION = "0.85.1"
|
|
16
|
-
TESTED_PI_VERSION = "0.
|
|
16
|
+
TESTED_PI_VERSION = "0.86.0"
|
|
17
17
|
|
|
18
18
|
# The client owns these options. In particular --print consumes an initial prompt.
|
|
19
19
|
_RESERVED = {
|
|
@@ -36,6 +36,7 @@ class ObservationStatus:
|
|
|
36
36
|
stdout_eof: bool = False
|
|
37
37
|
rpc_complete: bool = True
|
|
38
38
|
error: Exception | None = field(default=None, repr=False)
|
|
39
|
+
end_reason: Literal["stopped", "closed", "overflow", "process_end"] | None = None
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
class ProcessObservation(_Subscription[ProcessOutput]):
|
|
@@ -56,18 +57,39 @@ class ProcessObservation(_Subscription[ProcessOutput]):
|
|
|
56
57
|
def status(self) -> ObservationStatus:
|
|
57
58
|
return self._status
|
|
58
59
|
|
|
60
|
+
async def stop(self) -> None:
|
|
61
|
+
"""Unsubscribe without discarding queued output or closing the client.
|
|
62
|
+
|
|
63
|
+
Drain the iterator afterwards, then inspect status. Repeated stops retain
|
|
64
|
+
the first termination status, including overflow or process failure.
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
RuntimeError: If the observation context has not been entered.
|
|
68
|
+
"""
|
|
69
|
+
if not self._entered:
|
|
70
|
+
raise RuntimeError("Enter the observation context before stopping")
|
|
71
|
+
if not self._closed:
|
|
72
|
+
self._status = replace(self._status, end_reason="stopped")
|
|
73
|
+
self._finish()
|
|
74
|
+
|
|
59
75
|
def _finish(self, error: Exception | None = None) -> None:
|
|
60
76
|
if not self._closed and self._status.ended_at_ns is None:
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
overflow = isinstance(error, PiSubscriptionOverflow)
|
|
78
|
+
self._status = replace(
|
|
79
|
+
self._status,
|
|
63
80
|
ended_at_ns=time.time_ns(),
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
lost=self._status.lost or overflow,
|
|
82
|
+
error=error or self._status.error,
|
|
83
|
+
end_reason="overflow" if overflow else self._status.end_reason or "closed",
|
|
67
84
|
)
|
|
68
85
|
super()._finish(error)
|
|
69
86
|
|
|
70
87
|
def _discard(self, *, buffered: bool = False) -> None:
|
|
71
88
|
if self._records or buffered:
|
|
72
|
-
self._status = replace(
|
|
89
|
+
self._status = replace(
|
|
90
|
+
self._status,
|
|
91
|
+
complete=False,
|
|
92
|
+
lost=True,
|
|
93
|
+
end_reason="overflow" if self._status.end_reason == "overflow" else "closed",
|
|
94
|
+
)
|
|
73
95
|
super()._discard()
|
|
@@ -172,6 +172,10 @@ class RunStream:
|
|
|
172
172
|
if error is not None:
|
|
173
173
|
self._fail(error)
|
|
174
174
|
|
|
175
|
+
def _mark_submitted(self) -> None:
|
|
176
|
+
self._submitted = True
|
|
177
|
+
self._begin = time.monotonic()
|
|
178
|
+
|
|
175
179
|
async def _drive(self) -> RunResult:
|
|
176
180
|
assert self._ready is not None
|
|
177
181
|
failure: BaseException | None = None
|
|
@@ -183,8 +187,6 @@ class RunStream:
|
|
|
183
187
|
fields: dict[str, Any] = {"message": self._message}
|
|
184
188
|
if self._images is not None:
|
|
185
189
|
fields["images"] = self._images
|
|
186
|
-
self._submitted = True
|
|
187
|
-
self._begin = time.monotonic()
|
|
188
190
|
await self._client._request(
|
|
189
191
|
"prompt", fields, timeout=self._command_timeout, owner=self
|
|
190
192
|
)
|
|
@@ -300,8 +302,6 @@ class RunStream:
|
|
|
300
302
|
def __aiter__(self) -> Self:
|
|
301
303
|
if self._draining:
|
|
302
304
|
raise PiBusyError("Cannot iterate while result() drains the stream")
|
|
303
|
-
if self._iterating:
|
|
304
|
-
raise PiBusyError("A stream permits one event iterator")
|
|
305
305
|
self._iterating = True
|
|
306
306
|
return self
|
|
307
307
|
|
|
@@ -124,6 +124,7 @@ class Transport:
|
|
|
124
124
|
fields: dict[str, Any] | None = None,
|
|
125
125
|
*,
|
|
126
126
|
timeout: float | None = 30, # noqa: ASYNC109 - per-response API, distinct from write bound
|
|
127
|
+
before_write: Callable[[], None] | None = None,
|
|
127
128
|
) -> dict[str, Any]:
|
|
128
129
|
if not isinstance(command, str) or not command:
|
|
129
130
|
raise ValueError("command must be a nonempty string")
|
|
@@ -136,7 +137,9 @@ class Transport:
|
|
|
136
137
|
# A fast child can respond while drain() is still suspended.
|
|
137
138
|
self._pending[request_id] = _Pending(command, future)
|
|
138
139
|
try:
|
|
139
|
-
await self._write(
|
|
140
|
+
await self._write(
|
|
141
|
+
{"type": command, "id": request_id, **(fields or {})}, before_write=before_write
|
|
142
|
+
)
|
|
140
143
|
try:
|
|
141
144
|
# Keep cancellation on this task: wait_for can lose cancellation
|
|
142
145
|
# when its separate waiter completes at the same time on Python 3.11.
|
|
@@ -169,7 +172,9 @@ class Transport:
|
|
|
169
172
|
if not self.running:
|
|
170
173
|
raise PiProcessError("Pi subprocess is not running")
|
|
171
174
|
|
|
172
|
-
async def _write(
|
|
175
|
+
async def _write(
|
|
176
|
+
self, record: dict[str, Any], *, before_write: Callable[[], None] | None = None
|
|
177
|
+
) -> None:
|
|
173
178
|
# Escape lone UTF-16 surrogates, as JSON.stringify does, while keeping
|
|
174
179
|
# ordinary Unicode as UTF-8. Never emit invalid UTF-8 or replace values.
|
|
175
180
|
data = json.dumps(
|
|
@@ -177,6 +182,10 @@ class Transport:
|
|
|
177
182
|
).encode("utf-8", errors="backslashreplace")
|
|
178
183
|
if len(data) > self._limits.max_record_bytes:
|
|
179
184
|
raise ValueError("Outbound JSON record exceeds max_record_bytes")
|
|
185
|
+
# Local validation cannot submit work. Notify ownership before the first
|
|
186
|
+
# suspension so another run cannot race a validated, queued write.
|
|
187
|
+
if before_write is not None:
|
|
188
|
+
before_write()
|
|
180
189
|
wrote = False
|
|
181
190
|
try:
|
|
182
191
|
# Bound lock acquisition too: a wedged pipe must not queue writers forever.
|
|
@@ -424,9 +424,9 @@ class AsyncPiClient:
|
|
|
424
424
|
"""Observe selected process output; enter before start for lifetime coverage.
|
|
425
425
|
|
|
426
426
|
Raises ValueError if no source is selected. Slow consumers raise
|
|
427
|
-
PiSubscriptionOverflow.
|
|
428
|
-
checking status.
|
|
429
|
-
|
|
427
|
+
PiSubscriptionOverflow. Stop the observation or close the client, then
|
|
428
|
+
drain this iterator before checking final status. Known terminal process
|
|
429
|
+
failures remain in status.error even when stopped before cleanup ends.
|
|
430
430
|
"""
|
|
431
431
|
sources: set[OutputSource] = set()
|
|
432
432
|
if stderr:
|
|
@@ -486,6 +486,7 @@ class AsyncPiClient:
|
|
|
486
486
|
rpc_complete=rpc_complete,
|
|
487
487
|
complete=complete,
|
|
488
488
|
error=self._close_error if self._closed else self._terminal_error or error,
|
|
489
|
+
end_reason="process_end",
|
|
489
490
|
)
|
|
490
491
|
observer._finish()
|
|
491
492
|
|
|
@@ -551,6 +552,13 @@ class AsyncPiClient:
|
|
|
551
552
|
error = self._terminal_error
|
|
552
553
|
self._session = SessionInfo()
|
|
553
554
|
self._listeners.clear()
|
|
555
|
+
# Observers keep receiving shutdown output, but stop() must retain a
|
|
556
|
+
# failure already known before pipe drainage finishes. Normal close is
|
|
557
|
+
# not a process error for observation consumers.
|
|
558
|
+
for observer in self._observations:
|
|
559
|
+
observer._status = replace(
|
|
560
|
+
observer.status, error=self._close_error if self._closed else error
|
|
561
|
+
)
|
|
554
562
|
for task in tuple(self._ui_tasks):
|
|
555
563
|
if task is not asyncio.current_task() and task is not self._close_initiator:
|
|
556
564
|
task.cancel()
|
|
@@ -692,12 +700,23 @@ class AsyncPiClient:
|
|
|
692
700
|
)
|
|
693
701
|
if deadline is not None:
|
|
694
702
|
_validate_timeout(deadline)
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
703
|
+
|
|
704
|
+
def mark_submission() -> None:
|
|
705
|
+
if owner is not None:
|
|
706
|
+
owner._mark_submitted()
|
|
707
|
+
elif self._owner is None:
|
|
708
|
+
# Even rejection cannot prove extension preflight is idle.
|
|
709
|
+
self._unowned_submission = True
|
|
710
|
+
|
|
699
711
|
try:
|
|
700
|
-
response = await self._transport.request(
|
|
712
|
+
response = await self._transport.request(
|
|
713
|
+
command,
|
|
714
|
+
fields,
|
|
715
|
+
timeout=deadline,
|
|
716
|
+
before_write=(
|
|
717
|
+
mark_submission if command in {"prompt", "steer", "follow_up"} else None
|
|
718
|
+
),
|
|
719
|
+
)
|
|
701
720
|
if self._ui_error is not None:
|
|
702
721
|
error, self._ui_error = self._ui_error, None
|
|
703
722
|
raise error
|
|
@@ -756,6 +756,16 @@ class SyncProcessObservation(_SyncSubscription[ProcessOutput]):
|
|
|
756
756
|
subscription = client._client.observe(stderr=stderr, stdout=stdout, rpc=rpc)
|
|
757
757
|
super().__init__(client, lambda: subscription)
|
|
758
758
|
|
|
759
|
+
def stop(self) -> None:
|
|
760
|
+
"""Unsubscribe and preserve buffered output for iteration; keep Pi running.
|
|
761
|
+
|
|
762
|
+
Raises:
|
|
763
|
+
RuntimeError: If the observation context has not been entered.
|
|
764
|
+
"""
|
|
765
|
+
if self._subscription is None:
|
|
766
|
+
raise RuntimeError("Enter the observation context before stopping")
|
|
767
|
+
self._client._close_context(cast(ProcessObservation, self._subscription).stop)
|
|
768
|
+
|
|
759
769
|
@property
|
|
760
770
|
def status(self) -> ObservationStatus:
|
|
761
771
|
if self._subscription is None:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Pi 0.
|
|
1
|
+
"""Pi 0.86.0 wire annotations and small Python conveniences.
|
|
2
2
|
|
|
3
3
|
Wire fields retain Pi's spelling and remain ordinary dictionaries. These
|
|
4
4
|
annotations describe known shapes, not a recursive runtime validator: extensions
|
|
@@ -97,6 +97,26 @@ class AssistantMessageDiagnostic(TypedDict):
|
|
|
97
97
|
details: NotRequired[JSONObject]
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
class ToolDefinition(TypedDict):
|
|
101
|
+
name: str
|
|
102
|
+
description: str
|
|
103
|
+
parameters: JSONObject
|
|
104
|
+
constrainedSampling: NotRequired[Literal[False] | JSONObject]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ToolReference(TypedDict):
|
|
108
|
+
name: str
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class SystemMessage(TypedDict):
|
|
112
|
+
role: Literal["system"]
|
|
113
|
+
content: str | list[TextContent]
|
|
114
|
+
sections: NotRequired[dict[str, str | None]]
|
|
115
|
+
toolsAdded: NotRequired[list[ToolDefinition]]
|
|
116
|
+
toolsRemoved: NotRequired[list[ToolReference]]
|
|
117
|
+
timestamp: float
|
|
118
|
+
|
|
119
|
+
|
|
100
120
|
class UserMessage(TypedDict):
|
|
101
121
|
role: Literal["user"]
|
|
102
122
|
content: str | list[TextContent | ImageContent]
|
|
@@ -129,7 +149,7 @@ class ToolResultMessage(TypedDict):
|
|
|
129
149
|
content: list[TextContent | ImageContent]
|
|
130
150
|
details: NotRequired[JSONValue]
|
|
131
151
|
usage: NotRequired[Usage]
|
|
132
|
-
addedToolNames: NotRequired[list[str]]
|
|
152
|
+
addedToolNames: NotRequired[list[str]] # Legacy Pi 0.85.1 field.
|
|
133
153
|
isError: bool
|
|
134
154
|
timestamp: float
|
|
135
155
|
|
|
@@ -170,7 +190,8 @@ class CompactionSummaryMessage(TypedDict):
|
|
|
170
190
|
|
|
171
191
|
|
|
172
192
|
AgentMessage: TypeAlias = (
|
|
173
|
-
|
|
193
|
+
SystemMessage
|
|
194
|
+
| UserMessage
|
|
174
195
|
| AssistantMessage
|
|
175
196
|
| ToolResultMessage
|
|
176
197
|
| BashExecutionMessage
|
|
@@ -195,6 +216,11 @@ class ModelCost(ModelCostRates):
|
|
|
195
216
|
tiers: NotRequired[list[ModelCostTier]]
|
|
196
217
|
|
|
197
218
|
|
|
219
|
+
class ModelPromptCache(TypedDict, total=False):
|
|
220
|
+
short: float
|
|
221
|
+
long: float
|
|
222
|
+
|
|
223
|
+
|
|
198
224
|
class Model(TypedDict):
|
|
199
225
|
id: str
|
|
200
226
|
name: str
|
|
@@ -210,6 +236,7 @@ class Model(TypedDict):
|
|
|
210
236
|
samplingParams: NotRequired[JSONObject]
|
|
211
237
|
headers: NotRequired[dict[str, str]]
|
|
212
238
|
compat: NotRequired[JSONObject]
|
|
239
|
+
promptCache: NotRequired[ModelPromptCache]
|
|
213
240
|
|
|
214
241
|
|
|
215
242
|
class SessionState(TypedDict):
|
|
@@ -308,6 +335,15 @@ class ModelChangeEntry(_EntryBase):
|
|
|
308
335
|
modelId: str
|
|
309
336
|
|
|
310
337
|
|
|
338
|
+
class UsageEntry(_EntryBase):
|
|
339
|
+
type: Literal["usage"]
|
|
340
|
+
kind: str
|
|
341
|
+
provider: str
|
|
342
|
+
model: str
|
|
343
|
+
usage: Usage
|
|
344
|
+
note: NotRequired[str]
|
|
345
|
+
|
|
346
|
+
|
|
311
347
|
class CompactionEntry(_EntryBase):
|
|
312
348
|
type: Literal["compaction"]
|
|
313
349
|
summary: str
|
|
@@ -316,6 +352,7 @@ class CompactionEntry(_EntryBase):
|
|
|
316
352
|
details: NotRequired[JSONValue]
|
|
317
353
|
usage: NotRequired[Usage]
|
|
318
354
|
fromHook: NotRequired[bool]
|
|
355
|
+
systemMessage: NotRequired[SystemMessage]
|
|
319
356
|
|
|
320
357
|
|
|
321
358
|
class BranchSummaryEntry(_EntryBase):
|
|
@@ -356,6 +393,7 @@ SessionEntry: TypeAlias = (
|
|
|
356
393
|
MessageEntry
|
|
357
394
|
| ThinkingLevelChangeEntry
|
|
358
395
|
| ModelChangeEntry
|
|
396
|
+
| UsageEntry
|
|
359
397
|
| CompactionEntry
|
|
360
398
|
| BranchSummaryEntry
|
|
361
399
|
| CustomEntry
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|