acp-sdk 0.2.0 → 0.4.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +29 -16
  4. data/lib/acp/agent_connection/client.rb +27 -12
  5. data/lib/acp/agent_connection/optional_method/logout.rb +21 -0
  6. data/lib/acp/agent_connection.rb +21 -32
  7. data/lib/acp/agent_process.rb +119 -0
  8. data/lib/acp/client_connection.rb +15 -15
  9. data/lib/acp/request_error.rb +90 -0
  10. data/lib/acp/transport/reply.rb +4 -4
  11. data/lib/acp/transport/stdio.rb +28 -25
  12. data/lib/acp/types/session_update/tool_call.rb +8 -0
  13. data/lib/acp/types/session_update/tool_call_update.rb +8 -0
  14. data/lib/acp/types/tool_call.rb +8 -0
  15. data/lib/acp/types/tool_call_update.rb +8 -0
  16. data/lib/acp/version.rb +1 -1
  17. data/sig/generated/acp/agent_connection/client.rbs +23 -16
  18. data/sig/generated/acp/agent_connection/optional_method/logout.rbs +13 -0
  19. data/sig/generated/acp/agent_connection.rbs +9 -15
  20. data/sig/generated/acp/agent_process.rbs +72 -0
  21. data/sig/generated/acp/client_connection.rbs +16 -16
  22. data/sig/generated/acp/request_error.rbs +72 -0
  23. data/sig/generated/acp/transport/reply.rbs +5 -5
  24. data/sig/generated/acp/transport/stdio.rbs +14 -19
  25. data/sig/generated/acp/types/session_update/tool_call.rbs +5 -1
  26. data/sig/generated/acp/types/session_update/tool_call_update.rbs +5 -1
  27. data/sig/generated/acp/types/tool_call.rbs +5 -1
  28. data/sig/generated/acp/types/tool_call_update.rbs +5 -1
  29. data/sig/manual/acp/agent_connection/optional_method/logout.rbs +6 -0
  30. data/sig/manual/acp/agent_connection.rbs +24 -19
  31. data/sig/manual/acp/agent_process.rbs +7 -0
  32. data/sig/manual/acp/client_connection.rbs +1 -1
  33. data/sig/manual/acp/transport/stdio.rbs +7 -1
  34. metadata +9 -5
  35. data/lib/acp/transport/response_error.rb +0 -28
  36. data/lib/acp/transport/result.rb +0 -35
  37. data/sig/generated/acp/transport/response_error.rbs +0 -21
  38. data/sig/generated/acp/transport/result.rbs +0 -25
@@ -16,11 +16,9 @@ class ACP::Transport::Stdio
16
16
  # @rbs @next_id: Integer
17
17
  # @rbs @closed: bool
18
18
 
19
- INTERNAL_ERROR = -32_603 #: Integer
20
- PARSE_ERROR = ACP::Transport::ResponseError.new(code: -32_700, message: 'Parse error') #: ACP::Transport::ResponseError
21
- INVALID_REQUEST = ACP::Transport::ResponseError.new(code: -32_600, message: 'Invalid request') #: ACP::Transport::ResponseError
22
- METHOD_NOT_FOUND = ACP::Transport::ResponseError.new(code: -32_601, message: 'Method not found') #: ACP::Transport::ResponseError
23
- CONNECTION_CLOSED = ACP::Transport::ResponseError.new(code: INTERNAL_ERROR, message: 'Connection closed') #: ACP::Transport::ResponseError
19
+ CONNECTION_CLOSED = ACP::RequestError.new(
20
+ code: ACP::RequestError::INTERNAL_ERROR, message: 'Connection closed'
21
+ ) #: ACP::RequestError
24
22
 
25
23
  # @rbs input: _Reader
26
24
  # @rbs output: _Writer
@@ -52,14 +50,14 @@ class ACP::Transport::Stdio
52
50
 
53
51
  # @rbs method: String
54
52
  # @rbs params: untyped
55
- # @rbs return: ACP::Transport::Result
53
+ # @rbs return: (Hash[String, untyped] | ACP::RequestError)
56
54
  def request(method, params = nil)
57
55
  queue = Thread::Queue.new
58
56
  id = register(queue)
59
- return ACP::Transport::Result.error(CONNECTION_CLOSED) unless id
57
+ return CONNECTION_CLOSED unless id
60
58
 
61
59
  write({ 'jsonrpc' => '2.0', 'id' => id, 'method' => method, 'params' => params }.compact)
