acp-sdk 0.12.0 → 0.14.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/README.md +141 -69
  4. data/lib/acp/agent_connection/client.rb +4 -5
  5. data/lib/acp/agent_connection/optional_route.rb +45 -0
  6. data/lib/acp/agent_connection.rb +122 -78
  7. data/lib/acp/agent_process.rb +4 -4
  8. data/lib/acp/client_connection/elicitations.rb +44 -0
  9. data/lib/acp/client_connection/inbound/route.rb +29 -0
  10. data/lib/acp/client_connection/inbound.rb +232 -0
  11. data/lib/acp/client_connection/streams.rb +22 -54
  12. data/lib/acp/client_connection.rb +36 -311
  13. data/lib/acp/extensions.rb +6 -0
  14. data/lib/acp/protocol.rb +14 -4
  15. data/lib/acp/transport/reply.rb +2 -2
  16. data/lib/acp/transport/stdio.rb +2 -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/client.rbs +3 -3
  21. data/sig/generated/acp/agent_connection/optional_route.rbs +35 -0
  22. data/sig/generated/acp/agent_connection.rbs +8 -24
  23. data/sig/generated/acp/client_connection/elicitations.rbs +29 -0
  24. data/sig/generated/acp/client_connection/inbound/route.rbs +26 -0
  25. data/sig/generated/acp/client_connection/inbound.rbs +90 -0
  26. data/sig/generated/acp/client_connection/streams.rbs +8 -29
  27. data/sig/generated/acp/client_connection.rbs +13 -137
  28. data/sig/generated/acp/extensions.rbs +4 -0
  29. data/sig/generated/acp/protocol.rbs +8 -0
  30. data/sig/generated/acp/transport/reply.rbs +3 -3
  31. data/sig/generated/acp/transport/stdio.rbs +4 -4
  32. data/sig/generated/acp/types.rbs +9 -0
  33. data/sig/manual/acp/agent_connection.rbs +5 -79
  34. data/sig/manual/acp/client_connection.rbs +25 -5
  35. data/sig/manual/acp/transport/stdio.rbs +1 -5
  36. data/sig/manual/acp/transport.rbs +0 -16
  37. metadata +9 -5
  38. data/lib/acp/agent_connection/optional_method/spec.rb +0 -42
  39. data/lib/acp/agent_connection/optional_method.rb +0 -40
  40. data/sig/generated/acp/agent_connection/optional_method/spec.rbs +0 -32
  41. data/sig/generated/acp/agent_connection/optional_method.rbs +0 -7
@@ -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
@@ -15,14 +15,11 @@ class ACP::AgentConnection
15
15
 
16
16
  @capabilities: ACP::Types::AgentCapabilities
17
17
 
18
- @transport: ACP::Transport::_Transport
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
- # @rbs transport: ACP::Transport::_Transport
22
+ # @rbs transport: ACP::Transport::Stdio
26
23
  # @rbs capabilities: ACP::Types::AgentCapabilities
27
24
  # @rbs agent_info: ACP::Types::Implementation?
28
25
  # @rbs auth_methods: Array[ACP::Types::AuthMethod::t]
@@ -31,7 +28,7 @@ class ACP::AgentConnection
31
28
  # @rbs logger: ACP::Transport::_Logger
32
29
  # @rbs &factory: (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent
33
30
  # @rbs return: void
