acp-sdk 0.10.0 → 0.12.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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/README.md +19 -5
  4. data/lib/acp/agent_connection/client.rb +7 -19
  5. data/lib/acp/agent_connection/optional_method/spec.rb +42 -0
  6. data/lib/acp/agent_connection/optional_method.rb +36 -0
  7. data/lib/acp/agent_connection.rb +17 -40
  8. data/lib/acp/agent_process.rb +0 -13
  9. data/lib/acp/client_connection/streams.rb +183 -0
  10. data/lib/acp/client_connection.rb +227 -384
  11. data/lib/acp/protocol.rb +33 -0
  12. data/lib/acp/request_error.rb +17 -17
  13. data/lib/acp/transport/cancellation.rb +0 -7
  14. data/lib/acp/transport/reply.rb +0 -2
  15. data/lib/acp/transport/stderr_logger.rb +1 -2
  16. data/lib/acp/transport/stdio/serving.rb +18 -0
  17. data/lib/acp/transport/stdio.rb +67 -59
  18. data/lib/acp/types/audio_content.rb +3 -46
  19. data/lib/acp/types/auth_method_terminal.rb +3 -59
  20. data/lib/acp/types/available_commands_update.rb +3 -32
  21. data/lib/acp/types/boolean_property_schema.rb +3 -41
  22. data/lib/acp/types/check.rb +210 -0
  23. data/lib/acp/types/config_option_update.rb +3 -32
  24. data/lib/acp/types/content.rb +3 -29
  25. data/lib/acp/types/{elicitation_url_mode → create_elicitation_request/mode/form}/scope.rb +1 -1
  26. data/lib/acp/types/create_elicitation_request/mode/form.rb +3 -3
  27. data/lib/acp/types/{elicitation_form_mode → create_elicitation_request/mode/url}/scope.rb +1 -1
  28. data/lib/acp/types/create_elicitation_request/mode/url.rb +3 -3
  29. data/lib/acp/types/current_mode_update.rb +3 -29
  30. data/lib/acp/types/diff.rb +3 -41
  31. data/lib/acp/types/elicitation_accept_action.rb +3 -26
  32. data/lib/acp/types/elicitation_form_mode.rb +3 -33
  33. data/lib/acp/types/elicitation_url_mode.rb +3 -35
  34. data/lib/acp/types/embedded_resource.rb +3 -44
  35. data/lib/acp/types/image_content.rb +3 -58
  36. data/lib/acp/types/integer_property_schema.rb +3 -60
  37. data/lib/acp/types/mcp_server_http.rb +3 -44
  38. data/lib/acp/types/mcp_server_sse.rb +3 -44
  39. data/lib/acp/types/multi_select_property_schema.rb +3 -70
  40. data/lib/acp/types/number_property_schema.rb +3 -60
  41. data/lib/acp/types/parse_error.rb +37 -0
  42. data/lib/acp/types/plan.rb +3 -29
  43. data/lib/acp/types/resource_link.rb +3 -79
  44. data/lib/acp/types/selected_permission_outcome.rb +3 -26
  45. data/lib/acp/types/session_config_boolean.rb +3 -21
  46. data/lib/acp/types/session_config_select.rb +3 -33
  47. data/lib/acp/types/session_info_update.rb +3 -42
  48. data/lib/acp/types/string_multi_select_items.rb +3 -29
  49. data/lib/acp/types/string_property_schema.rb +3 -105
  50. data/lib/acp/types/terminal.rb +3 -29
  51. data/lib/acp/types/text_content.rb +3 -40
  52. data/lib/acp/types/tool_call.rb +3 -115
  53. data/lib/acp/types/unstable/compaction_summary_chunk.rb +3 -35
  54. data/lib/acp/types/unstable/compaction_update.rb +3 -56
  55. data/lib/acp/types/unstable/idle_state_update.rb +3 -40
  56. data/lib/acp/types/unstable/mcp_server_acp.rb +3 -35
  57. data/lib/acp/types/unstable/nes_edit_suggestion.rb +3 -61
  58. data/lib/acp/types/unstable/nes_jump_suggestion.rb +3 -45
  59. data/lib/acp/types/unstable/nes_rename_suggestion.rb +3 -51
  60. data/lib/acp/types/unstable/nes_search_and_replace_suggestion.rb +3 -60
  61. data/lib/acp/types/unstable/notice.rb +3 -41
  62. data/lib/acp/types/unstable/plan_file.rb +3 -35
  63. data/lib/acp/types/unstable/plan_items.rb +3 -38
  64. data/lib/acp/types/unstable/plan_markdown.rb +3 -35
  65. data/lib/acp/types/unstable/plan_removed.rb +3 -26
  66. data/lib/acp/types/unstable/plan_update.rb +3 -33
  67. data/lib/acp/types/unstable/requires_action_state_update.rb +3 -21
  68. data/lib/acp/types/unstable/running_state_update.rb +3 -21
  69. data/lib/acp/types/unstable/session_message.rb +3 -56
  70. data/lib/acp/types/unstable/session_message_chunk.rb +3 -53
  71. data/lib/acp/types/unstable/subagent_update.rb +3 -65
  72. data/lib/acp/types/unstable/unknown_state_update.rb +3 -21
  73. data/lib/acp/types/unstable.rb +20 -20
  74. data/lib/acp/types/usage_update.rb +3 -41
  75. data/lib/acp/types.rb +7 -246
  76. data/lib/acp/version.rb +1 -1
  77. data/sig/generated/acp/agent_connection/client.rbs +10 -19
  78. data/sig/generated/acp/agent_connection/optional_method/spec.rbs +32 -0
  79. data/sig/generated/acp/agent_connection/optional_method.rbs +3 -0
  80. data/sig/generated/acp/agent_connection.rbs +16 -24
  81. data/sig/generated/acp/agent_process.rbs +0 -13
  82. data/sig/generated/acp/client_connection/streams.rbs +94 -0
  83. data/sig/generated/acp/client_connection.rbs +100 -159
  84. data/sig/generated/acp/protocol.rbs +9 -0
  85. data/sig/generated/acp/request_error.rbs +15 -17
  86. data/sig/generated/acp/transport/cancellation.rbs +0 -7
  87. data/sig/generated/acp/transport/reply.rbs +0 -2
  88. data/sig/generated/acp/transport/stderr_logger.rbs +1 -2
  89. data/sig/generated/acp/transport/stdio/serving.rbs +14 -0
  90. data/sig/generated/acp/transport/stdio.rbs +31 -35
  91. data/sig/generated/acp/types/audio_content.rbs +1 -27
  92. data/sig/generated/acp/types/auth_method_terminal.rbs +1 -35
  93. data/sig/generated/acp/types/available_commands_update.rbs +1 -19
  94. data/sig/generated/acp/types/boolean_property_schema.rbs +1 -27
  95. data/sig/generated/acp/types/check.rbs +115 -0
  96. data/sig/generated/acp/types/config_option_update.rbs +1 -19
  97. data/sig/generated/acp/types/content.rbs +1 -19
  98. data/sig/generated/acp/types/{elicitation_url_mode → create_elicitation_request/mode/form}/scope.rbs +2 -2
  99. data/sig/generated/acp/types/create_elicitation_request/mode/form.rbs +3 -3
  100. data/sig/generated/acp/types/{elicitation_form_mode → create_elicitation_request/mode/url}/scope.rbs +2 -2
  101. data/sig/generated/acp/types/create_elicitation_request/mode/url.rbs +3 -3
  102. data/sig/generated/acp/types/current_mode_update.rbs +1 -19
  103. data/sig/generated/acp/types/diff.rbs +1 -27
  104. data/sig/generated/acp/types/elicitation_accept_action.rbs +1 -15
  105. data/sig/generated/acp/types/elicitation_form_mode.rbs +1 -19
  106. data/sig/generated/acp/types/elicitation_url_mode.rbs +1 -23
  107. data/sig/generated/acp/types/embedded_resource.rbs +1 -23
  108. data/sig/generated/acp/types/image_content.rbs +1 -31
  109. data/sig/generated/acp/types/integer_property_schema.rbs +1 -35
  110. data/sig/generated/acp/types/mcp_server_http.rbs +1 -27
  111. data/sig/generated/acp/types/mcp_server_sse.rbs +1 -27
  112. data/sig/generated/acp/types/multi_select_property_schema.rbs +1 -39
  113. data/sig/generated/acp/types/number_property_schema.rbs +1 -35
  114. data/sig/generated/acp/types/parse_error.rbs +22 -0
  115. data/sig/generated/acp/types/plan.rbs +1 -19
  116. data/sig/generated/acp/types/resource_link.rbs +1 -43
  117. data/sig/generated/acp/types/selected_permission_outcome.rbs +1 -19
  118. data/sig/generated/acp/types/session_config_boolean.rbs +1 -15
  119. data/sig/generated/acp/types/session_config_select.rbs +1 -19
  120. data/sig/generated/acp/types/session_info_update.rbs +1 -23
  121. data/sig/generated/acp/types/string_multi_select_items.rbs +1 -19
  122. data/sig/generated/acp/types/string_property_schema.rbs +1 -51
  123. data/sig/generated/acp/types/terminal.rbs +1 -19
  124. data/sig/generated/acp/types/text_content.rbs +1 -23
  125. data/sig/generated/acp/types/tool_call.rbs +1 -51
  126. data/sig/generated/acp/types/unstable/compaction_summary_chunk.rbs +1 -23
  127. data/sig/generated/acp/types/unstable/compaction_update.rbs +1 -31
  128. data/sig/generated/acp/types/unstable/idle_state_update.rbs +1 -23
  129. data/sig/generated/acp/types/unstable/mcp_server_acp.rbs +1 -23
  130. data/sig/generated/acp/types/unstable/nes_edit_suggestion.rbs +1 -31
  131. data/sig/generated/acp/types/unstable/nes_jump_suggestion.rbs +1 -27
  132. data/sig/generated/acp/types/unstable/nes_rename_suggestion.rbs +1 -31
  133. data/sig/generated/acp/types/unstable/nes_search_and_replace_suggestion.rbs +1 -35
  134. data/sig/generated/acp/types/unstable/notice.rbs +1 -27
  135. data/sig/generated/acp/types/unstable/plan_file.rbs +1 -23
  136. data/sig/generated/acp/types/unstable/plan_items.rbs +1 -23
  137. data/sig/generated/acp/types/unstable/plan_markdown.rbs +1 -23
  138. data/sig/generated/acp/types/unstable/plan_removed.rbs +1 -19
  139. data/sig/generated/acp/types/unstable/plan_update.rbs +1 -19
  140. data/sig/generated/acp/types/unstable/requires_action_state_update.rbs +1 -15
  141. data/sig/generated/acp/types/unstable/running_state_update.rbs +1 -15
  142. data/sig/generated/acp/types/unstable/session_message.rbs +1 -31
  143. data/sig/generated/acp/types/unstable/session_message_chunk.rbs +1 -31
  144. data/sig/generated/acp/types/unstable/subagent_update.rbs +1 -35
  145. data/sig/generated/acp/types/unstable/unknown_state_update.rbs +1 -15
  146. data/sig/generated/acp/types/usage_update.rbs +1 -27
  147. data/sig/generated/acp/types.rbs +6 -143
  148. data/sig/manual/acp/agent_connection.rbs +0 -30
  149. data/sig/manual/acp/client_connection.rbs +7 -2
  150. data/sig/manual/acp/{agent_connection/optional_method/logout.rbs → protocol.rbs} +3 -3
  151. data/sig/manual/acp/transport/stdio.rbs +0 -2
  152. data/sig/manual/acp/transport.rbs +25 -2
  153. metadata +18 -40
  154. data/lib/acp/agent_connection/optional_method/authenticate.rb +0 -21
  155. data/lib/acp/agent_connection/optional_method/close_session.rb +0 -21
  156. data/lib/acp/agent_connection/optional_method/delete_session.rb +0 -21
  157. data/lib/acp/agent_connection/optional_method/disable_provider.rb +0 -23
  158. data/lib/acp/agent_connection/optional_method/fork_session.rb +0 -23
  159. data/lib/acp/agent_connection/optional_method/list_providers.rb +0 -23
  160. data/lib/acp/agent_connection/optional_method/list_sessions.rb +0 -21
  161. data/lib/acp/agent_connection/optional_method/load_session.rb +0 -21
  162. data/lib/acp/agent_connection/optional_method/logout.rb +0 -21
  163. data/lib/acp/agent_connection/optional_method/resume_session.rb +0 -21
  164. data/lib/acp/agent_connection/optional_method/set_provider.rb +0 -23
  165. data/lib/acp/types/content_chunk.rb +0 -40
  166. data/sig/generated/acp/agent_connection/optional_method/authenticate.rbs +0 -13
  167. data/sig/generated/acp/agent_connection/optional_method/close_session.rbs +0 -13
  168. data/sig/generated/acp/agent_connection/optional_method/delete_session.rbs +0 -13
  169. data/sig/generated/acp/agent_connection/optional_method/disable_provider.rbs +0 -13
  170. data/sig/generated/acp/agent_connection/optional_method/fork_session.rbs +0 -13
  171. data/sig/generated/acp/agent_connection/optional_method/list_providers.rbs +0 -13
  172. data/sig/generated/acp/agent_connection/optional_method/list_sessions.rbs +0 -13
  173. data/sig/generated/acp/agent_connection/optional_method/load_session.rbs +0 -13
  174. data/sig/generated/acp/agent_connection/optional_method/logout.rbs +0 -13
  175. data/sig/generated/acp/agent_connection/optional_method/resume_session.rbs +0 -13
  176. data/sig/generated/acp/agent_connection/optional_method/set_provider.rbs +0 -13
  177. data/sig/generated/acp/types/content_chunk.rbs +0 -25
  178. data/sig/manual/acp/agent_connection/optional_method/authenticate.rbs +0 -6
  179. data/sig/manual/acp/agent_connection/optional_method/close_session.rbs +0 -6
  180. data/sig/manual/acp/agent_connection/optional_method/delete_session.rbs +0 -6
  181. data/sig/manual/acp/agent_connection/optional_method/disable_provider.rbs +0 -6
  182. data/sig/manual/acp/agent_connection/optional_method/fork_session.rbs +0 -6
  183. data/sig/manual/acp/agent_connection/optional_method/list_providers.rbs +0 -6
  184. data/sig/manual/acp/agent_connection/optional_method/list_sessions.rbs +0 -6
  185. data/sig/manual/acp/agent_connection/optional_method/load_session.rbs +0 -6
  186. data/sig/manual/acp/agent_connection/optional_method/resume_session.rbs +0 -6
  187. data/sig/manual/acp/agent_connection/optional_method/set_provider.rbs +0 -6
