acp-sdk 0.13.0 → 0.14.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/LICENSE +21 -0
  4. data/README.md +142 -70
  5. data/lib/acp/agent_connection/client.rb +2 -3
  6. data/lib/acp/agent_connection/optional_route.rb +45 -0
  7. data/lib/acp/agent_connection.rb +121 -77
  8. data/lib/acp/agent_process.rb +4 -4
  9. data/lib/acp/client_connection/elicitations.rb +44 -0
  10. data/lib/acp/client_connection/inbound.rb +240 -0
  11. data/lib/acp/client_connection/streams.rb +20 -52
  12. data/lib/acp/client_connection.rb +37 -315
  13. data/lib/acp/extensions.rb +6 -0
  14. data/lib/acp/protocol.rb +14 -4
  15. data/lib/acp/transport/reply.rb +5 -15
  16. data/lib/acp/transport/stdio.rb +7 -2
  17. data/lib/acp/types/parse_error.rb +1 -1
  18. data/lib/acp/types.rb +13 -0
  19. data/lib/acp/version.rb +1 -1
  20. data/sig/generated/acp/agent_connection/optional_route.rbs +35 -0
  21. data/sig/generated/acp/agent_connection.rbs +5 -21
  22. data/sig/generated/acp/client_connection/elicitations.rbs +29 -0
  23. data/sig/generated/acp/client_connection/inbound.rbs +109 -0
  24. data/sig/generated/acp/client_connection/streams.rbs +7 -28
  25. data/sig/generated/acp/client_connection.rbs +12 -139
  26. data/sig/generated/acp/extensions.rbs +4 -0
  27. data/sig/generated/acp/protocol.rbs +8 -0
  28. data/sig/generated/acp/transport/reply.rbs +11 -9
  29. data/sig/generated/acp/transport/stdio.rbs +17 -4
  30. data/sig/generated/acp/types.rbs +9 -0
  31. data/sig/manual/acp/agent_connection.rbs +5 -57
  32. data/sig/manual/acp/client_connection.rbs +27 -0
  33. data/sig/manual/acp/transport/stdio.rbs +1 -5
  34. metadata +10 -10
  35. data/LICENSE.txt +0 -9
  36. data/lib/acp/agent_connection/optional_method/spec.rb +0 -42
  37. data/lib/acp/agent_connection/optional_method.rb +0 -40
  38. data/lib/acp/transport/stdio/serving.rb +0 -18
  39. data/sig/generated/acp/agent_connection/optional_method/spec.rbs +0 -32
  40. data/sig/generated/acp/agent_connection/optional_method.rbs +0 -7
  41. data/sig/generated/acp/transport/stdio/serving.rbs +0 -14
data/lib/acp/types.rb CHANGED
@@ -9,4 +9,17 @@ module ACP::Types
9
9
  def self.unstable_enabled?
10
10
  !defined?(ACP::Types::Unstable).nil?
11
11
  end
12
+
13
+ # Generated from_h checks only nested values, so a payload that is not an
14
+ # object is rejected here: a String would answer nil for every key and parse
15
+ # as an empty object.
16
+ #
17
+ # @rbs type: ACP::Transport::_Parser
18
+ # @rbs payload: untyped
19
+ # @rbs return: untyped
20
+ def self.parse(type, payload)
21
+ ACP::Types::Check.object(payload, [], type)
22
+ rescue ACP::Types::ParseError => e
23
+ e
24
+ end
12
25
  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.13.0'
4
+ VERSION = '0.14.1'
5
5
  end