62
- queue.pop || ACP::Transport::Result.error(CONNECTION_CLOSED)
60
+ queue.pop || CONNECTION_CLOSED
63
61
  end
64
62
 
65
63
  # @rbs method: String
@@ -78,7 +76,7 @@ class ACP::Transport::Stdio
78
76
  def receive(line, requests, notifications)
79
77
  message = parse(line)
80
78
  case message
81
- when ACP::Transport::ResponseError then reply(nil, ACP::Transport::Result.error(message))
79
+ when ACP::RequestError then reply(nil, message)
82
80
  else route(message, requests, notifications)
83
81
  end
84
82
  end
@@ -98,25 +96,24 @@ class ACP::Transport::Stdio
98
96
  handler = notifications[method]
99
97
  quietly { handler.call(message['params']) } if handler
100
98
  elsif message.key?('result')
101
- settle(message['id'], ACP::Transport::Result.ok(message['result']))
99
+ settle(message['id'], message['result'])
102
100
  elsif error.is_a?(Hash) && error['code'].is_a?(Integer) && error['message'].is_a?(String)
103
101
  code, text, data = error.values_at('code', 'message', 'data')
104
- response_error = ACP::Transport::ResponseError.new(code:, message: text, data:)
105
- settle(message['id'], ACP::Transport::Result.error(response_error))
102
+ settle(message['id'], ACP::RequestError.new(code:, message: text, data:))
106
103
  else
107
- reply(nil, ACP::Transport::Result.error(INVALID_REQUEST))
104
+ reply(nil, ACP::RequestError.invalid_request)
108
105
  end
109
106
  end
110
107
 
111
108
  # @rbs line: String
112
- # @rbs return: Hash[String, untyped] | ACP::Transport::ResponseError
109
+ # @rbs return: Hash[String, untyped] | ACP::RequestError
113
110
  def parse(line)
114
- return PARSE_ERROR unless line.valid_encoding?
111
+ return ACP::RequestError.parse_error unless line.valid_encoding?
115
112
 
116
113
  message = JSON.parse(line)
117
- message.is_a?(Hash) ? message : INVALID_REQUEST
114
+ message.is_a?(Hash) ? message : ACP::RequestError.invalid_request
118
115
  rescue JSON::ParserError
119
- PARSE_ERROR
116
+ ACP::RequestError.parse_error
120
117
  end
121
118
 
122
119
  # @rbs handler: _Handler?
@@ -125,7 +122,7 @@ class ACP::Transport::Stdio
125
122
  # @rbs return: void
126
123
  def serve(handler, id, params)
127
124
  Thread.new do
128
- outcome = handler ? invoke(handler, params) : ACP::Transport::Result.error(METHOD_NOT_FOUND)
125
+ outcome = handler ? invoke(handler, params) : ACP::RequestError.method_not_found
129
126
  case outcome
130
127
  when ACP::Transport::Reply
131
128
  reply(id, outcome.result)
@@ -152,19 +149,25 @@ class ACP::Transport::Stdio
152
149
  #
153
150
  # @rbs handler: _Handler
154
151
  # @rbs params: untyped
155
- # @rbs return: ACP::Transport::Result | ACP::Transport::Reply
152
+ # @rbs return: (_ToH | ACP::RequestError | ACP::Transport::Reply)
156
153
  def invoke(handler, params)
157
154
  handler.call(params)
158
155
  rescue StandardError => e
159
- ACP::Transport::Result.error(ACP::Transport::ResponseError.new(code: INTERNAL_ERROR, message: e.message))
156
+ ACP::RequestError.new(code: ACP::RequestError::INTERNAL_ERROR, message: e.message)
160
157
  end
161
158
 
159
+ # The success arm is whatever the handler returned, which the transport only
160
+ # knows serializes with to_h; RequestError picks the error arm of the reply.
161
+ #
162
162
  # @rbs id: untyped
163
- # @rbs result: ACP::Transport::Result
163
+ # @rbs outcome: (_ToH | ACP::RequestError)
164
164
  # @rbs return: void
165
- def reply(id, result)
166
- error = result.error
167
- write({ 'jsonrpc' => '2.0', 'id' => id }.merge(error ? { 'error' => error.to_h } : { 'result' => result.value }))
165
+ def reply(id, outcome)
166
+ payload = case outcome
167
+ when ACP::RequestError then { 'error' => outcome.to_h }
168
+ else { 'result' => outcome.to_h }
169
+ end
170
+ write({ 'jsonrpc' => '2.0', 'id' => id }.merge(payload))
168
171
  end
169
172
 
