acp-sdk 0.6.0 → 0.8.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.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +5 -2
  4. data/lib/acp/agent_connection/client.rb +1 -1
  5. data/lib/acp/agent_connection.rb +3 -1
  6. data/lib/acp/client_connection.rb +220 -4
  7. data/lib/acp/request_error.rb +18 -4
  8. data/lib/acp/transport/stdio.rb +21 -6
  9. data/lib/acp/types/agent_auth_capabilities.rb +4 -1
  10. data/lib/acp/types/agent_capabilities.rb +20 -5
  11. data/lib/acp/types/annotations.rb +6 -3
  12. data/lib/acp/types/audio_content.rb +8 -3
  13. data/lib/acp/types/auth_capabilities.rb +1 -1
  14. data/lib/acp/types/auth_method/terminal.rb +11 -5
  15. data/lib/acp/types/auth_method_agent.rb +6 -1
  16. data/lib/acp/types/auth_method_terminal.rb +11 -5
  17. data/lib/acp/types/authenticate_request.rb +1 -1
  18. data/lib/acp/types/available_command.rb +3 -3
  19. data/lib/acp/types/available_commands_update.rb +7 -4
  20. data/lib/acp/types/blob_resource_contents.rb +6 -1
  21. data/lib/acp/types/boolean_property_schema.rb +6 -1
  22. data/lib/acp/types/cancel_notification.rb +4 -1
  23. data/lib/acp/types/cancel_request_notification.rb +9 -1
  24. data/lib/acp/types/client_capabilities.rb +15 -5
  25. data/lib/acp/types/client_session_capabilities.rb +6 -3
  26. data/lib/acp/types/close_session_request.rb +4 -1
  27. data/lib/acp/types/complete_elicitation_notification.rb +4 -1
  28. data/lib/acp/types/config_option_update.rb +7 -4
  29. data/lib/acp/types/content.rb +4 -1
  30. data/lib/acp/types/content_block/audio.rb +8 -3
  31. data/lib/acp/types/content_block/image.rb +9 -4
  32. data/lib/acp/types/content_block/resource.rb +11 -2
  33. data/lib/acp/types/content_block/resource_link.rb +12 -7
  34. data/lib/acp/types/content_block/text.rb +7 -2
  35. data/lib/acp/types/content_chunk.rb +2 -2
  36. data/lib/acp/types/cost.rb +5 -1
  37. data/lib/acp/types/create_elicitation_request/mode/form.rb +5 -1
  38. data/lib/acp/types/create_elicitation_request/mode/url.rb +2 -2
  39. data/lib/acp/types/create_elicitation_request.rb +1 -1
  40. data/lib/acp/types/create_elicitation_response/action/accept.rb +6 -1
  41. data/lib/acp/types/create_terminal_request.rb +12 -6
  42. data/lib/acp/types/create_terminal_response.rb +4 -1
  43. data/lib/acp/types/current_mode_update.rb +4 -1
  44. data/lib/acp/types/delete_session_request.rb +4 -1
  45. data/lib/acp/types/diff.rb +6 -1
  46. data/lib/acp/types/elicitation_accept_action.rb +6 -1
  47. data/lib/acp/types/elicitation_capabilities.rb +2 -2
  48. data/lib/acp/types/elicitation_form_mode.rb +5 -1
  49. data/lib/acp/types/elicitation_property_schema/boolean_property_schema.rb +6 -1
  50. data/lib/acp/types/elicitation_property_schema/integer_property_schema.rb +5 -5
  51. data/lib/acp/types/elicitation_property_schema/multi_select_property_schema.rb +9 -6
  52. data/lib/acp/types/elicitation_property_schema/number_property_schema.rb +5 -5
  53. data/lib/acp/types/elicitation_property_schema/string_property_schema.rb +15 -9
  54. data/lib/acp/types/elicitation_request_scope.rb +8 -1
  55. data/lib/acp/types/elicitation_schema.rb +11 -5
  56. data/lib/acp/types/elicitation_session_scope.rb +4 -1
  57. data/lib/acp/types/elicitation_url_mode.rb +2 -2
  58. data/lib/acp/types/embedded_resource.rb +11 -2
  59. data/lib/acp/types/enum_option.rb +6 -1
  60. data/lib/acp/types/env_variable.rb +5 -1
  61. data/lib/acp/types/file_system_capabilities.rb +5 -1
  62. data/lib/acp/types/http_header.rb +5 -1
  63. data/lib/acp/types/image_content.rb +9 -4
  64. data/lib/acp/types/implementation.rb +6 -1
  65. data/lib/acp/types/initialize_request.rb +18 -3
  66. data/lib/acp/types/initialize_response.rb +17 -4
  67. data/lib/acp/types/integer_property_schema.rb +5 -5
  68. data/lib/acp/types/kill_terminal_request.rb +5 -1
  69. data/lib/acp/types/list_sessions_request.rb +5 -1
  70. data/lib/acp/types/list_sessions_response.rb +5 -2
  71. data/lib/acp/types/load_session_request.rb +14 -4
  72. data/lib/acp/types/load_session_response.rb +5 -2
  73. data/lib/acp/types/mcp_capabilities.rb +5 -1
  74. data/lib/acp/types/mcp_server/http.rb +6 -3
  75. data/lib/acp/types/mcp_server/sse.rb +6 -3
  76. data/lib/acp/types/mcp_server_http.rb +6 -3
  77. data/lib/acp/types/mcp_server_sse.rb +6 -3
  78. data/lib/acp/types/mcp_server_stdio.rb +10 -4
  79. data/lib/acp/types/multi_select_items/string_multi_select_items.rb +4 -1
  80. data/lib/acp/types/multi_select_property_schema.rb +9 -6
  81. data/lib/acp/types/new_session_request.rb +13 -3
  82. data/lib/acp/types/new_session_response.rb +6 -3
  83. data/lib/acp/types/number_property_schema.rb +5 -5
  84. data/lib/acp/types/permission_option.rb +10 -1
  85. data/lib/acp/types/plan.rb +4 -1
  86. data/lib/acp/types/plan_entry.rb +7 -3
  87. data/lib/acp/types/prompt_capabilities.rb +6 -1
  88. data/lib/acp/types/prompt_request.rb +5 -2
  89. data/lib/acp/types/prompt_response.rb +8 -1
  90. data/lib/acp/types/read_text_file_request.rb +4 -4
  91. data/lib/acp/types/read_text_file_response.rb +1 -1
  92. data/lib/acp/types/release_terminal_request.rb +5 -1
  93. data/lib/acp/types/request_permission_outcome/selected.rb +1 -1
  94. data/lib/acp/types/request_permission_request.rb +10 -3
  95. data/lib/acp/types/request_permission_response.rb +8 -1
  96. data/lib/acp/types/resource_link.rb +12 -7
  97. data/lib/acp/types/resume_session_request.rb +14 -4
  98. data/lib/acp/types/resume_session_response.rb +5 -2
  99. data/lib/acp/types/selected_permission_outcome.rb +1 -1
  100. data/lib/acp/types/session_capabilities.rb +20 -7
  101. data/lib/acp/types/session_config_boolean.rb +1 -1
  102. data/lib/acp/types/session_config_option/kind/boolean.rb +1 -1
  103. data/lib/acp/types/session_config_option/kind/select.rb +6 -2
  104. data/lib/acp/types/session_config_option.rb +3 -3
  105. data/lib/acp/types/session_config_options_capabilities.rb +6 -1
  106. data/lib/acp/types/session_config_select.rb +6 -2
  107. data/lib/acp/types/session_config_select_group.rb +6 -3
  108. data/lib/acp/types/session_config_select_option.rb +6 -1
  109. data/lib/acp/types/session_config_select_options.rb +6 -2
  110. data/lib/acp/types/session_info.rb +12 -5
  111. data/lib/acp/types/session_info_update.rb +10 -1
  112. data/lib/acp/types/session_mode.rb +6 -1
  113. data/lib/acp/types/session_mode_state.rb +8 -2
  114. data/lib/acp/types/session_notification.rb +2 -2
  115. data/lib/acp/types/session_update/agent_message_chunk.rb +2 -2
  116. data/lib/acp/types/session_update/agent_thought_chunk.rb +2 -2
  117. data/lib/acp/types/session_update/available_commands_update.rb +7 -4
  118. data/lib/acp/types/session_update/config_option_update.rb +7 -4
  119. data/lib/acp/types/session_update/current_mode_update.rb +4 -1
  120. data/lib/acp/types/session_update/plan.rb +4 -1
  121. data/lib/acp/types/session_update/session_info_update.rb +10 -1
  122. data/lib/acp/types/session_update/tool_call.rb +23 -7
  123. data/lib/acp/types/session_update/tool_call_update.rb +23 -7
  124. data/lib/acp/types/session_update/usage_update.rb +3 -3
  125. data/lib/acp/types/session_update/user_message_chunk.rb +2 -2
  126. data/lib/acp/types/set_session_config_option_request/value/boolean.rb +1 -1
  127. data/lib/acp/types/set_session_config_option_request/value/value_id.rb +1 -1
  128. data/lib/acp/types/set_session_config_option_request.rb +2 -2
  129. data/lib/acp/types/set_session_config_option_response.rb +7 -4
  130. data/lib/acp/types/set_session_mode_request.rb +5 -1
  131. data/lib/acp/types/string_multi_select_items.rb +4 -1
  132. data/lib/acp/types/string_property_schema.rb +15 -9
  133. data/lib/acp/types/terminal.rb +4 -1
  134. data/lib/acp/types/terminal_exit_status.rb +5 -1
  135. data/lib/acp/types/terminal_output_request.rb +5 -1
  136. data/lib/acp/types/terminal_output_response.rb +8 -3
  137. data/lib/acp/types/text_content.rb +7 -2
  138. data/lib/acp/types/text_resource_contents.rb +6 -1
  139. data/lib/acp/types/titled_multi_select_items.rb +4 -1
  140. data/lib/acp/types/tool_call.rb +23 -7
  141. data/lib/acp/types/tool_call_content/content.rb +4 -1
  142. data/lib/acp/types/tool_call_content/diff.rb +6 -1
  143. data/lib/acp/types/tool_call_content/terminal.rb +4 -1
  144. data/lib/acp/types/tool_call_location.rb +5 -1
  145. data/lib/acp/types/tool_call_update.rb +23 -7
  146. data/lib/acp/types/unstructured_command_input.rb +1 -1
  147. data/lib/acp/types/usage_update.rb +3 -3
  148. data/lib/acp/types/wait_for_terminal_exit_request.rb +5 -1
  149. data/lib/acp/types/wait_for_terminal_exit_response.rb +5 -1
  150. data/lib/acp/types/write_text_file_request.rb +3 -3
  151. data/lib/acp/types.rb +247 -0
  152. data/lib/acp/version.rb +1 -1
  153. data/sig/generated/acp/client_connection.rbs +101 -12
  154. data/sig/generated/acp/request_error.rbs +14 -2
  155. data/sig/generated/acp/transport/stdio.rbs +13 -2
  156. data/sig/generated/acp/types.rbs +143 -0
  157. metadata +1 -1
