acp-sdk 0.9.0 → 0.11.0
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 +32 -0
- data/README.md +20 -8
- data/lib/acp/agent_connection/client.rb +31 -13
- data/lib/acp/agent_connection/optional_method/spec.rb +42 -0
- data/lib/acp/agent_connection/optional_method.rb +36 -0
- data/lib/acp/agent_connection.rb +67 -20
- data/lib/acp/agent_process.rb +0 -13
- data/lib/acp/client_connection/streams.rb +183 -0
- data/lib/acp/client_connection.rb +280 -338
- data/lib/acp/protocol.rb +33 -0
- data/lib/acp/request_error.rb +13 -13
- data/lib/acp/transport/cancellation.rb +13 -3
- data/lib/acp/transport/reply.rb +0 -2
- data/lib/acp/transport/stderr_logger.rb +1 -2
- data/lib/acp/transport/stdio.rb +25 -26
- data/lib/acp/types/audio_content.rb +3 -46
- data/lib/acp/types/auth_method_terminal.rb +3 -59
- data/lib/acp/types/available_commands_update.rb +3 -32
- data/lib/acp/types/boolean_property_schema.rb +3 -41
- data/lib/acp/types/check.rb +210 -0
- data/lib/acp/types/config_option_update.rb +3 -32
- data/lib/acp/types/content.rb +3 -29
- data/lib/acp/types/{elicitation_url_mode → create_elicitation_request/mode/form}/scope.rb +1 -1
- data/lib/acp/types/create_elicitation_request/mode/form.rb +3 -3
- data/lib/acp/types/{elicitation_form_mode → create_elicitation_request/mode/url}/scope.rb +1 -1
- data/lib/acp/types/create_elicitation_request/mode/url.rb +3 -3
- data/lib/acp/types/current_mode_update.rb +3 -29
- data/lib/acp/types/diff.rb +3 -41
- data/lib/acp/types/elicitation_accept_action.rb +3 -26
- data/lib/acp/types/elicitation_form_mode.rb +3 -33
- data/lib/acp/types/elicitation_url_mode.rb +3 -35
- data/lib/acp/types/embedded_resource.rb +3 -44
- data/lib/acp/types/image_content.rb +3 -58
- data/lib/acp/types/integer_property_schema.rb +3 -60
- data/lib/acp/types/mcp_server_http.rb +3 -44
- data/lib/acp/types/mcp_server_sse.rb +3 -44
- data/lib/acp/types/multi_select_property_schema.rb +3 -70
- data/lib/acp/types/number_property_schema.rb +3 -60
- data/lib/acp/types/parse_error.rb +37 -0
- data/lib/acp/types/plan.rb +3 -29
- data/lib/acp/types/resource_link.rb +3 -79
- data/lib/acp/types/selected_permission_outcome.rb +3 -26
- data/lib/acp/types/session_config_boolean.rb +3 -21
- data/lib/acp/types/session_config_select.rb +3 -33
- data/lib/acp/types/session_info_update.rb +3 -42
- data/lib/acp/types/string_multi_select_items.rb +3 -29
- data/lib/acp/types/string_property_schema.rb +3 -105
- data/lib/acp/types/terminal.rb +3 -29
- data/lib/acp/types/text_content.rb +3 -40
- data/lib/acp/types/tool_call.rb +3 -115
- data/lib/acp/types/unstable/compaction_summary_chunk.rb +3 -35
- data/lib/acp/types/unstable/compaction_update.rb +3 -56
- data/lib/acp/types/unstable/idle_state_update.rb +3 -40
- data/lib/acp/types/unstable/mcp_server_acp.rb +3 -35
- data/lib/acp/types/unstable/message_mcp_response/result.rb +1 -1
- data/lib/acp/types/unstable/nes_edit_suggestion.rb +3 -61
- data/lib/acp/types/unstable/nes_jump_suggestion.rb +3 -45
- data/lib/acp/types/unstable/nes_rename_suggestion.rb +3 -51
- data/lib/acp/types/unstable/nes_search_and_replace_suggestion.rb +3 -60
- data/lib/acp/types/unstable/notice.rb +3 -41
- data/lib/acp/types/unstable/plan_file.rb +3 -35
- data/lib/acp/types/unstable/plan_items.rb +3 -38
- data/lib/acp/types/unstable/plan_markdown.rb +3 -35
- data/lib/acp/types/unstable/plan_removed.rb +3 -26
- data/lib/acp/types/unstable/plan_update.rb +3 -33
- data/lib/acp/types/unstable/requires_action_state_update.rb +3 -21
- data/lib/acp/types/unstable/running_state_update.rb +3 -21
- data/lib/acp/types/unstable/session_message.rb +3 -56
- data/lib/acp/types/unstable/session_message_chunk.rb +3 -53
- data/lib/acp/types/unstable/subagent_update.rb +3 -65
- data/lib/acp/types/unstable/unknown_state_update.rb +3 -21
- data/lib/acp/types/unstable.rb +20 -20
- data/lib/acp/types/usage_update.rb +3 -41
- data/lib/acp/types.rb +7 -246
- data/lib/acp/version.rb +1 -1
- data/sig/generated/acp/agent_connection/client.rbs +25 -15
- data/sig/generated/acp/agent_connection/optional_method/spec.rbs +32 -0
- data/sig/generated/acp/agent_connection/optional_method.rbs +3 -0
- data/sig/generated/acp/agent_connection.rbs +34 -13
- data/sig/generated/acp/agent_process.rbs +0 -13
- data/sig/generated/acp/client_connection/streams.rbs +94 -0
- data/sig/generated/acp/client_connection.rbs +128 -131
- data/sig/generated/acp/protocol.rbs +9 -0
- data/sig/generated/acp/request_error.rbs +11 -13
- data/sig/generated/acp/transport/cancellation.rbs +9 -3
- data/sig/generated/acp/transport/reply.rbs +0 -2
- data/sig/generated/acp/transport/stderr_logger.rbs +1 -2
- data/sig/generated/acp/transport/stdio.rbs +14 -22
- data/sig/generated/acp/types/audio_content.rbs +1 -27
- data/sig/generated/acp/types/auth_method_terminal.rbs +1 -35
- data/sig/generated/acp/types/available_commands_update.rbs +1 -19
- data/sig/generated/acp/types/boolean_property_schema.rbs +1 -27
- data/sig/generated/acp/types/check.rbs +115 -0
- data/sig/generated/acp/types/config_option_update.rbs +1 -19
- data/sig/generated/acp/types/content.rbs +1 -19
- data/sig/generated/acp/types/{elicitation_url_mode → create_elicitation_request/mode/form}/scope.rbs +2 -2
- data/sig/generated/acp/types/create_elicitation_request/mode/form.rbs +3 -3
- data/sig/generated/acp/types/{elicitation_form_mode → create_elicitation_request/mode/url}/scope.rbs +2 -2
- data/sig/generated/acp/types/create_elicitation_request/mode/url.rbs +3 -3
- data/sig/generated/acp/types/current_mode_update.rbs +1 -19
- data/sig/generated/acp/types/diff.rbs +1 -27
- data/sig/generated/acp/types/elicitation_accept_action.rbs +1 -15
- data/sig/generated/acp/types/elicitation_form_mode.rbs +1 -19
- data/sig/generated/acp/types/elicitation_url_mode.rbs +1 -23
- data/sig/generated/acp/types/embedded_resource.rbs +1 -23
- data/sig/generated/acp/types/image_content.rbs +1 -31
- data/sig/generated/acp/types/integer_property_schema.rbs +1 -35
- data/sig/generated/acp/types/mcp_server_http.rbs +1 -27
- data/sig/generated/acp/types/mcp_server_sse.rbs +1 -27
- data/sig/generated/acp/types/multi_select_property_schema.rbs +1 -39
- data/sig/generated/acp/types/number_property_schema.rbs +1 -35
- data/sig/generated/acp/types/parse_error.rbs +22 -0
- data/sig/generated/acp/types/plan.rbs +1 -19
- data/sig/generated/acp/types/resource_link.rbs +1 -43
- data/sig/generated/acp/types/selected_permission_outcome.rbs +1 -19
- data/sig/generated/acp/types/session_config_boolean.rbs +1 -15
- data/sig/generated/acp/types/session_config_select.rbs +1 -19
- data/sig/generated/acp/types/session_info_update.rbs +1 -23
- data/sig/generated/acp/types/string_multi_select_items.rbs +1 -19
- data/sig/generated/acp/types/string_property_schema.rbs +1 -51
- data/sig/generated/acp/types/terminal.rbs +1 -19
- data/sig/generated/acp/types/text_content.rbs +1 -23
- data/sig/generated/acp/types/tool_call.rbs +1 -51
- data/sig/generated/acp/types/unstable/compaction_summary_chunk.rbs +1 -23
- data/sig/generated/acp/types/unstable/compaction_update.rbs +1 -31
- data/sig/generated/acp/types/unstable/idle_state_update.rbs +1 -23
- data/sig/generated/acp/types/unstable/mcp_server_acp.rbs +1 -23
- data/sig/generated/acp/types/unstable/nes_edit_suggestion.rbs +1 -31
- data/sig/generated/acp/types/unstable/nes_jump_suggestion.rbs +1 -27
- data/sig/generated/acp/types/unstable/nes_rename_suggestion.rbs +1 -31
- data/sig/generated/acp/types/unstable/nes_search_and_replace_suggestion.rbs +1 -35
- data/sig/generated/acp/types/unstable/notice.rbs +1 -27
- data/sig/generated/acp/types/unstable/plan_file.rbs +1 -23
- data/sig/generated/acp/types/unstable/plan_items.rbs +1 -23
- data/sig/generated/acp/types/unstable/plan_markdown.rbs +1 -23
- data/sig/generated/acp/types/unstable/plan_removed.rbs +1 -19
- data/sig/generated/acp/types/unstable/plan_update.rbs +1 -19
- data/sig/generated/acp/types/unstable/requires_action_state_update.rbs +1 -15
- data/sig/generated/acp/types/unstable/running_state_update.rbs +1 -15
- data/sig/generated/acp/types/unstable/session_message.rbs +1 -31
- data/sig/generated/acp/types/unstable/session_message_chunk.rbs +1 -31
- data/sig/generated/acp/types/unstable/subagent_update.rbs +1 -35
- data/sig/generated/acp/types/unstable/unknown_state_update.rbs +1 -15
- data/sig/generated/acp/types/usage_update.rbs +1 -27
- data/sig/generated/acp/types.rbs +6 -143
- data/sig/manual/acp/agent_connection.rbs +28 -28
- data/sig/manual/acp/client_connection.rbs +7 -2
- data/sig/manual/acp/{agent_connection/optional_method/logout.rbs → protocol.rbs} +3 -3
- data/sig/manual/acp/transport/stdio.rbs +0 -2
- data/sig/manual/acp/transport.rbs +25 -2
- metadata +17 -29
- data/lib/acp/agent_connection/optional_method/authenticate.rb +0 -21
- data/lib/acp/agent_connection/optional_method/close_session.rb +0 -21
- data/lib/acp/agent_connection/optional_method/delete_session.rb +0 -21
- data/lib/acp/agent_connection/optional_method/list_sessions.rb +0 -21
- data/lib/acp/agent_connection/optional_method/load_session.rb +0 -21
- data/lib/acp/agent_connection/optional_method/logout.rb +0 -21
- data/lib/acp/agent_connection/optional_method/resume_session.rb +0 -21
- data/lib/acp/types/content_chunk.rb +0 -40
- data/sig/generated/acp/agent_connection/optional_method/authenticate.rbs +0 -13
- data/sig/generated/acp/agent_connection/optional_method/close_session.rbs +0 -13
- data/sig/generated/acp/agent_connection/optional_method/delete_session.rbs +0 -13
- data/sig/generated/acp/agent_connection/optional_method/list_sessions.rbs +0 -13
- data/sig/generated/acp/agent_connection/optional_method/load_session.rbs +0 -13
- data/sig/generated/acp/agent_connection/optional_method/logout.rbs +0 -13
- data/sig/generated/acp/agent_connection/optional_method/resume_session.rbs +0 -13
- data/sig/generated/acp/types/content_chunk.rbs +0 -25
- data/sig/manual/acp/agent_connection/optional_method/authenticate.rbs +0 -6
- data/sig/manual/acp/agent_connection/optional_method/close_session.rbs +0 -6
- data/sig/manual/acp/agent_connection/optional_method/delete_session.rbs +0 -6
- data/sig/manual/acp/agent_connection/optional_method/list_sessions.rbs +0 -6
- data/sig/manual/acp/agent_connection/optional_method/load_session.rbs +0 -6
- data/sig/manual/acp/agent_connection/optional_method/resume_session.rbs +0 -6
data/lib/acp/types.rb
CHANGED
|
@@ -1,251 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ACP::Types
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# @rbs segments: Array[String | Integer]
|
|
12
|
-
# @rbs detail: String
|
|
13
|
-
# @rbs return: void
|
|
14
|
-
def initialize(segments, detail)
|
|
15
|
-
@segments = segments.freeze
|
|
16
|
-
@detail = detail
|
|
17
|
-
super("#{path}: #{detail}")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# @dynamic segments
|
|
21
|
-
attr_reader :segments #: Array[String | Integer]
|
|
22
|
-
|
|
23
|
-
# @rbs return: String
|
|
24
|
-
def path
|
|
25
|
-
segments.each_with_index.map do |segment, index|
|
|
26
|
-
if segment.is_a?(Integer) then "[#{segment}]"
|
|
27
|
-
elsif index.zero? then segment
|
|
28
|
-
else ".#{segment}"
|
|
29
|
-
end
|
|
30
|
-
end.join
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Prepends a container's segments so nested failures report an absolute path.
|
|
34
|
-
#
|
|
35
|
-
# @rbs *segments: (String | Integer)
|
|
36
|
-
# @rbs return: ACP::Types::ParseError
|
|
37
|
-
def prefix(*segments)
|
|
38
|
-
ParseError.new([*segments, *@segments], @detail)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# The guards the generated from_h methods call. Each takes the fetched value
|
|
43
|
-
# and the path to it, and raises ParseError naming that path when the value
|
|
44
|
-
# does not match the schema type. Nested from_h failures come back with the
|
|
45
|
-
# field path prepended, so the reported path is absolute.
|
|
46
|
-
module Check
|
|
47
|
-
# @rbs hash: Hash[String, untyped]
|
|
48
|
-
# @rbs key: String
|
|
49
|
-
# @rbs return: untyped
|
|
50
|
-
def self.key(hash, key)
|
|
51
|
-
hash.fetch(key)
|
|
52
|
-
rescue KeyError
|
|
53
|
-
raise ParseError.new([key], 'is required')
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# @rbs value: untyped
|
|
57
|
-
# @rbs path: String | Array[String | Integer]
|
|
58
|
-
# @rbs allow_nil: bool
|
|
59
|
-
# @rbs allow_unset: bool
|
|
60
|
-
# @rbs return: untyped
|
|
61
|
-
def self.string(value, path, allow_nil: false, allow_unset: false)
|
|
62
|
-
return value if value.is_a?(String) || skipped?(value, allow_nil, allow_unset)
|
|
63
|
-
|
|
64
|
-
raise ParseError.new(segments(path), "expected String, got #{describe(value)}")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# @rbs value: untyped
|
|
68
|
-
# @rbs path: String | Array[String | Integer]
|
|
69
|
-
# @rbs allow_nil: bool
|
|
70
|
-
# @rbs allow_unset: bool
|
|
71
|
-
# @rbs return: untyped
|
|
72
|
-
def self.boolean(value, path, allow_nil: false, allow_unset: false)
|
|
73
|
-
return value if value == true || value == false || skipped?(value, allow_nil, allow_unset)
|
|
74
|
-
|
|
75
|
-
raise ParseError.new(segments(path), "expected boolean, got #{describe(value)}")
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# @rbs value: untyped
|
|
79
|
-
# @rbs path: String | Array[String | Integer]
|
|
80
|
-
# @rbs min: Integer?
|
|
81
|
-
# @rbs max: Integer?
|
|
82
|
-
# @rbs allow_nil: bool
|
|
83
|
-
# @rbs allow_unset: bool
|
|
84
|
-
# @rbs return: untyped
|
|
85
|
-
def self.integer(value, path, min: nil, max: nil, allow_nil: false, allow_unset: false)
|
|
86
|
-
return value if (value.is_a?(Integer) && within?(value, min, max)) || skipped?(value, allow_nil, allow_unset)
|
|
87
|
-
|
|
88
|
-
raise ParseError.new(segments(path), "expected #{bounded('Integer', min, max)}, got #{describe(value)}")
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# @rbs value: untyped
|
|
92
|
-
# @rbs path: String | Array[String | Integer]
|
|
93
|
-
# @rbs min: Integer?
|
|
94
|
-
# @rbs max: Integer?
|
|
95
|
-
# @rbs allow_nil: bool
|
|
96
|
-
# @rbs allow_unset: bool
|
|
97
|
-
# @rbs return: untyped
|
|
98
|
-
def self.number(value, path, min: nil, max: nil, allow_nil: false, allow_unset: false)
|
|
99
|
-
return value if (value.is_a?(Numeric) && within?(value, min, max)) || skipped?(value, allow_nil, allow_unset)
|
|
100
|
-
|
|
101
|
-
raise ParseError.new(segments(path), "expected #{bounded('Numeric', min, max)}, got #{describe(value)}")
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# @rbs value: untyped
|
|
105
|
-
# @rbs path: String | Array[String | Integer]
|
|
106
|
-
# @rbs values: Array[untyped]
|
|
107
|
-
# @rbs allow_nil: bool
|
|
108
|
-
# @rbs allow_unset: bool
|
|
109
|
-
# @rbs return: untyped
|
|
110
|
-
def self.enum(value, path, values, allow_nil: false, allow_unset: false)
|
|
111
|
-
return value if values.include?(value) || skipped?(value, allow_nil, allow_unset)
|
|
112
|
-
|
|
113
|
-
expected = values.map(&:inspect).join(', ')
|
|
114
|
-
raise ParseError.new(segments(path), "expected one of #{expected}, got #{describe(value)}")
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# @rbs value: untyped
|
|
118
|
-
# @rbs path: String | Array[String | Integer]
|
|
119
|
-
# @rbs classes: Array[untyped]
|
|
120
|
-
# @rbs allow_nil: bool
|
|
121
|
-
# @rbs allow_unset: bool
|
|
122
|
-
# @rbs ?&items: (untyped, Array[String | Integer]) -> void
|
|
123
|
-
# @rbs return: untyped
|
|
124
|
-
def self.one_of(value, path, classes, allow_nil: false, allow_unset: false, &items)
|
|
125
|
-
return value if skipped?(value, allow_nil, allow_unset)
|
|
126
|
-
|
|
127
|
-
matched = classes.any? { |klass| value.is_a?(klass) }
|
|
128
|
-
unless matched
|
|
129
|
-
raise ParseError.new(segments(path), "expected #{classes.map(&:name).join(' | ')}, got #{describe(value)}")
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
return value unless value.is_a?(Array) && items
|
|
133
|
-
|
|
134
|
-
value.each_with_index { |item, index| yield(item, [*segments(path), index]) }
|
|
135
|
-
value
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# @rbs value: untyped
|
|
139
|
-
# @rbs path: String | Array[String | Integer]
|
|
140
|
-
# @rbs allow_nil: bool
|
|
141
|
-
# @rbs allow_unset: bool
|
|
142
|
-
# @rbs &check: (untyped, Array[String | Integer]) -> void
|
|
143
|
-
# @rbs return: untyped
|
|
144
|
-
def self.hash(value, path, allow_nil: false, allow_unset: false, &check)
|
|
145
|
-
return value if skipped?(value, allow_nil, allow_unset)
|
|
146
|
-
raise ParseError.new(segments(path), "expected object, got #{describe(value)}") unless value.is_a?(Hash)
|
|
147
|
-
|
|
148
|
-
parsed = {} #: Hash[String, untyped]
|
|
149
|
-
value.each { |key, item| parsed[key] = yield(item, [*segments(path), key]) }
|
|
150
|
-
parsed
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# @rbs value: untyped
|
|
154
|
-
# @rbs path: String | Array[String | Integer]
|
|
155
|
-
# @rbs allow_nil: bool
|
|
156
|
-
# @rbs allow_unset: bool
|
|
157
|
-
# @rbs &check: (untyped, Array[String | Integer]) -> void
|
|
158
|
-
# @rbs return: untyped
|
|
159
|
-
def self.array(value, path, allow_nil: false, allow_unset: false, &check)
|
|
160
|
-
return value if skipped?(value, allow_nil, allow_unset)
|
|
161
|
-
raise ParseError.new(segments(path), "expected array, got #{describe(value)}") unless value.is_a?(Array)
|
|
162
|
-
|
|
163
|
-
value.each_with_index.map { |item, index| yield(item, [*segments(path), index]) }
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# @rbs value: untyped
|
|
167
|
-
# @rbs path: String | Array[String | Integer]
|
|
168
|
-
# @rbs klass: untyped
|
|
169
|
-
# @rbs allow_nil: bool
|
|
170
|
-
# @rbs allow_unset: bool
|
|
171
|
-
# @rbs return: untyped
|
|
172
|
-
def self.object(value, path, klass, allow_nil: false, allow_unset: false)
|
|
173
|
-
return value if skipped?(value, allow_nil, allow_unset)
|
|
174
|
-
raise ParseError.new(segments(path), "expected object, got #{describe(value)}") unless value.is_a?(Hash)
|
|
175
|
-
|
|
176
|
-
begin
|
|
177
|
-
klass.from_h(value)
|
|
178
|
-
rescue ParseError => e
|
|
179
|
-
raise e.prefix(*segments(path))
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
# @rbs value: untyped
|
|
184
|
-
# @rbs path: String | Array[String | Integer]
|
|
185
|
-
# @rbs klass: untyped
|
|
186
|
-
# @rbs allow_nil: bool
|
|
187
|
-
# @rbs allow_unset: bool
|
|
188
|
-
# @rbs return: untyped
|
|
189
|
-
def self.objects(value, path, klass, allow_nil: false, allow_unset: false)
|
|
190
|
-
return value if skipped?(value, allow_nil, allow_unset)
|
|
191
|
-
raise ParseError.new(segments(path), "expected array, got #{describe(value)}") unless value.is_a?(Array)
|
|
192
|
-
|
|
193
|
-
value.each_with_index do |item, index|
|
|
194
|
-
next if item.is_a?(Hash)
|
|
195
|
-
|
|
196
|
-
raise ParseError.new([*segments(path), index], "expected object, got #{describe(item)}")
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
begin
|
|
200
|
-
klass.from_a(value)
|
|
201
|
-
rescue ParseError => e
|
|
202
|
-
raise e.prefix(*segments(path))
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
# @rbs value: untyped
|
|
207
|
-
# @rbs allow_nil: bool
|
|
208
|
-
# @rbs allow_unset: bool
|
|
209
|
-
# @rbs return: bool
|
|
210
|
-
def self.skipped?(value, allow_nil, allow_unset)
|
|
211
|
-
(value.nil? && allow_nil) || (allow_unset && value.equal?(:unset))
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# @rbs path: String | Array[String | Integer]
|
|
215
|
-
# @rbs return: Array[String | Integer]
|
|
216
|
-
def self.segments(path)
|
|
217
|
-
path.is_a?(Array) ? path : [path]
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# @rbs value: untyped
|
|
221
|
-
# @rbs return: String
|
|
222
|
-
def self.describe(value)
|
|
223
|
-
case value
|
|
224
|
-
when nil then 'null'
|
|
225
|
-
when true then 'true'
|
|
226
|
-
when false then 'false'
|
|
227
|
-
else value.class.name
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
# @rbs value: Numeric
|
|
232
|
-
# @rbs min: Integer?
|
|
233
|
-
# @rbs max: Integer?
|
|
234
|
-
# @rbs return: bool
|
|
235
|
-
def self.within?(value, min, max)
|
|
236
|
-
(min.nil? || value >= min) && (max.nil? || value <= max)
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
# @rbs name: String
|
|
240
|
-
# @rbs min: Integer?
|
|
241
|
-
# @rbs max: Integer?
|
|
242
|
-
# @rbs return: String
|
|
243
|
-
def self.bounded(name, min, max)
|
|
244
|
-
if min && max then "#{name} between #{min} and #{max}"
|
|
245
|
-
elsif min then "#{name} >= #{min}"
|
|
246
|
-
elsif max then "#{name} <= #{max}"
|
|
247
|
-
else name
|
|
248
|
-
end
|
|
249
|
-
end
|
|
4
|
+
# Lives on ACP::Types rather than ACP::Types::Unstable because the callers
|
|
5
|
+
# run in the stable-only load, where even naming the inner module would raise
|
|
6
|
+
# NameError.
|
|
7
|
+
#
|
|
8
|
+
# @rbs return: bool
|
|
9
|
+
def self.unstable_enabled?
|
|
10
|
+
!defined?(ACP::Types::Unstable).nil?
|
|
250
11
|
end
|
|
251
12
|
end
|
data/lib/acp/version.rb
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# Generated from lib/acp/agent_connection/client.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
class ACP::AgentConnection::Client
|
|
4
|
-
@
|
|
4
|
+
@mcp_advertised: bool
|
|
5
|
+
|
|
6
|
+
@peer: ACP::Transport::_Peer
|
|
5
7
|
|
|
6
8
|
# @dynamic capabilities, capabilities=
|
|
7
9
|
attr_accessor capabilities: ACP::Types::ClientCapabilities?
|
|
8
10
|
|
|
9
|
-
# @rbs peer: ACP::
|
|
11
|
+
# @rbs peer: ACP::Transport::_Peer
|
|
12
|
+
# @rbs mcp_advertised: bool
|
|
10
13
|
# @rbs return: void
|
|
11
|
-
def initialize: (peer: ACP::
|
|
14
|
+
def initialize: (peer: ACP::Transport::_Peer, ?mcp_advertised: bool) -> void
|
|
12
15
|
|
|
13
16
|
# @rbs session_id: String
|
|
14
17
|
# @rbs update: ACP::Types::SessionUpdate::t
|
|
@@ -20,13 +23,18 @@ class ACP::AgentConnection::Client
|
|
|
20
23
|
# @rbs return: void
|
|
21
24
|
def available_commands: (String session_id, Array[ACP::Types::AvailableCommand] commands) -> void
|
|
22
25
|
|
|
23
|
-
# Blocks the calling thread until the client answers or the connection
|
|
24
|
-
# closes.
|
|
25
|
-
#
|
|
26
26
|
# @rbs request: ACP::Types::RequestPermissionRequest
|
|
27
27
|
# @rbs return: ACP::Types::RequestPermissionResponse | ACP::RequestError
|
|
28
28
|
def request_permission: (ACP::Types::RequestPermissionRequest request) -> (ACP::Types::RequestPermissionResponse | ACP::RequestError)
|
|
29
29
|
|
|
30
|
+
# @rbs return: void
|
|
31
|
+
def cancel_requests: () -> void
|
|
32
|
+
|
|
33
|
+
# Always false off a handler thread.
|
|
34
|
+
#
|
|
35
|
+
# @rbs return: bool
|
|
36
|
+
def cancelled?: () -> bool
|
|
37
|
+
|
|
30
38
|
# @rbs request: ACP::Types::ReadTextFileRequest
|
|
31
39
|
# @rbs return: ACP::Types::ReadTextFileResponse | ACP::RequestError
|
|
32
40
|
def read_text_file: (ACP::Types::ReadTextFileRequest request) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError)
|
|
@@ -63,9 +71,11 @@ class ACP::AgentConnection::Client
|
|
|
63
71
|
# @rbs return: void
|
|
64
72
|
def complete_elicitation: (ACP::Types::CompleteElicitationNotification notification) -> void
|
|
65
73
|
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
|
|
74
|
+
# @rbs request: ACP::Types::Unstable::MessageMcpRequest
|
|
75
|
+
# @rbs return: (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError)
|
|
76
|
+
def mcp_message: (ACP::Types::Unstable::MessageMcpRequest request) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError)
|
|
77
|
+
|
|
78
|
+
# Extension methods have no schema to parse the result into.
|
|
69
79
|
#
|
|
70
80
|
# @rbs method: String
|
|
71
81
|
# @rbs params: untyped
|
|
@@ -80,14 +90,14 @@ class ACP::AgentConnection::Client
|
|
|
80
90
|
private
|
|
81
91
|
|
|
82
92
|
# @rbs rpc_method: String
|
|
83
|
-
# @rbs type: ACP::
|
|
84
|
-
# @rbs request: ACP::
|
|
93
|
+
# @rbs type: ACP::Transport::_Parser
|
|
94
|
+
# @rbs request: ACP::Transport::_Response
|
|
85
95
|
# @rbs return: untyped
|
|
86
|
-
def call: (String rpc_method, ACP::
|
|
96
|
+
def call: (String rpc_method, ACP::Transport::_Parser type, ACP::Transport::_Response request) -> untyped
|
|
87
97
|
|
|
88
98
|
# @rbs rpc_method: String
|
|
89
|
-
# @rbs type: ACP::
|
|
90
|
-
# @rbs request: ACP::
|
|
99
|
+
# @rbs type: ACP::Transport::_Parser
|
|
100
|
+
# @rbs request: ACP::Transport::_Response
|
|
91
101
|
# @rbs return: untyped
|
|
92
|
-
def terminal_call: (String rpc_method, ACP::
|
|
102
|
+
def terminal_call: (String rpc_method, ACP::Transport::_Parser type, ACP::Transport::_Response request) -> untyped
|
|
93
103
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated from lib/acp/agent_connection/optional_method/spec.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
class ACP::AgentConnection::OptionalMethod::Spec
|
|
4
|
+
# @dynamic rpc_method
|
|
5
|
+
attr_reader rpc_method: String
|
|
6
|
+
|
|
7
|
+
# @dynamic agent_method
|
|
8
|
+
attr_reader agent_method: Symbol
|
|
9
|
+
|
|
10
|
+
# @dynamic path
|
|
11
|
+
attr_reader path: Array[Symbol]
|
|
12
|
+
|
|
13
|
+
# @rbs rpc_method: String
|
|
14
|
+
# @rbs agent_method: Symbol
|
|
15
|
+
# @rbs path: Array[Symbol]
|
|
16
|
+
# @rbs return: void
|
|
17
|
+
def initialize: (rpc_method: String, agent_method: Symbol, path: Array[Symbol]) -> void
|
|
18
|
+
|
|
19
|
+
# Readers missing along the chain count as unadvertised, so the stable
|
|
20
|
+
# capabilities answer false for the unstable-only paths (fork, providers).
|
|
21
|
+
#
|
|
22
|
+
# @rbs initialize_response: ACP::Types::InitializeResponse
|
|
23
|
+
# @rbs return: bool
|
|
24
|
+
def advertised?: (ACP::Types::InitializeResponse initialize_response) -> bool
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# @rbs node: untyped
|
|
29
|
+
# @rbs name: Symbol
|
|
30
|
+
# @rbs return: untyped
|
|
31
|
+
def follow: (untyped node, Symbol name) -> untyped
|
|
32
|
+
end
|
|
@@ -15,18 +15,14 @@ class ACP::AgentConnection
|
|
|
15
15
|
|
|
16
16
|
@capabilities: ACP::Types::AgentCapabilities
|
|
17
17
|
|
|
18
|
-
@transport: ACP::
|
|
19
|
-
|
|
20
|
-
PROTOCOL_VERSION: Integer
|
|
21
|
-
|
|
22
|
-
OPTIONAL: Array[ACP::AgentConnection::_OptionalMethod]
|
|
18
|
+
@transport: ACP::Transport::_Transport
|
|
23
19
|
|
|
24
20
|
# The schema has no initialize capability for modes or config options: an
|
|
25
21
|
# agent offers them per session, in its session responses, so they are
|
|
26
22
|
# routed whenever the agent defines them.
|
|
27
23
|
PER_SESSION: Hash[String, Symbol]
|
|
28
24
|
|
|
29
|
-
# @rbs transport: ACP::
|
|
25
|
+
# @rbs transport: ACP::Transport::_Transport
|
|
30
26
|
# @rbs capabilities: ACP::Types::AgentCapabilities
|
|
31
27
|
# @rbs agent_info: ACP::Types::Implementation?
|
|
32
28
|
# @rbs auth_methods: Array[ACP::Types::AuthMethod::t]
|
|
@@ -35,7 +31,7 @@ class ACP::AgentConnection
|
|
|
35
31
|
# @rbs logger: ACP::Transport::_Logger
|
|
36
32
|
# @rbs &factory: (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent
|
|
37
33
|
# @rbs return: void
|
|
38
|
-
def initialize: (transport: ACP::
|
|
34
|
+
def initialize: (transport: ACP::Transport::_Transport, capabilities: ACP::Types::AgentCapabilities, ?agent_info: ACP::Types::Implementation?, ?auth_methods: Array[ACP::Types::AuthMethod::t], ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?logger: ACP::Transport::_Logger) { (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent } -> void
|
|
39
35
|
|
|
40
36
|
# @rbs return: Thread
|
|
41
37
|
def start: () -> Thread
|
|
@@ -44,8 +40,23 @@ class ACP::AgentConnection
|
|
|
44
40
|
|
|
45
41
|
# @rbs agent: ACP::AgentConnection::_Agent
|
|
46
42
|
# @rbs client: ACP::AgentConnection::Client
|
|
47
|
-
# @rbs return: Hash[String, ^(untyped) -> (ACP::
|
|
48
|
-
def requests: (ACP::AgentConnection::_Agent agent, ACP::AgentConnection::Client client) -> Hash[String, ^(untyped) -> (ACP::
|
|
43
|
+
# @rbs return: Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
|
|
44
|
+
def requests: (ACP::AgentConnection::_Agent agent, ACP::AgentConnection::Client client) -> Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
|
|
45
|
+
|
|
46
|
+
# The unstable request types are referenced while the hash is built, so
|
|
47
|
+
# without the guard start would raise NameError even for an agent that never
|
|
48
|
+
# advertises fork or providers.
|
|
49
|
+
#
|
|
50
|
+
# @rbs full: ACP::AgentConnection::_FullAgent
|
|
51
|
+
# @rbs return: Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
|
|
52
|
+
def unstable_requests: (ACP::AgentConnection::_FullAgent full) -> Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
|
|
53
|
+
|
|
54
|
+
# The unstable specs pair with the unstable request routes, which reference
|
|
55
|
+
# the unstable request classes, so both are only probed after the caller
|
|
56
|
+
# opted in with `require 'acp/types/unstable'`.
|
|
57
|
+
#
|
|
58
|
+
# @rbs return: Array[ACP::AgentConnection::OptionalMethod::Spec]
|
|
59
|
+
def optional_methods: () -> Array[ACP::AgentConnection::OptionalMethod::Spec]
|
|
49
60
|
|
|
50
61
|
# @rbs agent: ACP::AgentConnection::_Agent
|
|
51
62
|
# @rbs return: Hash[String, ^(untyped) -> void]
|
|
@@ -58,12 +69,22 @@ class ACP::AgentConnection
|
|
|
58
69
|
# @rbs return: void
|
|
59
70
|
def cancel: (ACP::AgentConnection::_Agent agent, untyped params) -> void
|
|
60
71
|
|
|
72
|
+
# @rbs return: bool
|
|
73
|
+
def mcp_acp_advertised?: () -> bool
|
|
74
|
+
|
|
75
|
+
# A notification has no reply to carry a parse failure.
|
|
76
|
+
#
|
|
77
|
+
# @rbs agent: ACP::AgentConnection::_Agent
|
|
78
|
+
# @rbs params: untyped
|
|
79
|
+
# @rbs return: void
|
|
80
|
+
def mcp_message_notification: (ACP::AgentConnection::_Agent agent, untyped params) -> void
|
|
81
|
+
|
|
61
82
|
# Generated from_h raises on a missing key or a value of the wrong shape.
|
|
62
83
|
#
|
|
63
|
-
# @rbs type: ACP::
|
|
64
|
-
# @rbs &handle: (untyped) -> (ACP::
|
|
65
|
-
# @rbs return: ^(untyped) -> (ACP::
|
|
66
|
-
def route: (ACP::
|
|
84
|
+
# @rbs type: ACP::Transport::_Parser
|
|
85
|
+
# @rbs &handle: (untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
|
|
86
|
+
# @rbs return: ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
|
|
87
|
+
def route: (ACP::Transport::_Parser type) { (untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply) } -> ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
|
|
67
88
|
|
|
68
89
|
# @rbs client: ACP::AgentConnection::Client
|
|
69
90
|
# @rbs request: ACP::Types::InitializeRequest
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# Generated from lib/acp/agent_process.rb with RBS::Inline
|
|
2
2
|
|
|
3
|
-
# A child agent process and the ACP::ClientConnection wired to its stdio.
|
|
4
|
-
# Spawn one with ACP::AgentProcess.spawn.
|
|
5
3
|
class ACP::AgentProcess
|
|
6
4
|
@stderr: String?
|
|
7
5
|
|
|
@@ -27,16 +25,9 @@ class ACP::AgentProcess
|
|
|
27
25
|
# @dynamic connection
|
|
28
26
|
attr_reader connection: ACP::ClientConnection
|
|
29
27
|
|
|
30
|
-
# Child stderr captured when spawn was given stderr: :capture, else nil.
|
|
31
|
-
#
|
|
32
28
|
# @dynamic stderr
|
|
33
29
|
attr_reader stderr: String?
|
|
34
30
|
|
|
35
|
-
# Starts a command with args, env and cwd, wires its stdio to a new
|
|
36
|
-
# ACP::ClientConnection and starts it. With a block, yields the connection
|
|
37
|
-
# and this process, then terminates the child when the block exits; without
|
|
38
|
-
# one, returns the process and terminate is the caller's job.
|
|
39
|
-
#
|
|
40
31
|
# @rbs command: String
|
|
41
32
|
# @rbs *args: String
|
|
42
33
|
# @rbs env: Hash[String, String]?
|
|
@@ -48,10 +39,6 @@ class ACP::AgentProcess
|
|
|
48
39
|
# @rbs return: (untyped | ACP::AgentProcess)
|
|
49
40
|
def self.spawn: (String command, *String args, permission: ACP::ClientConnection::_PermissionHandler, ?env: Hash[String, String]?, ?cwd: String?, ?stderr: :inherit | :capture, ?updates: ACP::ClientConnection::_UpdateHandler) ?{ (ACP::ClientConnection, ACP::AgentProcess) -> untyped } -> (untyped | ACP::AgentProcess)
|
|
50
41
|
|
|
51
|
-
# Closes stdin, waits for the child to exit — sending TERM and then KILL if
|
|
52
|
-
# it will not — and joins the transport reader before closing the pipe it
|
|
53
|
-
# reads.
|
|
54
|
-
#
|
|
55
42
|
# @rbs return: void
|
|
56
43
|
def terminate: () -> void
|
|
57
44
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Generated from lib/acp/client_connection/streams.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
# It holds no send facade of its own — requests go through the sender and
|
|
4
|
+
# answers to the agent ride the connection's routes — so it is unit-testable
|
|
5
|
+
# without a transport.
|
|
6
|
+
class ACP::ClientConnection::Streams
|
|
7
|
+
CANCELLED: ACP::Types::RequestPermissionResponse
|
|
8
|
+
|
|
9
|
+
@outstanding_elicitations: Hash[String, bool]
|
|
10
|
+
|
|
11
|
+
@pending_permissions: Hash[String, Array[Thread::Queue]]
|
|
12
|
+
|
|
13
|
+
@streams: Hash[String, Thread::Queue]
|
|
14
|
+
|
|
15
|
+
@lock: Thread::Mutex
|
|
16
|
+
|
|
17
|
+
@logger: ACP::Transport::_Logger
|
|
18
|
+
|
|
19
|
+
@complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
|
|
20
|
+
|
|
21
|
+
@updates: ACP::ClientConnection::_UpdateHandler
|
|
22
|
+
|
|
23
|
+
@permission: ACP::ClientConnection::_PermissionHandler
|
|
24
|
+
|
|
25
|
+
@sender: ACP::ClientConnection::Streams::_Sender
|
|
26
|
+
|
|
27
|
+
# @rbs sender: ACP::ClientConnection::Streams::_Sender
|
|
28
|
+
# @rbs permission: ACP::ClientConnection::_PermissionHandler
|
|
29
|
+
# @rbs updates: ACP::ClientConnection::_UpdateHandler
|
|
30
|
+
# @rbs logger: ACP::Transport::_Logger
|
|
31
|
+
# @rbs complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
|
|
32
|
+
# @rbs return: void
|
|
33
|
+
def initialize: (sender: ACP::ClientConnection::Streams::_Sender, permission: ACP::ClientConnection::_PermissionHandler, updates: ACP::ClientConnection::_UpdateHandler, logger: ACP::Transport::_Logger, ?complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?) -> void
|
|
34
|
+
|
|
35
|
+
# The request waits on its own thread so the caller's thread can yield each
|
|
36
|
+
# update as it arrives. The reader thread queues an update before it settles
|
|
37
|
+
# a reply sent after it, so the queue closes only after the last one.
|
|
38
|
+
#
|
|
39
|
+
# @rbs session_id: String
|
|
40
|
+
# @rbs method: String
|
|
41
|
+
# @rbs params: Hash[String, untyped]
|
|
42
|
+
# @rbs &block: (ACP::Types::SessionUpdate::t) -> void
|
|
43
|
+
# @rbs return: (Hash[String, untyped] | ACP::RequestError)
|
|
44
|
+
def stream: (String session_id, String method, Hash[String, untyped] params) { (ACP::Types::SessionUpdate::t) -> void } -> (Hash[String, untyped] | ACP::RequestError)
|
|
45
|
+
|
|
46
|
+
# Pushes under the lock so a stream cannot close its queue between the
|
|
47
|
+
# lookup and the push. A malformed notification has no reply to carry the
|
|
48
|
+
# failure.
|
|
49
|
+
#
|
|
50
|
+
# @rbs params: untyped
|
|
51
|
+
# @rbs return: void
|
|
52
|
+
def dispatch: (untyped params) -> void
|
|
53
|
+
|
|
54
|
+
# The handler runs on its own thread so a cancelled request is answered
|
|
55
|
+
# without waiting for it, and whatever it returns after that is pushed to a
|
|
56
|
+
# queue nobody reads.
|
|
57
|
+
#
|
|
58
|
+
# @rbs params: untyped
|
|
59
|
+
# @rbs return: (ACP::Types::RequestPermissionResponse | ACP::RequestError)
|
|
60
|
+
def request_permission: (untyped params) -> (ACP::Types::RequestPermissionResponse | ACP::RequestError)
|
|
61
|
+
|
|
62
|
+
# The spec requires a pending session/request_permission to be answered with
|
|
63
|
+
# the cancelled outcome once the turn is cancelled, so every queue registered
|
|
64
|
+
# for the session gets one before this returns.
|
|
65
|
+
#
|
|
66
|
+
# @rbs session_id: String
|
|
67
|
+
# @rbs return: void
|
|
68
|
+
def cancel: (String session_id) -> void
|
|
69
|
+
|
|
70
|
+
# @rbs elicitation_id: String
|
|
71
|
+
# @rbs return: void
|
|
72
|
+
def register_elicitation: (String elicitation_id) -> void
|
|
73
|
+
|
|
74
|
+
# The spec requires a completion for an unknown or already-completed
|
|
75
|
+
# elicitation id to be ignored, so only an id registered by a served
|
|
76
|
+
# url-mode request reaches the handler. It runs on the transport's reader
|
|
77
|
+
# thread, so it must return quickly.
|
|
78
|
+
#
|
|
79
|
+
# @rbs params: untyped
|
|
80
|
+
# @rbs return: void
|
|
81
|
+
def complete_elicitation: (untyped params) -> void
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
# @rbs session_id: String
|
|
86
|
+
# @rbs replies: Thread::Queue
|
|
87
|
+
# @rbs return: void
|
|
88
|
+
def register_permission: (String session_id, Thread::Queue replies) -> void
|
|
89
|
+
|
|
90
|
+
# @rbs session_id: String
|
|
91
|
+
# @rbs replies: Thread::Queue
|
|
92
|
+
# @rbs return: void
|
|
93
|
+
def unregister_permission: (String session_id, Thread::Queue replies) -> void
|
|
94
|
+
end
|