170
173
  # @rbs queue: Thread::Queue
@@ -180,7 +183,7 @@ class ACP::Transport::Stdio
180
183
  end
181
184
 
182
185
  # @rbs id: untyped
183
- # @rbs result: ACP::Transport::Result
186
+ # @rbs result: (Hash[String, untyped] | ACP::RequestError)
184
187
  # @rbs return: void
185
188
  def settle(id, result)
186
189
  @lock.synchronize { @pending.delete(id) }&.push(result)
@@ -9,6 +9,9 @@ class ACP::Types::SessionUpdate::ToolCall
9
9
  # @dynamic title
10
10
  attr_reader :title #: String
11
11
 
12
+ # @dynamic name
13
+ attr_reader :name #: String?
14
+
12
15
  # @dynamic kind
13
16
  attr_reader :kind #: String?
14
17
 
@@ -32,6 +35,7 @@ class ACP::Types::SessionUpdate::ToolCall
32
35
 
33
36
  # @rbs tool_call_id: String
34
37
  # @rbs title: String
38
+ # @rbs name: String?
35
39
  # @rbs kind: String?
36
40
  # @rbs status: String?
37
41
  # @rbs content: Array[ACP::Types::ToolCallContent::t]?
@@ -43,6 +47,7 @@ class ACP::Types::SessionUpdate::ToolCall
43
47
  def initialize(
44
48
  tool_call_id:,
45
49
  title:,
50
+ name: nil,
46
51
  kind: nil,
47
52
  status: nil,
48
53
  content: nil,
@@ -53,6 +58,7 @@ class ACP::Types::SessionUpdate::ToolCall
53
58
  )
54
59
  @tool_call_id = tool_call_id
55
60
  @title = title
61
+ @name = name
56
62
  @kind = kind
57
63
  @status = status
58
64
  @content = content