data/lib/acp/types.rb CHANGED
@@ -1,4 +1,251 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ACP::Types
4
+ # Raised by the generated from_h when a param does not match its schema
5
+ # type; the connection boundaries rescue it into an invalid-params reply
6
+ # that names the failing path.
7
+ class ParseError < StandardError
8
+ # @rbs @segments: Array[String | Integer]
9
+ # @rbs @detail: String
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
250
+ end
4
251
  end
data/lib/acp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ACP
4
- VERSION = '0.6.0'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -1,29 +1,49 @@
1
1
  # Generated from lib/acp/client_connection.rb with RBS::Inline
2
2
 
3
3
  class ACP::ClientConnection
4
- @logger: ACP::Transport::_Logger
4
+ @transport: ACP::AgentConnection::_Transport
5
5
 
6
- @pending_permissions: Hash[String, Array[Thread::Queue]]
6
+ @permission: ACP::ClientConnection::_PermissionHandler
7
7
 
8
- @streams: Hash[String, Thread::Queue]
8
+ @read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
9
9
 
10
- @lock: Thread::Mutex
10
+ @write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
11
11
 
12
- @extension_notifications: Hash[String, ^(untyped) -> void]
12
+ @create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?
13
13
 
14
- @extension_requests: Hash[String, ^(untyped) -> untyped]
14
+ @terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?
15
15
 
