acp-sdk 0.7.0 → 0.8.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 +12 -0
- data/README.md +2 -1
- data/lib/acp/agent_connection/client.rb +1 -1
- data/lib/acp/agent_connection.rb +3 -1
- data/lib/acp/client_connection.rb +93 -4
- data/lib/acp/request_error.rb +15 -2
- data/lib/acp/types/agent_auth_capabilities.rb +4 -1
- data/lib/acp/types/agent_capabilities.rb +20 -5
- data/lib/acp/types/annotations.rb +6 -3
- data/lib/acp/types/audio_content.rb +8 -3
- data/lib/acp/types/auth_capabilities.rb +1 -1
- data/lib/acp/types/auth_method/terminal.rb +11 -5
- data/lib/acp/types/auth_method_agent.rb +6 -1
- data/lib/acp/types/auth_method_terminal.rb +11 -5
- data/lib/acp/types/authenticate_request.rb +1 -1
- data/lib/acp/types/available_command.rb +3 -3
- data/lib/acp/types/available_commands_update.rb +7 -4
- data/lib/acp/types/blob_resource_contents.rb +6 -1
- data/lib/acp/types/boolean_property_schema.rb +6 -1
- data/lib/acp/types/cancel_notification.rb +4 -1
- data/lib/acp/types/cancel_request_notification.rb +9 -1
- data/lib/acp/types/client_capabilities.rb +15 -5
- data/lib/acp/types/client_session_capabilities.rb +6 -3
- data/lib/acp/types/close_session_request.rb +4 -1
- data/lib/acp/types/complete_elicitation_notification.rb +4 -1
- data/lib/acp/types/config_option_update.rb +7 -4
- data/lib/acp/types/content.rb +4 -1
- data/lib/acp/types/content_block/audio.rb +8 -3
- data/lib/acp/types/content_block/image.rb +9 -4
- data/lib/acp/types/content_block/resource.rb +11 -2
- data/lib/acp/types/content_block/resource_link.rb +12 -7
- data/lib/acp/types/content_block/text.rb +7 -2
- data/lib/acp/types/content_chunk.rb +2 -2
- data/lib/acp/types/cost.rb +5 -1
- data/lib/acp/types/create_elicitation_request/mode/form.rb +5 -1
- data/lib/acp/types/create_elicitation_request/mode/url.rb +2 -2
- data/lib/acp/types/create_elicitation_request.rb +1 -1
- data/lib/acp/types/create_elicitation_response/action/accept.rb +6 -1
- data/lib/acp/types/create_terminal_request.rb +12 -6
- data/lib/acp/types/create_terminal_response.rb +4 -1
- data/lib/acp/types/current_mode_update.rb +4 -1
- data/lib/acp/types/delete_session_request.rb +4 -1
- data/lib/acp/types/diff.rb +6 -1
- data/lib/acp/types/elicitation_accept_action.rb +6 -1
- data/lib/acp/types/elicitation_capabilities.rb +2 -2
- data/lib/acp/types/elicitation_form_mode.rb +5 -1
- data/lib/acp/types/elicitation_property_schema/boolean_property_schema.rb +6 -1
- data/lib/acp/types/elicitation_property_schema/integer_property_schema.rb +5 -5
- data/lib/acp/types/elicitation_property_schema/multi_select_property_schema.rb +9 -6
- data/lib/acp/types/elicitation_property_schema/number_property_schema.rb +5 -5
- data/lib/acp/types/elicitation_property_schema/string_property_schema.rb +15 -9
- data/lib/acp/types/elicitation_request_scope.rb +8 -1
- data/lib/acp/types/elicitation_schema.rb +11 -5
- data/lib/acp/types/elicitation_session_scope.rb +4 -1
- data/lib/acp/types/elicitation_url_mode.rb +2 -2
- data/lib/acp/types/embedded_resource.rb +11 -2
- data/lib/acp/types/enum_option.rb +6 -1
- data/lib/acp/types/env_variable.rb +5 -1
- data/lib/acp/types/file_system_capabilities.rb +5 -1
- data/lib/acp/types/http_header.rb +5 -1
- data/lib/acp/types/image_content.rb +9 -4
- data/lib/acp/types/implementation.rb +6 -1
- data/lib/acp/types/initialize_request.rb +18 -3
- data/lib/acp/types/initialize_response.rb +17 -4
- data/lib/acp/types/integer_property_schema.rb +5 -5
- data/lib/acp/types/kill_terminal_request.rb +5 -1
- data/lib/acp/types/list_sessions_request.rb +5 -1
- data/lib/acp/types/list_sessions_response.rb +5 -2
- data/lib/acp/types/load_session_request.rb +14 -4
- data/lib/acp/types/load_session_response.rb +5 -2
- data/lib/acp/types/mcp_capabilities.rb +5 -1
- data/lib/acp/types/mcp_server/http.rb +6 -3
- data/lib/acp/types/mcp_server/sse.rb +6 -3
- data/lib/acp/types/mcp_server_http.rb +6 -3
- data/lib/acp/types/mcp_server_sse.rb +6 -3
- data/lib/acp/types/mcp_server_stdio.rb +10 -4
- data/lib/acp/types/multi_select_items/string_multi_select_items.rb +4 -1
- data/lib/acp/types/multi_select_property_schema.rb +9 -6
- data/lib/acp/types/new_session_request.rb +13 -3
- data/lib/acp/types/new_session_response.rb +6 -3
- data/lib/acp/types/number_property_schema.rb +5 -5
- data/lib/acp/types/permission_option.rb +10 -1
- data/lib/acp/types/plan.rb +4 -1
- data/lib/acp/types/plan_entry.rb +7 -3
- data/lib/acp/types/prompt_capabilities.rb +6 -1
- data/lib/acp/types/prompt_request.rb +5 -2
- data/lib/acp/types/prompt_response.rb +8 -1
- data/lib/acp/types/read_text_file_request.rb +4 -4
- data/lib/acp/types/read_text_file_response.rb +1 -1
- data/lib/acp/types/release_terminal_request.rb +5 -1
- data/lib/acp/types/request_permission_outcome/selected.rb +1 -1
- data/lib/acp/types/request_permission_request.rb +10 -3
- data/lib/acp/types/request_permission_response.rb +8 -1
- data/lib/acp/types/resource_link.rb +12 -7
- data/lib/acp/types/resume_session_request.rb +14 -4
- data/lib/acp/types/resume_session_response.rb +5 -2
- data/lib/acp/types/selected_permission_outcome.rb +1 -1
- data/lib/acp/types/session_capabilities.rb +20 -7
- data/lib/acp/types/session_config_boolean.rb +1 -1
- data/lib/acp/types/session_config_option/kind/boolean.rb +1 -1
- data/lib/acp/types/session_config_option/kind/select.rb +6 -2
- data/lib/acp/types/session_config_option.rb +3 -3
- data/lib/acp/types/session_config_options_capabilities.rb +6 -1
- data/lib/acp/types/session_config_select.rb +6 -2
- data/lib/acp/types/session_config_select_group.rb +6 -3
- data/lib/acp/types/session_config_select_option.rb +6 -1
- data/lib/acp/types/session_config_select_options.rb +6 -2
- data/lib/acp/types/session_info.rb +12 -5
- data/lib/acp/types/session_info_update.rb +10 -1
- data/lib/acp/types/session_mode.rb +6 -1
- data/lib/acp/types/session_mode_state.rb +8 -2
- data/lib/acp/types/session_notification.rb +2 -2
- data/lib/acp/types/session_update/agent_message_chunk.rb +2 -2
- data/lib/acp/types/session_update/agent_thought_chunk.rb +2 -2
- data/lib/acp/types/session_update/available_commands_update.rb +7 -4
- data/lib/acp/types/session_update/config_option_update.rb +7 -4
- data/lib/acp/types/session_update/current_mode_update.rb +4 -1
- data/lib/acp/types/session_update/plan.rb +4 -1
- data/lib/acp/types/session_update/session_info_update.rb +10 -1
- data/lib/acp/types/session_update/tool_call.rb +23 -7
- data/lib/acp/types/session_update/tool_call_update.rb +23 -7
- data/lib/acp/types/session_update/usage_update.rb +3 -3
- data/lib/acp/types/session_update/user_message_chunk.rb +2 -2
- data/lib/acp/types/set_session_config_option_request/value/boolean.rb +1 -1
- data/lib/acp/types/set_session_config_option_request/value/value_id.rb +1 -1
- data/lib/acp/types/set_session_config_option_request.rb +2 -2
- data/lib/acp/types/set_session_config_option_response.rb +7 -4
- data/lib/acp/types/set_session_mode_request.rb +5 -1
- data/lib/acp/types/string_multi_select_items.rb +4 -1
- data/lib/acp/types/string_property_schema.rb +15 -9
- data/lib/acp/types/terminal.rb +4 -1
- data/lib/acp/types/terminal_exit_status.rb +5 -1
- data/lib/acp/types/terminal_output_request.rb +5 -1
- data/lib/acp/types/terminal_output_response.rb +8 -3
- data/lib/acp/types/text_content.rb +7 -2
- data/lib/acp/types/text_resource_contents.rb +6 -1
- data/lib/acp/types/titled_multi_select_items.rb +4 -1
- data/lib/acp/types/tool_call.rb +23 -7
- data/lib/acp/types/tool_call_content/content.rb +4 -1
- data/lib/acp/types/tool_call_content/diff.rb +6 -1
- data/lib/acp/types/tool_call_content/terminal.rb +4 -1
- data/lib/acp/types/tool_call_location.rb +5 -1
- data/lib/acp/types/tool_call_update.rb +23 -7
- data/lib/acp/types/unstructured_command_input.rb +1 -1
- data/lib/acp/types/usage_update.rb +3 -3
- data/lib/acp/types/wait_for_terminal_exit_request.rb +5 -1
- data/lib/acp/types/wait_for_terminal_exit_response.rb +5 -1
- data/lib/acp/types/write_text_file_request.rb +3 -3
- data/lib/acp/types.rb +247 -0
- data/lib/acp/version.rb +1 -1
- data/sig/generated/acp/client_connection.rbs +39 -1
- data/sig/generated/acp/request_error.rbs +12 -1
- data/sig/generated/acp/types.rbs +143 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0b8b181c4cbd41a411868aecdf9f34d0356b490526c446a962287a5a3ae01cc
|
|
4
|
+
data.tar.gz: 1376e6d42bc4369de51a645ed423a563e7aa9b35c4c49b060c77a983cb2c603c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c5d6271be17f17e203c178664ad6de2234c4b1a7b1857663c1ebb20bdbe1fa3c282db70ac6fe3c3e6b9647dfaadbe761bd018972943393a0cb3dec3d10bb2a3
|
|
7
|
+
data.tar.gz: 9ca3cae203c38496096dd020403054daaa4cb6797183c95b04a75c045f4a8aff89754a07af0fd74eb4c2a45f48dbc6d7c64352faf572000f118130d473283f0b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.0](https://github.com/bottrall/acp-sdk/compare/v0.7.0...v0.8.0) (2026-10-06)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* elicitation handlers on ACP::ClientConnection ([#78](https://github.com/bottrall/acp-sdk/issues/78)) ([94ee653](https://github.com/bottrall/acp-sdk/commit/94ee65374a0b463ccbd7ed57e05fe1ad76b08a62))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* validate primitive and enum types when parsing params ([#79](https://github.com/bottrall/acp-sdk/issues/79)) ([624be63](https://github.com/bottrall/acp-sdk/commit/624be63f667468fba7c1a61064b84f43c226b060))
|
|
14
|
+
|
|
3
15
|
## [0.7.0](https://github.com/bottrall/acp-sdk/compare/v0.6.0...v0.7.0) (2026-10-05)
|
|
4
16
|
|
|
5
17
|
|
data/README.md
CHANGED
|
@@ -49,7 +49,7 @@ connection.start.join
|
|
|
49
49
|
The agent's contract:
|
|
50
50
|
|
|
51
51
|
- It defines `new_session`, `prompt` and `cancel`. `load_session`, `list_sessions`, `resume_session`, `close_session` and `delete_session` are required only when `capabilities` advertises `load_session` or `session_capabilities.list`, `.resume`, `.close` or `.delete`, and `authenticate` only when `auth_methods` is non-empty, and `logout` only when `capabilities` advertises `auth.logout`; `start` raises `ArgumentError` when one is advertised but missing, and a method that is not advertised is answered with `-32601`. `change_session_mode` and `change_session_config_option` are optional, since modes and config options are offered per session rather than in `initialize`; `session/set_mode` and `session/set_config_option` are answered with `-32601` when the agent does not define them. `session_created`, if defined, runs right after the `session/new` reply is sent.
|
|
52
|
-
- Each request method returns its response type or an `ACP::RequestError`, which is sent as the error reply. Params that do not match the schema are answered with `-32602` before the agent sees them.
|
|
52
|
+
- Each request method returns its response type or an `ACP::RequestError`, which is sent as the error reply. Params that do not match the schema are answered with `-32602` before the agent sees them, with `data` naming the failing path, e.g. `{ errors: ['sessionId: expected String, got Integer'] }`.
|
|
53
53
|
- A handler that raises is answered with `-32603` and the message `Internal error`. Nothing from the exception reaches the peer — its class and message are logged to the transport's logger instead, since messages can interpolate paths, queries or credentials. Return an `ACP::RequestError` from the handler when the peer should see a real error message.
|
|
54
54
|
- `cancel` runs on the transport's reader thread, so it must return quickly: set a flag and let the prompt notice it.
|
|
55
55
|
- After a cancel, the agent must itself end the turn with `stopReason: cancelled`. `ACP::AgentConnection` does not enforce it.
|
|
@@ -107,6 +107,7 @@ connection = ACP::ClientConnection.new(
|
|
|
107
107
|
- `permission` answers `session/request_permission` with an `ACP::Types::RequestPermissionResponse` or an `ACP::RequestError`. It runs on its own thread, so it may block while the user decides, and `session_cancel` can be sent meanwhile.
|
|
108
108
|
- `read_text_file` and `write_text_file` answer the agent's `fs/read_text_file` and `fs/write_text_file` with an `ACP::Types::ReadTextFileResponse`, an `ACP::Types::WriteTextFileResponse` or an `ACP::RequestError`. They are routed by the `fs` capabilities `connect` sends: a method the client does not advertise is answered with `-32601` without reaching the handler, and `connect` raises `ArgumentError` — before sending `initialize` — when the request advertises a capability that has no handler.
|
|
109
109
|
- `create_terminal`, `terminal_output`, `wait_for_terminal_exit`, `kill_terminal` and `release_terminal` answer the agent's `terminal/create`, `terminal/output`, `terminal/wait_for_exit`, `terminal/kill` and `terminal/release` with the matching `ACP::Types` response or an `ACP::RequestError`. They are routed by the `terminal` capability `connect` sends, the same way as `fs`: a method the client does not advertise is answered with `-32601` without reaching the handler, and `connect` raises `ArgumentError` — before sending `initialize` — when the request advertises `terminal` with any of the five missing. The transport serves each request on its own thread, so `wait_for_terminal_exit` may block without holding up the others.
|
|
110
|
+
- `elicitation` answers the agent's `elicitation/create` with an `ACP::Types::CreateElicitationResponse` or an `ACP::RequestError`, serving both form and url mode, and `complete_elicitation` receives the agent's `elicitation/complete` notification. They are routed by the `elicitation` capabilities `connect` sends: a request whose mode the client does not advertise is answered with `-32602` without reaching the handler, and `connect` raises `ArgumentError` — before sending `initialize` — when the request advertises `elicitation.form` or `elicitation.url` with no `elicitation` handler. The client tracks the elicitation ids of the url-mode requests it serves, so a completion for an unknown or already-completed id is ignored. `complete_elicitation` runs on the reader thread and must return quickly; it may be omitted, in which case completions are only tracked.
|
|
110
111
|
|
|
111
112
|
Extensions work the same way in both directions: `extension_requests` and `extension_notifications` are hashes keyed by the raw `_`-prefixed wire name, `ext_request` sends one to the agent and returns its result as-is, and `ext_notify` sends an extension notification. A handler name without the `_` prefix raises `ArgumentError`, and an extension request nothing answers gets `-32601`.
|
|
112
113
|
|
|
@@ -136,7 +136,7 @@ class ACP::AgentConnection::Client
|
|
|
136
136
|
return result if result.is_a?(ACP::RequestError)
|
|
137
137
|
|
|
138
138
|
type.from_h(result)
|
|
139
|
-
rescue KeyError, TypeError, NoMethodError
|
|
139
|
+
rescue ACP::Types::ParseError, KeyError, TypeError, NoMethodError
|
|
140
140
|
ACP::RequestError.invalid_response(result)
|
|
141
141
|
end
|
|
142
142
|
|
data/lib/acp/agent_connection.rb
CHANGED
|
@@ -117,7 +117,7 @@ class ACP::AgentConnection
|
|
|
117
117
|
# @rbs return: void
|
|
118
118
|
def cancel(agent, params)
|
|
119
119
|
notification = ACP::Types::CancelNotification.from_h(params)
|
|
120
|
-
rescue KeyError, TypeError, NoMethodError => e
|
|
120
|
+
rescue ACP::Types::ParseError, KeyError, TypeError, NoMethodError => e
|
|
121
121
|
@logger.warn("dropped malformed session/cancel: #{e.class}: #{e.message}")
|
|
122
122
|
else
|
|
123
123
|
agent.cancel(notification)
|
|
@@ -131,6 +131,8 @@ class ACP::AgentConnection
|
|
|
131
131
|
def route(type, &)
|
|
132
132
|
lambda do |params|
|
|
133
133
|
request = type.from_h(params)
|
|
134
|
+
rescue ACP::Types::ParseError => e
|
|
135
|
+
ACP::RequestError.invalid_params([e.message])
|
|
134
136
|
rescue KeyError, TypeError, NoMethodError
|
|
135
137
|
ACP::RequestError.invalid_params
|
|
136
138
|
else
|
|
@@ -11,14 +11,19 @@ class ACP::ClientConnection
|
|
|
11
11
|
# (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?
|
|
12
12
|
# @rbs @kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?
|
|
13
13
|
# @rbs @release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?
|
|
14
|
+
# @rbs @elicitation: (^(ACP::Types::CreateElicitationRequest) ->
|
|
15
|
+
# (ACP::Types::CreateElicitationResponse | ACP::RequestError))?
|
|
16
|
+
# @rbs @complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
|
|
14
17
|
# @rbs @updates: ACP::ClientConnection::_UpdateHandler
|
|
15
18
|
# @rbs @fs_capabilities: ACP::Types::FileSystemCapabilities?
|
|
16
19
|
# @rbs @terminal: bool?
|
|
20
|
+
# @rbs @elicitation_capabilities: ACP::Types::ElicitationCapabilities?
|
|
17
21
|
# @rbs @extension_requests: Hash[String, ^(untyped) -> untyped]
|
|
18
22
|
# @rbs @extension_notifications: Hash[String, ^(untyped) -> void]
|
|
19
23
|
# @rbs @lock: Thread::Mutex
|
|
20
24
|
# @rbs @streams: Hash[String, Thread::Queue]
|
|
21
25
|
# @rbs @pending_permissions: Hash[String, Array[Thread::Queue]]
|
|
26
|
+
# @rbs @outstanding_elicitations: Hash[String, bool]
|
|
22
27
|
# @rbs @logger: ACP::Transport::_Logger
|
|
23
28
|
|
|
24
29
|
PROTOCOL_VERSION = ACP::AgentConnection::PROTOCOL_VERSION #: Integer
|
|
@@ -39,6 +44,9 @@ class ACP::ClientConnection
|
|
|
39
44
|
# (ACP::Types::WaitForTerminalExitResponse | ACP::RequestError))?
|
|
40
45
|
# @rbs kill_terminal: (^(ACP::Types::KillTerminalRequest) -> (ACP::Types::KillTerminalResponse | ACP::RequestError))?
|
|
41
46
|
# @rbs release_terminal: (^(ACP::Types::ReleaseTerminalRequest) -> (ACP::Types::ReleaseTerminalResponse | ACP::RequestError))?
|
|
47
|
+
# @rbs elicitation: (^(ACP::Types::CreateElicitationRequest) ->
|
|
48
|
+
# (ACP::Types::CreateElicitationResponse | ACP::RequestError))?
|
|
49
|
+
# @rbs complete_elicitation: (^(ACP::Types::CompleteElicitationNotification) -> void)?
|
|
42
50
|
# @rbs updates: ACP::ClientConnection::_UpdateHandler
|
|
43
51
|
# @rbs extension_requests: Hash[String, ^(untyped) -> untyped]
|
|
44
52
|
# @rbs extension_notifications: Hash[String, ^(untyped) -> void]
|
|
@@ -54,6 +62,8 @@ class ACP::ClientConnection
|
|
|
54
62
|
wait_for_terminal_exit: nil,
|
|
55
63
|
kill_terminal: nil,
|
|
56
64
|
release_terminal: nil,
|
|
65
|
+
elicitation: nil,
|
|
66
|
+
complete_elicitation: nil,
|
|
57
67
|
updates: IGNORE,
|
|
58
68
|
extension_requests: {},
|
|
59
69
|
extension_notifications: {},
|
|
@@ -68,9 +78,12 @@ class ACP::ClientConnection
|
|
|
68
78
|
@wait_for_terminal_exit = wait_for_terminal_exit
|
|
69
79
|
@kill_terminal = kill_terminal
|
|
70
80
|
@release_terminal = release_terminal
|
|
81
|
+
@elicitation = elicitation
|
|
82
|
+
@complete_elicitation = complete_elicitation
|
|
71
83
|
@updates = updates
|
|
72
84
|
@fs_capabilities = nil
|
|
73
85
|
@terminal = nil
|
|
86
|
+
@elicitation_capabilities = nil
|
|
74
87
|
@extension_requests = extension_requests
|
|
75
88
|
@extension_notifications = extension_notifications
|
|
76
89
|
extension_requests.each_key { |name| ACP::Extensions.validate_name(name) }
|
|
@@ -78,6 +91,7 @@ class ACP::ClientConnection
|
|
|
78
91
|
@lock = Mutex.new
|
|
79
92
|
@streams = {}
|
|
80
93
|
@pending_permissions = {}
|
|
94
|
+
@outstanding_elicitations = {}
|
|
81
95
|
@logger = logger
|
|
82
96
|
end
|
|
83
97
|
|
|
@@ -92,9 +106,11 @@ class ACP::ClientConnection
|
|
|
92
106
|
'terminal/output' => method(:terminal_output),
|
|
93
107
|
'terminal/wait_for_exit' => method(:wait_for_terminal_exit),
|
|
94
108
|
'terminal/kill' => method(:kill_terminal),
|
|
95
|
-
'terminal/release' => method(:release_terminal)
|
|
109
|
+
'terminal/release' => method(:release_terminal),
|
|
110
|
+
'elicitation/create' => method(:create_elicitation)
|
|
96
111
|
}.merge(@extension_requests),
|
|
97
|
-
notifications: { 'session/update' => method(:dispatch)
|
|
112
|
+
notifications: { 'session/update' => method(:dispatch),
|
|
113
|
+
'elicitation/complete' => method(:complete_elicitation) }.merge(@extension_notifications)
|
|
98
114
|
)
|
|
99
115
|
end
|
|
100
116
|
|
|
@@ -116,8 +132,15 @@ class ACP::ClientConnection
|
|
|
116
132
|
raise ArgumentError, "initialize advertises terminal methods no handler serves: #{unserved.join(', ')}"
|
|
117
133
|
end
|
|
118
134
|
|
|
135
|
+
elicitation = request.client_capabilities&.elicitation
|
|
136
|
+
unserved = unserved_elicitation_modes(elicitation)
|
|
137
|
+
unless unserved.empty?
|
|
138
|
+
raise ArgumentError, "initialize advertises elicitation modes no handler serves: #{unserved.join(', ')}"
|
|
139
|
+
end
|
|
140
|
+
|
|
119
141
|
@fs_capabilities = capabilities
|
|
120
142
|
@terminal = terminal
|
|
143
|
+
@elicitation_capabilities = elicitation
|
|
121
144
|
parse(ACP::Types::InitializeResponse, @transport.request('initialize', request.to_h)).then do |response|
|
|
122
145
|
next response if response.is_a?(ACP::RequestError)
|
|
123
146
|
|
|
@@ -246,7 +269,7 @@ class ACP::ClientConnection
|
|
|
246
269
|
return result if result.is_a?(ACP::RequestError)
|
|
247
270
|
|
|
248
271
|
type.from_h(result)
|
|
249
|
-
rescue KeyError, TypeError, NoMethodError
|
|
272
|
+
rescue ACP::Types::ParseError, KeyError, TypeError, NoMethodError
|
|
250
273
|
ACP::RequestError.invalid_response(result)
|
|
251
274
|
end
|
|
252
275
|
|
|
@@ -295,7 +318,7 @@ class ACP::ClientConnection
|
|
|
295
318
|
# @rbs return: void
|
|
296
319
|
def dispatch(params)
|
|
297
320
|
notification = ACP::Types::SessionNotification.from_h(params)
|
|
298
|
-
rescue KeyError, TypeError, NoMethodError => e
|
|
321
|
+
rescue ACP::Types::ParseError, KeyError, TypeError, NoMethodError => e
|
|
299
322
|
@logger.warn("dropped malformed session/update: #{e.class}: #{e.message}")
|
|
300
323
|
else
|
|
301
324
|
queue = @lock.synchronize { @streams[notification.session_id]&.push(notification.update) }
|
|
@@ -310,6 +333,8 @@ class ACP::ClientConnection
|
|
|
310
333
|
# @rbs return: (ACP::Types::RequestPermissionResponse | ACP::RequestError)
|
|
311
334
|
def request_permission(params)
|
|
312
335
|
request = ACP::Types::RequestPermissionRequest.from_h(params)
|
|
336
|
+
rescue ACP::Types::ParseError => e
|
|
337
|
+
ACP::RequestError.invalid_params([e.message])
|
|
313
338
|
rescue KeyError, TypeError, NoMethodError
|
|
314
339
|
ACP::RequestError.invalid_params
|
|
315
340
|
else
|
|
@@ -363,6 +388,8 @@ class ACP::ClientConnection
|
|
|
363
388
|
return ACP::RequestError.unadvertised('fs.readTextFile') unless @fs_capabilities&.read_text_file
|
|
364
389
|
|
|
365
390
|
request = ACP::Types::ReadTextFileRequest.from_h(params)
|
|
391
|
+
rescue ACP::Types::ParseError => e
|
|
392
|
+
ACP::RequestError.invalid_params([e.message])
|
|
366
393
|
rescue KeyError, TypeError, NoMethodError
|
|
367
394
|
ACP::RequestError.invalid_params
|
|
368
395
|
else
|
|
@@ -377,6 +404,8 @@ class ACP::ClientConnection
|
|
|
377
404
|
return ACP::RequestError.unadvertised('fs.writeTextFile') unless @fs_capabilities&.write_text_file
|
|
378
405
|
|
|
379
406
|
request = ACP::Types::WriteTextFileRequest.from_h(params)
|
|
407
|
+
rescue ACP::Types::ParseError => e
|
|
408
|
+
ACP::RequestError.invalid_params([e.message])
|
|
380
409
|
rescue KeyError, TypeError, NoMethodError
|
|
381
410
|
ACP::RequestError.invalid_params
|
|
382
411
|
else
|
|
@@ -461,6 +490,54 @@ class ACP::ClientConnection
|
|
|
461
490
|
handler.call(request)
|
|
462
491
|
end
|
|
463
492
|
|
|
493
|
+
# The routes are registered at start, before connect records the advertised
|
|
494
|
+
# capabilities, so a request for an unadvertised mode answers -32602.
|
|
495
|
+
#
|
|
496
|
+
# @rbs params: untyped
|
|
497
|
+
# @rbs return: (ACP::Types::CreateElicitationResponse | ACP::RequestError)
|
|
498
|
+
def create_elicitation(params)
|
|
499
|
+
request = ACP::Types::CreateElicitationRequest.from_h(params)
|
|
500
|
+
rescue KeyError, TypeError, NoMethodError
|
|
501
|
+
ACP::RequestError.invalid_params
|
|
502
|
+
else
|
|
503
|
+
case request.mode
|
|
504
|
+
when ACP::Types::CreateElicitationRequest::Mode::Form
|
|
505
|
+
return ACP::RequestError.unadvertised_mode('elicitation.form') unless @elicitation_capabilities&.form
|
|
506
|
+
when ACP::Types::CreateElicitationRequest::Mode::Url
|
|
507
|
+
return ACP::RequestError.unadvertised_mode('elicitation.url') unless @elicitation_capabilities&.url
|
|
508
|
+
|
|
509
|
+
register_elicitation(request.mode.elicitation_id)
|
|
510
|
+
else
|
|
511
|
+
return ACP::RequestError.unadvertised_mode("elicitation.#{request.mode['mode']}")
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
# Safe: connect refuses an advertised mode no handler serves.
|
|
515
|
+
handler = @elicitation #: ^(ACP::Types::CreateElicitationRequest) -> (ACP::Types::CreateElicitationResponse | ACP::RequestError)
|
|
516
|
+
handler.call(request)
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
# The spec requires a completion for an unknown or already-completed
|
|
520
|
+
# elicitation id to be ignored, so only an id registered by a served
|
|
521
|
+
# url-mode request reaches the handler. It runs on the transport's reader
|
|
522
|
+
# thread, so it must return quickly.
|
|
523
|
+
#
|
|
524
|
+
# @rbs params: untyped
|
|
525
|
+
# @rbs return: void
|
|
526
|
+
def complete_elicitation(params)
|
|
527
|
+
notification = ACP::Types::CompleteElicitationNotification.from_h(params)
|
|
528
|
+
rescue KeyError, TypeError, NoMethodError => e
|
|
529
|
+
@logger.warn("dropped malformed elicitation/complete: #{e.class}: #{e.message}")
|
|
530
|
+
else
|
|
531
|
+
known = @lock.synchronize { @outstanding_elicitations.delete(notification.elicitation_id) }
|
|
532
|
+
@complete_elicitation&.call(notification) if known
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
# @rbs elicitation_id: String
|
|
536
|
+
# @rbs return: void
|
|
537
|
+
def register_elicitation(elicitation_id)
|
|
538
|
+
@lock.synchronize { @outstanding_elicitations[elicitation_id] = true }
|
|
539
|
+
end
|
|
540
|
+
|
|
464
541
|
# The fs capabilities initialize advertises that no injected handler serves.
|
|
465
542
|
#
|
|
466
543
|
# @rbs capabilities: ACP::Types::FileSystemCapabilities?
|
|
@@ -486,4 +563,16 @@ class ACP::ClientConnection
|
|
|
486
563
|
'terminal.release' => capabilities && !@release_terminal
|
|
487
564
|
}.select { |_, unserved| unserved }.keys
|
|
488
565
|
end
|
|
566
|
+
|
|
567
|
+
# The elicitation capabilities initialize advertises that no injected
|
|
568
|
+
# handler serves.
|
|
569
|
+
#
|
|
570
|
+
# @rbs capabilities: ACP::Types::ElicitationCapabilities?
|
|
571
|
+
# @rbs return: Array[String]
|
|
572
|
+
def unserved_elicitation_modes(capabilities)
|
|
573
|
+
{
|
|
574
|
+
'elicitation.form' => capabilities&.form && !@elicitation,
|
|
575
|
+
'elicitation.url' => capabilities&.url && !@elicitation
|
|
576
|
+
}.select { |_, unserved| unserved }.keys
|
|
577
|
+
end
|
|
489
578
|
end
|
data/lib/acp/request_error.rb
CHANGED
|
@@ -54,9 +54,10 @@ class ACP::RequestError
|
|
|
54
54
|
new(code: METHOD_NOT_FOUND, message: 'Method not found', data: method && { method: method })
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# @rbs errors: Array[String]?
|
|
57
58
|
# @rbs return: ACP::RequestError
|
|
58
|
-
def self.invalid_params
|
|
59
|
-
new(code: INVALID_PARAMS, message: 'Invalid params')
|
|
59
|
+
def self.invalid_params(errors = nil)
|
|
60
|
+
new(code: INVALID_PARAMS, message: 'Invalid params', data: errors && { errors: errors })
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
# The method-not-found code for a method the client's capabilities do not
|
|
@@ -69,6 +70,18 @@ class ACP::RequestError
|
|
|
69
70
|
new(code: METHOD_NOT_FOUND, message: "Client does not advertise #{capability}")
|
|
70
71
|
end
|
|
71
72
|
|
|
73
|
+
# The invalid-params code for a request whose mode the client's
|
|
74
|
+
# capabilities do not advertise, with a message that names the mode so it
|
|
75
|
+
# can be told apart from malformed params. The spec gives elicitation a
|
|
76
|
+
# mode in its params, so an unadvertised one is invalid params rather than
|
|
77
|
+
# method not found.
|
|
78
|
+
#
|
|
79
|
+
# @rbs mode: String
|
|
80
|
+
# @rbs return: ACP::RequestError
|
|
81
|
+
def self.unadvertised_mode(mode)
|
|
82
|
+
new(code: INVALID_PARAMS, message: "Client does not advertise #{mode}")
|
|
83
|
+
end
|
|
84
|
+
|
|
72
85
|
# @rbs return: ACP::RequestError
|
|
73
86
|
def self.internal_error
|
|
74
87
|
new(code: INTERNAL_ERROR, message: 'Internal error')
|
|
@@ -21,7 +21,10 @@ class ACP::Types::AgentAuthCapabilities
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::AgentAuthCapabilities
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
new(
|
|
24
|
+
new(
|
|
25
|
+
logout: ACP::Types::Check.object(hash['logout'], 'logout', ACP::Types::LogoutCapabilities, allow_nil: true),
|
|
26
|
+
meta: hash['_meta']
|
|
27
|
+
)
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
# @rbs return: Hash[String, untyped]
|
|
@@ -49,11 +49,26 @@ class ACP::Types::AgentCapabilities
|
|
|
49
49
|
# @rbs return: ACP::Types::AgentCapabilities
|
|
50
50
|
def self.from_h(hash)
|
|
51
51
|
new(
|
|
52
|
-
load_session: hash['loadSession'],
|
|
53
|
-
prompt_capabilities:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
load_session: ACP::Types::Check.boolean(hash['loadSession'], 'loadSession', allow_nil: true),
|
|
53
|
+
prompt_capabilities: ACP::Types::Check.object(
|
|
54
|
+
hash['promptCapabilities'],
|
|
55
|
+
'promptCapabilities',
|
|
56
|
+
ACP::Types::PromptCapabilities,
|
|
57
|
+
allow_nil: true
|
|
58
|
+
),
|
|
59
|
+
mcp_capabilities: ACP::Types::Check.object(
|
|
60
|
+
hash['mcpCapabilities'],
|
|
61
|
+
'mcpCapabilities',
|
|
62
|
+
ACP::Types::McpCapabilities,
|
|
63
|
+
allow_nil: true
|
|
64
|
+
),
|
|
65
|
+
session_capabilities: ACP::Types::Check.object(
|
|
66
|
+
hash['sessionCapabilities'],
|
|
67
|
+
'sessionCapabilities',
|
|
68
|
+
ACP::Types::SessionCapabilities,
|
|
69
|
+
allow_nil: true
|
|
70
|
+
),
|
|
71
|
+
auth: ACP::Types::Check.object(hash['auth'], 'auth', ACP::Types::AgentAuthCapabilities, allow_nil: true),
|
|
57
72
|
meta: hash['_meta']
|
|
58
73
|
)
|
|
59
74
|
end
|
|
@@ -31,10 +31,13 @@ class ACP::Types::Annotations
|
|
|
31
31
|
# @rbs hash: Hash[String, untyped]
|
|
32
32
|
# @rbs return: ACP::Types::Annotations
|
|
33
33
|
def self.from_h(hash)
|
|
34
|
+
audience = ACP::Types::Check.array(hash['audience'], 'audience', allow_nil: true) do |item, path|
|
|
35
|
+
ACP::Types::Check.enum(item, path, %w[assistant user])
|
|
36
|
+
end
|
|
34
37
|
new(
|
|
35
|
-
audience
|
|
36
|
-
last_modified: hash['lastModified'],
|
|
37
|
-
priority: hash['priority'],
|
|
38
|
+
audience:,
|
|
39
|
+
last_modified: ACP::Types::Check.string(hash['lastModified'], 'lastModified', allow_nil: true),
|
|
40
|
+
priority: ACP::Types::Check.number(hash['priority'], 'priority', allow_nil: true),
|
|
38
41
|
meta: hash['_meta']
|
|
39
42
|
)
|
|
40
43
|
end
|
|
@@ -32,9 +32,14 @@ class ACP::Types::AudioContent
|
|
|
32
32
|
# @rbs return: ACP::Types::AudioContent
|
|
33
33
|
def self.from_h(hash)
|
|
34
34
|
new(
|
|
35
|
-
annotations:
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
annotations: ACP::Types::Check.object(
|
|
36
|
+
hash['annotations'],
|
|
37
|
+
'annotations',
|
|
38
|
+
ACP::Types::Annotations,
|
|
39
|
+
allow_nil: true
|
|
40
|
+
),
|
|
41
|
+
data: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'data'), 'data'),
|
|
42
|
+
mime_type: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'mimeType'), 'mimeType'),
|
|
38
43
|
meta: hash['_meta']
|
|
39
44
|
)
|
|
40
45
|
end
|
|
@@ -21,7 +21,7 @@ class ACP::Types::AuthCapabilities
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::AuthCapabilities
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
new(terminal: hash['terminal'], meta: hash['_meta'])
|
|
24
|
+
new(terminal: ACP::Types::Check.boolean(hash['terminal'], 'terminal', allow_nil: true), meta: hash['_meta'])
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# @rbs return: Hash[String, untyped]
|
|
@@ -41,12 +41,18 @@ class ACP::Types::AuthMethod::Terminal
|
|
|
41
41
|
# @rbs hash: Hash[String, untyped]
|
|
42
42
|
# @rbs return: ACP::Types::AuthMethod::Terminal
|
|
43
43
|
def self.from_h(hash)
|
|
44
|
+
args = ACP::Types::Check.array(hash['args'], 'args', allow_nil: true) do |item, path|
|
|
45
|
+
ACP::Types::Check.string(item, path)
|
|
46
|
+
end
|
|
47
|
+
env = ACP::Types::Check.hash(hash['env'], 'env', allow_nil: true) do |value, path|
|
|
48
|
+
ACP::Types::Check.string(value, path)
|
|
49
|
+
end
|
|
44
50
|
new(
|
|
45
|
-
id:
|
|
46
|
-
name:
|
|
47
|
-
description: hash['description'],
|
|
48
|
-
args
|
|
49
|
-
env
|
|
51
|
+
id: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'id'), 'id'),
|
|
52
|
+
name: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'name'), 'name'),
|
|
53
|
+
description: ACP::Types::Check.string(hash['description'], 'description', allow_nil: true),
|
|
54
|
+
args:,
|
|
55
|
+
env:,
|
|
50
56
|
meta: hash['_meta']
|
|
51
57
|
)
|
|
52
58
|
end
|
|
@@ -31,7 +31,12 @@ class ACP::Types::AuthMethodAgent
|
|
|
31
31
|
# @rbs hash: Hash[String, untyped]
|
|
32
32
|
# @rbs return: ACP::Types::AuthMethodAgent
|
|
33
33
|
def self.from_h(hash)
|
|
34
|
-
new(
|
|
34
|
+
new(
|
|
35
|
+
id: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'id'), 'id'),
|
|
36
|
+
name: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'name'), 'name'),
|
|
37
|
+
description: ACP::Types::Check.string(hash['description'], 'description', allow_nil: true),
|
|
38
|
+
meta: hash['_meta']
|
|
39
|
+
)
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
# @rbs return: Hash[String, untyped]
|
|
@@ -41,12 +41,18 @@ class ACP::Types::AuthMethodTerminal
|
|
|
41
41
|
# @rbs hash: Hash[String, untyped]
|
|
42
42
|
# @rbs return: ACP::Types::AuthMethodTerminal
|
|
43
43
|
def self.from_h(hash)
|
|
44
|
+
args = ACP::Types::Check.array(hash['args'], 'args', allow_nil: true) do |item, path|
|
|
45
|
+
ACP::Types::Check.string(item, path)
|
|
46
|
+
end
|
|
47
|
+
env = ACP::Types::Check.hash(hash['env'], 'env', allow_nil: true) do |value, path|
|
|
48
|
+
ACP::Types::Check.string(value, path)
|
|
49
|
+
end
|
|
44
50
|
new(
|
|
45
|
-
id:
|
|
46
|
-
name:
|
|
47
|
-
description: hash['description'],
|
|
48
|
-
args
|
|
49
|
-
env
|
|
51
|
+
id: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'id'), 'id'),
|
|
52
|
+
name: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'name'), 'name'),
|
|
53
|
+
description: ACP::Types::Check.string(hash['description'], 'description', allow_nil: true),
|
|
54
|
+
args:,
|
|
55
|
+
env:,
|
|
50
56
|
meta: hash['_meta']
|
|
51
57
|
)
|
|
52
58
|
end
|
|
@@ -21,7 +21,7 @@ class ACP::Types::AuthenticateRequest
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::AuthenticateRequest
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
new(method_id:
|
|
24
|
+
new(method_id: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'methodId'), 'methodId'), meta: hash['_meta'])
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# @rbs return: Hash[String, untyped]
|
|
@@ -32,9 +32,9 @@ class ACP::Types::AvailableCommand
|
|
|
32
32
|
# @rbs return: ACP::Types::AvailableCommand
|
|
33
33
|
def self.from_h(hash)
|
|
34
34
|
new(
|
|
35
|
-
name:
|
|
36
|
-
description:
|
|
37
|
-
input: hash['input']
|
|
35
|
+
name: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'name'), 'name'),
|
|
36
|
+
description: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'description'), 'description'),
|
|
37
|
+
input: ACP::Types::Check.object(hash['input'], 'input', ACP::Types::AvailableCommandInput, allow_nil: true),
|
|
38
38
|
meta: hash['_meta']
|
|
39
39
|
)
|
|
40
40
|
end
|
|
@@ -21,10 +21,13 @@ class ACP::Types::AvailableCommandsUpdate
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::AvailableCommandsUpdate
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
24
|
+
available_commands = ACP::Types::Check.array(
|
|
25
|
+
ACP::Types::Check.key(hash, 'availableCommands'),
|
|
26
|
+
'availableCommands'
|
|
27
|
+
) do |item, path|
|
|
28
|
+
ACP::Types::Check.object(item, path, ACP::Types::AvailableCommand)
|
|
29
|
+
end
|
|
30
|
+
new(available_commands:, meta: hash['_meta'])
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
# @rbs return: Hash[String, untyped]
|
|
@@ -31,7 +31,12 @@ class ACP::Types::BlobResourceContents
|
|
|
31
31
|
# @rbs hash: Hash[String, untyped]
|
|
32
32
|
# @rbs return: ACP::Types::BlobResourceContents
|
|
33
33
|
def self.from_h(hash)
|
|
34
|
-
new(
|
|
34
|
+
new(
|
|
35
|
+
blob: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'blob'), 'blob'),
|
|
36
|
+
mime_type: ACP::Types::Check.string(hash['mimeType'], 'mimeType', allow_nil: true),
|
|
37
|
+
uri: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'uri'), 'uri'),
|
|
38
|
+
meta: hash['_meta']
|
|
39
|
+
)
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
# @rbs return: Hash[String, untyped]
|
|
@@ -31,7 +31,12 @@ class ACP::Types::BooleanPropertySchema
|
|
|
31
31
|
# @rbs hash: Hash[String, untyped]
|
|
32
32
|
# @rbs return: ACP::Types::BooleanPropertySchema
|
|
33
33
|
def self.from_h(hash)
|
|
34
|
-
new(
|
|
34
|
+
new(
|
|
35
|
+
title: ACP::Types::Check.string(hash['title'], 'title', allow_nil: true),
|
|
36
|
+
description: ACP::Types::Check.string(hash['description'], 'description', allow_nil: true),
|
|
37
|
+
default: ACP::Types::Check.boolean(hash['default'], 'default', allow_nil: true),
|
|
38
|
+
meta: hash['_meta']
|
|
39
|
+
)
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
# @rbs return: Hash[String, untyped]
|
|
@@ -21,7 +21,10 @@ class ACP::Types::CancelNotification
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::CancelNotification
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
new(
|
|
24
|
+
new(
|
|
25
|
+
session_id: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'sessionId'), 'sessionId'),
|
|
26
|
+
meta: hash['_meta']
|
|
27
|
+
)
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
# @rbs return: Hash[String, untyped]
|
|
@@ -21,7 +21,15 @@ class ACP::Types::CancelRequestNotification
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::CancelRequestNotification
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
new(
|
|
24
|
+
new(
|
|
25
|
+
request_id: ACP::Types::Check.one_of(
|
|
26
|
+
ACP::Types::Check.key(hash, 'requestId'),
|
|
27
|
+
'requestId',
|
|
28
|
+
[Integer, String],
|
|
29
|
+
allow_nil: true
|
|
30
|
+
),
|
|
31
|
+
meta: hash['_meta']
|
|
32
|
+
)
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
# @rbs return: Hash[String, untyped]
|
|
@@ -42,11 +42,21 @@ class ACP::Types::ClientCapabilities
|
|
|
42
42
|
# @rbs return: ACP::Types::ClientCapabilities
|
|
43
43
|
def self.from_h(hash)
|
|
44
44
|
new(
|
|
45
|
-
fs: hash['fs']
|
|
46
|
-
terminal: hash['terminal'],
|
|
47
|
-
session:
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
fs: ACP::Types::Check.object(hash['fs'], 'fs', ACP::Types::FileSystemCapabilities, allow_nil: true),
|
|
46
|
+
terminal: ACP::Types::Check.boolean(hash['terminal'], 'terminal', allow_nil: true),
|
|
47
|
+
session: ACP::Types::Check.object(
|
|
48
|
+
hash['session'],
|
|
49
|
+
'session',
|
|
50
|
+
ACP::Types::ClientSessionCapabilities,
|
|
51
|
+
allow_nil: true
|
|
52
|
+
),
|
|
53
|
+
auth: ACP::Types::Check.object(hash['auth'], 'auth', ACP::Types::AuthCapabilities, allow_nil: true),
|
|
54
|
+
elicitation: ACP::Types::Check.object(
|
|
55
|
+
hash['elicitation'],
|
|
56
|
+
'elicitation',
|
|
57
|
+
ACP::Types::ElicitationCapabilities,
|
|
58
|
+
allow_nil: true
|
|
59
|
+
),
|
|
50
60
|
meta: hash['_meta']
|
|
51
61
|
)
|
|
52
62
|
end
|
|
@@ -22,9 +22,12 @@ class ACP::Types::ClientSessionCapabilities
|
|
|
22
22
|
# @rbs return: ACP::Types::ClientSessionCapabilities
|
|
23
23
|
def self.from_h(hash)
|
|
24
24
|
new(
|
|
25
|
-
config_options:
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
config_options: ACP::Types::Check.object(
|
|
26
|
+
hash['configOptions'],
|
|
27
|
+
'configOptions',
|
|
28
|
+
ACP::Types::SessionConfigOptionsCapabilities,
|
|
29
|
+
allow_nil: true
|
|
30
|
+
),
|
|
28
31
|
meta: hash['_meta']
|
|
29
32
|
)
|
|
30
33
|
end
|
|
@@ -21,7 +21,10 @@ class ACP::Types::CloseSessionRequest
|
|
|
21
21
|
# @rbs hash: Hash[String, untyped]
|
|
22
22
|
# @rbs return: ACP::Types::CloseSessionRequest
|
|
23
23
|
def self.from_h(hash)
|
|
24
|
-
new(
|
|
24
|
+
new(
|
|
25
|
+
session_id: ACP::Types::Check.string(ACP::Types::Check.key(hash, 'sessionId'), 'sessionId'),
|
|
26
|
+
meta: hash['_meta']
|
|
27
|
+
)
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
# @rbs return: Hash[String, untyped]
|