@@ -69,6 +75,7 @@ class ACP::Types::SessionUpdate::ToolCall
69
75
  new(
70
76
  tool_call_id: hash.fetch('toolCallId'),
71
77
  title: hash.fetch('title'),
78
+ name: hash['name'],
72
79
  kind: hash['kind'],
73
80
  status: hash['status'],
74
81
  content: hash['content']&.map { |item| ACP::Types::ToolCallContent.from_h(item) },
@@ -85,6 +92,7 @@ class ACP::Types::SessionUpdate::ToolCall
85
92
  'sessionUpdate' => 'tool_call',
86
93
  'toolCallId' => tool_call_id,
87
94
  'title' => title,
95
+ 'name' => name,
88
96
  'kind' => kind,
89
97
  'status' => status,
90
98
  'content' => content&.map(&:to_h),
@@ -15,6 +15,9 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
15
15
  # @dynamic title
16
16
  attr_reader :title #: String?
17
17
 
18
+ # @dynamic name
19
+ attr_reader :name #: String?
20
+
18
21
  # @dynamic content
19
22
  attr_reader :content #: Array[ACP::Types::ToolCallContent::t]?
20
23
 
@@ -34,6 +37,7 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
34
37
  # @rbs kind: String?
35
38
  # @rbs status: String?
36
39
  # @rbs title: String?
40
+ # @rbs name: String?
37
41
  # @rbs content: Array[ACP::Types::ToolCallContent::t]?
38
42
  # @rbs locations: Array[ACP::Types::ToolCallLocation]?
39
43
  # @rbs raw_input: untyped
@@ -45,6 +49,7 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
45
49
  kind: nil,
46
50
  status: nil,
47
51
  title: nil,
52
+ name: nil,
48
53
  content: nil,
49
54
  locations: nil,
50
55
  raw_input: nil,
@@ -55,6 +60,7 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
55
60
  @kind = kind
56
61
  @status = status
57
62
  @title = title
63
+ @name = name
58
64
  @content = content
59
65
  @locations = locations
60
66
  @raw_input = raw_input
@@ -71,6 +77,7 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
71
77
  kind: hash['kind'],
72
78
  status: hash['status'],
73
79
  title: hash['title'],
80
+ name: hash['name'],
74
81
  content: hash['content']&.map { |item| ACP::Types::ToolCallContent.from_h(item) },
75
82
  locations: hash['locations']&.map { |item| ACP::Types::ToolCallLocation.from_h(item) },
76
83
  raw_input: hash['rawInput'],
@@ -87,6 +94,7 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
87
94
  'kind' => kind,
88
95
  'status' => status,
89
96
  'title' => title,
97
+ 'name' => name,
90
98
  'content' => content&.map(&:to_h),
91
99
  'locations' => locations&.map(&:to_h),
92
100
  'rawInput' => raw_input,
@@ -9,6 +9,9 @@ class ACP::Types::ToolCall
9
9
  # @dynamic title
10
10
  attr_reader :title #: String
11
11
 
12
+ # @dynamic name
13
+ attr_reader :name #: String?
14
+
12
15
  # @dynamic kind
13
16
  attr_reader :kind #: String?
14
17
 
@@ -32,6 +35,7 @@ class ACP::Types::ToolCall
32
35
 
33
36
  # @rbs tool_call_id: String
34
37
  # @rbs title: String
38
+ # @rbs name: String?
35
39
  # @rbs kind: String?
36
40
  # @rbs status: String?
37
41
  # @rbs content: Array[ACP::Types::ToolCallContent::t]?
@@ -43,6 +47,7 @@ class ACP::Types::ToolCall
43
47
  def initialize(
44
48
  tool_call_id:,
45
49
  title:,
50
+ name: nil,
46
51
  kind: nil,
47
52
  status: nil,
48
53
  content: nil,
@@ -53,6 +58,7 @@ class ACP::Types::ToolCall
53
58
  )
54
59
  @tool_call_id = tool_call_id
55
60
  @title = title
61
+ @name = name
56
62
  @kind = kind
57
63
  @status = status
58
64
  @content = content
@@ -69,6 +75,7 @@ class ACP::Types::ToolCall
69
75
  new(
70
76
  tool_call_id: hash.fetch('toolCallId'),
71
77
  title: hash.fetch('title'),
78
+ name: hash['name'],
72
79
  kind: hash['kind'],
73
80
  status: hash['status'],
74
81
  content: hash['content']&.map { |item| ACP::Types::ToolCallContent.from_h(item) },
@@ -84,6 +91,7 @@ class ACP::Types::ToolCall
84
91
  {
85
92
  'toolCallId' => tool_call_id,
86
93
  'title' => title,
94
+ 'name' => name,
87
95
  'kind' => kind,
88
96
  'status' => status,
89
97
  'content' => content&.map(&:to_h),
@@ -15,6 +15,9 @@ class ACP::Types::ToolCallUpdate
15
15
  # @dynamic title
16
16
  attr_reader :title #: String?
17
17
 
18
+ # @dynamic name
19
+ attr_reader :name #: String?
20
+
18
21
  # @dynamic content
19
22
  attr_reader :content #: Array[ACP::Types::ToolCallContent::t]?
20
23
 
@@ -34,6 +37,7 @@ class ACP::Types::ToolCallUpdate
34
37
  # @rbs kind: String?
35
38
  # @rbs status: String?
36
39
  # @rbs title: String?
40
+ # @rbs name: String?
37
41
  # @rbs content: Array[ACP::Types::ToolCallContent::t]?
38
42
  # @rbs locations: Array[ACP::Types::ToolCallLocation]?
39
43
  # @rbs raw_input: untyped
@@ -45,6 +49,7 @@ class ACP::Types::ToolCallUpdate
45
49
  kind: nil,
46
50
  status: nil,
47
51
  title: nil,
52
+ name: nil,
48
53
  content: nil,
49
54
  locations: nil,
50
55
  raw_input: nil,
@@ -55,6 +60,7 @@ class ACP::Types::ToolCallUpdate
55
60
  @kind = kind
56
61
  @status = status
57
62
  @title = title
63
+ @name = name
58
64
  @content = content
59
65
  @locations = locations
60
66
  @raw_input = raw_input
@@ -71,6 +77,7 @@ class ACP::Types::ToolCallUpdate
71
77
  kind: hash['kind'],
72
78
  status: hash['status'],
73
79
  title: hash['title'],
80
+ name: hash['name'],
74
81
  content: hash['content']&.map { |item| ACP::Types::ToolCallContent.from_h(item) },
75
82
  locations: hash['locations']&.map { |item| ACP::Types::ToolCallLocation.from_h(item) },
76
83
  raw_input: hash['rawInput'],
@@ -86,6 +93,7 @@ class ACP::Types::ToolCallUpdate
86
93
  'kind' => kind,
87
94
  'status' => status,
88
95
  'title' => title,
96
+ 'name' => name,
89
97
  'content' => content&.map(&:to_h),
90
98
  'locations' => locations&.map(&:to_h),
91
99
  'rawInput' => raw_input,
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.2.0'
4
+ VERSION = '0.4.0'
5
5
  end
@@ -24,36 +24,36 @@ class ACP::AgentConnection::Client
24
24
  # closes.
25
25
  #
26
26
  # @rbs request: ACP::Types::RequestPermissionRequest
27
- # @rbs return: ACP::Types::RequestPermissionResponse | ACP::Transport::ResponseError
28
- def request_permission: (ACP::Types::RequestPermissionRequest request) -> (ACP::Types::RequestPermissionResponse | ACP::Transport::ResponseError)
27
+ # @rbs return: ACP::Types::RequestPermissionResponse | ACP::RequestError
28
+ def request_permission: (ACP::Types::RequestPermissionRequest request) -> (ACP::Types::RequestPermissionResponse | ACP::RequestError)
29
29
 
30
30
  # @rbs request: ACP::Types::ReadTextFileRequest
31
- # @rbs return: ACP::Types::ReadTextFileResponse | ACP::Transport::ResponseError
32
- def read_text_file: (ACP::Types::ReadTextFileRequest request) -> (ACP::Types::ReadTextFileResponse | ACP::Transport::ResponseError)
31
+ # @rbs return: ACP::Types::ReadTextFileResponse | ACP::RequestError
32
+ def read_text_file: (ACP::Types::ReadTextFileRequest request) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError)
33
33
 
34
34
  # @rbs request: ACP::Types::WriteTextFileRequest
35
- # @rbs return: ACP::Types::WriteTextFileResponse | ACP::Transport::ResponseError
36
- def write_text_file: (ACP::Types::WriteTextFileRequest request) -> (ACP::Types::WriteTextFileResponse | ACP::Transport::ResponseError)
35
+ # @rbs return: ACP::Types::WriteTextFileResponse | ACP::RequestError
36
+ def write_text_file: (ACP::Types::WriteTextFileRequest request) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError)
37
37
 
38
38
  # @rbs request: ACP::Types::CreateTerminalRequest
39
- # @rbs return: ACP::Types::CreateTerminalResponse | ACP::Transport::ResponseError
40
- def create_terminal: (ACP::Types::CreateTerminalRequest request) -> (ACP::Types::CreateTerminalResponse | ACP::Transport::ResponseError)
39
+ # @rbs return: ACP::Types::CreateTerminalResponse | ACP::RequestError
40
+ def create_terminal: (ACP::Types::CreateTerminalRequest request) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError)
41
41
 