@@ -0,0 +1,35 @@
1
+ # Generated from lib/acp/agent_connection/optional_route.rb with RBS::Inline
2
+
3
+ class ACP::AgentConnection::OptionalRoute
4
+ # @dynamic rpc_method
5
+ attr_reader rpc_method: String
6
+
7
+ # @dynamic type
8
+ attr_reader type: ACP::Transport::_Parser
9
+
10
+ # @dynamic agent_method
11
+ attr_reader agent_method: Symbol
12
+
13
+ # @dynamic path
14
+ attr_reader path: Array[Symbol]?
15
+
16
+ # @dynamic handle
17
+ attr_reader handle: ^(ACP::AgentConnection::_FullAgent, untyped) -> (ACP::Transport::_Response | ACP::RequestError)
18
+
19
+ # @rbs rpc_method: String
20
+ # @rbs type: ACP::Transport::_Parser
21
+ # @rbs agent_method: Symbol
22
+ # @rbs path: Array[Symbol]?
23
+ # @rbs &handle: (ACP::AgentConnection::_FullAgent, untyped) -> (ACP::Transport::_Response | ACP::RequestError)
24
+ # @rbs return: void
25
+ def initialize: (rpc_method: String, type: ACP::Transport::_Parser, agent_method: Symbol, path: Array[Symbol]?) { (ACP::AgentConnection::_FullAgent, untyped) -> (ACP::Transport::_Response | ACP::RequestError) } -> void
26
+
27
+ # @rbs initialize_response: ACP::Types::InitializeResponse
28
+ # @rbs return: bool
29
+ def advertised?: (ACP::Types::InitializeResponse initialize_response) -> bool
30
+
31
+ # @rbs initialize_response: ACP::Types::InitializeResponse
32
+ # @rbs agent: ACP::AgentConnection::_Agent
33
+ # @rbs return: bool
34
+ def routed?: (ACP::Types::InitializeResponse initialize_response, ACP::AgentConnection::_Agent agent) -> bool
35
+ end
@@ -17,10 +17,7 @@ class ACP::AgentConnection
17
17
 
18
18
  @transport: ACP::Transport::Stdio
19
19
 
20
- # The schema has no initialize capability for modes or config options: an
21
- # agent offers them per session, in its session responses, so they are
22
- # routed whenever the agent defines them.
23
- PER_SESSION: Hash[String, Symbol]
20
+ OPTIONAL_ROUTES: Array[ACP::AgentConnection::OptionalRoute]
24
21
 
25
22
  # @rbs transport: ACP::Transport::Stdio
26
23
  # @rbs capabilities: ACP::Types::AgentCapabilities
@@ -40,23 +37,12 @@ class ACP::AgentConnection
40
37
 
41
38
  # @rbs agent: ACP::AgentConnection::_Agent
42
39
  # @rbs client: ACP::AgentConnection::Client
40
+ # @rbs optional: Array[ACP::AgentConnection::OptionalRoute]
43
41
  # @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)]
42
+ def requests: (ACP::AgentConnection::_Agent agent, ACP::AgentConnection::Client client, Array[ACP::AgentConnection::OptionalRoute] optional) -> Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
45
43
 
46
- # The unstable request types are referenced while the hash is built, so
47
- # without the guard start would raise NameError even for an agent that never
48
- # advertises fork or providers.
49
- #
50
- # @rbs full: ACP::AgentConnection::_FullAgent
51
- # @rbs return: Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
52
- def unstable_requests: (ACP::AgentConnection::_FullAgent full) -> Hash[String, ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)]
53
-
54
- # The unstable specs pair with the unstable request routes, which reference
55
- # the unstable request classes, so both are only probed after the caller
56
- # opted in with `require 'acp/types/unstable'`.
57
- #
58
- # @rbs return: Array[ACP::AgentConnection::OptionalMethod::Spec]
59
- def optional_methods: () -> Array[ACP::AgentConnection::OptionalMethod::Spec]
44
+ # @rbs return: Array[ACP::AgentConnection::OptionalRoute]
45
+ def unstable_routes: () -> Array[ACP::AgentConnection::OptionalRoute]
60
46
 
61
47
  # @rbs agent: ACP::AgentConnection::_Agent
62
48
  # @rbs return: Hash[String, ^(untyped) -> void]
@@ -79,8 +65,6 @@ class ACP::AgentConnection
79
65
  # @rbs return: void
80
66
  def mcp_message_notification: (ACP::AgentConnection::_Agent agent, untyped params) -> void
81
67
 
82
- # Generated from_h raises on a missing key or a value of the wrong shape.
83
- #
84
68
  # @rbs type: ACP::Transport::_Parser
85
69
  # @rbs &handle: (untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
86
70
  # @rbs return: ^(untyped) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