16
- @fs_capabilities: ACP::Types::FileSystemCapabilities?
16
+ @wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?
17
+
18
+ @kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?
19
+
20
+ @release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?
21
+
22
+ @elicitation: (^(ACP::Types::CreateElicitationRequest) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError))?
23
+
24
+ @complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
17
25
 
18
26
  @updates: ACP::ClientConnection::_UpdateHandler
19
27
 
20
- @write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
28
+ @fs_capabilities: ACP::Types::FileSystemCapabilities?
21
29
 
22
- @read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
30
+ @terminal: bool?
23
31
 
24
- @permission: ACP::ClientConnection::_PermissionHandler
32
+ @elicitation_capabilities: ACP::Types::ElicitationCapabilities?
25
33
 
26
- @transport: ACP::AgentConnection::_Transport
34
+ @extension_requests: Hash[String, ^(untyped) -> untyped]
35
+
36
+ @extension_notifications: Hash[String, ^(untyped) -> void]
37
+
38
+ @lock: Thread::Mutex
39
+
40
+ @streams: Hash[String, Thread::Queue]
41
+
42
+ @pending_permissions: Hash[String, Array[Thread::Queue]]
43
+
44
+ @outstanding_elicitations: Hash[String, bool]
45
+
46
+ @logger: ACP::Transport::_Logger
27
47
 
