pi-agent-python-sdk 0.1.0__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.1.0/.gitignore +12 -0
- pi_agent_python_sdk-0.1.0/CHANGELOG.md +28 -0
- pi_agent_python_sdk-0.1.0/LICENSE +21 -0
- pi_agent_python_sdk-0.1.0/PKG-INFO +231 -0
- pi_agent_python_sdk-0.1.0/README.md +208 -0
- pi_agent_python_sdk-0.1.0/pyproject.toml +69 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/__init__.py +47 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/_events.py +108 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/_launch.py +203 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/_runs.py +317 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/_transport.py +360 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/_usage.py +88 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/client.py +796 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/errors.py +87 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/py.typed +0 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/sync.py +684 -0
- pi_agent_python_sdk-0.1.0/src/pi_agent/types.py +960 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.1.0
|
|
6
|
+
|
|
7
|
+
- Introduce the `pi-agent-python-sdk` distribution with the `pi_agent` Python
|
|
8
|
+
import. Users of earlier source checkouts must update their imports.
|
|
9
|
+
- Keep the standalone SDK scoped to core RPC with zero runtime dependencies;
|
|
10
|
+
document loading caller-owned extensions through native Pi arguments.
|
|
11
|
+
- Prevent owned runs from claiming delayed events after low-level submissions.
|
|
12
|
+
- Bound retained run messages independently of event queues.
|
|
13
|
+
- Preserve unknown usage measurements, concatenate final text blocks directly,
|
|
14
|
+
and measure run latency from submission to settlement.
|
|
15
|
+
- Reject malformed known text deltas while preserving unknown event variants.
|
|
16
|
+
- Add `AsyncPiClient` and `PiClient` with explicit methods for all 33 Pi 0.85.1 RPC commands.
|
|
17
|
+
- Add typed wire payloads, future-only event subscriptions, extension dialogs,
|
|
18
|
+
streamed text, and settled results with session identity and observed usage.
|
|
19
|
+
- Preserve Pi configuration while owning process readiness, bounded I/O,
|
|
20
|
+
checked failures, cancellation cleanup, and offline compatibility checks.
|
|
21
|
+
- Add deterministic subprocess tests and isolated real-Pi integration using a
|
|
22
|
+
local faux provider, including retries, compaction, tools, and saved sessions.
|
|
23
|
+
- Add nine runnable examples and guides for the API, errors, compatibility,
|
|
24
|
+
dependency updates, and releases.
|
|
25
|
+
- Add Python/platform CI, Dependabot, daily latest-Pi checks, reviewed source
|
|
26
|
+
fingerprints, distribution inspection, and Trusted Publishing workflows.
|
|
27
|
+
- Verify published wheel and source hashes, and smoke-test index installations
|
|
28
|
+
before promoting the same artifacts from TestPyPI to PyPI.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cheenulabs
|
|
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.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pi-agent-python-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Typed async and synchronous Python clients for Pi's agent RPC runtime
|
|
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.0/docs
|
|
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.0/CHANGELOG.md
|
|
9
|
+
Author: cheenulabs
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agent,asyncio,pi,rpc
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Pi Agent Python SDK
|
|
25
|
+
|
|
26
|
+
[][metadata]
|
|
27
|
+
[][license]
|
|
28
|
+
|
|
29
|
+
**Run Pi from Python. Stream responses, continue conversations, and control sessions.**
|
|
30
|
+
|
|
31
|
+
A community Python SDK for [Pi coding agent](https://github.com/earendil-works/pi).
|
|
32
|
+
Use synchronous or asynchronous clients with typed access to Pi's RPC commands
|
|
33
|
+
and no third-party Python runtime dependencies. Pi runs as a subprocess and keeps
|
|
34
|
+
its usual models, authentication, tools, extensions, skills, and configuration.
|
|
35
|
+
|
|
36
|
+
> Requires Python **3.11+** and a separate Pi installation. The tested protocol
|
|
37
|
+
> baseline is **Pi 0.85.1**; see [compatibility][compatibility] for version and
|
|
38
|
+
> platform scope.
|
|
39
|
+
|
|
40
|
+
[Quick start](#quick-start) · [Streaming](#streaming) · [Async](#async-usage) ·
|
|
41
|
+
[Configuration](#configuration) · [RPC](#rpc-access) · [Documentation](#documentation)
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
Install Pi with Node.js **22.19.0 or newer**:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
npm install -g @earendil-works/pi-coding-agent@0.85.1
|
|
49
|
+
pi --version
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Run `pi` once to configure your provider and model using Pi's normal setup.
|
|
53
|
+
The SDK uses that configuration when it starts Pi.
|
|
54
|
+
|
|
55
|
+
Install the Python package:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
python -m pip install pi-agent-python-sdk==0.1.0
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The distribution is named `pi-agent-python-sdk`; import it as
|
|
62
|
+
`pi_agent`.
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pi_agent import PiClient
|
|
66
|
+
|
|
67
|
+
with PiClient() as pi:
|
|
68
|
+
result = pi.run("Explain the current project without changing files.")
|
|
69
|
+
print(result.text)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The context manager starts and closes Pi. `run()` waits for the conversation to
|
|
73
|
+
settle, including retries and queued follow-ups. The result includes finalized
|
|
74
|
+
messages, session identity, elapsed time, and observed assistant usage.
|
|
75
|
+
|
|
76
|
+
## What you can do
|
|
77
|
+
|
|
78
|
+
- **Run and stream:** get a final answer or consume text, thinking, and tool events.
|
|
79
|
+
- **Keep a conversation:** send follow-up prompts, resume sessions, fork, or clone.
|
|
80
|
+
- **Control Pi:** select models, adjust thinking, steer work, compact context, and
|
|
81
|
+
call all 33 RPC commands in the pinned baseline.
|
|
82
|
+
- **Integrate with your application:** use sync or async clients, typed results,
|
|
83
|
+
raw event dictionaries, and extension UI callbacks.
|
|
84
|
+
|
|
85
|
+
## Streaming
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from pi_agent import PiClient
|
|
89
|
+
|
|
90
|
+
with PiClient() as pi:
|
|
91
|
+
with pi.stream("Explain this project's entry points without editing files.") as stream:
|
|
92
|
+
for event in stream:
|
|
93
|
+
if event.text_delta is not None:
|
|
94
|
+
print(event.text_delta, end="", flush=True)
|
|
95
|
+
result = stream.result()
|
|
96
|
+
print(f"\nStop reason: {result.stop_reason}")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`event.raw` contains the full Pi event, including fields the SDK does not yet
|
|
100
|
+
recognize. Keep the stream inside its context: leaving early clears queued input
|
|
101
|
+
and aborts the work it owns. See [errors and cancellation][errors] for
|
|
102
|
+
handling timeouts and partial results.
|
|
103
|
+
|
|
104
|
+
## Async usage
|
|
105
|
+
|
|
106
|
+
Use `AsyncPiClient` in applications that already run an event loop. Command
|
|
107
|
+
arguments and results match the synchronous client.
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import asyncio
|
|
111
|
+
|
|
112
|
+
from pi_agent import AsyncPiClient
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
async def main() -> None:
|
|
116
|
+
async with AsyncPiClient() as pi:
|
|
117
|
+
result = await pi.run("Explain the current project without changing files.")
|
|
118
|
+
print(result.text)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
asyncio.run(main())
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Async streaming uses `async with pi.stream(...)`, `async for event in stream`,
|
|
126
|
+
and `await stream.result()`. See the [complete streaming example][stream-example].
|
|
127
|
+
|
|
128
|
+
## Configuration
|
|
129
|
+
|
|
130
|
+
Choose the project directory and whether to save the conversation:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from pi_agent import PiClient
|
|
134
|
+
|
|
135
|
+
with PiClient(cwd=".", no_session=True) as pi:
|
|
136
|
+
print(pi.run("Describe this project without changing files.").text)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Leave `no_session` unset to preserve Pi's normal session persistence. Use
|
|
140
|
+
`provider=` and `model=` to override Pi's configured model, or `session=` to open
|
|
141
|
+
an existing session. See [constructor options][constructor-options]
|
|
142
|
+
for environment overrides, executable paths, and deadlines.
|
|
143
|
+
|
|
144
|
+
Extensions are installed and configured through Pi. To load your own extension,
|
|
145
|
+
pass `extra_args=["--extension", "/absolute/path/to/your-extension.ts"]` to either
|
|
146
|
+
client. See [using your own extensions][extensions]
|
|
147
|
+
for details and [extension UI][ui-example] for an interactive example.
|
|
148
|
+
|
|
149
|
+
## RPC access
|
|
150
|
+
|
|
151
|
+
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
Your Python application
|
|
155
|
+
PiClient / AsyncPiClient
|
|
156
|
+
pi --mode rpc
|
|
157
|
+
Models · tools · extensions · sessions
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Choose the interface that fits the work:
|
|
161
|
+
|
|
162
|
+
| You need | Use |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| A completed conversation result | `run()` |
|
|
165
|
+
| Events while a conversation runs | `stream()` |
|
|
166
|
+
| Prompt acknowledgement and your own event handling | `prompt()` with `events()` |
|
|
167
|
+
| A specific Pi operation | `get_state()`, `set_model()`, `fork()`, and other command methods |
|
|
168
|
+
| A raw command response envelope | `request()` |
|
|
169
|
+
|
|
170
|
+
For example, inspect session state without starting a model run:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
from pi_agent import PiClient
|
|
174
|
+
|
|
175
|
+
with PiClient() as pi:
|
|
176
|
+
state = pi.get_state()
|
|
177
|
+
print(state["sessionId"])
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Python arguments use `snake_case`; wire dictionaries retain Pi's `camelCase`
|
|
181
|
+
fields. `prompt()` acknowledges submission, which may be handled entirely by an
|
|
182
|
+
extension. It does not wait for a completed answer.
|
|
183
|
+
|
|
184
|
+
One client owns one conversation at a time; create separate clients for
|
|
185
|
+
independent conversations. After a low-level prompt submitted outside an owned
|
|
186
|
+
run, use a fresh client for `run()` or `stream()` so events cannot be attributed
|
|
187
|
+
to the wrong work. The SDK launches a new process and cannot attach to an existing
|
|
188
|
+
Pi terminal session.
|
|
189
|
+
|
|
190
|
+
See [RPC structure][rpc] for the protocol mapping and module layout, and
|
|
191
|
+
the [command reference][commands] for every method.
|
|
192
|
+
|
|
193
|
+
## Documentation
|
|
194
|
+
|
|
195
|
+
| Guide | Contents |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| [Usage][usage] | Sessions, images, concurrency, events, and extension UI |
|
|
198
|
+
| [API reference][api] | Constructors, commands, types, and results |
|
|
199
|
+
| [Errors and cancellation][errors] | Deadlines, partial results, cleanup, and recovery |
|
|
200
|
+
| [RPC structure][rpc] | How the Python client maps to Pi's protocol |
|
|
201
|
+
| [Compatibility][compatibility] | Runtime versions and platform validation |
|
|
202
|
+
| [Examples][examples] | Runnable sync, async, streaming, sessions, steering, and UI examples |
|
|
203
|
+
|
|
204
|
+
Examples use your configured Pi and may make provider calls. Development checks
|
|
205
|
+
use an isolated local test provider; see [CONTRIBUTING.md][contributing] for
|
|
206
|
+
setup and validation commands.
|
|
207
|
+
|
|
208
|
+
Maintainers: [protocol discovery][discovery] ·
|
|
209
|
+
[maintenance][maintenance] · [release checklist][releasing].
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
[MIT][license]
|
|
214
|
+
|
|
215
|
+
[metadata]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/pyproject.toml
|
|
216
|
+
[license]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/LICENSE
|
|
217
|
+
[compatibility]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/compatibility.md
|
|
218
|
+
[errors]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/errors.md
|
|
219
|
+
[stream-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/examples/stream.py
|
|
220
|
+
[constructor-options]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/api.md#constructor-options
|
|
221
|
+
[extensions]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/usage.md#using-your-own-extensions
|
|
222
|
+
[ui-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/examples/ui.py
|
|
223
|
+
[rpc]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/rpc.md
|
|
224
|
+
[commands]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/api.md#all-33-rpc-commands
|
|
225
|
+
[usage]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/usage.md
|
|
226
|
+
[api]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/api.md
|
|
227
|
+
[examples]: https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.1.0/examples
|
|
228
|
+
[contributing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/CONTRIBUTING.md
|
|
229
|
+
[discovery]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/discovery.md
|
|
230
|
+
[maintenance]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/maintenance.md
|
|
231
|
+
[releasing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/releasing.md
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Pi Agent Python SDK
|
|
2
|
+
|
|
3
|
+
[][metadata]
|
|
4
|
+
[][license]
|
|
5
|
+
|
|
6
|
+
**Run Pi from Python. Stream responses, continue conversations, and control sessions.**
|
|
7
|
+
|
|
8
|
+
A community Python SDK for [Pi coding agent](https://github.com/earendil-works/pi).
|
|
9
|
+
Use synchronous or asynchronous clients with typed access to Pi's RPC commands
|
|
10
|
+
and no third-party Python runtime dependencies. Pi runs as a subprocess and keeps
|
|
11
|
+
its usual models, authentication, tools, extensions, skills, and configuration.
|
|
12
|
+
|
|
13
|
+
> Requires Python **3.11+** and a separate Pi installation. The tested protocol
|
|
14
|
+
> baseline is **Pi 0.85.1**; see [compatibility][compatibility] for version and
|
|
15
|
+
> platform scope.
|
|
16
|
+
|
|
17
|
+
[Quick start](#quick-start) · [Streaming](#streaming) · [Async](#async-usage) ·
|
|
18
|
+
[Configuration](#configuration) · [RPC](#rpc-access) · [Documentation](#documentation)
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
Install Pi with Node.js **22.19.0 or newer**:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm install -g @earendil-works/pi-coding-agent@0.85.1
|
|
26
|
+
pi --version
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Run `pi` once to configure your provider and model using Pi's normal setup.
|
|
30
|
+
The SDK uses that configuration when it starts Pi.
|
|
31
|
+
|
|
32
|
+
Install the Python package:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
python -m pip install pi-agent-python-sdk==0.1.0
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The distribution is named `pi-agent-python-sdk`; import it as
|
|
39
|
+
`pi_agent`.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from pi_agent import PiClient
|
|
43
|
+
|
|
44
|
+
with PiClient() as pi:
|
|
45
|
+
result = pi.run("Explain the current project without changing files.")
|
|
46
|
+
print(result.text)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The context manager starts and closes Pi. `run()` waits for the conversation to
|
|
50
|
+
settle, including retries and queued follow-ups. The result includes finalized
|
|
51
|
+
messages, session identity, elapsed time, and observed assistant usage.
|
|
52
|
+
|
|
53
|
+
## What you can do
|
|
54
|
+
|
|
55
|
+
- **Run and stream:** get a final answer or consume text, thinking, and tool events.
|
|
56
|
+
- **Keep a conversation:** send follow-up prompts, resume sessions, fork, or clone.
|
|
57
|
+
- **Control Pi:** select models, adjust thinking, steer work, compact context, and
|
|
58
|
+
call all 33 RPC commands in the pinned baseline.
|
|
59
|
+
- **Integrate with your application:** use sync or async clients, typed results,
|
|
60
|
+
raw event dictionaries, and extension UI callbacks.
|
|
61
|
+
|
|
62
|
+
## Streaming
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pi_agent import PiClient
|
|
66
|
+
|
|
67
|
+
with PiClient() as pi:
|
|
68
|
+
with pi.stream("Explain this project's entry points without editing files.") as stream:
|
|
69
|
+
for event in stream:
|
|
70
|
+
if event.text_delta is not None:
|
|
71
|
+
print(event.text_delta, end="", flush=True)
|
|
72
|
+
result = stream.result()
|
|
73
|
+
print(f"\nStop reason: {result.stop_reason}")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`event.raw` contains the full Pi event, including fields the SDK does not yet
|
|
77
|
+
recognize. Keep the stream inside its context: leaving early clears queued input
|
|
78
|
+
and aborts the work it owns. See [errors and cancellation][errors] for
|
|
79
|
+
handling timeouts and partial results.
|
|
80
|
+
|
|
81
|
+
## Async usage
|
|
82
|
+
|
|
83
|
+
Use `AsyncPiClient` in applications that already run an event loop. Command
|
|
84
|
+
arguments and results match the synchronous client.
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import asyncio
|
|
88
|
+
|
|
89
|
+
from pi_agent import AsyncPiClient
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
async def main() -> None:
|
|
93
|
+
async with AsyncPiClient() as pi:
|
|
94
|
+
result = await pi.run("Explain the current project without changing files.")
|
|
95
|
+
print(result.text)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
asyncio.run(main())
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Async streaming uses `async with pi.stream(...)`, `async for event in stream`,
|
|
103
|
+
and `await stream.result()`. See the [complete streaming example][stream-example].
|
|
104
|
+
|
|
105
|
+
## Configuration
|
|
106
|
+
|
|
107
|
+
Choose the project directory and whether to save the conversation:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from pi_agent import PiClient
|
|
111
|
+
|
|
112
|
+
with PiClient(cwd=".", no_session=True) as pi:
|
|
113
|
+
print(pi.run("Describe this project without changing files.").text)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Leave `no_session` unset to preserve Pi's normal session persistence. Use
|
|
117
|
+
`provider=` and `model=` to override Pi's configured model, or `session=` to open
|
|
118
|
+
an existing session. See [constructor options][constructor-options]
|
|
119
|
+
for environment overrides, executable paths, and deadlines.
|
|
120
|
+
|
|
121
|
+
Extensions are installed and configured through Pi. To load your own extension,
|
|
122
|
+
pass `extra_args=["--extension", "/absolute/path/to/your-extension.ts"]` to either
|
|
123
|
+
client. See [using your own extensions][extensions]
|
|
124
|
+
for details and [extension UI][ui-example] for an interactive example.
|
|
125
|
+
|
|
126
|
+
## RPC access
|
|
127
|
+
|
|
128
|
+
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
Your Python application
|
|
132
|
+
PiClient / AsyncPiClient
|
|
133
|
+
pi --mode rpc
|
|
134
|
+
Models · tools · extensions · sessions
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Choose the interface that fits the work:
|
|
138
|
+
|
|
139
|
+
| You need | Use |
|
|
140
|
+
| --- | --- |
|
|
141
|
+
| A completed conversation result | `run()` |
|
|
142
|
+
| Events while a conversation runs | `stream()` |
|
|
143
|
+
| Prompt acknowledgement and your own event handling | `prompt()` with `events()` |
|
|
144
|
+
| A specific Pi operation | `get_state()`, `set_model()`, `fork()`, and other command methods |
|
|
145
|
+
| A raw command response envelope | `request()` |
|
|
146
|
+
|
|
147
|
+
For example, inspect session state without starting a model run:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from pi_agent import PiClient
|
|
151
|
+
|
|
152
|
+
with PiClient() as pi:
|
|
153
|
+
state = pi.get_state()
|
|
154
|
+
print(state["sessionId"])
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Python arguments use `snake_case`; wire dictionaries retain Pi's `camelCase`
|
|
158
|
+
fields. `prompt()` acknowledges submission, which may be handled entirely by an
|
|
159
|
+
extension. It does not wait for a completed answer.
|
|
160
|
+
|
|
161
|
+
One client owns one conversation at a time; create separate clients for
|
|
162
|
+
independent conversations. After a low-level prompt submitted outside an owned
|
|
163
|
+
run, use a fresh client for `run()` or `stream()` so events cannot be attributed
|
|
164
|
+
to the wrong work. The SDK launches a new process and cannot attach to an existing
|
|
165
|
+
Pi terminal session.
|
|
166
|
+
|
|
167
|
+
See [RPC structure][rpc] for the protocol mapping and module layout, and
|
|
168
|
+
the [command reference][commands] for every method.
|
|
169
|
+
|
|
170
|
+
## Documentation
|
|
171
|
+
|
|
172
|
+
| Guide | Contents |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| [Usage][usage] | Sessions, images, concurrency, events, and extension UI |
|
|
175
|
+
| [API reference][api] | Constructors, commands, types, and results |
|
|
176
|
+
| [Errors and cancellation][errors] | Deadlines, partial results, cleanup, and recovery |
|
|
177
|
+
| [RPC structure][rpc] | How the Python client maps to Pi's protocol |
|
|
178
|
+
| [Compatibility][compatibility] | Runtime versions and platform validation |
|
|
179
|
+
| [Examples][examples] | Runnable sync, async, streaming, sessions, steering, and UI examples |
|
|
180
|
+
|
|
181
|
+
Examples use your configured Pi and may make provider calls. Development checks
|
|
182
|
+
use an isolated local test provider; see [CONTRIBUTING.md][contributing] for
|
|
183
|
+
setup and validation commands.
|
|
184
|
+
|
|
185
|
+
Maintainers: [protocol discovery][discovery] ·
|
|
186
|
+
[maintenance][maintenance] · [release checklist][releasing].
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
[MIT][license]
|
|
191
|
+
|
|
192
|
+
[metadata]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/pyproject.toml
|
|
193
|
+
[license]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/LICENSE
|
|
194
|
+
[compatibility]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/compatibility.md
|
|
195
|
+
[errors]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/errors.md
|
|
196
|
+
[stream-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/examples/stream.py
|
|
197
|
+
[constructor-options]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/api.md#constructor-options
|
|
198
|
+
[extensions]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/usage.md#using-your-own-extensions
|
|
199
|
+
[ui-example]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/examples/ui.py
|
|
200
|
+
[rpc]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/rpc.md
|
|
201
|
+
[commands]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/api.md#all-33-rpc-commands
|
|
202
|
+
[usage]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/usage.md
|
|
203
|
+
[api]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/api.md
|
|
204
|
+
[examples]: https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.1.0/examples
|
|
205
|
+
[contributing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/CONTRIBUTING.md
|
|
206
|
+
[discovery]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/discovery.md
|
|
207
|
+
[maintenance]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/maintenance.md
|
|
208
|
+
[releasing]: https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/docs/releasing.md
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pi-agent-python-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Typed async and synchronous Python clients for Pi's agent RPC runtime"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{name = "cheenulabs"}]
|
|
14
|
+
keywords = ["pi", "agent", "rpc", "asyncio"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = []
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/cheenulabs/pi-agent-python-sdk"
|
|
29
|
+
Documentation = "https://github.com/cheenulabs/pi-agent-python-sdk/tree/v0.1.0/docs"
|
|
30
|
+
Issues = "https://github.com/cheenulabs/pi-agent-python-sdk/issues"
|
|
31
|
+
Changelog = "https://github.com/cheenulabs/pi-agent-python-sdk/blob/v0.1.0/CHANGELOG.md"
|
|
32
|
+
|
|
33
|
+
[dependency-groups]
|
|
34
|
+
dev = [
|
|
35
|
+
"build>=1.2.2",
|
|
36
|
+
"mypy>=1.15",
|
|
37
|
+
"pytest>=8.3",
|
|
38
|
+
"pytest-asyncio>=0.25",
|
|
39
|
+
"ruff>=0.11",
|
|
40
|
+
"twine>=6.1",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.wheel]
|
|
44
|
+
packages = ["src/pi_agent"]
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.sdist]
|
|
47
|
+
only-include = ["src/pi_agent", "pyproject.toml", "README.md", "LICENSE", "CHANGELOG.md"]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
asyncio_mode = "auto"
|
|
51
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
markers = [
|
|
54
|
+
"integration: real local Pi runtime with a synthetic provider",
|
|
55
|
+
"live: explicit opt-in model-backed smoke tests",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.ruff]
|
|
59
|
+
target-version = "py311"
|
|
60
|
+
line-length = 100
|
|
61
|
+
|
|
62
|
+
[tool.ruff.lint]
|
|
63
|
+
select = ["E", "F", "I", "UP", "B", "ASYNC"]
|
|
64
|
+
ignore = ["ASYNC109"] # Public per-operation deadlines are part of the client interface.
|
|
65
|
+
|
|
66
|
+
[tool.mypy]
|
|
67
|
+
python_version = "3.11"
|
|
68
|
+
strict = true
|
|
69
|
+
files = ["src"]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Python access to an existing Pi agent runtime.
|
|
2
|
+
|
|
3
|
+
Importing this package never launches Pi or changes its configuration.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .client import AsyncPiClient
|
|
7
|
+
from .errors import (
|
|
8
|
+
PiBusyError,
|
|
9
|
+
PiCommandError,
|
|
10
|
+
PiError,
|
|
11
|
+
PiProcessError,
|
|
12
|
+
PiProtocolError,
|
|
13
|
+
PiResultOverflow,
|
|
14
|
+
PiRunError,
|
|
15
|
+
PiRunOwnershipError,
|
|
16
|
+
PiRunStartTimeout,
|
|
17
|
+
PiSubscriptionOverflow,
|
|
18
|
+
PiTimeoutError,
|
|
19
|
+
PiUIHandlerError,
|
|
20
|
+
PiVersionError,
|
|
21
|
+
)
|
|
22
|
+
from .sync import PiClient
|
|
23
|
+
from .types import Event, ImageContent, Limits, RunResult, SessionInfo, UsageSummary
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"AsyncPiClient",
|
|
27
|
+
"Event",
|
|
28
|
+
"ImageContent",
|
|
29
|
+
"Limits",
|
|
30
|
+
"PiBusyError",
|
|
31
|
+
"PiCommandError",
|
|
32
|
+
"PiClient",
|
|
33
|
+
"PiError",
|
|
34
|
+
"PiProcessError",
|
|
35
|
+
"PiProtocolError",
|
|
36
|
+
"PiResultOverflow",
|
|
37
|
+
"PiRunError",
|
|
38
|
+
"PiRunOwnershipError",
|
|
39
|
+
"PiRunStartTimeout",
|
|
40
|
+
"PiSubscriptionOverflow",
|
|
41
|
+
"PiTimeoutError",
|
|
42
|
+
"PiUIHandlerError",
|
|
43
|
+
"PiVersionError",
|
|
44
|
+
"RunResult",
|
|
45
|
+
"SessionInfo",
|
|
46
|
+
"UsageSummary",
|
|
47
|
+
]
|