@@ -0,0 +1,29 @@
1
+ # Generated from lib/acp/client_connection/elicitations.rb with RBS::Inline
2
+
3
+ class ACP::ClientConnection::Elicitations
4
+ @handler: ACP::ClientConnection::_Elicitation?
5
+
6
+ @logger: ACP::Transport::_Logger
7
+
8
+ @lock: Thread::Mutex
9
+
10
+ @outstanding: Hash[String, bool]
11
+
12
+ # @rbs handler: ACP::ClientConnection::_Elicitation?
13
+ # @rbs logger: ACP::Transport::_Logger
14
+ # @rbs return: void
15
+ def initialize: (handler: ACP::ClientConnection::_Elicitation?, logger: ACP::Transport::_Logger) -> void
16
+
17
+ # @rbs elicitation_id: String
18
+ # @rbs return: void
19
+ def register: (String elicitation_id) -> void
20
+
21
+ # The spec requires a completion for an unknown or already-completed
22
+ # elicitation id to be ignored, so only an id registered by a served
23
+ # url-mode request reaches the handler. It runs on the transport's reader
24
+ # thread, so it must return quickly.
25
+ #
26
+ # @rbs params: untyped
27
+ # @rbs return: void
28
+ def complete: (untyped params) -> void
29
+ end
@@ -0,0 +1,109 @@
1
+ # Generated from lib/acp/client_connection/inbound.rb with RBS::Inline
2
+
3
+ class ACP::ClientConnection::Inbound
4
+ @capabilities: ACP::Types::ClientCapabilities?
5
+
6
+ @extension_notifications: Hash[String, ^(untyped) -> void]
7
+
8
+ @extension_requests: Hash[String, ^(untyped) -> untyped]
9
+
10
+ @mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?
11
+
12
+ @elicitations: ACP::ClientConnection::Elicitations
13
+
14
+ @elicitation: ACP::ClientConnection::_Elicitation?
15
+
16
+ @terminal: ACP::ClientConnection::_Terminal?
17
+
18
+ @fs: ACP::ClientConnection::_FileSystem?
19
+
20
+ class Route < Data
21
+ attr_reader rpc_method(): String
22
+
23
+ attr_reader type(): ACP::Transport::_Parser
24
+
25
+ attr_reader handler_method(): Symbol
26
+
27
+ attr_reader path(): Array[Symbol]
28
+
29
+ attr_reader capability(): String
30
+
31
+ def self.new: (String rpc_method, ACP::Transport::_Parser type, Symbol handler_method, Array[Symbol] path, String capability) -> instance
32
+ | (rpc_method: String, type: ACP::Transport::_Parser, handler_method: Symbol, path: Array[Symbol], capability: String) -> instance
33
+
34
+ def self.members: () -> [ :rpc_method, :type, :handler_method, :path, :capability ]
35
+
36
+ def members: () -> [ :rpc_method, :type, :handler_method, :path, :capability ]
37
+ end
38
+
39
+ FS_ROUTES: Array[ACP::ClientConnection::Inbound::Route]
40
+
41
+ # The terminal capability is a single bool, so its five routes share one
42
+ # gate. Their handlers may block for as long as the command runs, so the
43
+ # transport must serve each request on its own thread for this not to hold
44
+ # up others.
45
+ TERMINAL_ROUTES: Array[ACP::ClientConnection::Inbound::Route]
46
+
47
+ # @dynamic mcp_advertised=
48
+ attr_writer mcp_advertised: bool
49
+
50
+ # @rbs elicitations: ACP::ClientConnection::Elicitations
51
+ # @rbs fs: ACP::ClientConnection::_FileSystem?
52
+ # @rbs terminal: ACP::ClientConnection::_Terminal?
53
+ # @rbs elicitation: ACP::ClientConnection::_Elicitation?
54
+ # @rbs mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) ->
55
+ # (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?
56
+ # @rbs extension_requests: Hash[String, ^(untyped) -> untyped]
57
+ # @rbs extension_notifications: Hash[String, ^(untyped) -> void]
58
+ # @rbs return: void
59
+ def initialize: (elicitations: ACP::ClientConnection::Elicitations, ?fs: ACP::ClientConnection::_FileSystem?, ?terminal: ACP::ClientConnection::_Terminal?, ?elicitation: ACP::ClientConnection::_Elicitation?, ?mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?, ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void]) -> void
60
+
61
+ # @rbs return: Hash[String, ACP::Transport::Stdio::_Handler]
62
+ def requests: () -> Hash[String, ACP::Transport::Stdio::_Handler]
63
+
64
+ # @rbs return: Hash[String, ACP::Transport::Stdio::_NotificationHandler]
65
+ def notifications: () -> Hash[String, ACP::Transport::Stdio::_NotificationHandler]
66
+
67
+ # @rbs capabilities: ACP::Types::ClientCapabilities?
68
+ # @rbs return: void
69
+ def advertise: (ACP::Types::ClientCapabilities? capabilities) -> void
70
+
71
+ private
72
+
73
+ # @rbs route: ACP::ClientConnection::Inbound::Route
74
+ # @rbs handler: untyped
75
+ # @rbs return: ^(untyped) -> untyped
76
+ def serve: (ACP::ClientConnection::Inbound::Route route, untyped handler) -> ^(untyped) -> untyped
77
+
78
+ # @rbs type: ACP::Transport::_Parser
79
+ # @rbs params: untyped
80
+ # @rbs &block: (untyped) -> untyped
81
+ # @rbs return: untyped
82
+ def parsed: (ACP::Transport::_Parser type, untyped params) { (untyped) -> untyped } -> untyped
83
+
84
+ # @rbs routes: Array[ACP::ClientConnection::Inbound::Route]
85
+ # @rbs handler: untyped
86
+ # @rbs capabilities: ACP::Types::ClientCapabilities?
87
+ # @rbs return: Array[String]
88
+ def unserved: (Array[ACP::ClientConnection::Inbound::Route] routes, untyped handler, ACP::Types::ClientCapabilities? capabilities) -> Array[String]
89
+
90
+ # @rbs capabilities: ACP::Types::ElicitationCapabilities?
91
+ # @rbs return: Array[String]
92
+ def unserved_elicitation_modes: (ACP::Types::ElicitationCapabilities? capabilities) -> Array[String]
93
+
94
+ # @rbs what: String
95
+ # @rbs unserved: Array[String]
96
+ # @rbs return: void
97
+ def check_served: (String what, Array[String] unserved) -> void
98
+
99
+ # @rbs return: Hash[String, ^(untyped) -> untyped]
100
+ def mcp_requests: () -> Hash[String, ^(untyped) -> untyped]
101
+
102
+ # @rbs params: untyped
103
+ # @rbs return: (ACP::Types::CreateElicitationResponse | ACP::RequestError)
104
+ def create_elicitation: (untyped params) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError)
105
+
106
+ # @rbs request: ACP::Types::CreateElicitationRequest
107
+ # @rbs return: ACP::RequestError?
108
+ def elicitation_refusal: (ACP::Types::CreateElicitationRequest request) -> ACP::RequestError?
109
+ end
@@ -1,36 +1,28 @@
1
1
  # Generated from lib/acp/client_connection/streams.rb with RBS::Inline