42
42
  # @rbs request: ACP::Types::TerminalOutputRequest
43
- # @rbs return: ACP::Types::TerminalOutputResponse | ACP::Transport::ResponseError
44
- def terminal_output: (ACP::Types::TerminalOutputRequest request) -> (ACP::Types::TerminalOutputResponse | ACP::Transport::ResponseError)
43
+ # @rbs return: ACP::Types::TerminalOutputResponse | ACP::RequestError
44
+ def terminal_output: (ACP::Types::TerminalOutputRequest request) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError)
45
45
 
46
46
  # @rbs request: ACP::Types::WaitForTerminalExitRequest
47
- # @rbs return: ACP::Types::WaitForTerminalExitResponse | ACP::Transport::ResponseError
48
- def wait_for_terminal_exit: (ACP::Types::WaitForTerminalExitRequest request) -> (ACP::Types::WaitForTerminalExitResponse | ACP::Transport::ResponseError)
47
+ # @rbs return: ACP::Types::WaitForTerminalExitResponse | ACP::RequestError
48
+ def wait_for_terminal_exit: (ACP::Types::WaitForTerminalExitRequest request) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError)
49
49
 
50
50
  # @rbs request: ACP::Types::KillTerminalRequest
51
- # @rbs return: ACP::Types::KillTerminalResponse | ACP::Transport::ResponseError
52
- def kill_terminal: (ACP::Types::KillTerminalRequest request) -> (ACP::Types::KillTerminalResponse | ACP::Transport::ResponseError)
51
+ # @rbs return: ACP::Types::KillTerminalResponse | ACP::RequestError
52
+ def kill_terminal: (ACP::Types::KillTerminalRequest request) -> (ACP::Types::KillTerminalResponse | ACP::RequestError)
53
53
 
54
54
  # @rbs request: ACP::Types::ReleaseTerminalRequest
55
- # @rbs return: ACP::Types::ReleaseTerminalResponse | ACP::Transport::ResponseError
56
- def release_terminal: (ACP::Types::ReleaseTerminalRequest request) -> (ACP::Types::ReleaseTerminalResponse | ACP::Transport::ResponseError)
55
+ # @rbs return: ACP::Types::ReleaseTerminalResponse | ACP::RequestError
56
+ def release_terminal: (ACP::Types::ReleaseTerminalRequest request) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError)
57
57
 