34
- def initialize: (transport: ACP::Transport::_Transport, capabilities: ACP::Types::AgentCapabilities, ?agent_info: ACP::Types::Implementation?, ?auth_methods: Array[ACP::Types::AuthMethod::t], ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?logger: ACP::Transport::_Logger) { (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent } -> void
31
+ def initialize: (transport: ACP::Transport::Stdio, capabilities: ACP::Types::AgentCapabilities, ?agent_info: ACP::Types::Implementation?, ?auth_methods: Array[ACP::Types::AuthMethod::t], ?extension_requests: Hash[String, ^(untyped) -> untyped], ?extension_notifications: Hash[String, ^(untyped) -> void], ?logger: ACP::Transport::_Logger) { (ACP::AgentConnection::Client) -> ACP::AgentConnection::_Agent } -> void
35
32
 
36
33
  # @rbs return: Thread
37
34
  def start: () -> Thread
@@ -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,26 @@
1
+ # Generated from lib/acp/client_connection/inbound/route.rb with RBS::Inline
2
+
3
+ class ACP::ClientConnection::Inbound::Route
4
+ # @dynamic rpc_method
5
+ attr_reader rpc_method: String
6
+
7
+ # @dynamic type
8
+ attr_reader type: ACP::Transport::_Parser
9
+
10
+ # @dynamic handler_method
11
+ attr_reader handler_method: Symbol
12
+
13
+ # @dynamic path
14
+ attr_reader path: Array[Symbol]
15
+
16
+ # @dynamic capability
17
+ attr_reader capability: String
18
+
19
+ # @rbs rpc_method: String
20
+ # @rbs type: ACP::Transport::_Parser
21
+ # @rbs handler_method: Symbol
22
+ # @rbs path: Array[Symbol]
23
+ # @rbs capability: String
24
+ # @rbs return: void
25
+ def initialize: (rpc_method: String, type: ACP::Transport::_Parser, handler_method: Symbol, path: Array[Symbol], capability: String) -> void
26
+ end
@@ -0,0 +1,90 @@
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
+ FS_ROUTES: Array[ACP::ClientConnection::Inbound::Route]
21
+
22
+ # The terminal capability is a single bool, so its five routes share one
23
+ # gate. Their handlers may block for as long as the command runs, so the
24
+ # transport must serve each request on its own thread for this not to hold
25
+ # up others.
26
+ TERMINAL_ROUTES: Array[ACP::ClientConnection::Inbound::Route]
27
+
28
+ # @dynamic mcp_advertised=
29
+ attr_writer mcp_advertised: bool
30
+
31
+ # @rbs elicitations: ACP::ClientConnection::Elicitations
32
+ # @rbs fs: ACP::ClientConnection::_FileSystem?
33
+ # @rbs terminal: ACP::ClientConnection::_Terminal?
34
+ # @rbs elicitation: ACP::ClientConnection::_Elicitation?
35
+ # @rbs mcp_message: (^(ACP::Types::Unstable::MessageMcpRequest) ->
36
+ # (ACP::Types::Unstable::MessageMcpResponse::t | ACP::RequestError))?
37
+ # @rbs extension_requests: Hash[String, ^(untyped) -> untyped]
38
+ # @rbs extension_notifications: Hash[String, ^(untyped) -> void]
39
+ # @rbs return: void
40
+ 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
41
+
42
+ # @rbs return: Hash[String, ACP::Transport::Stdio::_Handler]
43
+ def requests: () -> Hash[String, ACP::Transport::Stdio::_Handler]
44
+
45
+ # @rbs return: Hash[String, ACP::Transport::Stdio::_NotificationHandler]
46
+ def notifications: () -> Hash[String, ACP::Transport::Stdio::_NotificationHandler]
47
+
48
+ # @rbs capabilities: ACP::Types::ClientCapabilities?
49
+ # @rbs return: void
50
+ def advertise: (ACP::Types::ClientCapabilities? capabilities) -> void
51
+
52
+ private
53
+
54
+ # @rbs route: ACP::ClientConnection::Inbound::Route
55
+ # @rbs handler: untyped
56
+ # @rbs return: ^(untyped) -> untyped
57
+ def serve: (ACP::ClientConnection::Inbound::Route route, untyped handler) -> ^(untyped) -> untyped
58
+
59
+ # @rbs type: ACP::Transport::_Parser
60
+ # @rbs params: untyped
61
+ # @rbs &block: (untyped) -> untyped
62
+ # @rbs return: untyped
63
+ def parsed: (ACP::Transport::_Parser type, untyped params) { (untyped) -> untyped } -> untyped
64
+
65
+ # @rbs routes: Array[ACP::ClientConnection::Inbound::Route]
66
+ # @rbs handler: untyped
67
+ # @rbs capabilities: ACP::Types::ClientCapabilities?
68
+ # @rbs return: Array[String]
69
+ def unserved: (Array[ACP::ClientConnection::Inbound::Route] routes, untyped handler, ACP::Types::ClientCapabilities? capabilities) -> Array[String]
70
+
71
+ # @rbs capabilities: ACP::Types::ElicitationCapabilities?
72
+ # @rbs return: Array[String]
73
+ def unserved_elicitation_modes: (ACP::Types::ElicitationCapabilities? capabilities) -> Array[String]
74
+
75
+ # @rbs what: String
76
+ # @rbs unserved: Array[String]
77
+ # @rbs return: void
78
+ def check_served: (String what, Array[String] unserved) -> void
79
+
80
+ # @rbs return: Hash[String, ^(untyped) -> untyped]
81
+ def mcp_requests: () -> Hash[String, ^(untyped) -> untyped]
82
+
83
+ # @rbs params: untyped
84
+ # @rbs return: (ACP::Types::CreateElicitationResponse | ACP::RequestError)
85
+ def create_elicitation: (untyped params) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError)
86
+
87
+ # @rbs request: ACP::Types::CreateElicitationRequest
88
+ # @rbs return: ACP::RequestError?
89
+ def elicitation_refusal: (ACP::Types::CreateElicitationRequest request) -> ACP::RequestError?
90
+ 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]
6
+ @sender: ACP::Transport::Stdio
10
7
 