28
48
  PROTOCOL_VERSION: Integer
29
49
 
@@ -35,12 +55,21 @@ class ACP::ClientConnection
35
55
  # @rbs permission: ACP::ClientConnection::_PermissionHandler
36
56
  # @rbs read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
37
57
  # @rbs write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
58
+ # @rbs create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?
59
+ # @rbs terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?
60
+ # @rbs wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) ->
61
+ # (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?
62
+ # @rbs kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?
63
+ # @rbs release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?
64
+ # @rbs elicitation: (^(ACP::Types::CreateElicitationRequest) ->
65
+ # (ACP::Types::CreateElicitationResponse | ACP::RequestError))?
66
+ # @rbs complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
38
67
  # @rbs updates: ACP::ClientConnection::_UpdateHandler
39
68
  # @rbs extension_requests: Hash[String, ^(untyped) -> untyped]
40
69
  # @rbs extension_notifications: Hash[String, ^(untyped) -> void]
41
70
  # @rbs logger: ACP::Transport::_Logger
42
71
  # @rbs return: void
43
- def initialize: (transport: ACP::AgentConnection::_Transport, permission: ACP::ClientConnection::_PermissionHandler, ?read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?, ?write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?, ?updates: ACP::ClientConnection::_UpdateHandler, ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?logger: ACP::Transport::_Logger) -> void
72
+ def initialize: (transport: ACP::AgentConnection::_Transport, permission: ACP::ClientConnection::_PermissionHandler, ?read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?, ?write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?, ?create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?, ?terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?, ?wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?, ?kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?, ?release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?, ?elicitation: (^(ACP::Types::CreateElicitationRequest) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError))?, ?complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?, ?updates: ACP::ClientConnection::_UpdateHandler, ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?logger: ACP::Transport::_Logger) -> void
44
73
 
45
74
  # @rbs return: Thread
46
75
  def start: () -> Thread
@@ -182,9 +211,69 @@ class ACP::ClientConnection
182
211
  # @rbs return: (ACP::Types::WriteTextFileResponse | ACP::RequestError)
183
212
  def write_text_file: (untyped params) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError)
184
213
 
214
+ # The terminal routes are registered at start, before connect records the
215
+ # advertised capability, so each one answers -32601 until then.
216
+ #
217
+ # @rbs params: untyped
218
+ # @rbs return: (ACP::Types::CreateTerminalResponse | ACP::RequestError)
219
+ def create_terminal: (untyped params) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError)
220
+
221
+ # @rbs params: untyped
222
+ # @rbs return: (ACP::Types::TerminalOutputResponse | ACP::RequestError)
223
+ def terminal_output: (untyped params) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError)
224
+
225
+ # The handler may block for as long as the command runs, so the transport
226
+ # must serve each request on its own thread for this not to hold up others.
227
+ #
228
+ # @rbs params: untyped
229
+ # @rbs return: (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError)
230
+ def wait_for_terminal_exit: (untyped params) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError)
231
+
232
+ # @rbs params: untyped
233
+ # @rbs return: (ACP::Types::KillTerminalResponse | ACP::RequestError)
234
+ def kill_terminal: (untyped params) -> (ACP::Types::KillTerminalResponse | ACP::RequestError)
235
+
236
+ # @rbs params: untyped
237
+ # @rbs return: (ACP::Types::ReleaseTerminalResponse | ACP::RequestError)
238
+ def release_terminal: (untyped params) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError)
239
+
240
+ # The routes are registered at start, before connect records the advertised
241
+ # capabilities, so a request for an unadvertised mode answers -32602.
242
+ #
243
+ # @rbs params: untyped
244
+ # @rbs return: (ACP::Types::CreateElicitationResponse | ACP::RequestError)
245
+ def create_elicitation: (untyped params) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError)
246
+
247
+ # The spec requires a completion for an unknown or already-completed
248
+ # elicitation id to be ignored, so only an id registered by a served
249
+ # url-mode request reaches the handler. It runs on the transport's reader
250
+ # thread, so it must return quickly.
251
+ #
252
+ # @rbs params: untyped
253
+ # @rbs return: void
254
+ def complete_elicitation: (untyped params) -> void
255
+
256
+ # @rbs elicitation_id: String
257
+ # @rbs return: void
258
+ def register_elicitation: (String elicitation_id) -> void
259
+
185
260
  # The fs capabilities initialize advertises that no injected handler serves.