58
58
  private
59
59
 
@@ -68,4 +68,11 @@ class ACP::AgentConnection::Client
68
68
  # @rbs request: ACP::AgentConnection::_Response
69
69
  # @rbs return: untyped
70
70
  def terminal_call: (String rpc_method, ACP::AgentConnection::_Parser type, ACP::AgentConnection::_Response request) -> untyped
71
+
72
+ # Same method-not-found code a peer would send, but with a message that says
73
+ # the refusal was local, so logs can tell the two cases apart.
74
+ #
75
+ # @rbs capability: String
76
+ # @rbs return: ACP::RequestError
77
+ def unadvertised: (String capability) -> ACP::RequestError
71
78
  end
@@ -0,0 +1,13 @@
1
+ # Generated from lib/acp/agent_connection/optional_method/logout.rb with RBS::Inline
2
+
3
+ module ACP::AgentConnection::OptionalMethod::Logout
4
+ # @rbs return: String
5
+ def rpc_method: () -> String
6
+
7
+ # @rbs return: Symbol
8
+ def agent_method: () -> Symbol
9
+
10
+ # @rbs initialize_response: ACP::Types::InitializeResponse
11
+ # @rbs return: bool
12
+ def advertised?: (ACP::Types::InitializeResponse initialize_response) -> bool
13
+ end
@@ -9,8 +9,6 @@ class ACP::AgentConnection
9
9
 
10
10
  PROTOCOL_VERSION: Integer
11
11
 
12
- INVALID_PARAMS: ACP::Transport::ResponseError
13
-
14
12
  OPTIONAL: Array[ACP::AgentConnection::_OptionalMethod]
15
13
 
16
14
  # The schema has no initialize capability for modes or config options: an
@@ -33,8 +31,8 @@ class ACP::AgentConnection
33
31
 
34
32
  # @rbs agent: ACP::AgentConnection::_Agent
35
33
  # @rbs client: ACP::AgentConnection::Client
36
- # @rbs return: Hash[String, ^(untyped) -> (ACP::Transport::Result | ACP::Transport::Reply)]
37
- def requests: (ACP::AgentConnection::_Agent agent, ACP::AgentConnection::Client client) -> Hash[String, ^(untyped) -> (ACP::Transport::Result | ACP::Transport::Reply)]
34
+ # @rbs return: Hash[String, ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)]
35
+ def requests: (ACP::AgentConnection::_Agent agent, ACP::AgentConnection::Client client) -> Hash[String, ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)]
38
36
 
39
37
  # @rbs agent: ACP::AgentConnection::_Agent
40
38
  # @rbs return: Hash[String, ^(untyped) -> void]
@@ -43,24 +41,20 @@ class ACP::AgentConnection
43
41
  # Generated from_h raises on a missing key or a value of the wrong shape.
44
42
  #
45
43
  # @rbs type: ACP::AgentConnection::_Parser
46
- # @rbs &handle: (untyped) -> (ACP::Transport::Result | ACP::Transport::Reply)
47
- # @rbs return: ^(untyped) -> (ACP::Transport::Result | ACP::Transport::Reply)
48
- def route: (ACP::AgentConnection::_Parser type) { (untyped) -> (ACP::Transport::Result | ACP::Transport::Reply) } -> ^(untyped) -> (ACP::Transport::Result | ACP::Transport::Reply)
49
-
50
- # @rbs response: ACP::AgentConnection::_Response | ACP::Transport::ResponseError
51
- # @rbs return: ACP::Transport::Result
52
- def respond: (ACP::AgentConnection::_Response | ACP::Transport::ResponseError response) -> ACP::Transport::Result
44
+ # @rbs &handle: (untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)
45
+ # @rbs return: ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)
46
+ def route: (ACP::AgentConnection::_Parser type) { (untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply) } -> ^(untyped) -> (ACP::AgentConnection::_Response | ACP::RequestError | ACP::Transport::Reply)
53
47
 
54
48
  # @rbs client: ACP::AgentConnection::Client
55
49
  # @rbs request: ACP::Types::InitializeRequest
56
- # @rbs return: ACP::Transport::Result
57
- def connect: (ACP::AgentConnection::Client client, ACP::Types::InitializeRequest request) -> ACP::Transport::Result
50
+ # @rbs return: ACP::Types::InitializeResponse
51
+ def connect: (ACP::AgentConnection::Client client, ACP::Types::InitializeRequest request) -> ACP::Types::InitializeResponse
58
52
 
