pi-agent-rb 0.2.1 → 0.2.2
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 +43 -0
- data/README.md +28 -2
- data/lib/pi_agent/client.rb +7 -2
- data/lib/pi_agent/extension_ui.rb +21 -7
- data/lib/pi_agent/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: db7831746ed3cbbd46e215293bb6a6e34dff2e31915b47a733737aa91ae15e4b
|
|
4
|
+
data.tar.gz: 61af774b3c9125f05aa4cfcafe11e5af31459a7db8a796487ed8857f5b677c1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb4424e7698e4481dbda464cd5df382a3a555316ee923d5ca5d55faf9692701b606932d753e13ebf5dacf94c878868c7455e401786e1b5667f0d8daaccbf5c15
|
|
7
|
+
data.tar.gz: ccc703e5e81c2bf3ff3b47fa2605a391eeea66e9f1cee7603fba83db2e74f948a7c4b14b90db79ade99a5d8024513619c8764595a9d9456a8af6ede8b34815d1
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.2] - 2026-07-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Added the optional `on_extension_ui_error` callback to `PiAgent.open`,
|
|
14
|
+
`PiAgent.session`, and `PiAgent::Client`. Applications can now observe an
|
|
15
|
+
Extension UI handler exception together with its request while the dialog
|
|
16
|
+
still fails closed as cancelled. Exceptions raised by the observer are also
|
|
17
|
+
isolated so they cannot prevent the cancellation response.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Bumped pinned upstream `pi-coding-agent` version to `0.83.0` (from
|
|
21
|
+
`0.82.1`). This is a CLI/provider/extension batch; none of the changes
|
|
22
|
+
alter the JSONL RPC command/response shapes this gem drives, so no gem
|
|
23
|
+
API change is required.
|
|
24
|
+
- Adds `pi auth print-api-key` and `pi auth print-bearer-token` for
|
|
25
|
+
exporting configured credentials to external clients, with automatic
|
|
26
|
+
OAuth refresh and configurable minimum token validity. These are CLI
|
|
27
|
+
subcommands, outside the RPC surface this gem speaks.
|
|
28
|
+
- Adds headless OpenRouter sign-in (paste the redirect URL or
|
|
29
|
+
authorization code when the loopback callback is unavailable) and
|
|
30
|
+
Claude Opus 5 on GitHub Copilot with adaptive thinking and a 1M
|
|
31
|
+
context window. Both are provider/`/login` concerns.
|
|
32
|
+
- Exposes the session's resolved model scope as `ctx.scopedModels` to
|
|
33
|
+
extensions, adds a `"pending"` stop reason for partial streaming
|
|
34
|
+
messages, and surfaces raw provider stop reasons across Google,
|
|
35
|
+
Anthropic, Bedrock, Mistral, and OpenAI (unmapped terminal reasons now
|
|
36
|
+
surface as provider errors). These are SDK/extension and
|
|
37
|
+
provider-stream concerns; RPC event payloads still flow through
|
|
38
|
+
`PiAgent::Event` transparently.
|
|
39
|
+
- **Breaking for TypeScript extensions only:** upstream upgraded bundled
|
|
40
|
+
TypeBox aliases to 1.3.7, removing deprecated APIs (`Type.Base`,
|
|
41
|
+
`Type.Awaited`, `Type.Promise`, `Type.AsyncIterator`, `Type.Iterator`,
|
|
42
|
+
`Type.Options`, `Value.Mutate`) and fixing nullable-array tool-argument
|
|
43
|
+
validation. This does not affect this Ruby gem, which does not author
|
|
44
|
+
TypeBox schemas.
|
|
45
|
+
- The remainder are inherited fixes (tool-output expansion status line,
|
|
46
|
+
file-backed `SYSTEM.md`/`APPEND_SYSTEM.md` startup listing, worktree
|
|
47
|
+
context double-load, llama.cpp usage accounting, session replacement
|
|
48
|
+
during active responses, Git package install retries, `/model`
|
|
49
|
+
selector, direct RPC bash bypassing `user_bash` handlers, resource
|
|
50
|
+
metadata, and assorted provider fixes) that leave the RPC contract
|
|
51
|
+
unchanged.
|
|
52
|
+
|
|
10
53
|
## [0.2.1] - 2026-07-25
|
|
11
54
|
|
|
12
55
|
### 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` 0.80.4+ 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.83.0`; other versions may work but are not verified.
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -105,7 +105,7 @@ Pi emits `agent_end` after each low-level agent run, but may then retry,
|
|
|
105
105
|
compact and retry, or process queued continuations. It emits
|
|
106
106
|
`agent_settled` only when no automatic work remains, so high-level streams
|
|
107
107
|
use that as their completion boundary. Upstream added the RPC event in pi
|
|
108
|
-
0.80.4; it is available in this gem's pinned pi 0.
|
|
108
|
+
0.80.4; it is available in this gem's pinned pi 0.83.0.
|
|
109
109
|
|
|
110
110
|
`events` is a lower-level, prompt-less drain of the same stream. Because it
|
|
111
111
|
subscribes lazily when iteration begins, it only works when you subscribe
|
|
@@ -175,6 +175,32 @@ Returning `nil` from a dialog handler cancels it. With no handler,
|
|
|
175
175
|
dialogs are auto-cancelled so the agent never hangs. Handlers run on
|
|
176
176
|
their own thread and never block the event stream.
|
|
177
177
|
|
|
178
|
+
If a handler raises, the dialog is cancelled as a fail-safe. Use
|
|
179
|
+
`on_extension_ui_error` when the application needs to observe those failures:
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
on_ui_error = lambda do |error, request|
|
|
183
|
+
logger.error(
|
|
184
|
+
"Extension UI handler failed",
|
|
185
|
+
error: error.class.name,
|
|
186
|
+
request_id: request.id,
|
|
187
|
+
method: request.method
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
PiAgent.session(
|
|
192
|
+
extension_ui: handler,
|
|
193
|
+
on_extension_ui_error: on_ui_error
|
|
194
|
+
) do |session|
|
|
195
|
+
session.prompt("Refactor the parser") { |e| ... }
|
|
196
|
+
end
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The observer runs on the same worker thread and cannot change the fail-safe
|
|
200
|
+
cancellation. If it raises, the dialog is still cancelled. Requests can contain
|
|
201
|
+
sensitive titles, messages, options, or prefilled text, so avoid logging
|
|
202
|
+
`request.raw` without application-specific filtering.
|
|
203
|
+
|
|
178
204
|
## Forking
|
|
179
205
|
|
|
180
206
|
```ruby
|
data/lib/pi_agent/client.rb
CHANGED
|
@@ -52,8 +52,9 @@ module PiAgent
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def initialize(bin: nil, args: DEFAULT_ARGS, env: {}, cwd: nil, approve: nil,
|
|
55
|
-
extension_ui: nil, transport_factory: nil)
|
|
55
|
+
extension_ui: nil, on_extension_ui_error: nil, transport_factory: nil)
|
|
56
56
|
@extension_ui_handler = extension_ui
|
|
57
|
+
@extension_ui_error_handler = on_extension_ui_error
|
|
57
58
|
args = [*args, approve ? "--approve" : "--no-approve"] unless approve.nil?
|
|
58
59
|
@transport_factory = transport_factory || build_subprocess_factory(bin, args, env, cwd)
|
|
59
60
|
@pending = {}
|
|
@@ -70,7 +71,11 @@ module PiAgent
|
|
|
70
71
|
on_message: method(:handle_message),
|
|
71
72
|
on_stderr: method(:handle_stderr)
|
|
72
73
|
)
|
|
73
|
-
@extension_ui = ExtensionUI.new(
|
|
74
|
+
@extension_ui = ExtensionUI.new(
|
|
75
|
+
writer: @transport,
|
|
76
|
+
handler: @extension_ui_handler,
|
|
77
|
+
on_error: @extension_ui_error_handler
|
|
78
|
+
)
|
|
74
79
|
@transport.start
|
|
75
80
|
self
|
|
76
81
|
end
|
|
@@ -19,6 +19,7 @@ module PiAgent
|
|
|
19
19
|
# - fire-and-forget methods : return value ignored
|
|
20
20
|
#
|
|
21
21
|
# With no handler, dialogs are auto-cancelled so the agent never hangs.
|
|
22
|
+
# Handler failures also cancel the dialog; pass `on_error` to observe them.
|
|
22
23
|
class ExtensionUI
|
|
23
24
|
DIALOG_METHODS = %i[select confirm input editor].freeze
|
|
24
25
|
|
|
@@ -50,9 +51,10 @@ module PiAgent
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
53
|
-
def initialize(writer:, handler: nil)
|
|
54
|
+
def initialize(writer:, handler: nil, on_error: nil)
|
|
54
55
|
@writer = writer
|
|
55
56
|
@handler = handler
|
|
57
|
+
@on_error = on_error
|
|
56
58
|
@threads = []
|
|
57
59
|
@mutex = Mutex.new
|
|
58
60
|
end
|
|
@@ -75,7 +77,21 @@ module PiAgent
|
|
|
75
77
|
private
|
|
76
78
|
|
|
77
79
|
def handle(request)
|
|
78
|
-
result = invoke_handler(request)
|
|
80
|
+
result, error = invoke_handler(request)
|
|
81
|
+
write_response(request, result)
|
|
82
|
+
notify_error(error, request) if error
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def invoke_handler(request)
|
|
86
|
+
return [nil, nil] if @handler.nil?
|
|
87
|
+
|
|
88
|
+
[@handler.call(request), nil]
|
|
89
|
+
rescue StandardError => e
|
|
90
|
+
# A raising handler cancels the dialog rather than hanging the agent.
|
|
91
|
+
[nil, e]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def write_response(request, result)
|
|
79
95
|
return unless request.dialog?
|
|
80
96
|
|
|
81
97
|
@writer.write(response_for(request, result))
|
|
@@ -83,12 +99,10 @@ module PiAgent
|
|
|
83
99
|
# Transport closed during shutdown; the response is moot.
|
|
84
100
|
end
|
|
85
101
|
|
|
86
|
-
def
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@handler.call(request)
|
|
102
|
+
def notify_error(error, request)
|
|
103
|
+
@on_error&.call(error, request)
|
|
90
104
|
rescue StandardError
|
|
91
|
-
#
|
|
105
|
+
# Error observers cannot prevent the fail-closed response.
|
|
92
106
|
nil
|
|
93
107
|
end
|
|
94
108
|
|
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.2.
|
|
4
|
+
VERSION = "0.2.2"
|
|
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.83.0"
|
|
9
9
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pi-agent-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- chagel
|
|
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
85
85
|
- !ruby/object:Gem::Version
|
|
86
86
|
version: '0'
|
|
87
87
|
requirements: []
|
|
88
|
-
rubygems_version:
|
|
88
|
+
rubygems_version: 3.6.9
|
|
89
89
|
specification_version: 4
|
|
90
90
|
summary: Ruby client for the pi coding agent (drives `pi --mode rpc`)
|
|
91
91
|
test_files: []
|