2
2
 
3
- # It holds no send facade of its own — requests go through the sender and
4
- # answers to the agent ride the connection's routes — so it is unit-testable
5
- # without a transport.
6
3
  class ACP::ClientConnection::Streams
7
4
  CANCELLED: ACP::Types::RequestPermissionResponse
8
5
 
9
- @outstanding_elicitations: Hash[String, bool]
10
-
11
- @pending_permissions: Hash[String, Array[Thread::Queue]]
6
+ @sender: ACP::Transport::Stdio
12
7
 
13
- @streams: Hash[String, Thread::Queue]
8
+ @permission: ACP::ClientConnection::_PermissionHandler
14
9
 
15
- @lock: Thread::Mutex
10
+ @updates: ACP::ClientConnection::_UpdateHandler
16
11
 
17
12
  @logger: ACP::Transport::_Logger
18
13
 
19
- @complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
20
-
21
- @updates: ACP::ClientConnection::_UpdateHandler
14
+ @lock: Thread::Mutex
22
15
 
23
- @permission: ACP::ClientConnection::_PermissionHandler
16
+ @streams: Hash[String, Thread::Queue]
24
17
 
25
- @sender: ACP::Transport::Stdio
18
+ @pending_permissions: Hash[String, Array[Thread::Queue]]
26
19
 
27
20
  # @rbs sender: ACP::Transport::Stdio