@@ -19,8 +19,6 @@ require_relative 'unstable/client_session_capabilities'
19
19
  require_relative 'unstable/close_nes_request'
20
20
  require_relative 'unstable/close_nes_response'
21
21
  require_relative 'unstable/compaction_status'
22
- require_relative 'unstable/compaction_summary_chunk'
23
- require_relative 'unstable/compaction_update'
24
22
  require_relative 'unstable/did_change_document_notification'
25
23
  require_relative 'unstable/did_close_document_notification'
26
24
  require_relative 'unstable/did_focus_document_notification'
@@ -30,7 +28,6 @@ require_relative 'unstable/disable_provider_request'
30
28
  require_relative 'unstable/disable_provider_response'
31
29
  require_relative 'unstable/fork_session_request'
32
30
  require_relative 'unstable/fork_session_response'
33
- require_relative 'unstable/idle_state_update'
34
31
  require_relative 'unstable/initialize_response'
35
32
  require_relative 'unstable/list_providers_request'
36
33
  require_relative 'unstable/list_providers_response'
@@ -41,7 +38,6 @@ require_relative 'unstable/mcp_server'
41
38
  require_relative 'unstable/mcp_server/acp'
42
39
  require_relative 'unstable/mcp_server/http'
43
40
  require_relative 'unstable/mcp_server/sse'
