acp-sdk 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +11 -4
- data/lib/acp/agent_connection/client.rb +28 -14
- data/lib/acp/agent_connection/optional_method/logout.rb +21 -0
- data/lib/acp/agent_connection.rb +66 -13
- data/lib/acp/client_connection.rb +148 -5
- data/lib/acp/request_error.rb +30 -0
- data/lib/acp/transport/stderr_logger.rb +17 -0
- data/lib/acp/transport/stdio.rb +15 -6
- data/lib/acp/types/session_update/tool_call.rb +8 -0
- data/lib/acp/types/session_update/tool_call_update.rb +8 -0
- data/lib/acp/types/tool_call.rb +8 -0
- data/lib/acp/types/tool_call_update.rb +8 -0
- data/lib/acp/version.rb +1 -1
- data/sig/generated/acp/agent_connection/client.rbs +8 -7
- data/sig/generated/acp/agent_connection/optional_method/logout.rbs +13 -0
- data/sig/generated/acp/agent_connection.rbs +30 -4
- data/sig/generated/acp/client_connection.rbs +67 -2
- data/sig/generated/acp/request_error.rbs +24 -0
- data/sig/generated/acp/transport/stderr_logger.rbs +13 -0
- data/sig/generated/acp/transport/stdio.rbs +9 -2
- data/sig/generated/acp/types/session_update/tool_call.rbs +5 -1
- data/sig/generated/acp/types/session_update/tool_call_update.rbs +5 -1
- data/sig/generated/acp/types/tool_call.rbs +5 -1
- data/sig/generated/acp/types/tool_call_update.rbs +5 -1
- data/sig/manual/acp/agent_connection/optional_method/logout.rbs +6 -0
- data/sig/manual/acp/agent_connection.rbs +7 -0
- data/sig/manual/acp/transport.rbs +8 -0
- metadata +7 -1
data/lib/acp/transport/stdio.rb
CHANGED
|
@@ -15,6 +15,7 @@ class ACP::Transport::Stdio
|
|
|
15
15
|
# @rbs @pending: Hash[untyped, Thread::Queue]
|
|
16
16
|
# @rbs @next_id: Integer
|
|
17
17
|
# @rbs @closed: bool
|
|
18
|
+
# @rbs @logger: ACP::Transport::_Logger
|
|
18
19
|
|
|
19
20
|
CONNECTION_CLOSED = ACP::RequestError.new(
|
|
20
21
|
code: ACP::RequestError::INTERNAL_ERROR, message: 'Connection closed'
|
|
@@ -22,8 +23,9 @@ class ACP::Transport::Stdio
|
|
|
22
23
|
|
|
23
24
|
# @rbs input: _Reader
|
|
24
25
|
# @rbs output: _Writer
|
|
26
|
+
# @rbs logger: ACP::Transport::_Logger
|
|
25
27
|
# @rbs return: void
|
|
26
|
-
def initialize(input:, output:)
|
|
28
|
+
def initialize(input:, output:, logger: ACP::Transport::StderrLogger.new)
|
|
27
29
|
@input = input
|
|
28
30
|
@output = output
|
|
29
31
|
@write_lock = Mutex.new
|
|
@@ -31,6 +33,7 @@ class ACP::Transport::Stdio
|
|
|
31
33
|
@pending = {}
|
|
32
34
|
@next_id = 0
|
|
33
35
|
@closed = false
|
|
36
|
+
@logger = logger
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
# Returns the reader thread, which ends at EOF on input after releasing any
|
|
@@ -94,7 +97,7 @@ class ACP::Transport::Stdio
|
|
|
94
97
|
# Run on the reader thread so notifications (session/update) keep their
|
|
95
98
|
# order; a JSON-RPC notification has no reply to carry a handler error.
|
|
96
99
|
handler = notifications[method]
|
|
97
|
-
quietly { handler.call(message['params']) } if handler
|
|
100
|
+
quietly('notification handler') { handler.call(message['params']) } if handler
|
|
98
101
|
elsif message.key?('result')
|
|
99
102
|
settle(message['id'], message['result'])
|
|
100
103
|
elsif error.is_a?(Hash) && error['code'].is_a?(Integer) && error['message'].is_a?(String)
|
|
@@ -126,7 +129,7 @@ class ACP::Transport::Stdio
|
|
|
126
129
|
case outcome
|
|
127
130
|
when ACP::Transport::Reply
|
|
128
131
|
reply(id, outcome.result)
|
|
129
|
-
quietly(&outcome.after)
|
|
132
|
+
quietly('reply after callback', &outcome.after)
|
|
130
133
|
else reply(id, outcome)
|
|
131
134
|
end
|
|
132
135
|
end
|
|
@@ -136,12 +139,13 @@ class ACP::Transport::Stdio
|
|
|
136
139
|
# Reply's after once the reply is on the wire. An exception must not kill
|
|
137
140
|
# the reader thread or print a thread report.
|
|
138
141
|
#
|
|
142
|
+
# @rbs label: String
|
|
139
143
|
# @rbs &block: () -> void
|
|
140
144
|
# @rbs return: void
|
|
141
|
-
def quietly
|
|
145
|
+
def quietly(label)
|
|
142
146
|
yield
|
|
143
|
-
rescue StandardError
|
|
144
|
-
|
|
147
|
+
rescue StandardError => e
|
|
148
|
+
@logger.error("#{label} raised #{e.class}: #{e.message}")
|
|
145
149
|
end
|
|
146
150
|
|
|
147
151
|
# Handlers are application code at the protocol boundary: an exception
|
|
@@ -198,6 +202,9 @@ class ACP::Transport::Stdio
|
|
|
198
202
|
end
|
|
199
203
|
end
|
|
200
204
|
|
|
205
|
+
# A closed peer must not kill the thread writing the reply: the reader has
|
|
206
|
+
# to keep draining input so pending requests still settle at EOF.
|
|
207
|
+
#
|
|
201
208
|
# @rbs message: Hash[String, untyped]
|
|
202
209
|
# @rbs return: void
|
|
203
210
|
def write(message)
|
|
@@ -206,5 +213,7 @@ class ACP::Transport::Stdio
|
|
|
206
213
|
@output.write(line)
|
|
207
214
|
@output.flush
|
|
208
215
|
end
|
|
216
|
+
rescue Errno::EPIPE => e
|
|
217
|
+
@logger.warn("write to closed peer: #{e.class}: #{e.message}")
|
|
209
218
|
end
|
|
210
219
|
end
|
|
@@ -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,
|
data/lib/acp/types/tool_call.rb
CHANGED
|
@@ -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
|
@@ -55,6 +55,14 @@ class ACP::AgentConnection::Client
|
|
|
55
55
|
# @rbs return: ACP::Types::ReleaseTerminalResponse | ACP::RequestError
|
|
56
56
|
def release_terminal: (ACP::Types::ReleaseTerminalRequest request) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError)
|
|
57
57
|
|
|
58
|
+
# @rbs request: ACP::Types::CreateElicitationRequest
|
|
59
|
+
# @rbs return: ACP::Types::CreateElicitationResponse | ACP::RequestError
|
|
60
|
+
def create_elicitation: (ACP::Types::CreateElicitationRequest request) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError)
|
|
61
|
+
|
|
62
|
+
# @rbs notification: ACP::Types::CompleteElicitationNotification
|
|
63
|
+
# @rbs return: void
|
|
64
|
+
def complete_elicitation: (ACP::Types::CompleteElicitationNotification notification) -> void
|
|
65
|
+
|
|
58
66
|
private
|
|
59
67
|
|
|
60
68
|
# @rbs rpc_method: String
|
|
@@ -68,11 +76,4 @@ class ACP::AgentConnection::Client
|
|
|
68
76
|
# @rbs request: ACP::AgentConnection::_Response
|
|
69
77
|
# @rbs return: untyped
|
|
70
78
|
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
|
|
78
79
|
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
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
# Generated from lib/acp/agent_connection.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
class ACP::AgentConnection
|
|
4
|
-
@
|
|
5
|
-
|
|
6
|
-
@initialize_response: ACP::Types::InitializeResponse
|
|
4
|
+
@logger: ACP::Transport::_Logger
|
|
7
5
|
|
|
8
6
|
@factory: ^(ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent
|
|
9
7
|
|
|
8
|
+
@auth_methods: Array[ACP::Types::AuthMethod::t]
|
|
9
|
+
|
|
10
|
+
@agent_info: ACP::Types::Implementation?
|
|
11
|
+
|
|
12
|
+
@capabilities: ACP::Types::AgentCapabilities
|
|
13
|
+
|
|
14
|
+
@transport: ACP::AgentConnection::_Transport
|
|
15
|
+
|
|
10
16
|
PROTOCOL_VERSION: Integer
|
|
11
17
|
|
|
12
18
|
OPTIONAL: Array[ACP::AgentConnection::_OptionalMethod]
|
|
@@ -20,9 +26,10 @@ class ACP::AgentConnection
|
|
|
20
26
|
# @rbs capabilities: ACP::Types::AgentCapabilities
|
|
21
27
|
# @rbs agent_info: ACP::Types::Implementation?
|
|
22
28
|
# @rbs auth_methods: Array[ACP::Types::AuthMethod::t]
|
|
29
|
+
# @rbs logger: ACP::Transport::_Logger
|
|
23
30
|
# @rbs &factory: (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent
|
|
24
31
|
# @rbs return: void
|
|
25
|
-
def initialize: (transport: ACP::AgentConnection::_Transport, capabilities: ACP::Types::AgentCapabilities, ?agent_info: ACP::Types::Implementation?, ?auth_methods: Array[ACP::Types::AuthMethod::t]) { (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent } -> void
|
|
32
|
+
def initialize: (transport: ACP::AgentConnection::_Transport, capabilities: ACP::Types::AgentCapabilities, ?agent_info: ACP::Types::Implementation?, ?auth_methods: Array[ACP::Types::AuthMethod::t], ?logger: ACP::Transport::_Logger) { (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent } -> void
|
|
26
33
|
|
|
27
34
|
# @rbs return: Thread
|
|
28
35
|
def start: () -> Thread
|
|
@@ -38,6 +45,13 @@ class ACP::AgentConnection
|
|
|
38
45
|
# @rbs return: Hash[String, ^(untyped) -> void]
|
|
39
46
|
def notifications: (ACP::AgentConnection::_Agent agent) -> Hash[String, ^(untyped) -> void]
|
|
40
47
|
|
|
48
|
+
# A notification has no reply to carry a parse failure.
|
|
49
|
+
#
|
|
50
|
+
# @rbs agent: ACP::AgentConnection::_Agent
|
|
51
|
+
# @rbs params: untyped
|
|
52
|
+
# @rbs return: void
|
|
53
|
+
def cancel: (ACP::AgentConnection::_Agent agent, untyped params) -> void
|
|
54
|
+
|
|
41
55
|
# Generated from_h raises on a missing key or a value of the wrong shape.
|
|
42
56
|
#
|
|
43
57
|
# @rbs type: ACP::AgentConnection::_Parser
|
|
@@ -50,6 +64,18 @@ class ACP::AgentConnection
|
|
|
50
64
|
# @rbs return: ACP::Types::InitializeResponse
|
|
51
65
|
def connect: (ACP::AgentConnection::Client client, ACP::Types::InitializeRequest request) -> ACP::Types::InitializeResponse
|
|
52
66
|
|
|
67
|
+
# @rbs auth_methods: Array[ACP::Types::AuthMethod::t]
|
|
68
|
+
# @rbs return: ACP::Types::InitializeResponse
|
|
69
|
+
def initialize_response: (Array[ACP::Types::AuthMethod::t] auth_methods) -> ACP::Types::InitializeResponse
|
|
70
|
+
|
|
71
|
+
# @rbs capabilities: ACP::Types::ClientCapabilities
|
|
72
|
+
# @rbs return: Array[ACP::Types::AuthMethod::t]
|
|
73
|
+
def auth_methods: (ACP::Types::ClientCapabilities capabilities) -> Array[ACP::Types::AuthMethod::t]
|
|
74
|
+
|
|
75
|
+
# @rbs method: ACP::Types::AuthMethod::t
|
|
76
|
+
# @rbs return: bool
|
|
77
|
+
def terminal_auth_method?: (ACP::Types::AuthMethod::t method) -> bool
|
|
78
|
+
|
|
53
79
|
# session_created runs after the reply because the client must know the
|
|
54
80
|
# session id before updates for it (e.g. available commands) arrive.
|
|
55
81
|
#
|
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
# Generated from lib/acp/client_connection.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
class ACP::ClientConnection
|
|
4
|
+
@logger: ACP::Transport::_Logger
|
|
5
|
+
|
|
4
6
|
@streams: Hash[String, Thread::Queue]
|
|
5
7
|
|
|
6
8
|
@lock: Thread::Mutex
|
|
7
9
|
|
|
10
|
+
@fs_capabilities: ACP::Types::FileSystemCapabilities?
|
|
11
|
+
|
|
8
12
|
@updates: ACP::ClientConnection::_UpdateHandler
|
|
9
13
|
|
|
14
|
+
@write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
|
|
15
|
+
|
|
16
|
+
@read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
|
|
17
|
+
|
|
10
18
|
@permission: ACP::ClientConnection::_PermissionHandler
|
|
11
19
|
|
|
12
20
|
@transport: ACP::AgentConnection::_Transport
|
|
13
21
|
|
|
22
|
+
PROTOCOL_VERSION: Integer
|
|
23
|
+
|
|
14
24
|
IGNORE: ^(ACP::Types::SessionNotification) -> void
|
|
15
25
|
|
|
16
26
|
# @rbs transport: ACP::AgentConnection::_Transport
|
|
17
27
|
# @rbs permission: ACP::ClientConnection::_PermissionHandler
|
|
28
|
+
# @rbs read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
|
|
29
|
+
# @rbs write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
|
|
18
30
|
# @rbs updates: ACP::ClientConnection::_UpdateHandler
|
|
31
|
+
# @rbs logger: ACP::Transport::_Logger
|
|
19
32
|
# @rbs return: void
|
|
20
|
-
def initialize: (transport: ACP::AgentConnection::_Transport, permission: ACP::ClientConnection::_PermissionHandler, ?updates: ACP::ClientConnection::_UpdateHandler) -> void
|
|
33
|
+
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, ?logger: ACP::Transport::_Logger) -> void
|
|
21
34
|
|
|
22
35
|
# @rbs return: Thread
|
|
23
36
|
def start: () -> Thread
|
|
@@ -47,10 +60,44 @@ class ACP::ClientConnection
|
|
|
47
60
|
# @rbs return: ACP::Types::ListSessionsResponse | ACP::RequestError
|
|
48
61
|
def session_list: (ACP::Types::ListSessionsRequest request) -> (ACP::Types::ListSessionsResponse | ACP::RequestError)
|
|
49
62
|
|
|
63
|
+
# The agent does not replay history on resume, so unlike session_load there
|
|
64
|
+
# is nothing to stream and no block is taken.
|
|
65
|
+
#
|
|
66
|
+
# @rbs request: ACP::Types::ResumeSessionRequest
|
|
67
|
+
# @rbs return: ACP::Types::ResumeSessionResponse | ACP::RequestError
|
|
68
|
+
def session_resume: (ACP::Types::ResumeSessionRequest request) -> (ACP::Types::ResumeSessionResponse | ACP::RequestError)
|
|
69
|
+
|
|
70
|
+
# @rbs request: ACP::Types::CloseSessionRequest
|
|
71
|
+
# @rbs return: ACP::Types::CloseSessionResponse | ACP::RequestError
|
|
72
|
+
def session_close: (ACP::Types::CloseSessionRequest request) -> (ACP::Types::CloseSessionResponse | ACP::RequestError)
|
|
73
|
+
|
|
74
|
+
# @rbs request: ACP::Types::DeleteSessionRequest
|
|
75
|
+
# @rbs return: ACP::Types::DeleteSessionResponse | ACP::RequestError
|
|
76
|
+
def session_delete: (ACP::Types::DeleteSessionRequest request) -> (ACP::Types::DeleteSessionResponse | ACP::RequestError)
|
|
77
|
+
|
|
50
78
|
# @rbs notification: ACP::Types::CancelNotification
|
|
51
79
|
# @rbs return: void
|
|
52
80
|
def session_cancel: (ACP::Types::CancelNotification notification) -> void
|
|
53
81
|
|
|
82
|
+
# @rbs request: ACP::Types::SetSessionModeRequest
|
|
83
|
+
# @rbs return: ACP::Types::SetSessionModeResponse | ACP::RequestError
|
|
84
|
+
def session_set_mode: (ACP::Types::SetSessionModeRequest request) -> (ACP::Types::SetSessionModeResponse | ACP::RequestError)
|
|
85
|
+
|
|
86
|
+
# The reply carries the session's complete option list, so it replaces any
|
|
87
|
+
# state held from an earlier reply rather than merging into it.
|
|
88
|
+
#
|
|
89
|
+
# @rbs request: ACP::Types::SetSessionConfigOptionRequest
|
|
90
|
+
# @rbs return: ACP::Types::SetSessionConfigOptionResponse | ACP::RequestError
|
|
91
|
+
def session_set_config_option: (ACP::Types::SetSessionConfigOptionRequest request) -> (ACP::Types::SetSessionConfigOptionResponse | ACP::RequestError)
|
|
92
|
+
|
|
93
|
+
# @rbs request: ACP::Types::AuthenticateRequest
|
|
94
|
+
# @rbs return: ACP::Types::AuthenticateResponse | ACP::RequestError
|
|
95
|
+
def authenticate: (ACP::Types::AuthenticateRequest request) -> (ACP::Types::AuthenticateResponse | ACP::RequestError)
|
|
96
|
+
|
|
97
|
+
# @rbs request: ACP::Types::LogoutRequest
|
|
98
|
+
# @rbs return: ACP::Types::LogoutResponse | ACP::RequestError
|
|
99
|
+
def logout: (ACP::Types::LogoutRequest request) -> (ACP::Types::LogoutResponse | ACP::RequestError)
|
|
100
|
+
|
|
54
101
|
private
|
|
55
102
|
|
|
56
103
|
# @rbs type: ACP::AgentConnection::_Parser
|
|
@@ -70,7 +117,8 @@ class ACP::ClientConnection
|
|
|
70
117
|
def stream: (String session_id, String method, Hash[String, untyped] params) { (ACP::Types::SessionUpdate::t) -> void } -> (Hash[String, untyped] | ACP::RequestError)
|
|
71
118
|
|
|
72
119
|
# Pushes under the lock so a stream cannot close its queue between the
|
|
73
|
-
# lookup and the push.
|
|
120
|
+
# lookup and the push. A malformed notification has no reply to carry the
|
|
121
|
+
# failure.
|
|
74
122
|
#
|
|
75
123
|
# @rbs params: untyped
|
|
76
124
|
# @rbs return: void
|
|
@@ -79,4 +127,21 @@ class ACP::ClientConnection
|
|
|
79
127
|
# @rbs params: untyped
|
|
80
128
|
# @rbs return: (ACP::Types::RequestPermissionResponse | ACP::RequestError)
|
|
81
129
|
def request_permission: (untyped params) -> (ACP::Types::RequestPermissionResponse | ACP::RequestError)
|
|
130
|
+
|
|
131
|
+
# The routes are registered at start, before connect records the advertised
|
|
132
|
+
# capabilities, so each one answers -32601 until then.
|
|
133
|
+
#
|
|
134
|
+
# @rbs params: untyped
|
|
135
|
+
# @rbs return: (ACP::Types::ReadTextFileResponse | ACP::RequestError)
|
|
136
|
+
def read_text_file: (untyped params) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError)
|
|
137
|
+
|
|
138
|
+
# @rbs params: untyped
|
|
139
|
+
# @rbs return: (ACP::Types::WriteTextFileResponse | ACP::RequestError)
|
|
140
|
+
def write_text_file: (untyped params) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError)
|
|
141
|
+
|
|
142
|
+
# The fs capabilities initialize advertises that no injected handler serves.
|
|
143
|
+
#
|
|
144
|
+
# @rbs capabilities: ACP::Types::FileSystemCapabilities?
|
|
145
|
+
# @rbs return: Array[String]
|
|
146
|
+
def unserved_fs_methods: (ACP::Types::FileSystemCapabilities? capabilities) -> Array[String]
|
|
82
147
|
end
|
|
@@ -50,9 +50,33 @@ class ACP::RequestError
|
|
|
50
50
|
# @rbs return: ACP::RequestError
|
|
51
51
|
def self.invalid_params: () -> ACP::RequestError
|
|
52
52
|
|
|
53
|
+
# The method-not-found code for a method the client's capabilities do not
|
|
54
|
+
# advertise, with a message that names the capability so it can be told
|
|
55
|
+
# apart from an unknown method.
|
|
56
|
+
#
|
|
57
|
+
# @rbs capability: String
|
|
58
|
+
# @rbs return: ACP::RequestError
|
|
59
|
+
def self.unadvertised: (String capability) -> ACP::RequestError
|
|
60
|
+
|
|
53
61
|
# @rbs return: ACP::RequestError
|
|
54
62
|
def self.internal_error: () -> ACP::RequestError
|
|
55
63
|
|
|
64
|
+
# The message tells a malformed peer reply apart from an internal error a
|
|
65
|
+
# handler raised, though both use the -32603 code.
|
|
66
|
+
#
|
|
67
|
+
# @rbs response: untyped
|
|
68
|
+
# @rbs return: ACP::RequestError
|
|
69
|
+
def self.invalid_response: (untyped response) -> ACP::RequestError
|
|
70
|
+
|
|
71
|
+
# A local refusal of an initialize reply that names a version the SDK does
|
|
72
|
+
# not speak; the message names both versions so logs can tell it from a
|
|
73
|
+
# peer's error.
|
|
74
|
+
#
|
|
75
|
+
# @rbs requested: Integer
|
|
76
|
+
# @rbs returned: Integer
|
|
77
|
+
# @rbs return: ACP::RequestError
|
|
78
|
+
def self.unsupported_protocol_version: (requested: Integer, returned: Integer) -> ACP::RequestError
|
|
79
|
+
|
|
56
80
|
# @rbs return: ACP::RequestError
|
|
57
81
|
def self.request_cancelled: () -> ACP::RequestError
|
|
58
82
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Generated from lib/acp/transport/stderr_logger.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
# The default sink for dropped messages and swallowed errors: the spec
|
|
4
|
+
# sanctions agents logging to stderr.
|
|
5
|
+
class ACP::Transport::StderrLogger
|
|
6
|
+
# @rbs message: String
|
|
7
|
+
# @rbs return: void
|
|
8
|
+
def warn: (String message) -> void
|
|
9
|
+
|
|
10
|
+
# @rbs message: String
|
|
11
|
+
# @rbs return: void
|
|
12
|
+
def error: (String message) -> void
|
|
13
|
+
end
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
# outbound request mid-turn and still see notifications (e.g. session/cancel)
|
|
7
7
|
# that arrive meanwhile.
|
|
8
8
|
class ACP::Transport::Stdio
|
|
9
|
+
@logger: ACP::Transport::_Logger
|
|
10
|
+
|
|
9
11
|
@closed: bool
|
|
10
12
|
|
|
11
13
|
@next_id: Integer
|
|
@@ -24,8 +26,9 @@ class ACP::Transport::Stdio
|
|
|
24
26
|
|
|
25
27
|
# @rbs input: _Reader
|
|
26
28
|
# @rbs output: _Writer
|
|
29
|
+
# @rbs logger: ACP::Transport::_Logger
|
|
27
30
|
# @rbs return: void
|
|
28
|
-
def initialize: (input: _Reader, output: _Writer) -> void
|
|
31
|
+
def initialize: (input: _Reader, output: _Writer, ?logger: ACP::Transport::_Logger) -> void
|
|
29
32
|
|
|
30
33
|
# Returns the reader thread, which ends at EOF on input after releasing any
|
|
31
34
|
# pending outbound requests.
|
|
@@ -73,9 +76,10 @@ class ACP::Transport::Stdio
|
|
|
73
76
|
# Reply's after once the reply is on the wire. An exception must not kill
|
|
74
77
|
# the reader thread or print a thread report.
|
|
75
78
|
#
|
|
79
|
+
# @rbs label: String
|
|
76
80
|
# @rbs &block: () -> void
|
|
77
81
|
# @rbs return: void
|
|
78
|
-
def quietly: () { () -> void } -> void
|
|
82
|
+
def quietly: (String label) { () -> void } -> void
|
|
79
83
|
|
|
80
84
|
# Handlers are application code at the protocol boundary: an exception
|
|
81
85
|
# becomes an error response instead of killing the thread serving it.
|
|
@@ -105,6 +109,9 @@ class ACP::Transport::Stdio
|
|
|
105
109
|
# @rbs return: void
|
|
106
110
|
def close: () -> void
|
|
107
111
|
|
|
112
|
+
# A closed peer must not kill the thread writing the reply: the reader has
|
|
113
|
+
# to keep draining input so pending requests still settle at EOF.
|
|
114
|
+
#
|
|
108
115
|
# @rbs message: Hash[String, untyped]
|
|
109
116
|
# @rbs return: void
|
|
110
117
|
def write: (Hash[String, untyped] message) -> void
|
|
@@ -7,6 +7,9 @@ class ACP::Types::SessionUpdate::ToolCall
|
|
|
7
7
|
# @dynamic title
|
|
8
8
|
attr_reader title: String
|
|
9
9
|
|
|
10
|
+
# @dynamic name
|
|
11
|
+
attr_reader name: String?
|
|
12
|
+
|
|
10
13
|
# @dynamic kind
|
|
11
14
|
attr_reader kind: String?
|
|
12
15
|
|
|
@@ -30,6 +33,7 @@ class ACP::Types::SessionUpdate::ToolCall
|
|
|
30
33
|
|
|
31
34
|
# @rbs tool_call_id: String
|
|
32
35
|
# @rbs title: String
|
|
36
|
+
# @rbs name: String?
|
|
33
37
|
# @rbs kind: String?
|
|
34
38
|
# @rbs status: String?
|
|
35
39
|
# @rbs content: Array[ACP::Types::ToolCallContent::t]?
|
|
@@ -38,7 +42,7 @@ class ACP::Types::SessionUpdate::ToolCall
|
|
|
38
42
|
# @rbs raw_output: untyped
|
|
39
43
|
# @rbs meta: Hash[String, untyped]?
|
|
40
44
|
# @rbs return: void
|
|
41
|
-
def initialize: (tool_call_id: String, title: String, ?kind: String?, ?status: String?, ?content: Array[ACP::Types::ToolCallContent::t]?, ?locations: Array[ACP::Types::ToolCallLocation]?, ?raw_input: untyped, ?raw_output: untyped, ?meta: Hash[String, untyped]?) -> void
|
|
45
|
+
def initialize: (tool_call_id: String, title: String, ?name: String?, ?kind: String?, ?status: String?, ?content: Array[ACP::Types::ToolCallContent::t]?, ?locations: Array[ACP::Types::ToolCallLocation]?, ?raw_input: untyped, ?raw_output: untyped, ?meta: Hash[String, untyped]?) -> void
|
|
42
46
|
|
|
43
47
|
# @rbs hash: Hash[String, untyped]
|
|
44
48
|
# @rbs return: ACP::Types::SessionUpdate::ToolCall
|
|
@@ -13,6 +13,9 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
|
|
|
13
13
|
# @dynamic title
|
|
14
14
|
attr_reader title: String?
|
|
15
15
|
|
|
16
|
+
# @dynamic name
|
|
17
|
+
attr_reader name: String?
|
|
18
|
+
|
|
16
19
|
# @dynamic content
|
|
17
20
|
attr_reader content: Array[ACP::Types::ToolCallContent::t]?
|
|
18
21
|
|
|
@@ -32,13 +35,14 @@ class ACP::Types::SessionUpdate::ToolCallUpdate
|
|
|
32
35
|
# @rbs kind: String?
|
|
33
36
|
# @rbs status: String?
|
|
34
37
|
# @rbs title: String?
|
|
38
|
+
# @rbs name: String?
|
|
35
39
|
# @rbs content: Array[ACP::Types::ToolCallContent::t]?
|
|
36
40
|
# @rbs locations: Array[ACP::Types::ToolCallLocation]?
|
|
37
41
|
# @rbs raw_input: untyped
|
|
38
42
|
# @rbs raw_output: untyped
|
|
39
43
|
# @rbs meta: Hash[String, untyped]?
|
|
40
44
|
# @rbs return: void
|
|
41
|
-
def initialize: (tool_call_id: String, ?kind: String?, ?status: String?, ?title: String?, ?content: Array[ACP::Types::ToolCallContent::t]?, ?locations: Array[ACP::Types::ToolCallLocation]?, ?raw_input: untyped, ?raw_output: untyped, ?meta: Hash[String, untyped]?) -> void
|
|
45
|
+
def initialize: (tool_call_id: String, ?kind: String?, ?status: String?, ?title: String?, ?name: String?, ?content: Array[ACP::Types::ToolCallContent::t]?, ?locations: Array[ACP::Types::ToolCallLocation]?, ?raw_input: untyped, ?raw_output: untyped, ?meta: Hash[String, untyped]?) -> void
|
|
42
46
|
|
|
43
47
|
# @rbs hash: Hash[String, untyped]
|
|
44
48
|
# @rbs return: ACP::Types::SessionUpdate::ToolCallUpdate
|
|
@@ -7,6 +7,9 @@ class ACP::Types::ToolCall
|
|
|
7
7
|
# @dynamic title
|
|
8
8
|
attr_reader title: String
|
|
9
9
|
|
|
10
|
+
# @dynamic name
|
|
11
|
+
attr_reader name: String?
|
|
12
|
+
|
|
10
13
|
# @dynamic kind
|
|
11
14
|
attr_reader kind: String?
|
|
12
15
|
|
|
@@ -30,6 +33,7 @@ class ACP::Types::ToolCall
|
|
|
30
33
|
|
|
31
34
|
# @rbs tool_call_id: String
|
|
32
35
|
# @rbs title: String
|
|
36
|
+
# @rbs name: String?
|
|
33
37
|
# @rbs kind: String?
|
|
34
38
|
# @rbs status: String?
|
|
35
39
|
# @rbs content: Array[ACP::Types::ToolCallContent::t]?
|
|
@@ -38,7 +42,7 @@ class ACP::Types::ToolCall
|
|
|
38
42
|
# @rbs raw_output: untyped
|
|
39
43
|
# @rbs meta: Hash[String, untyped]?
|
|
40
44
|
# @rbs return: void
|
|
41
|
-
def initialize: (tool_call_id: String, title: String, ?kind: String?, ?status: String?, ?content: Array[ACP::Types::ToolCallContent::t]?, ?locations: Array[ACP::Types::ToolCallLocation]?, ?raw_input: untyped, ?raw_output: untyped, ?meta: Hash[String, untyped]?) -> void
|
|
45
|
+
def initialize: (tool_call_id: String, title: String, ?name: String?, ?kind: String?, ?status: String?, ?content: Array[ACP::Types::ToolCallContent::t]?, ?locations: Array[ACP::Types::ToolCallLocation]?, ?raw_input: untyped, ?raw_output: untyped, ?meta: Hash[String, untyped]?) -> void
|
|
42
46
|
|
|
43
47
|
# @rbs hash: Hash[String, untyped]
|
|
44
48
|
# @rbs return: ACP::Types::ToolCall
|