28
21
  # @rbs permission: ACP::ClientConnection::_PermissionHandler
29
22
  # @rbs updates: ACP::ClientConnection::_UpdateHandler
30
23
  # @rbs logger: ACP::Transport::_Logger
31
- # @rbs complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
32
24
  # @rbs return: void
33
- def initialize: (sender: ACP::Transport::Stdio, permission: ACP::ClientConnection::_PermissionHandler, updates: ACP::ClientConnection::_UpdateHandler, logger: ACP::Transport::_Logger, ?complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?) -> void
25
+ def initialize: (sender: ACP::Transport::Stdio, permission: ACP::ClientConnection::_PermissionHandler, updates: ACP::ClientConnection::_UpdateHandler, logger: ACP::Transport::_Logger) -> void
34
26
 
35
27
  # The request waits on its own thread so the caller's thread can yield each
36
28
  # update as it arrives. The reader thread queues an update before it settles
@@ -67,19 +59,6 @@ class ACP::ClientConnection::Streams
67
59
  # @rbs return: void
68
60
  def cancel: (String session_id) -> void
69
61
 
70
- # @rbs elicitation_id: String
71
- # @rbs return: void
72
- def register_elicitation: (String elicitation_id) -> void
73
-
74
- # The spec requires a completion for an unknown or already-completed
75
- # elicitation id to be ignored, so only an id registered by a served
76
- # url-mode request reaches the handler. It runs on the transport's reader
77
- # thread, so it must return quickly.
78
- #
79
- # @rbs params: untyped
80
- # @rbs return: void
81
- def complete_elicitation: (untyped params) -> void
82
-
83
62
  private
84
63
 
85
64
  # @rbs session_id: String
@@ -1,123 +1,33 @@
1
1
  # Generated from lib/acp/client_connection.rb with RBS::Inline
2
2
 
3
3
  class ACP::ClientConnection
4
- @transport: ACP::Transport::Stdio
5
-
6
- @permission: ACP::ClientConnection::_PermissionHandler
7
-
8
- @read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
9
-
10
- @write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
11
-
12
- @create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?
13
-
14
- @terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?
15
-
16
- @wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?
17
-
18
- @kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?
19
-
20
- @release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?
21
-
22
- @elicitation: (^(ACP::Types::CreateElicitationRequest) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError))?
23
-
24
- @mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?
25
-
26
- @mcp_advertised: bool?
27
-
28
- @fs_capabilities: ACP::Types::FileSystemCapabilities?
29
-
30
- @terminal: bool?
31
-
32
- @elicitation_capabilities: ACP::Types::ElicitationCapabilities?
33
-
34
- @extension_requests: Hash[String, ^(untyped) -> untyped]
35
-
36
- @extension_notifications: Hash[String, ^(untyped) -> void]
4
+ @inbound: ACP::ClientConnection::Inbound
37
5
 
38
6
  @streams: ACP::ClientConnection::Streams
39
7
 
40
- @logger: ACP::Transport::_Logger
8
+ @transport: ACP::Transport::Stdio
41
9
 
42
10
  IGNORE: ^(ACP::Types::SessionNotification) -> void
43
11
 
44
- class Route
45
- @label: String
46
-
47
- @key: String
48
-
49
- @refuse: Symbol
50
-
51
- @advertised: ^(untyped) -> (bool | nil)
52
-
53
- @family: Symbol
54
-
55
- @handler: Symbol
56
-
57
- @type: ACP::Transport::_Parser
58
-
59
- @wire: String
60
-
61
- # @rbs wire: String
62
- # @rbs type: ACP::Transport::_Parser
63
- # @rbs handler: Symbol
64
- # @rbs family: Symbol
65
- # @rbs key: String
66
- # @rbs advertised: ^(untyped) -> (bool | nil)
67
- # @rbs refuse: Symbol
68
- # @rbs label: String?
69
- # @rbs return: void
70
- def initialize: (wire: String, type: ACP::Transport::_Parser, handler: Symbol, family: Symbol, key: String, ?advertised: ^(untyped) -> (bool | nil), ?refuse: Symbol, ?label: String?) -> void
71
-
72
- # @dynamic wire, type, handler, family, advertised, refuse, key, label
73
- attr_reader wire: String
74
-
75
- attr_reader type: ACP::Transport::_Parser
76
-
77
- attr_reader handler: Symbol
78
-
79
- attr_reader family: Symbol
80
-
81
- attr_reader advertised: ^(untyped) -> (bool | nil)
82
-
83
- attr_reader refuse: Symbol
84
-
85
- attr_reader key: String
86
-
87
- attr_reader label: String
88
- end
89
-
90
- # The routes are registered at start, before connect records the
91
- # advertisement, so each one answers its refusal until then. The terminal
92
- # capability is a single bool, so its five routes share one gate.
93
- #
94
- # The terminal handlers may block for as long as the command runs, so the
95
- # transport must serve each request on its own thread for this not to hold
96
- # up others.
97
- SERVE: Array[ACP::ClientConnection::Route]
98
-
99
12
  # @rbs transport: ACP::Transport::Stdio
