pi-agent-python-sdk 0.1.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.1/CHANGELOG.md +92 -0
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/PKG-INFO +114 -42
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/README.md +111 -39
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/pyproject.toml +3 -3
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/__init__.py +3 -0
- pi_agent_python_sdk-0.2.1/src/pi_agent/_collections.py +59 -0
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_events.py +60 -17
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_launch.py +1 -1
- pi_agent_python_sdk-0.2.1/src/pi_agent/_observation.py +95 -0
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_runs.py +53 -28
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_transport.py +118 -27
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/client.py +297 -51
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/errors.py +1 -1
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/sync.py +232 -37
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/types.py +62 -19
- pi_agent_python_sdk-0.1.0/CHANGELOG.md +0 -28
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/.gitignore +0 -0
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/LICENSE +0 -0
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/_usage.py +0 -0
- {pi_agent_python_sdk-0.1.0 → pi_agent_python_sdk-0.2.1}/src/pi_agent/py.typed +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
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
|
+
|
|
31
|
+
## 0.2.0
|
|
32
|
+
|
|
33
|
+
### Breaking changes
|
|
34
|
+
|
|
35
|
+
- `prompt()` returns `None` after checked acknowledgement. Use `request("prompt", ...)`
|
|
36
|
+
for the response envelope and ID; `AcceptanceReceipt` is removed.
|
|
37
|
+
- `cycle_thinking_level()` and `export_html()` return their complete result
|
|
38
|
+
dictionaries, preserving unknown fields. Read `result["level"]` or `result["path"]`.
|
|
39
|
+
- Session mutations invalidate cached identity without an implicit state query.
|
|
40
|
+
Call `get_state()` explicitly when updated identity is needed.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- TypeScript-style listeners and settlement helpers: `on_event()`,
|
|
45
|
+
`collect_events()`, `wait_for_idle()`, and `prompt_and_wait()` through both facades.
|
|
46
|
+
- Opt-in observation of original stderr/stdout bytes and all parsed RPC objects,
|
|
47
|
+
with bounded queues and explicit completion/loss status.
|
|
48
|
+
- Subscriptions before startup, including extension events and startup failures.
|
|
49
|
+
- Maintained TypeScript command/event comparison for source checkouts and installed
|
|
50
|
+
wheels across supported Python and operating-system versions.
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- Stream events before prompt acknowledgement while still requiring successful
|
|
55
|
+
acknowledgement and settlement before completing a result.
|
|
56
|
+
- Preserve UI callback causes; dialog expiry cancels only the dialog, and late
|
|
57
|
+
handler answers cannot override it.
|
|
58
|
+
- Deliver buffered event prefixes before terminal failures; preserve overflow
|
|
59
|
+
errors during concurrent blocking-context cleanup.
|
|
60
|
+
- Yield during finite output bursts and batch blocking reads; result-only runs
|
|
61
|
+
no longer buffer discarded progress. Slow consumers still fail explicitly.
|
|
62
|
+
- Preserve JSON-escaped lone surrogates on outbound commands and UI replies.
|
|
63
|
+
|
|
64
|
+
- Share deadline validation across runs, commands, collectors, and limits; invalid
|
|
65
|
+
types and integers too large for timers consistently raise `ValueError`.
|
|
66
|
+
- Document the retained run/stream conveniences and the reasons for their
|
|
67
|
+
internal ownership, session, and cleanup rules.
|
|
68
|
+
|
|
69
|
+
## 0.1.0
|
|
70
|
+
|
|
71
|
+
- Introduce the `pi-agent-python-sdk` distribution with the `pi_agent` Python
|
|
72
|
+
import. Users of earlier source checkouts must update their imports.
|
|
73
|
+
- Keep the standalone SDK scoped to core RPC with zero runtime dependencies;
|
|
74
|
+
document loading caller-owned extensions through native Pi arguments.
|
|
75
|
+
- Prevent owned runs from claiming delayed events after low-level submissions.
|
|
76
|
+
- Bound retained run messages independently of event queues.
|
|
77
|
+
- Preserve unknown usage measurements, concatenate final text blocks directly,
|
|
78
|
+
and measure run latency from submission to settlement.
|
|
79
|
+
- Reject malformed known text deltas while preserving unknown event variants.
|
|
80
|
+
- Add `AsyncPiClient` and `PiClient` with explicit methods for all 33 Pi 0.85.1 RPC commands.
|
|
81
|
+
- Add typed wire payloads, future-only event subscriptions, extension dialogs,
|
|
82
|
+
streamed text, and settled results with session identity and observed usage.
|
|
83
|
+
- Preserve Pi configuration while owning process readiness, bounded I/O,
|
|
84
|
+
checked failures, cancellation cleanup, and offline compatibility checks.
|
|
85
|
+
- Add deterministic subprocess tests and isolated real-Pi integration using a
|
|
86
|
+
local faux provider, including retries, compaction, tools, and saved sessions.
|
|
87
|
+
- Add nine runnable examples and guides for the API, errors, compatibility,
|
|
88
|
+
dependency updates, and releases.
|
|
89
|
+
- Add Python/platform CI, Dependabot, daily latest-Pi checks, reviewed source
|
|
90
|
+
fingerprints, distribution inspection, and Trusted Publishing workflows.
|
|
91
|
+
- Verify published wheel and source hashes, and smoke-test index installations
|
|
92
|
+
before promoting the same artifacts from TestPyPI to PyPI.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pi-agent-python-sdk
|
|
3
|
-
Version: 0.1
|
|
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.1
|
|
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.1
|
|
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,39 +23,70 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
# Pi Agent Python SDK
|
|
25
25
|
|
|
26
|
+
[][pypi]
|
|
26
27
|
[][metadata]
|
|
27
28
|
[][license]
|
|
28
29
|
|
|
29
|
-
**
|
|
30
|
+
**Use your installed Pi coding agent as a Python API. Stream responses,
|
|
31
|
+
continue conversations, and control sessions from Python.**
|
|
30
32
|
|
|
31
33
|
A community Python SDK for [Pi coding agent](https://github.com/earendil-works/pi).
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
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.
|
|
35
36
|
|
|
36
37
|
> Requires Python **3.11+** and a separate Pi installation. The tested protocol
|
|
37
|
-
> baseline is **Pi 0.
|
|
38
|
+
> baseline is **Pi 0.86.0**; see [compatibility][compatibility] for version and
|
|
38
39
|
> platform scope.
|
|
39
40
|
|
|
40
41
|
[Quick start](#quick-start) · [Streaming](#streaming) · [Async](#async-usage) ·
|
|
41
|
-
[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.
|
|
42
73
|
|
|
43
74
|
## Quick start
|
|
44
75
|
|
|
45
76
|
Install Pi with Node.js **22.19.0 or newer**:
|
|
46
77
|
|
|
47
78
|
```sh
|
|
48
|
-
npm install -g @earendil-works/pi-coding-agent@0.
|
|
79
|
+
npm install -g @earendil-works/pi-coding-agent@0.86.0
|
|
49
80
|
pi --version
|
|
50
81
|
```
|
|
51
82
|
|
|
52
83
|
Run `pi` once to configure your provider and model using Pi's normal setup.
|
|
53
84
|
The SDK uses that configuration when it starts Pi.
|
|
54
85
|
|
|
55
|
-
Install the Python package:
|
|
86
|
+
Install the Python package from [PyPI][pypi]:
|
|
56
87
|
|
|
57
88
|
```sh
|
|
58
|
-
python -m pip install pi-agent-python-sdk==0.1
|
|
89
|
+
python -m pip install pi-agent-python-sdk==0.2.1
|
|
59
90
|
```
|
|
60
91
|
|
|
61
92
|
The distribution is named `pi-agent-python-sdk`; import it as
|
|
@@ -73,14 +104,18 @@ The context manager starts and closes Pi. `run()` waits for the conversation to
|
|
|
73
104
|
settle, including retries and queued follow-ups. The result includes finalized
|
|
74
105
|
messages, session identity, elapsed time, and observed assistant usage.
|
|
75
106
|
|
|
76
|
-
|
|
107
|
+
Continue the conversation with another call on the same client:
|
|
77
108
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
```python
|
|
110
|
+
from pi_agent import PiClient
|
|
111
|
+
|
|
112
|
+
with PiClient() as pi:
|
|
113
|
+
print(pi.run("Explain this project's entry points without editing files.").text)
|
|
114
|
+
print(pi.run("Which of those entry points handles configuration?").text)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Pi keeps the conversation context. Each result contains only the messages and
|
|
118
|
+
answer from that call; a call with no assistant output has empty text.
|
|
84
119
|
|
|
85
120
|
## Streaming
|
|
86
121
|
|
|
@@ -97,8 +132,7 @@ with PiClient() as pi:
|
|
|
97
132
|
```
|
|
98
133
|
|
|
99
134
|
`event.raw` contains the full Pi event, including fields the SDK does not yet
|
|
100
|
-
recognize. Keep the stream inside its context: leaving early
|
|
101
|
-
and aborts the work it owns. See [errors and cancellation][errors] for
|
|
135
|
+
recognize. Keep the stream inside its context: leaving early cleans up unfinished work. See [errors and cancellation][errors] for
|
|
102
136
|
handling timeouts and partial results.
|
|
103
137
|
|
|
104
138
|
## Async usage
|
|
@@ -146,6 +180,38 @@ pass `extra_args=["--extension", "/absolute/path/to/your-extension.ts"]` to eith
|
|
|
146
180
|
client. See [using your own extensions][extensions]
|
|
147
181
|
for details and [extension UI][ui-example] for an interactive example.
|
|
148
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
|
+
|
|
149
215
|
## RPC access
|
|
150
216
|
|
|
151
217
|
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
|
|
@@ -164,6 +230,8 @@ Choose the interface that fits the work:
|
|
|
164
230
|
| A completed conversation result | `run()` |
|
|
165
231
|
| Events while a conversation runs | `stream()` |
|
|
166
232
|
| Prompt acknowledgement and your own event handling | `prompt()` with `events()` |
|
|
233
|
+
| Session events through the next settlement | `prompt_and_wait()` or `collect_events()` |
|
|
234
|
+
| Every event without retaining history | `on_event(callback)` |
|
|
167
235
|
| A specific Pi operation | `get_state()`, `set_model()`, `fork()`, and other command methods |
|
|
168
236
|
| A raw command response envelope | `request()` |
|
|
169
237
|
|
|
@@ -181,10 +249,10 @@ Python arguments use `snake_case`; wire dictionaries retain Pi's `camelCase`
|
|
|
181
249
|
fields. `prompt()` acknowledges submission, which may be handled entirely by an
|
|
182
250
|
extension. It does not wait for a completed answer.
|
|
183
251
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
252
|
+
Use one client per conversation and wait for each `run()` or stream to finish
|
|
253
|
+
before starting the next. After using `prompt()` for your own event handling,
|
|
254
|
+
use a fresh client for `run()` or `stream()` so results cannot include delayed
|
|
255
|
+
events from earlier work. The SDK launches a new process and cannot attach to an existing
|
|
188
256
|
Pi terminal session.
|
|
189
257
|
|
|
190
258
|
See [RPC structure][rpc] for the protocol mapping and module layout, and
|
|
@@ -200,6 +268,7 @@ the [command reference][commands] for every method.
|
|
|
200
268
|
| [RPC structure][rpc] | How the Python client maps to Pi's protocol |
|
|
201
269
|
| [Compatibility][compatibility] | Runtime versions and platform validation |
|
|
202
270
|
| [Examples][examples] | Runnable sync, async, streaming, sessions, steering, and UI examples |
|
|
271
|
+
| [Release notes][release] | Changes included in 0.2.1 |
|
|
203
272
|
|
|
204
273
|
Examples use your configured Pi and may make provider calls. Development checks
|
|
205
274
|
use an isolated local test provider; see [CONTRIBUTING.md][contributing] for
|
|
@@ -212,20 +281,23 @@ Maintainers: [protocol discovery][discovery] ·
|
|
|
212
281
|
|
|
213
282
|
[MIT][license]
|
|
214
283
|
|
|
215
|
-
[
|
|
216
|
-
[
|
|
217
|
-
[
|
|
218
|
-
[
|
|
219
|
-
[
|
|
220
|
-
[
|
|
221
|
-
[
|
|
222
|
-
[
|
|
223
|
-
[
|
|
224
|
-
[
|
|
225
|
-
[
|
|
226
|
-
[
|
|
227
|
-
[
|
|
228
|
-
[
|
|
229
|
-
[
|
|
230
|
-
[
|
|
231
|
-
[
|
|
284
|
+
[pypi]: https://pypi.org/project/pi-agent-python-sdk/
|
|
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,38 +1,69 @@
|
|
|
1
1
|
# Pi Agent Python SDK
|
|
2
2
|
|
|
3
|
+
[][pypi]
|
|
3
4
|
[][metadata]
|
|
4
5
|
[][license]
|
|
5
6
|
|
|
6
|
-
**
|
|
7
|
+
**Use your installed Pi coding agent as a Python API. Stream responses,
|
|
8
|
+
continue conversations, and control sessions from Python.**
|
|
7
9
|
|
|
8
10
|
A community Python SDK for [Pi coding agent](https://github.com/earendil-works/pi).
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
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.
|
|
12
13
|
|
|
13
14
|
> Requires Python **3.11+** and a separate Pi installation. The tested protocol
|
|
14
|
-
> baseline is **Pi 0.
|
|
15
|
+
> baseline is **Pi 0.86.0**; see [compatibility][compatibility] for version and
|
|
15
16
|
> platform scope.
|
|
16
17
|
|
|
17
18
|
[Quick start](#quick-start) · [Streaming](#streaming) · [Async](#async-usage) ·
|
|
18
|
-
[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.
|
|
19
50
|
|
|
20
51
|
## Quick start
|
|
21
52
|
|
|
22
53
|
Install Pi with Node.js **22.19.0 or newer**:
|
|
23
54
|
|
|
24
55
|
```sh
|
|
25
|
-
npm install -g @earendil-works/pi-coding-agent@0.
|
|
56
|
+
npm install -g @earendil-works/pi-coding-agent@0.86.0
|
|
26
57
|
pi --version
|
|
27
58
|
```
|
|
28
59
|
|
|
29
60
|
Run `pi` once to configure your provider and model using Pi's normal setup.
|
|
30
61
|
The SDK uses that configuration when it starts Pi.
|
|
31
62
|
|
|
32
|
-
Install the Python package:
|
|
63
|
+
Install the Python package from [PyPI][pypi]:
|
|
33
64
|
|
|
34
65
|
```sh
|
|
35
|
-
python -m pip install pi-agent-python-sdk==0.1
|
|
66
|
+
python -m pip install pi-agent-python-sdk==0.2.1
|
|
36
67
|
```
|
|
37
68
|
|
|
38
69
|
The distribution is named `pi-agent-python-sdk`; import it as
|
|
@@ -50,14 +81,18 @@ The context manager starts and closes Pi. `run()` waits for the conversation to
|
|
|
50
81
|
settle, including retries and queued follow-ups. The result includes finalized
|
|
51
82
|
messages, session identity, elapsed time, and observed assistant usage.
|
|
52
83
|
|
|
53
|
-
|
|
84
|
+
Continue the conversation with another call on the same client:
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
86
|
+
```python
|
|
87
|
+
from pi_agent import PiClient
|
|
88
|
+
|
|
89
|
+
with PiClient() as pi:
|
|
90
|
+
print(pi.run("Explain this project's entry points without editing files.").text)
|
|
91
|
+
print(pi.run("Which of those entry points handles configuration?").text)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Pi keeps the conversation context. Each result contains only the messages and
|
|
95
|
+
answer from that call; a call with no assistant output has empty text.
|
|
61
96
|
|
|
62
97
|
## Streaming
|
|
63
98
|
|
|
@@ -74,8 +109,7 @@ with PiClient() as pi:
|
|
|
74
109
|
```
|
|
75
110
|
|
|
76
111
|
`event.raw` contains the full Pi event, including fields the SDK does not yet
|
|
77
|
-
recognize. Keep the stream inside its context: leaving early
|
|
78
|
-
and aborts the work it owns. See [errors and cancellation][errors] for
|
|
112
|
+
recognize. Keep the stream inside its context: leaving early cleans up unfinished work. See [errors and cancellation][errors] for
|
|
79
113
|
handling timeouts and partial results.
|
|
80
114
|
|
|
81
115
|
## Async usage
|
|
@@ -123,6 +157,38 @@ pass `extra_args=["--extension", "/absolute/path/to/your-extension.ts"]` to eith
|
|
|
123
157
|
client. See [using your own extensions][extensions]
|
|
124
158
|
for details and [extension UI][ui-example] for an interactive example.
|
|
125
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
|
+
|
|
126
192
|
## RPC access
|
|
127
193
|
|
|
128
194
|
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
|
|
@@ -141,6 +207,8 @@ Choose the interface that fits the work:
|
|
|
141
207
|
| A completed conversation result | `run()` |
|
|
142
208
|
| Events while a conversation runs | `stream()` |
|
|
143
209
|
| Prompt acknowledgement and your own event handling | `prompt()` with `events()` |
|
|
210
|
+
| Session events through the next settlement | `prompt_and_wait()` or `collect_events()` |
|
|
211
|
+
| Every event without retaining history | `on_event(callback)` |
|
|
144
212
|
| A specific Pi operation | `get_state()`, `set_model()`, `fork()`, and other command methods |
|
|
145
213
|
| A raw command response envelope | `request()` |
|
|
146
214
|
|
|
@@ -158,10 +226,10 @@ Python arguments use `snake_case`; wire dictionaries retain Pi's `camelCase`
|
|
|
158
226
|
fields. `prompt()` acknowledges submission, which may be handled entirely by an
|
|
159
227
|
extension. It does not wait for a completed answer.
|
|
160
228
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
229
|
+
Use one client per conversation and wait for each `run()` or stream to finish
|
|
230
|
+
before starting the next. After using `prompt()` for your own event handling,
|
|
231
|
+
use a fresh client for `run()` or `stream()` so results cannot include delayed
|
|
232
|
+
events from earlier work. The SDK launches a new process and cannot attach to an existing
|
|
165
233
|
Pi terminal session.
|
|
166
234
|
|
|
167
235
|
See [RPC structure][rpc] for the protocol mapping and module layout, and
|
|
@@ -177,6 +245,7 @@ the [command reference][commands] for every method.
|
|
|
177
245
|
| [RPC structure][rpc] | How the Python client maps to Pi's protocol |
|
|
178
246
|
| [Compatibility][compatibility] | Runtime versions and platform validation |
|
|
179
247
|
| [Examples][examples] | Runnable sync, async, streaming, sessions, steering, and UI examples |
|
|
248
|
+
| [Release notes][release] | Changes included in 0.2.1 |
|
|
180
249
|
|
|
181
250
|
Examples use your configured Pi and may make provider calls. Development checks
|
|
182
251
|
use an isolated local test provider; see [CONTRIBUTING.md][contributing] for
|
|
@@ -189,20 +258,23 @@ Maintainers: [protocol discovery][discovery] ·
|
|
|
189
258
|
|
|
190
259
|
[MIT][license]
|
|
191
260
|
|
|
192
|
-
[
|
|
193
|
-
[
|
|
194
|
-
[
|
|
195
|
-
[
|
|
196
|
-
[
|
|
197
|
-
[
|
|
198
|
-
[
|
|
199
|
-
[
|
|
200
|
-
[
|
|
201
|
-
[
|
|
202
|
-
[
|
|
203
|
-
[
|
|
204
|
-
[
|
|
205
|
-
[
|
|
206
|
-
[
|
|
207
|
-
[
|
|
208
|
-
[
|
|
261
|
+
[pypi]: https://pypi.org/project/pi-agent-python-sdk/
|
|
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.1
|
|
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.1
|
|
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.1
|
|
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 = [
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Importing this package never launches Pi or changes its configuration.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from ._observation import ObservationStatus, ProcessOutput
|
|
6
7
|
from .client import AsyncPiClient
|
|
7
8
|
from .errors import (
|
|
8
9
|
PiBusyError,
|
|
@@ -27,6 +28,8 @@ __all__ = [
|
|
|
27
28
|
"Event",
|
|
28
29
|
"ImageContent",
|
|
29
30
|
"Limits",
|
|
31
|
+
"ObservationStatus",
|
|
32
|
+
"ProcessOutput",
|
|
30
33
|
"PiBusyError",
|
|
31
34
|
"PiCommandError",
|
|
32
35
|
"PiClient",
|