claude_agent 0.7.13 → 0.7.14
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 +8 -0
- data/lib/claude_agent/client.rb +0 -2
- data/lib/claude_agent/control_protocol/lifecycle.rb +4 -1
- data/lib/claude_agent/control_protocol/messaging.rb +4 -7
- data/lib/claude_agent/control_protocol.rb +23 -0
- data/lib/claude_agent/conversation.rb +8 -1
- data/lib/claude_agent/query.rb +0 -2
- data/lib/claude_agent/transport/subprocess.rb +2 -2
- data/lib/claude_agent/version.rb +1 -1
- 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: 6b6188550282e29001c6bf2996842b5c11cd013de37aeeded995c982cef67399
|
|
4
|
+
data.tar.gz: 33e7d2e6b000d5f085093f236fd531c136e3711be170c3af4c11715fbdedda77
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b5ec2de8caa5ef32681e671645dd6d6540d58f86221c3d99186cc7ab7e9a076b892fe41c16e2472b94399c296439b5ceba72f573eb0b218b8b2ff507661d162f
|
|
7
|
+
data.tar.gz: c00a1312f295f1f15949cac076155750b2259f5412cfb0cbe6acffa8bcb789927887bb58ebacdc94fd92fa492851f985b975a14bb31abe68b78e23ce4fda8c5d
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.14] - 2026-03-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Replace busy-wait polling (`Queue#pop(true)` + `sleep 0.01`) in `ControlProtocol::Messaging#each_message` with blocking `Queue#pop` and `:done` sentinel, eliminating CPU waste and up-to-10ms per-message latency
|
|
14
|
+
- Fix `Conversation#partition_kwargs` misrouting `on_elicitation` (and any future `on_*` Options attributes) as event callbacks instead of forwarding to Options; now uses explicit allowlist derived from `EventHandler::EVENTS`
|
|
15
|
+
- Remove global `ENV["CLAUDE_CODE_ENTRYPOINT"]` mutation from `Client#connect` and `ClaudeAgent.query`; the subprocess already receives this via `Options#to_env`
|
|
16
|
+
- Log stderr callback errors instead of silently swallowing them in `Transport::Subprocess`
|
|
17
|
+
|
|
10
18
|
## [0.7.13] - 2026-03-14
|
|
11
19
|
|
|
12
20
|
### Added
|
data/lib/claude_agent/client.rb
CHANGED
|
@@ -77,8 +77,6 @@ module ClaudeAgent
|
|
|
77
77
|
def connect(prompt: nil)
|
|
78
78
|
raise CLIConnectionError, "Already connected" if @connected
|
|
79
79
|
|
|
80
|
-
ENV["CLAUDE_CODE_ENTRYPOINT"] = "sdk-rb-client"
|
|
81
|
-
|
|
82
80
|
logger.info("client") { "Connecting" }
|
|
83
81
|
@protocol = ControlProtocol.new(transport: @transport, options: @options)
|
|
84
82
|
@protocol.permission_queue = @permission_queue
|
|
@@ -72,7 +72,8 @@ module ClaudeAgent
|
|
|
72
72
|
@condition.broadcast
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
#
|
|
75
|
+
# Unblock the consumer and terminate the transport
|
|
76
|
+
@message_queue.push(:done)
|
|
76
77
|
@transport.terminate if @transport.respond_to?(:terminate)
|
|
77
78
|
end
|
|
78
79
|
|
|
@@ -107,6 +108,8 @@ module ClaudeAgent
|
|
|
107
108
|
rescue AbortError
|
|
108
109
|
logger.debug("protocol") { "Reader thread exiting: abort signal" }
|
|
109
110
|
@running = false
|
|
111
|
+
ensure
|
|
112
|
+
@message_queue.push(:done)
|
|
110
113
|
end
|
|
111
114
|
end
|
|
112
115
|
end
|
|
@@ -26,19 +26,16 @@ module ClaudeAgent
|
|
|
26
26
|
def each_message
|
|
27
27
|
return enum_for(:each_message) unless block_given?
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
# Check abort signal
|
|
29
|
+
loop do
|
|
31
30
|
@abort_signal&.check!
|
|
32
31
|
|
|
32
|
+
raw = @message_queue.pop # blocks until data available
|
|
33
|
+
break if raw == :done # sentinel from reader_loop
|
|
34
|
+
|
|
33
35
|
begin
|
|
34
|
-
raw = @message_queue.pop(true)
|
|
35
36
|
message = @parser.parse(raw)
|
|
36
37
|
yield message
|
|
37
|
-
rescue ThreadError
|
|
38
|
-
# Queue empty, wait a bit
|
|
39
|
-
sleep 0.01
|
|
40
38
|
rescue AbortError
|
|
41
|
-
# Re-raise abort errors
|
|
42
39
|
raise
|
|
43
40
|
rescue => e
|
|
44
41
|
logger.warn("protocol") { "Message parse error: #{e.message}" }
|
|
@@ -25,6 +25,28 @@ module ClaudeAgent
|
|
|
25
25
|
# protocol.start
|
|
26
26
|
# protocol.each_message { |msg| process(msg) }
|
|
27
27
|
#
|
|
28
|
+
# State ownership across modules:
|
|
29
|
+
#
|
|
30
|
+
# Owned by Lifecycle:
|
|
31
|
+
# @running, @reader_thread
|
|
32
|
+
#
|
|
33
|
+
# Owned by RequestHandling:
|
|
34
|
+
# @hook_callbacks
|
|
35
|
+
#
|
|
36
|
+
# Owned by Primitives:
|
|
37
|
+
# write_message, read helpers (stateless)
|
|
38
|
+
#
|
|
39
|
+
# Owned by Commands:
|
|
40
|
+
# interrupt, rewind (stateless, uses @transport)
|
|
41
|
+
#
|
|
42
|
+
# Shared (initialized here, used by multiple modules):
|
|
43
|
+
# @transport, @options, @parser, @server_info
|
|
44
|
+
# @request_counter, @pending_requests, @pending_results (Primitives + RequestHandling)
|
|
45
|
+
# @mutex, @condition (Primitives + Lifecycle + RequestHandling)
|
|
46
|
+
# @message_queue (Lifecycle + Messaging)
|
|
47
|
+
# @abort_signal (Lifecycle + Messaging)
|
|
48
|
+
# @permission_queue (RequestHandling, set externally by Client)
|
|
49
|
+
#
|
|
28
50
|
class ControlProtocol
|
|
29
51
|
DEFAULT_TIMEOUT = 60
|
|
30
52
|
REQUEST_ID_PREFIX = "req"
|
|
@@ -78,6 +100,7 @@ module ClaudeAgent
|
|
|
78
100
|
|
|
79
101
|
# Abort signal from options
|
|
80
102
|
@abort_signal = options&.abort_signal
|
|
103
|
+
@abort_signal&.on_abort { @message_queue.push(:done) }
|
|
81
104
|
end
|
|
82
105
|
|
|
83
106
|
private
|
|
@@ -193,6 +193,13 @@ module ClaudeAgent
|
|
|
193
193
|
|
|
194
194
|
private
|
|
195
195
|
|
|
196
|
+
# Callback keys derived from EventHandler events + aliases + on_permission
|
|
197
|
+
CALLBACK_KEYS = (
|
|
198
|
+
EventHandler::EVENTS.map { |e| :"on_#{e}" } +
|
|
199
|
+
CALLBACK_ALIASES.keys +
|
|
200
|
+
[ :on_permission ]
|
|
201
|
+
).freeze
|
|
202
|
+
|
|
196
203
|
def partition_kwargs(kwargs)
|
|
197
204
|
callbacks = {}
|
|
198
205
|
conversation_kwargs = {}
|
|
@@ -201,7 +208,7 @@ module ClaudeAgent
|
|
|
201
208
|
kwargs.each do |key, value|
|
|
202
209
|
if CONVERSATION_KEYS.include?(key)
|
|
203
210
|
conversation_kwargs[key] = value
|
|
204
|
-
elsif
|
|
211
|
+
elsif CALLBACK_KEYS.include?(key)
|
|
205
212
|
callbacks[key] = value
|
|
206
213
|
else
|
|
207
214
|
options_kwargs[key] = value
|
data/lib/claude_agent/query.rb
CHANGED
|
@@ -41,8 +41,6 @@ module ClaudeAgent
|
|
|
41
41
|
transport ||= Transport::Subprocess.new(options: options)
|
|
42
42
|
|
|
43
43
|
Enumerator.new do |yielder|
|
|
44
|
-
# Set entrypoint environment variable
|
|
45
|
-
ENV["CLAUDE_CODE_ENTRYPOINT"] = "sdk-rb"
|
|
46
44
|
query_logger = options.effective_logger
|
|
47
45
|
query_logger.info("query") { "Starting query" }
|
|
48
46
|
query_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
@@ -387,8 +387,8 @@ module ClaudeAgent
|
|
|
387
387
|
@stderr.each_line do |line|
|
|
388
388
|
# Call callback if provided, otherwise just drain
|
|
389
389
|
@options.stderr_callback&.call(line.chomp)
|
|
390
|
-
rescue
|
|
391
|
-
|
|
390
|
+
rescue => e
|
|
391
|
+
logger.debug("transport") { "stderr callback error: #{e.message}" }
|
|
392
392
|
end
|
|
393
393
|
rescue IOError
|
|
394
394
|
# Stream closed, exit thread
|
data/lib/claude_agent/version.rb
CHANGED