100
13
  # @rbs permission: ACP::ClientConnection::_PermissionHandler
101
- # @rbs read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?
102
- # @rbs write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?
103
- # @rbs create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?
104
- # @rbs terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?
105
- # @rbs wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) ->
106
- # (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?
107
- # @rbs kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?
108
- # @rbs release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?
109
- # @rbs elicitation: (^(ACP::Types::CreateElicitationRequest) ->
110
- # (ACP::Types::CreateElicitationResponse | ACP::RequestError))?
111
- # @rbs complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
112
14
  # @rbs updates: ACP::ClientConnection::_UpdateHandler
15
+ # @rbs fs: ACP::ClientConnection::_FileSystem?
16
+ # @rbs terminal: ACP::ClientConnection::_Terminal?
17
+ # @rbs elicitation: ACP::ClientConnection::_Elicitation?
113
18
  # @rbs mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) ->
114
19
  # (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?
115
20
  # @rbs extension_requests: Hash[String, ^(untyped) -> untyped]
116
21
  # @rbs extension_notifications: Hash[String, ^(untyped) -> void]
117
- # @rbs streams: ACP::ClientConnection::Streams?
118
22
  # @rbs logger: ACP::Transport::_Logger
23
+ # @rbs return: ACP::ClientConnection
24
+ def self.build: (transport: ACP::Transport::Stdio, permission: ACP::ClientConnection::_PermissionHandler, ?updates: ACP::ClientConnection::_UpdateHandler, ?fs: ACP::ClientConnection::_FileSystem?, ?terminal: ACP::ClientConnection::_Terminal?, ?elicitation: ACP::ClientConnection::_Elicitation?, ?mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?, ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?logger: ACP::Transport::_Logger) -> ACP::ClientConnection
25
+
26
+ # @rbs transport: ACP::Transport::Stdio
27
+ # @rbs streams: ACP::ClientConnection::Streams
28
+ # @rbs inbound: ACP::ClientConnection::Inbound
119
29
  # @rbs return: void
120
- def initialize: (transport: ACP::Transport::Stdio, permission: ACP::ClientConnection::_PermissionHandler, ?read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?, ?write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?, ?create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?, ?terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?, ?wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?, ?kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?, ?release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?, ?elicitation: (^(ACP::Types::CreateElicitationRequest) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError))?, ?complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?, ?updates: ACP::ClientConnection::_UpdateHandler, ?mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) -> (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?, ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?streams: ACP::ClientConnection::Streams?, ?logger: ACP::Transport::_Logger) -> void
30
+ def initialize: (transport: ACP::Transport::Stdio, streams: ACP::ClientConnection::Streams, inbound: ACP::ClientConnection::Inbound) -> void
121
31
 
122
32
  # @rbs return: Thread
123
33
  def start: () -> Thread
@@ -172,7 +82,6 @@ class ACP::ClientConnection
172
82
 
173
83
  # @rbs request: ACP::Types::Unstable::SetProviderRequest
174
84
  # @rbs return: (ACP::Types::Unstable::SetProviderResponse | ACP::RequestError)
175
- # The name is the wire-mandated providers/set, not an attribute writer.
176
85
  def set_provider: (ACP::Types::Unstable::SetProviderRequest request) -> (ACP::Types::Unstable::SetProviderResponse | ACP::RequestError)
177
86
 