59
53
  # session_created runs after the reply because the client must know the
60
54
  # session id before updates for it (e.g. available commands) arrive.
61
55
  #
62
56
  # @rbs agent: ACP::AgentConnection::_Agent
63
57
  # @rbs request: ACP::Types::NewSessionRequest
64
- # @rbs return: ACP::Transport::Result | ACP::Transport::Reply
65
- def new_session: (ACP::AgentConnection::_Agent agent, ACP::Types::NewSessionRequest request) -> (ACP::Transport::Result | ACP::Transport::Reply)
58
+ # @rbs return: (ACP::Types::NewSessionResponse | ACP::RequestError | ACP::Transport::Reply)
59
+ def new_session: (ACP::AgentConnection::_Agent agent, ACP::Types::NewSessionRequest request) -> (ACP::Types::NewSessionResponse | ACP::RequestError | ACP::Transport::Reply)
66
60
  end
@@ -0,0 +1,72 @@
1
+ # Generated from lib/acp/agent_process.rb with RBS::Inline
2
+
3
+ # A child agent process and the ACP::ClientConnection wired to its stdio.
4
+ # Spawn one with ACP::AgentProcess.spawn.
5
+ class ACP::AgentProcess
6
+ @stderr: String?
7
+
8
+ @err_reader: Thread?
9
+
10
+ @err_r: IO?
11
+
12
+ @waiter: Process::Waiter
13
+
14
+ @stdout: IO
15
+
16
+ @stdin: IO
17
+
18
+ @pid: Integer
19
+
20
+ @reader: Thread
21
+
22
+ @connection: ACP::ClientConnection
23
+
24
+ # @dynamic pid
25
+ attr_reader pid: Integer
26
+
27
+ # @dynamic connection
28
+ attr_reader connection: ACP::ClientConnection
29
+
30
+ # Child stderr captured when spawn was given stderr: :capture, else nil.
31
+ #
32
+ # @dynamic stderr
33
+ attr_reader stderr: String?
34
+
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
+ # @rbs command: String
41
+ # @rbs *args: String
42
+ # @rbs env: Hash[String, String]?
43
+ # @rbs cwd: String?
44
+ # @rbs stderr: (:inherit | :capture)
45
+ # @rbs permission: ACP::ClientConnection::_PermissionHandler
46
+ # @rbs updates: ACP::ClientConnection::_UpdateHandler
47
+ # @rbs &block: ? (ACP::ClientConnection, ACP::AgentProcess) -> untyped
48
+ # @rbs return: (untyped | ACP::AgentProcess)
49
+ 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
+
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
+ # @rbs return: void
56
+ def terminate: () -> void
57
+
58
+ private
59
+
60
+ # @rbs connection: ACP::ClientConnection
61
+ # @rbs reader: Thread
62
+ # @rbs stdin: IO
63
+ # @rbs stdout: IO
64
+ # @rbs waiter: Process::Waiter
65
+ # @rbs err_r: IO?
66
+ # @rbs return: void
67
+ def initialize: (connection: ACP::ClientConnection, reader: Thread, stdin: IO, stdout: IO, waiter: Process::Waiter, err_r: IO?) -> void
68
+
69
+ # @rbs sig: String
70
+ # @rbs return: void
71
+ def signal: (String sig) -> void
72
+ end
@@ -26,26 +26,26 @@ class ACP::ClientConnection
26
26
  # sent by connect.
27
27
  #
28
28
  # @rbs request: ACP::Types::InitializeRequest
29
- # @rbs return: ACP::Types::InitializeResponse | ACP::Transport::ResponseError
30
- def connect: (ACP::Types::InitializeRequest request) -> (ACP::Types::InitializeResponse | ACP::Transport::ResponseError)
29
+ # @rbs return: ACP::Types::InitializeResponse | ACP::RequestError
30
+ def connect: (ACP::Types::InitializeRequest request) -> (ACP::Types::InitializeResponse | ACP::RequestError)
31
31
 
32
32
  # @rbs request: ACP::Types::NewSessionRequest
33
- # @rbs return: ACP::Types::NewSessionResponse | ACP::Transport::ResponseError
34
- def session_new: (ACP::Types::NewSessionRequest request) -> (ACP::Types::NewSessionResponse | ACP::Transport::ResponseError)
33
+ # @rbs return: ACP::Types::NewSessionResponse | ACP::RequestError
34
+ def session_new: (ACP::Types::NewSessionRequest request) -> (ACP::Types::NewSessionResponse | ACP::RequestError)
35
35
 