186
261
  #
187
262
  # @rbs capabilities: ACP::Types::FileSystemCapabilities?
188
263
  # @rbs return: Array[String]
189
264
  def unserved_fs_methods: (ACP::Types::FileSystemCapabilities? capabilities) -> Array[String]
265
+
266
+ # The terminal capabilities initialize advertises that no injected handler
267
+ # serves.
268
+ #
269
+ # @rbs capabilities: bool?
270
+ # @rbs return: Array[String]
271
+ def unserved_terminal_methods: (bool? capabilities) -> Array[String]
272
+
273
+ # The elicitation capabilities initialize advertises that no injected
274
+ # handler serves.
275
+ #
276
+ # @rbs capabilities: ACP::Types::ElicitationCapabilities?
277
+ # @rbs return: Array[String]
278
+ def unserved_elicitation_modes: (ACP::Types::ElicitationCapabilities? capabilities) -> Array[String]
190
279
  end
@@ -44,11 +44,13 @@ class ACP::RequestError
44
44
  # @rbs return: ACP::RequestError
45
45
  def self.invalid_request: () -> ACP::RequestError
46
46
 
47
+ # @rbs method: String?
47
48
  # @rbs return: ACP::RequestError
48
- def self.method_not_found: () -> ACP::RequestError
49
+ def self.method_not_found: (?String? method) -> ACP::RequestError
49
50
 
51
+ # @rbs errors: Array[String]?
50
52
  # @rbs return: ACP::RequestError
51
- def self.invalid_params: () -> ACP::RequestError
53
+ def self.invalid_params: (?Array[String]? errors) -> ACP::RequestError
52
54
 
53
55
  # The method-not-found code for a method the client's capabilities do not
54
56
  # advertise, with a message that names the capability so it can be told
@@ -58,6 +60,16 @@ class ACP::RequestError
58
60
  # @rbs return: ACP::RequestError
59
61
  def self.unadvertised: (String capability) -> ACP::RequestError
60
62
 
63
+ # The invalid-params code for a request whose mode the client's
64
+ # capabilities do not advertise, with a message that names the mode so it
65
+ # can be told apart from malformed params. The spec gives elicitation a
66
+ # mode in its params, so an unadvertised one is invalid params rather than
67
+ # method not found.
68
+ #
69
+ # @rbs mode: String
70
+ # @rbs return: ACP::RequestError
71
+ def self.unadvertised_mode: (String mode) -> ACP::RequestError
72
+
61
73
  # @rbs return: ACP::RequestError
62
74
  def self.internal_error: () -> ACP::RequestError
63
75
 
@@ -62,6 +62,14 @@ class ACP::Transport::Stdio
62
62
  # @rbs return: void
63
63
  def route: (Hash[String, untyped] message, Hash[String, _Handler] requests, Hash[String, _NotificationHandler] notifications) -> void
64
64
 
65
+ # JSON-RPC 2.0 says an error reply echoes the request id whenever it can be
66
+ # detected; ids outside the spec's String/Number/Null types are not, so
67
+ # those replies keep id null.
68
+ #
69
+ # @rbs message: Hash[String, untyped]
70
+ # @rbs return: untyped
71
+ def detectable_id: (Hash[String, untyped] message) -> untyped
72
+
65
73
  # @rbs line: String
66
74
  # @rbs return: Hash[String, untyped] | ACP::RequestError