44
- require_relative 'unstable/mcp_server_acp'
45
41
  require_relative 'unstable/message_mcp_notification'
46
42
  require_relative 'unstable/message_mcp_request'
47
43
  require_relative 'unstable/message_mcp_response'
@@ -60,11 +56,9 @@ require_relative 'unstable/nes_document_did_save_capabilities'
60
56
  require_relative 'unstable/nes_document_event_capabilities'
61
57
  require_relative 'unstable/nes_edit_history_capabilities'
62
58
  require_relative 'unstable/nes_edit_history_entry'
63
- require_relative 'unstable/nes_edit_suggestion'
64
59
  require_relative 'unstable/nes_event_capabilities'
65
60
  require_relative 'unstable/nes_excerpt'
66
61
  require_relative 'unstable/nes_jump_capabilities'
67
- require_relative 'unstable/nes_jump_suggestion'
68
62
  require_relative 'unstable/nes_open_file'
69
63
  require_relative 'unstable/nes_open_files_capabilities'
70
64
  require_relative 'unstable/nes_recent_file'
@@ -73,10 +67,8 @@ require_relative 'unstable/nes_reject_reason'
73
67
  require_relative 'unstable/nes_related_snippet'
74
68
  require_relative 'unstable/nes_related_snippets_capabilities'