36
36
  # @rbs request: ACP::Types::PromptRequest
37
37
  # @rbs &block: (ACP::Types::SessionUpdate::t) -> void
38
- # @rbs return: ACP::Types::PromptResponse | ACP::Transport::ResponseError
39
- def session_prompt: (ACP::Types::PromptRequest request) { (ACP::Types::SessionUpdate::t) -> void } -> (ACP::Types::PromptResponse | ACP::Transport::ResponseError)
38
+ # @rbs return: ACP::Types::PromptResponse | ACP::RequestError
39
+ def session_prompt: (ACP::Types::PromptRequest request) { (ACP::Types::SessionUpdate::t) -> void } -> (ACP::Types::PromptResponse | ACP::RequestError)
40
40
 
41
41
  # @rbs request: ACP::Types::LoadSessionRequest
42
42
  # @rbs &block: (ACP::Types::SessionUpdate::t) -> void
43
- # @rbs return: ACP::Types::LoadSessionResponse | ACP::Transport::ResponseError
44
- def session_load: (ACP::Types::LoadSessionRequest request) { (ACP::Types::SessionUpdate::t) -> void } -> (ACP::Types::LoadSessionResponse | ACP::Transport::ResponseError)
43
+ # @rbs return: ACP::Types::LoadSessionResponse | ACP::RequestError
44
+ def session_load: (ACP::Types::LoadSessionRequest request) { (ACP::Types::SessionUpdate::t) -> void } -> (ACP::Types::LoadSessionResponse | ACP::RequestError)
45
45
 
46
46
  # @rbs request: ACP::Types::ListSessionsRequest
47
- # @rbs return: ACP::Types::ListSessionsResponse | ACP::Transport::ResponseError
48
- def session_list: (ACP::Types::ListSessionsRequest request) -> (ACP::Types::ListSessionsResponse | ACP::Transport::ResponseError)
47
+ # @rbs return: ACP::Types::ListSessionsResponse | ACP::RequestError
48
+ def session_list: (ACP::Types::ListSessionsRequest request) -> (ACP::Types::ListSessionsResponse | ACP::RequestError)
49
49
 
50
50
  # @rbs notification: ACP::Types::CancelNotification
51
51
  # @rbs return: void
@@ -54,9 +54,9 @@ class ACP::ClientConnection
54
54
  private
55
55
 
56
56
  # @rbs type: ACP::AgentConnection::_Parser
57
- # @rbs result: ACP::Transport::Result
57
+ # @rbs result: (Hash[String, untyped] | ACP::RequestError)
58
58
  # @rbs return: untyped
59
- def parse: (ACP::AgentConnection::_Parser type, ACP::Transport::Result result) -> untyped
59
+ def parse: (ACP::AgentConnection::_Parser type, Hash[String, untyped] | ACP::RequestError result) -> untyped
60
60
 
61
61
  # The request waits on its own thread so the caller's thread can yield each
62
62
  # update as it arrives. The reader thread queues an update before it settles
@@ -66,8 +66,8 @@ class ACP::ClientConnection
66
66
  # @rbs method: String
67
67
  # @rbs params: Hash[String, untyped]
68
68
  # @rbs &block: (ACP::Types::SessionUpdate::t) -> void
69
- # @rbs return: ACP::Transport::Result
70
- def stream: (String session_id, String method, Hash[String, untyped] params) { (ACP::Types::SessionUpdate::t) -> void } -> ACP::Transport::Result
69
+ # @rbs return: (Hash[String, untyped] | ACP::RequestError)
70
+ def stream: (String session_id, String method, Hash[String, untyped] params) { (ACP::Types::SessionUpdate::t) -> void } -> (Hash[String, untyped] | ACP::RequestError)
71
71
 
72
72
  # Pushes under the lock so a stream cannot close its queue between the
73
73
  # lookup and the push.
@@ -77,6 +77,6 @@ class ACP::ClientConnection
77
77
  def dispatch: (untyped params) -> void
78
78
 
79
79
  # @rbs params: untyped
80
- # @rbs return: ACP::Transport::Result
81
- def request_permission: (untyped params) -> ACP::Transport::Result
80
+ # @rbs return: (ACP::Types::RequestPermissionResponse | ACP::RequestError)
81
+ def request_permission: (untyped params) -> (ACP::Types::RequestPermissionResponse | ACP::RequestError)
82
82
  end