67
75
  def parse: (String line) -> (Hash[String, untyped] | ACP::RequestError)
@@ -69,8 +77,9 @@ class ACP::Transport::Stdio
69
77
  # @rbs handler: _Handler?
70
78
  # @rbs id: untyped
71
79
  # @rbs params: untyped
80
+ # @rbs method: String
72
81
  # @rbs return: void
73
- def serve: (_Handler? handler, untyped id, untyped params) -> void
82
+ def serve: (_Handler? handler, untyped id, untyped params, String method) -> void
74
83
 
75
84
  # For code with no reply to carry an error: a notification handler, or a
76
85
  # Reply's after once the reply is on the wire. An exception must not kill
@@ -82,7 +91,9 @@ class ACP::Transport::Stdio
82
91
  def quietly: (String label) { () -> void } -> void
83
92
 
84
93
  # Handlers are application code at the protocol boundary: an exception
85
- # becomes an error response instead of killing the thread serving it.
94
+ # becomes an error response instead of killing the thread serving it. The
95
+ # exception is only logged, not sent: its message can carry paths, SQL or
96
+ # anything else the handler interpolated, which must not reach the peer.
86
97
  #
87
98
  # @rbs handler: _Handler
88
99
  # @rbs params: untyped
@@ -1,4 +1,147 @@
1
1
  # Generated from lib/acp/types.rb with RBS::Inline
2
2
 
3
3
  module ACP::Types