178
87
  # @rbs request: ACP::Types::Unstable::DisableProviderRequest
@@ -189,7 +98,6 @@ class ACP::ClientConnection
189
98
 
190
99
  # @rbs request: ACP::Types::SetSessionModeRequest
191
100
  # @rbs return: ACP::Types::SetSessionModeResponse | ACP::RequestError
192
- # The name is the wire-mandated session/set_mode, not an attribute writer.
193
101
  def set_session_mode: (ACP::Types::SetSessionModeRequest request) -> (ACP::Types::SetSessionModeResponse | ACP::RequestError)
194
102
 
195
103
  # The reply carries the session's complete option list, so it replaces any
@@ -197,7 +105,6 @@ class ACP::ClientConnection
197
105
  #
198
106
  # @rbs request: ACP::Types::SetSessionConfigOptionRequest
199
107
  # @rbs return: ACP::Types::SetSessionConfigOptionResponse | ACP::RequestError
200
- # The name is the wire-mandated session/set_config_option, not an attribute writer.
201
108
  def set_session_config_option: (ACP::Types::SetSessionConfigOptionRequest request) -> (ACP::Types::SetSessionConfigOptionResponse | ACP::RequestError)
202
109
 
203
110
  # @rbs request: ACP::Types::AuthenticateRequest
@@ -235,42 +142,8 @@ class ACP::ClientConnection
235
142
 
236
143
  private
237
144
 
238
- # @rbs route: ACP::ClientConnection::Route
239
- # @rbs return: ^(untyped) -> (untyped | ACP::RequestError)
240
- def serve: (ACP::ClientConnection::Route route) -> ^(untyped) -> (untyped | ACP::RequestError)
241
-
242
- # @rbs route: ACP::ClientConnection::Route
243
- # @rbs return: ACP::RequestError
244
- def refuse: (ACP::ClientConnection::Route route) -> ACP::RequestError
245
-
246
- # @rbs name: String
247
- # @rbs family: Symbol
248
- # @rbs capabilities: untyped
249
- # @rbs return: void
250
- def check_served: (String name, Symbol family, untyped capabilities) -> void
251
-
252
- # The unstable types are referenced while the row is built, so the route can
253
- # only be served when the caller opted in with `require 'acp/types/unstable'`.
254
- # It is registered only when a handler serves it: unlike the fs and terminal
255
- # gates, the mcp gate reads the agent's advertisement, so nothing forces an
256
- # advertised request to have a handler.
257
- #
258
- # @rbs return: Hash[String, ^(untyped) -> (untyped | ACP::RequestError)]
259
- def mcp_requests: () -> Hash[String, ^(untyped) -> (untyped | ACP::RequestError)]
260
-
261
145
  # @rbs type: ACP::Transport::_Parser
262
146
  # @rbs result: (Hash[String, untyped] | ACP::RequestError)
263
147
  # @rbs return: untyped
264
148
  def parse: (ACP::Transport::_Parser type, Hash[String, untyped] | ACP::RequestError result) -> untyped
265
-
266
- # The route is registered at start, before connect records the advertised
267
- # capabilities, so a request for an unadvertised mode answers -32602.
268
- #
269
- # @rbs params: untyped
270
- # @rbs return: (ACP::Types::CreateElicitationResponse | ACP::RequestError)
271
- def create_elicitation: (untyped params) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError)
272
-
273
- # @rbs capabilities: ACP::Types::ElicitationCapabilities?
274
- # @rbs return: Array[String]
275
- def unserved_elicitation_modes: (ACP::Types::ElicitationCapabilities? capabilities) -> Array[String]
276
149
  end
@@ -6,4 +6,8 @@ module ACP::Extensions
6
6
  # @rbs name: String
7
7
  # @rbs return: void
8
8
  def validate_name: (String name) -> void
9
+
10
+ # @rbs names: Array[String]
11
+ # @rbs return: void
12
+ def validate_names: (Array[String] names) -> void
9
13
  end
@@ -3,6 +3,14 @@
3
3
  module ACP::Protocol
4
4
  PROTOCOL_VERSION: Integer
5
5
 