75
69
  require_relative 'unstable/nes_rename_capabilities'
76
- require_relative 'unstable/nes_rename_suggestion'
77
70
  require_relative 'unstable/nes_repository'
78
71
  require_relative 'unstable/nes_search_and_replace_capabilities'
79
- require_relative 'unstable/nes_search_and_replace_suggestion'
80
72
  require_relative 'unstable/nes_suggest_context'
81
73
  require_relative 'unstable/nes_suggestion'
82
74
  require_relative 'unstable/nes_suggestion/edit'
@@ -87,14 +79,8 @@ require_relative 'unstable/nes_text_edit'
87
79
  require_relative 'unstable/nes_trigger_kind'
88
80
  require_relative 'unstable/nes_user_action'
89
81
  require_relative 'unstable/nes_user_actions_capabilities'
90
- require_relative 'unstable/notice'
91
82
  require_relative 'unstable/notice_severity'
92
83
  require_relative 'unstable/plan_capabilities'
93
- require_relative 'unstable/plan_file'
94
- require_relative 'unstable/plan_items'
95
- require_relative 'unstable/plan_markdown'
96
- require_relative 'unstable/plan_removed'
97
- require_relative 'unstable/plan_update'
98
84
  require_relative 'unstable/plan_update_content'
99
85
  require_relative 'unstable/plan_update_content/file'