4
+ # Raised by the generated from_h when a param does not match its schema
5
+ # type; the connection boundaries rescue it into an invalid-params reply
6
+ # that names the failing path.
7
+ class ParseError < StandardError
8
+ @segments: Array[String | Integer]
9
+
10
+ @detail: String
11
+
12
+ # @rbs segments: Array[String | Integer]
13
+ # @rbs detail: String
14
+ # @rbs return: void
15
+ def initialize: (Array[String | Integer] segments, String detail) -> void
16
+
17
+ # @dynamic segments
18
+ attr_reader segments: Array[String | Integer]
19
+
20
+ # @rbs return: String
21
+ def path: () -> String
22
+
23
+ # Prepends a container's segments so nested failures report an absolute path.
24
+ #
25
+ # @rbs *segments: (String | Integer)
26
+ # @rbs return: ACP::Types::ParseError
27
+ def prefix: (*String | Integer segments) -> ACP::Types::ParseError
28
+ end
29
+
30
+ # The guards the generated from_h methods call. Each takes the fetched value
31
+ # and the path to it, and raises ParseError naming that path when the value
32
+ # does not match the schema type. Nested from_h failures come back with the
33
+ # field path prepended, so the reported path is absolute.
34
+ module Check
35
+ # @rbs hash: Hash[String, untyped]
36
+ # @rbs key: String
37
+ # @rbs return: untyped
38
+ def self.key: (Hash[String, untyped] hash, String key) -> untyped
39
+
40
+ # @rbs value: untyped
41
+ # @rbs path: String | Array[String | Integer]
42
+ # @rbs allow_nil: bool
43
+ # @rbs allow_unset: bool
44
+ # @rbs return: untyped
45
+ def self.string: (untyped value, String | Array[String | Integer] path, ?allow_nil: bool, ?allow_unset: bool) -> untyped
46
+
47
+ # @rbs value: untyped
48
+ # @rbs path: String | Array[String | Integer]
49
+ # @rbs allow_nil: bool
50
+ # @rbs allow_unset: bool
51
+ # @rbs return: untyped
52
+ def self.boolean: (untyped value, String | Array[String | Integer] path, ?allow_nil: bool, ?allow_unset: bool) -> untyped
53
+
54
+ # @rbs value: untyped
55
+ # @rbs path: String | Array[String | Integer]
56
+ # @rbs min: Integer?
57
+ # @rbs max: Integer?
58
+ # @rbs allow_nil: bool
59
+ # @rbs allow_unset: bool
60
+ # @rbs return: untyped
61
+ def self.integer: (untyped value, String | Array[String | Integer] path, ?min: Integer?, ?max: Integer?, ?allow_nil: bool, ?allow_unset: bool) -> untyped
62
+
63
+ # @rbs value: untyped
64
+ # @rbs path: String | Array[String | Integer]
65
+ # @rbs min: Integer?
66
+ # @rbs max: Integer?
67
+ # @rbs allow_nil: bool
68
+ # @rbs allow_unset: bool
69
+ # @rbs return: untyped
70
+ def self.number: (untyped value, String | Array[String | Integer] path, ?min: Integer?, ?max: Integer?, ?allow_nil: bool, ?allow_unset: bool) -> untyped
71
+
72
+ # @rbs value: untyped
73
+ # @rbs path: String | Array[String | Integer]
74
+ # @rbs values: Array[untyped]
75
+ # @rbs allow_nil: bool
76
+ # @rbs allow_unset: bool
77
+ # @rbs return: untyped
78
+ def self.enum: (untyped value, String | Array[String | Integer] path, Array[untyped] values, ?allow_nil: bool, ?allow_unset: bool) -> untyped
79
+
80
+ # @rbs value: untyped
81
+ # @rbs path: String | Array[String | Integer]
82
+ # @rbs classes: Array[untyped]
83
+ # @rbs allow_nil: bool
84
+ # @rbs allow_unset: bool
85
+ # @rbs ?&items: (untyped, Array[String | Integer]) -> void
86
+ # @rbs return: untyped
87
+ def self.one_of: (untyped value, String | Array[String | Integer] path, Array[untyped] classes, ?allow_nil: bool, ?allow_unset: bool) ?{ (?) -> untyped } -> untyped
88
+
89
+ # @rbs value: untyped
90
+ # @rbs path: String | Array[String | Integer]
91
+ # @rbs allow_nil: bool
92
+ # @rbs allow_unset: bool
93
+ # @rbs &check: (untyped, Array[String | Integer]) -> void
94
+ # @rbs return: untyped
95
+ def self.hash: (untyped value, String | Array[String | Integer] path, ?allow_nil: bool, ?allow_unset: bool) { (untyped, Array[String | Integer]) -> void } -> untyped
96
+
97
+ # @rbs value: untyped
98
+ # @rbs path: String | Array[String | Integer]
99
+ # @rbs allow_nil: bool
100
+ # @rbs allow_unset: bool
101
+ # @rbs &check: (untyped, Array[String | Integer]) -> void
102
+ # @rbs return: untyped
103
+ def self.array: (untyped value, String | Array[String | Integer] path, ?allow_nil: bool, ?allow_unset: bool) { (untyped, Array[String | Integer]) -> void } -> untyped
104
+
105
+ # @rbs value: untyped
106
+ # @rbs path: String | Array[String | Integer]
107
+ # @rbs klass: untyped
108
+ # @rbs allow_nil: bool
109
+ # @rbs allow_unset: bool
110
+ # @rbs return: untyped
111
+ def self.object: (untyped value, String | Array[String | Integer] path, untyped klass, ?allow_nil: bool, ?allow_unset: bool) -> untyped
112
+
113
+ # @rbs value: untyped
114
+ # @rbs path: String | Array[String | Integer]
115
+ # @rbs klass: untyped
116
+ # @rbs allow_nil: bool
117
+ # @rbs allow_unset: bool
118
+ # @rbs return: untyped
119
+ def self.objects: (untyped value, String | Array[String | Integer] path, untyped klass, ?allow_nil: bool, ?allow_unset: bool) -> untyped
120
+
121
+ # @rbs value: untyped
122
+ # @rbs allow_nil: bool
123
+ # @rbs allow_unset: bool
124
+ # @rbs return: bool
125
+ def self.skipped?: (untyped value, bool allow_nil, bool allow_unset) -> bool
126
+
127
+ # @rbs path: String | Array[String | Integer]
128
+ # @rbs return: Array[String | Integer]
129
+ def self.segments: (String | Array[String | Integer] path) -> Array[String | Integer]
130
+
131
+ # @rbs value: untyped
132
+ # @rbs return: String
133
+ def self.describe: (untyped value) -> String
134
+
135
+ # @rbs value: Numeric
136
+ # @rbs min: Integer?
137
+ # @rbs max: Integer?
138
+ # @rbs return: bool
139
+ def self.within?: (Numeric value, Integer? min, Integer? max) -> bool
140
+
141
+ # @rbs name: String
142
+ # @rbs min: Integer?
143
+ # @rbs max: Integer?
144
+ # @rbs return: String
145
+ def self.bounded: (String name, Integer? min, Integer? max) -> String
146
+ end
4
147
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acp-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Bottrall