11
- @pending_permissions: Hash[String, Array[Thread::Queue]]
12
-
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::ClientConnection::Streams::_Sender
18
+ @pending_permissions: Hash[String, Array[Thread::Queue]]
26
19
 
27
- # @rbs sender: ACP::ClientConnection::Streams::_Sender
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::ClientConnection::Streams::_Sender, 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::_Transport
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
- # @rbs transport: ACP::Transport::_Transport
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::_Transport, permission: ACP::ClientConnection::_PermissionHandler, ?read_text_file: (^(ACP::Types::ReadTextFileRequest) -> (ACP::Types::ReadTextFileResponse | ACP::RequestError))?, ?write_text_file: (^(ACP::Types::WriteTextFileRequest) -> (ACP::Types::WriteTextFileResponse | ACP::RequestError))?, ?create_terminal: (^(ACP::Types::CreateTerminalRequest) -> (ACP::Types::CreateTerminalResponse | ACP::RequestError))?, ?terminal_output: (^(ACP::Types::TerminalOutputRequest) -> (ACP::Types::TerminalOutputResponse | ACP::RequestError))?, ?wait_for_terminal_exit: (^(ACP::Types::WaitForTerminalExitRequest) -> (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?, ?kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?, ?release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?, ?elicitation: (^(ACP::Types::CreateElicitationRequest) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError))?, ?complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?, ?updates: ACP::ClientConnection::_UpdateHandler, ?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
@@ -235,42 +145,8 @@ class ACP::ClientConnection
235
145
 
236
146
  private
237
147
 
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
148
  # @rbs type: ACP::Transport::_Parser
262
149
  # @rbs result: (Hash[String, untyped] | ACP::RequestError)
263
150
  # @rbs return: untyped
264
151
  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
152
  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
@@ -2,13 +2,13 @@
2
2
 
3
3
  class ACP::Transport::Reply
4
4
  # @dynamic result
5
- attr_reader result: ACP::Transport::Stdio::_ToH
5
+ attr_reader result: ACP::Transport::_Response
6
6
 
7
7
  # @dynamic after
8
8
  attr_reader after: ^() -> void
9
9
 
10
- # @rbs result: ACP::Transport::Stdio::_ToH
10
+ # @rbs result: ACP::Transport::_Response
11
11
  # @rbs after: ^() -> void
12
12
  # @rbs return: void
13
- def initialize: (ACP::Transport::Stdio::_ToH result, after: ^() -> void) -> void
13
+ def initialize: (ACP::Transport::_Response result, after: ^() -> void) -> void
14
14
  end
@@ -134,13 +134,13 @@ class ACP::Transport::Stdio
134
134
  #
135
135
  # @rbs handler: _Handler
136
136
  # @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)
137
+ # @rbs return: (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
138
+ def invoke: (_Handler handler, untyped params) -> (ACP::Transport::_Response | ACP::RequestError | ACP::Transport::Reply)
139
139
 
140
140
  # @rbs id: untyped
141
- # @rbs outcome: (_ToH | ACP::RequestError)
141
+ # @rbs outcome: (ACP::Transport::_Response | ACP::RequestError)
142
142
  # @rbs return: void
143
- def reply: (untyped id, _ToH | ACP::RequestError outcome) -> void
143
+ def reply: (untyped id, ACP::Transport::_Response | ACP::RequestError outcome) -> void
144
144
 
145
145
  # @rbs queue: Thread::Queue
146
146
  # @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