pi-agent-rb 0.1.9 → 0.1.10
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +22 -2
- data/lib/pi_agent/session.rb +52 -8
- data/lib/pi_agent/version.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 764c10abd215cb94244b349a446dd3743637196556fe3b302abf0c221c78d554
|
|
4
|
+
data.tar.gz: 19cc0cc64de81a17d120dceffe88ad862c959c210d791400b1883e160648a0ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22022aa55d47d49cd2d9b547a2ee846e590dd4bbe3133a577b579662b806d560a99a852f0ee9667c5bdd9138cd32c6292f2d217cedf8e1d2acd1a76fd77ffbf3
|
|
7
|
+
data.tar.gz: aaa78bfe30ee3e2b9db5aab67b0eba26bbd6c8e62a3d3626aff496a0c345815fde43fe001894bccfbec01497fc8586244140a7f597d22cb73d825f034414e441
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.10] - 2026-06-25
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Bumped pinned upstream `pi-coding-agent` version to `0.80.2` (rolls up
|
|
14
|
+
0.80.0–0.80.2: the old global `@earendil-works/pi-ai` API moved to the
|
|
15
|
+
`@earendil-works/pi-ai/compat` entrypoint and the selective `/base`
|
|
16
|
+
provider entrypoints were removed; plus provider/auth resolution fixes
|
|
17
|
+
(Bedrock, Cloudflare, Fireworks, OpenAI Responses/Codex), session-name
|
|
18
|
+
newline normalization, and a `Ctrl+J` newline keybinding). These are
|
|
19
|
+
SDK/library-level changes; no changes to the RPC protocol surface or the
|
|
20
|
+
`--approve`/`--no-approve` flags this gem drives.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- `Session#follow_up` now accepts a block to drain the agent cycle the queued
|
|
24
|
+
message triggers, mirroring `prompt`'s block contract. It is race-free —
|
|
25
|
+
the event subscription is established before the message is sent, so none
|
|
26
|
+
of the cycle's events are missed.
|
|
27
|
+
- `Session#events`: a lower-level, prompt-less drain of the agent event
|
|
28
|
+
stream, for callers that subscribe before the cycle starts (e.g. from a
|
|
29
|
+
thread). Mirrors `prompt`'s block/Enumerator contract. (The class docstring
|
|
30
|
+
already referenced this method; it now exists.)
|
|
31
|
+
|
|
10
32
|
## [0.1.9] - 2026-06-22
|
|
11
33
|
|
|
12
34
|
### Changed
|
data/README.md
CHANGED
|
@@ -14,7 +14,7 @@ building interactive agent UIs (web, TUI) on top of pi.
|
|
|
14
14
|
|
|
15
15
|
- Ruby 3.3+
|
|
16
16
|
- `pi` on `PATH` (install via `npm i -g @earendil-works/pi-coding-agent`)
|
|
17
|
-
- This gem is pinned against pi `0.
|
|
17
|
+
- This gem is pinned against pi `0.80.2`; other versions may work but are not verified.
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -69,7 +69,7 @@ end
|
|
|
69
69
|
|
|
70
70
|
Other session methods:
|
|
71
71
|
|
|
72
|
-
- Prompting: `steer`, `follow_up`, `abort`
|
|
72
|
+
- Prompting: `steer`, `follow_up`, `events`, `abort`
|
|
73
73
|
- Model: `set_model`, `cycle_model`, `available_models`, `set_thinking`
|
|
74
74
|
- State: `get_state`, `messages`, `last_assistant_text`, `session_stats`
|
|
75
75
|
- Context: `compact`
|
|
@@ -79,6 +79,26 @@ Other session methods:
|
|
|
79
79
|
`set_model` accepts either `set_model("anthropic/claude-sonnet-4-5")` or
|
|
80
80
|
`set_model("anthropic", "claude-sonnet-4-5")`.
|
|
81
81
|
|
|
82
|
+
A `prompt` streams one agent cycle (`agent_start`..`agent_end`). A message
|
|
83
|
+
queued with `follow_up` runs in a *later* cycle; pass a block to `follow_up`
|
|
84
|
+
to drain that cycle. Like `prompt`, it yields each `Event` until `agent_end`:
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
PiAgent.session do |session|
|
|
88
|
+
session.prompt("Draft a haiku") { |e| print e.delta if e.type == :message_update }
|
|
89
|
+
session.follow_up("Now translate it to French") { |e| print e.delta if e.type == :message_update }
|
|
90
|
+
end
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The block form is race-free: `follow_up` subscribes to the event stream
|
|
94
|
+
*before* sending the message, so none of the cycle's events are missed.
|
|
95
|
+
|
|
96
|
+
`events` is a lower-level, prompt-less drain of the same stream. Because it
|
|
97
|
+
subscribes lazily when iteration begins, it only works when you subscribe
|
|
98
|
+
*before* the cycle starts — e.g. begin iterating it from a thread, then
|
|
99
|
+
trigger the cycle. For the common follow-up case, prefer the block form
|
|
100
|
+
above.
|
|
101
|
+
|
|
82
102
|
### Images
|
|
83
103
|
|
|
84
104
|
`prompt`, `steer`, and `follow_up` accept an `images:` array. Entries
|
data/lib/pi_agent/session.rb
CHANGED
|
@@ -14,9 +14,11 @@ module PiAgent
|
|
|
14
14
|
# create/select step — the Session *is* the running pi process.
|
|
15
15
|
#
|
|
16
16
|
# v1 limitation: `prompt` streams one agent cycle (agent_start..agent_end).
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# `prompt
|
|
17
|
+
# A message queued with `follow_up` runs in a later cycle; pass a block to
|
|
18
|
+
# `follow_up` to drain that cycle race-free (it subscribes before sending).
|
|
19
|
+
# `events` is a prompt-less drain of the same stream for when you have
|
|
20
|
+
# already subscribed before the cycle starts. Bidirectional extension UI
|
|
21
|
+
# is not yet surfaced here.
|
|
20
22
|
class Session
|
|
21
23
|
# Max time to wait for the next event before assuming the agent stalled.
|
|
22
24
|
DEFAULT_EVENT_TIMEOUT = 300
|
|
@@ -44,6 +46,26 @@ module PiAgent
|
|
|
44
46
|
self
|
|
45
47
|
end
|
|
46
48
|
|
|
49
|
+
# Drain the event stream without submitting a new prompt. With a block,
|
|
50
|
+
# yields each Event until the cycle finishes (agent_end) and returns
|
|
51
|
+
# self; without a block, returns an Enumerator of Events.
|
|
52
|
+
#
|
|
53
|
+
# The subscription is established lazily, when iteration begins — so any
|
|
54
|
+
# cycle triggered *before* you call `events` may have already emitted
|
|
55
|
+
# events that are then missed. To drain a `follow_up` cycle race-free,
|
|
56
|
+
# pass a block to `follow_up` instead. Use `events` only when you
|
|
57
|
+
# subscribe before the cycle starts (e.g. from a thread that begins
|
|
58
|
+
# iterating, then trigger the cycle). With nothing queued, it blocks
|
|
59
|
+
# for `event_timeout` (300s default).
|
|
60
|
+
def events(event_timeout: DEFAULT_EVENT_TIMEOUT, &block)
|
|
61
|
+
stream = subscribed_stream(event_timeout: event_timeout)
|
|
62
|
+
|
|
63
|
+
return stream unless block
|
|
64
|
+
|
|
65
|
+
stream.each(&block)
|
|
66
|
+
self
|
|
67
|
+
end
|
|
68
|
+
|
|
47
69
|
# Queue a steering message while the agent is running. Delivered after
|
|
48
70
|
# the current assistant turn finishes its tool calls, before the next
|
|
49
71
|
# LLM call. Fire-and-forget; raises on rejection.
|
|
@@ -53,8 +75,21 @@ module PiAgent
|
|
|
53
75
|
end
|
|
54
76
|
|
|
55
77
|
# Queue a follow-up message, delivered only after the agent stops.
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
#
|
|
79
|
+
# Without a block this is fire-and-forget: it queues the message and
|
|
80
|
+
# returns self. With a block it drains the resulting agent cycle
|
|
81
|
+
# race-free — the subscription is established *before* the message is
|
|
82
|
+
# sent, so no events are missed — yielding each Event until agent_end
|
|
83
|
+
# and returning self. Prefer the block form to consume a follow-up;
|
|
84
|
+
# the standalone `events` drain only works if you subscribe first.
|
|
85
|
+
def follow_up(message, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT, &block)
|
|
86
|
+
params = message_params(message, images)
|
|
87
|
+
unless block
|
|
88
|
+
@client.request("follow_up", params).value!(timeout: DEFAULT_ACK_TIMEOUT)
|
|
89
|
+
return self
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
event_stream("follow_up", params, event_timeout: event_timeout).each(&block)
|
|
58
93
|
self
|
|
59
94
|
end
|
|
60
95
|
|
|
@@ -207,14 +242,23 @@ module PiAgent
|
|
|
207
242
|
end
|
|
208
243
|
|
|
209
244
|
# Subscribe, send the command, then yield Events from the notification
|
|
210
|
-
# stream until a terminal event.
|
|
211
|
-
# iteration of the returned Enumerator so cleanup is deterministic.
|
|
245
|
+
# stream until a terminal event.
|
|
212
246
|
def event_stream(type, params, event_timeout:)
|
|
247
|
+
subscribed_stream(event_timeout: event_timeout) do
|
|
248
|
+
@client.request(type, params).value!(timeout: DEFAULT_ACK_TIMEOUT)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Subscribe, run `before_pump` (e.g. send a command) once the
|
|
253
|
+
# subscription is live so no events are missed in the gap, then yield
|
|
254
|
+
# Events until a terminal event. The subscription is scoped to one
|
|
255
|
+
# iteration of the returned Enumerator so cleanup is deterministic.
|
|
256
|
+
def subscribed_stream(event_timeout:, &before_pump)
|
|
213
257
|
Enumerator.new do |yielder|
|
|
214
258
|
queue = Queue.new
|
|
215
259
|
handle = @client.subscribe { |msg| queue << msg }
|
|
216
260
|
begin
|
|
217
|
-
|
|
261
|
+
before_pump&.call
|
|
218
262
|
pump_events(queue, yielder, event_timeout)
|
|
219
263
|
ensure
|
|
220
264
|
@client.unsubscribe(handle)
|
data/lib/pi_agent/version.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module PiAgent
|
|
4
|
-
VERSION = "0.1.
|
|
4
|
+
VERSION = "0.1.10"
|
|
5
5
|
|
|
6
6
|
# Pinned upstream pi-coding-agent version this gem is verified against.
|
|
7
7
|
# See: https://www.npmjs.com/package/@earendil-works/pi-coding-agent
|
|
8
|
-
SUPPORTED_PI_VERSION = "0.
|
|
8
|
+
SUPPORTED_PI_VERSION = "0.80.2"
|
|
9
9
|
end
|