100
86
  require_relative 'unstable/plan_update_content/items'
@@ -107,13 +93,9 @@ require_relative 'unstable/provider_info'
107
93
  require_relative 'unstable/providers_capabilities'
108
94
  require_relative 'unstable/range'
109
95
  require_relative 'unstable/reject_nes_notification'
110
- require_relative 'unstable/requires_action_state_update'
111
- require_relative 'unstable/running_state_update'
112
96
  require_relative 'unstable/session_cancel_capabilities'
113
97
  require_relative 'unstable/session_capabilities'
114
98
  require_relative 'unstable/session_fork_capabilities'
115
- require_relative 'unstable/session_message'
116
- require_relative 'unstable/session_message_chunk'
117
99
  require_relative 'unstable/session_update'
118
100
  require_relative 'unstable/session_update/agent_message_chunk'
119
101
  require_relative 'unstable/session_update/agent_thought_chunk'
@@ -145,11 +127,29 @@ require_relative 'unstable/state_update/running'
145
127
  require_relative 'unstable/state_update/unknown'
146
128
  require_relative 'unstable/subagent_capabilities'
147
129
  require_relative 'unstable/subagent_session_capabilities'
148
- require_relative 'unstable/subagent_update'
149
130
  require_relative 'unstable/suggest_nes_request'
