///|
using @jsonrpc {type RequestId, jsonrpc_decode_int64}
///|
using @protocol_data {
type ElicitationCreateParams,
type ElicitationCompleteParams,
type ProtocolDecodeError,
type ReadTextFileParams,
type RequestPermissionRequest,
type TerminalCreateParams,
type TerminalKillParams,
type TerminalOutputParams,
type TerminalReleaseParams,
type TerminalWaitForExitParams,
type WriteTextFileParams,
elicitation_complete_params_from_json,
elicitation_create_params_from_json,
protocol_reject_unknown,
protocol_required,
protocol_require_object,
request_permission_request_from_json,
read_text_file_params_from_json,
terminal_create_params_from_json,
terminal_kill_params_from_json,
terminal_output_params_from_json,
terminal_release_params_from_json,
terminal_wait_for_exit_params_from_json,
write_text_file_params_from_json,
}
///|
using @session_protocol {
type SessionUpdateParams,
session_update_params_from_json,
}
///|
/// The complete stable v1 request surface delivered to a Client.
///
/// Every variant contains a protocol-validated payload. The closed union
/// prevents Agent-to-Client dispatch from falling through to an untyped JSON
/// handler.
pub(all) enum ClientRequest {
SessionRequestPermission(RequestPermissionRequest)
FsReadTextFile(ReadTextFileParams)
FsWriteTextFile(WriteTextFileParams)
TerminalCreate(TerminalCreateParams)
TerminalOutput(TerminalOutputParams)
TerminalWaitForExit(TerminalWaitForExitParams)
TerminalKill(TerminalKillParams)
TerminalRelease(TerminalReleaseParams)
ElicitationCreate(ElicitationCreateParams)
} derive(Eq, Debug)
///|
/// Stable v1 notifications delivered to a Client, including the
/// bidirectional JSON-RPC cancellation notification.
pub(all) enum ClientNotification {
SessionUpdate(SessionUpdateParams)
ElicitationComplete(ElicitationCompleteParams)
CancelRequest(RequestId)
} derive(Eq, Debug)
///|
/// Errors raised while mapping a method and params value to the Client-side
/// closed unions above.
pub(all) suberror ClientMessageError {
InvalidParams(method_name~ : String, cause~ : ProtocolDecodeError)
UnknownMethod(method_name~ : String)
WrongDirection(method_name~ : String)
WrongKind(method_name~ : String)
} derive(Eq, Debug)
///|
/// Return the exact wire method represented by an accepted request.
pub fn ClientRequest::method_name(self : ClientRequest) -> String {
match self {
SessionRequestPermission(_) => "session/request_permission"
FsReadTextFile(_) => "fs/read_text_file"
FsWriteTextFile(_) => "fs/write_text_file"
TerminalCreate(_) => "terminal/create"
TerminalOutput(_) => "terminal/output"
TerminalWaitForExit(_) => "terminal/wait_for_exit"
TerminalKill(_) => "terminal/kill"
TerminalRelease(_) => "terminal/release"
ElicitationCreate(_) => "elicitation/create"
}
}
///|
/// Return the exact wire method represented by an accepted notification.
pub fn ClientNotification::method_name(self : ClientNotification) -> String {
match self {
SessionUpdate(_) => "session/update"
ElicitationComplete(_) => "elicitation/complete"
CancelRequest(_) => "$/cancel_request"
}
}
///|
fn[T] client_decode_params(
method_name : String,
params : Json?,
decode : (Json) -> T raise ProtocolDecodeError,
) -> T raise ClientMessageError {
let value = match params {
Some(value) => value
None =>
raise InvalidParams(
method_name~,
cause=MissingField(path=method_name + ".params"),
)
}
decode(value) catch {
error => raise InvalidParams(method_name~, cause=error)
}
}
///|
/// Decode one Agent-to-Client request params value into the closed request
/// union. Known Client-to-Agent methods and notifications are rejected
/// explicitly rather than being treated as unknown methods.
pub fn decode_client_request(
method_name : String,
params : Json?,
) -> ClientRequest raise ClientMessageError {
match method_name {
"session/request_permission" =>
SessionRequestPermission(
client_decode_params(method_name, params, value => {
request_permission_request_from_json(value)
}),
)
"fs/read_text_file" =>
FsReadTextFile(
client_decode_params(method_name, params, value => {
read_text_file_params_from_json(value)
}),
)
"fs/write_text_file" =>
FsWriteTextFile(
client_decode_params(method_name, params, value => {
write_text_file_params_from_json(value)
}),
)
"terminal/create" =>
TerminalCreate(
client_decode_params(method_name, params, value => {
terminal_create_params_from_json(value)
}),
)
"terminal/output" =>
TerminalOutput(
client_decode_params(method_name, params, value => {
terminal_output_params_from_json(value)
}),
)
"terminal/wait_for_exit" =>
TerminalWaitForExit(
client_decode_params(method_name, params, value => {
terminal_wait_for_exit_params_from_json(value)
}),
)
"terminal/kill" =>
TerminalKill(
client_decode_params(method_name, params, value => {
terminal_kill_params_from_json(value)
}),
)
"terminal/release" =>
TerminalRelease(
client_decode_params(method_name, params, value => {
terminal_release_params_from_json(value)
}),
)
"elicitation/create" =>
ElicitationCreate(
client_decode_params(method_name, params, value => {
elicitation_create_params_from_json(value)
}),
)
"session/update" | "elicitation/complete" =>
raise WrongDirection(method_name~)
"initialize"
| "authenticate"
| "logout"
| "session/new"
| "session/load"
| "session/resume"
| "session/list"
| "session/delete"
| "session/close"
| "session/set_mode"
| "session/set_config_option"
| "session/prompt"
| "session/cancel" => raise WrongDirection(method_name~)
"$/cancel_request" => raise WrongKind(method_name~)
_ => raise UnknownMethod(method_name~)
}
}
///|
fn client_decode_cancel_request_id(
value : Json,
path~ : String,
) -> RequestId raise ProtocolDecodeError {
match value {
String(value) => String(value)
Number(value, repr~) =>
Number(
jsonrpc_decode_int64(value, repr, path~) catch {
_ =>
raise InvalidField(path~, reason="expected a signed 64-bit integer")
},
)
Null => Null
_ => raise InvalidField(path~, reason="must be a string, integer, or null")
}
}
///|
/// Decode one Agent-to-Client notification params value. String, integer, and
/// null cancellation identifiers remain distinct typed `RequestId` values.
pub fn decode_client_notification(
method_name : String,
params : Json?,
) -> ClientNotification raise ClientMessageError {
match method_name {
"session/update" =>
SessionUpdate(
client_decode_params(method_name, params, value => {
session_update_params_from_json(value)
}),
)
"elicitation/complete" =>
ElicitationComplete(
client_decode_params(method_name, params, value => {
elicitation_complete_params_from_json(value)
}),
)
"$/cancel_request" =>
CancelRequest(
client_decode_params(method_name, params, value => {
let fields = protocol_require_object(value, path=method_name)
protocol_reject_unknown(fields, ["requestId"], prefix=method_name)
let request_id = protocol_required(
fields,
"requestId",
path=method_name + ".requestId",
)
client_decode_cancel_request_id(
request_id,
path=method_name + ".requestId",
)
}),
)
"initialize"
| "authenticate"
| "logout"
| "session/new"
| "session/load"
| "session/resume"
| "session/list"
| "session/delete"
| "session/close"
| "session/set_mode"
| "session/set_config_option"
| "session/prompt"
| "session/cancel"
| "session/request_permission"
| "fs/read_text_file"
| "fs/write_text_file"
| "terminal/create"
| "terminal/output"
| "terminal/wait_for_exit"
| "terminal/kill"
| "terminal/release"
| "elicitation/create" => raise WrongDirection(method_name~)
_ => raise UnknownMethod(method_name~)
}
}