6
+ # Readers missing along the chain count as unadvertised, so the stable
7
+ # capabilities answer false for the unstable-only paths (fork, providers).
8
+ #
9
+ # @rbs capabilities: untyped
10
+ # @rbs path: Array[Symbol]
11
+ # @rbs return: bool
12
+ def advertised?: (untyped capabilities, Array[Symbol] path) -> bool
13
+
6
14
  # @rbs capabilities: (ACP::Types::AgentCapabilities | ACP::Types::Unstable::AgentCapabilities | Hash[String, untyped])
7
15
  # @rbs return: bool
8
16
  def mcp_acp_advertised?: (ACP::Types::AgentCapabilities | ACP::Types::Unstable::AgentCapabilities | Hash[String, untyped] capabilities) -> bool
@@ -1,14 +1,16 @@
1
1
  # Generated from lib/acp/transport/reply.rb with RBS::Inline
2
2
 
3
- class ACP::Transport::Reply
4
- # @dynamic result
5
- attr_reader result: ACP::Transport::Stdio::_ToH
3
+ module ACP::Transport
4
+ class Reply < Data
5
+ attr_reader result(): ACP::Transport::_Response
6
6
 
7
- # @dynamic after
8
- attr_reader after: ^() -> void
7
+ attr_reader after(): ^() -> void
9
8
 
10
- # @rbs result: ACP::Transport::Stdio::_ToH
11
- # @rbs after: ^() -> void
12
- # @rbs return: void
13
- def initialize: (ACP::Transport::Stdio::_ToH result, after: ^() -> void) -> void
9
+ def self.new: (ACP::Transport::_Response result, ^() -> void after) -> instance
10
+ | (result: ACP::Transport::_Response, after: ^() -> void) -> instance
11
+
12
+ def self.members: () -> [ :result, :after ]
13
+
14
+ def members: () -> [ :result, :after ]
15
+ end
14
16
  end
@@ -25,6 +25,19 @@ class ACP::Transport::Stdio
25
25
 
26
26
  CONNECTION_CLOSED: ACP::RequestError
27
27
 
28
+ class Serving < Data
29
+ attr_reader id(): untyped
30
+
31
+ attr_reader cancellation(): ACP::Transport::Cancellation
32
+
33
+ def self.new: (untyped id, ACP::Transport::Cancellation cancellation) -> instance
34
+ | (id: untyped, cancellation: ACP::Transport::Cancellation) -> instance
35
+
36
+ def self.members: () -> [ :id, :cancellation ]
37
+
38
+ def members: () -> [ :id, :cancellation ]
39
+ end
40
+
28
41
  # @rbs input: _Reader
29
42
  # @rbs output: _Writer
30
43
  # @rbs logger: ACP::Transport::_Logger
@@ -134,13 +147,13 @@ class ACP::Transport::Stdio
134
147
  #
135
148
  # @rbs handler: _Handler
136
149
  # @rbs params: untyped
137
- # @rbs return: (_ToH | ACP::RequestError | ACP::Transport::Reply)
138
- def invoke: (_Handler handler, untyped params) -> (_ToH | ACP::RequestError | ACP::Transport::Reply)
150
+ # @rbs return: (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
151
+ def invoke: (_Handler handler, untyped params) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
139
152
 
140
153
  # @rbs id: untyped
141
- # @rbs outcome: (_ToH | ACP::RequestError)
154
+ # @rbs outcome: (ACP::Transport::_Response | ACP::RequestError)
142
155
  # @rbs return: void
143
- def reply: (untyped id, _ToH | ACP::RequestError outcome) -> void
156
+ def reply: (untyped id, ACP::Transport::_Response | ACP::RequestError outcome) -> void
144
157
 
145
158
  # @rbs queue: Thread::Queue
146
159
  # @rbs return: Integer?
@@ -7,4 +7,13 @@ module ACP::Types
7
7
  #
8
8
  # @rbs return: bool
9
9
  def self.unstable_enabled?: () -> bool
10
+
11
+ # Generated from_h checks only nested values, so a payload that is not an
12
+ # object is rejected here: a String would answer nil for every key and parse
13
+ # as an empty object.
14
+ #
15
+ # @rbs type: ACP::Transport::_Parser
16
+ # @rbs payload: untyped
17
+ # @rbs return: untyped
18
+ def self.parse: (ACP::Transport::_Parser type, untyped payload) -> untyped
10
19
  end