150
131
  require_relative 'unstable/suggest_nes_response'
151
132
  require_relative 'unstable/text_document_content_change_event'
152
133
  require_relative 'unstable/text_document_sync_kind'
153
- require_relative 'unstable/unknown_state_update'
154
134
  require_relative 'unstable/usage'
155
135
  require_relative 'unstable/workspace_folder'
136
+ require_relative 'unstable/compaction_summary_chunk'
137
+ require_relative 'unstable/compaction_update'
138
+ require_relative 'unstable/idle_state_update'
139
+ require_relative 'unstable/mcp_server_acp'
140
+ require_relative 'unstable/nes_edit_suggestion'
141
+ require_relative 'unstable/nes_jump_suggestion'
142
+ require_relative 'unstable/nes_rename_suggestion'
143
+ require_relative 'unstable/nes_search_and_replace_suggestion'
144
+ require_relative 'unstable/notice'
145
+ require_relative 'unstable/plan_file'
146
+ require_relative 'unstable/plan_items'
147
+ require_relative 'unstable/plan_markdown'
148
+ require_relative 'unstable/plan_removed'
149
+ require_relative 'unstable/plan_update'
150
+ require_relative 'unstable/requires_action_state_update'
151
+ require_relative 'unstable/running_state_update'
152
+ require_relative 'unstable/session_message'
153
+ require_relative 'unstable/session_message_chunk'
154
+ require_relative 'unstable/subagent_update'
155
+ require_relative 'unstable/unknown_state_update'
@@ -2,45 +2,7 @@
2
2
 
3
3
  # Generated by bin/types from schema/schema.json. Do not edit.
4
4
 
5
- class ACP::Types::UsageUpdate
6
- # @dynamic used
7
- attr_reader :used #: Integer
5
+ # @rbs!
6
+ # class ACP::Types::UsageUpdate = ACP::Types::SessionUpdate::UsageUpdate
8
7
 
9
- # @dynamic size
10
- attr_reader :size #: Integer
11
-
12
- # @dynamic cost
13
- attr_reader :cost #: ACP::Types::Cost?
14
-
15
- # @dynamic meta
16
- attr_reader :meta #: Hash[String, untyped]?
17
-
18
- # @rbs used: Integer
19
- # @rbs size: Integer
20
- # @rbs cost: ACP::Types::Cost?
21
- # @rbs meta: Hash[String, untyped]?
22
- # @rbs return: void
23
- def initialize(used:, size:, cost: nil, meta: nil)
24
- @used = used
25
- @size = size
26
- @cost = cost
27
- @meta = meta
28
- freeze
29
- end
30
-
31
- # @rbs hash: Hash[String, untyped]
32
- # @rbs return: ACP::Types::UsageUpdate
33
- def self.from_h(hash)
34
- new(
35
- used: ACP::Types::Check.integer(ACP::Types::Check.key(hash, 'used'), 'used', min: 0),
36
- size: ACP::Types::Check.integer(ACP::Types::Check.key(hash, 'size'), 'size', min: 0),
37
- cost: ACP::Types::Check.object(hash['cost'], 'cost', ACP::Types::Cost, allow_nil: true),
38
- meta: hash['_meta']
39
- )
40
- end
41
-
42
- # @rbs return: Hash[String, untyped]
43
- def to_h
44
- { 'used' => used, 'size' => size, 'cost' => cost&.to_h, '_meta' => meta }.compact
45
- end
46
- end
8
+ ACP::Types::UsageUpdate = ACP::Types::SessionUpdate::UsageUpdate
data/lib/acp/types.rb CHANGED
@@ -1,251 +1,12 @@
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
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,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ACP
4
- VERSION = '0.10.0'
4
+ VERSION = '0.12.0'
5
5
  end
@@ -3,15 +3,15 @@
3
3
  class ACP::AgentConnection::Client
4
4
  @mcp_advertised: bool
5
5
 
6
- @peer: ACP::AgentConnection::_Peer
6
+ @peer: ACP::Transport::_Peer
7
7
 
8
8
  # @dynamic capabilities, capabilities=
9
9
  attr_accessor capabilities: ACP::Types::ClientCapabilities?
10
10
 
11
- # @rbs peer: ACP::AgentConnection::_Peer
11
+ # @rbs peer: ACP::Transport::_Peer
12
12
  # @rbs mcp_advertised: bool
13
13
  # @rbs return: void
14
- def initialize: (peer: ACP::AgentConnection::_Peer, ?mcp_advertised: bool) -> void
14
+ def initialize: (peer: ACP::Transport::_Peer, ?mcp_advertised: bool) -> void
15
15
 
16
16
  # @rbs session_id: String
17
17
  # @rbs update: ACP::Types::SessionUpdate::t
@@ -23,9 +23,6 @@ class ACP::AgentConnection::Client
23
23
  # @rbs return: void
24
24
  def available_commands: (String session_id, Array[ACP::Types::AvailableCommand] commands) -> void
25
25
 
26
- # Blocks the calling thread until the client answers or the connection
27
- # closes.
28
- #
29
26
  # @rbs request: ACP::Types::RequestPermissionRequest
30
27
  # @rbs return: ACP::Types::RequestPermissionResponse | ACP::RequestError
31
28
  def request_permission: (ACP::Types::RequestPermissionRequest request) -> (ACP::Types::RequestPermissionResponse | ACP::RequestError)
@@ -74,17 +71,11 @@ class ACP::AgentConnection::Client
74
71
  # @rbs return: void
75
72
  def complete_elicitation: (ACP::Types::CompleteElicitationNotification notification) -> void
76
73
 
77
- # Sends one inner MCP operation to the client's declared ACP MCP server. The
78
- # reply's result may be null, and a reply matching neither carrier branch
79
- # comes back as the raw hash.
80
- #
81
74
  # @rbs request: ACP::Types::Unstable::MessageMcpRequest
82
75
  # @rbs return: (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError)
83
76
  def mcp_message: (ACP::Types::Unstable::MessageMcpRequest request) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError)
84
77
 
85
- # Sends an extension request, keyed by its raw `_`-prefixed wire name, and
86
- # returns the client's reply as-is: extension methods have no schema to
87
- # parse the result into.
78
+ # Extension methods have no schema to parse the result into.
88
79
  #
89
80
  # @rbs method: String
90
81
  # @rbs params: untyped
@@ -99,14 +90,14 @@ class ACP::AgentConnection::Client
99
90
  private
100
91
 
101
92
  # @rbs rpc_method: String
102
- # @rbs type: ACP::AgentConnection::_Parser
103
- # @rbs request: ACP::AgentConnection::_Response
93
+ # @rbs type: ACP::Transport::_Parser
94
+ # @rbs request: ACP::Transport::_Response
104
95
  # @rbs return: untyped
105
- def call: (String rpc_method, ACP::AgentConnection::_Parser type, ACP::AgentConnection::_Response request) -> untyped
96
+ def call: (String rpc_method, ACP::Transport::_Parser type, ACP::Transport::_Response request) -> untyped
106
97
 
107
98
  # @rbs rpc_method: String
108
- # @rbs type: ACP::AgentConnection::_Parser
109
- # @rbs request: ACP::AgentConnection::_Response
99
+ # @rbs type: ACP::Transport::_Parser
100
+ # @rbs request: ACP::Transport::_Response
110
101
  # @rbs return: untyped
111
- def terminal_call: (String rpc_method, ACP::AgentConnection::_Parser type, ACP::AgentConnection::_Response request) -> untyped
102
+ def terminal_call: (String rpc_method, ACP::Transport::_Parser type, ACP::Transport::_Response request) -> untyped
112
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
@@ -1,4 +1,7 @@
1
1
  # Generated from lib/acp/agent_connection/optional_method.rb with RBS::Inline
2
2
 
3
3
  module ACP::AgentConnection::OptionalMethod
4
+ SPECS: Array[Spec]
5
+
6
+ UNSTABLE_SPECS: Array[Spec]
4
7
  end
@@ -15,18 +15,14 @@ class ACP::AgentConnection
15
15
 
16
16
  @capabilities: ACP::Types::AgentCapabilities
17
17
 
18
- @transport: ACP::AgentConnection::_Transport
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::AgentConnection::_Transport
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::AgentConnection::_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
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,23 +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::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)]
48
- def requests: (ACP::AgentConnection::_Agent agent, ACP::AgentConnection::Client client) -> Hash[String, ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)]
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)]
49
45
 
50
46
  # The unstable request types are referenced while the hash is built, so
51
47
  # without the guard start would raise NameError even for an agent that never
52
48
  # advertises fork or providers.
53
49
  #
54
50
  # @rbs full: ACP::AgentConnection::_FullAgent
55
- # @rbs return: Hash[String, ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)]
56
- def unstable_requests: (ACP::AgentConnection::_FullAgent full) -> Hash[String, ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)]
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)]
57
53
 
58
- # ForkSession's and the provider methods' advertised? reference the unstable
59
- # types, so they can only be probed when the caller opted in with
60
- # `require 'acp/types/unstable'`.
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'`.
61
57
  #
62
- # @rbs return: Array[ACP::AgentConnection::_OptionalMethod]
63
- def optional_methods: () -> Array[ACP::AgentConnection::_OptionalMethod]
58
+ # @rbs return: Array[ACP::AgentConnection::OptionalMethod::Spec]
59
+ def optional_methods: () -> Array[ACP::AgentConnection::OptionalMethod::Spec]
64
60
 
65
61
  # @rbs agent: ACP::AgentConnection::_Agent
66
62
  # @rbs return: Hash[String, ^(untyped) -> void]
@@ -73,10 +69,6 @@ class ACP::AgentConnection
73
69
  # @rbs return: void
74
70
  def cancel: (ACP::AgentConnection::_Agent agent, untyped params) -> void
75
71
 
76
- # The unstable gates reference the unstable types, so they can only be
77
- # probed when the caller opted in with `require 'acp/types/unstable'`; the
78
- # stable McpCapabilities has no acp field at all.
79
- #
80
72
  # @rbs return: bool
81
73
  def mcp_acp_advertised?: () -> bool
82
74
 
@@ -89,10 +81,10 @@ class ACP::AgentConnection
89
81
 
90
82
  # Generated from_h raises on a missing key or a value of the wrong shape.
91
83
  #
92
- # @rbs type: ACP::AgentConnection::_Parser
93
- # @rbs &handle: (untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)
94
- # @rbs return: ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)
95
- def route: (ACP::AgentConnection::_Parser type) { (untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply) } -> ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)
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)
96
88
 
97
89
  # @rbs client: ACP::AgentConnection::Client
98
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