My agentic slop goes here. Not intended for anyone else!

more

+19 -1
claudeio/lib/message.ml
···
module System = struct
module Data = struct
-
type t = value
let empty = `O []
···
let get_int t key = JU.get_field_int_opt t key
let get_bool t key = JU.get_field_bool_opt t key
let to_json t = t
let of_json json = json
···
module System = struct
module Data = struct
+
(* Store both the raw JSON and provide typed accessors *)
+
type t = value (* The full JSON data *)
let empty = `O []
···
let get_int t key = JU.get_field_int_opt t key
let get_bool t key = JU.get_field_bool_opt t key
+
+
let get_float t key = JU.get_field_float_opt t key
+
+
let get_list t key =
+
match t with
+
| `O fields ->
+
(match List.assoc_opt key fields with
+
| Some (`A lst) -> Some lst
+
| _ -> None)
+
| _ -> None
+
+
let get_field t key =
+
match t with
+
| `O fields -> List.assoc_opt key fields
+
| _ -> None
+
+
let raw_json t = t
let to_json t = t
let of_json json = json
+14 -1
claudeio/lib/message.mli
···
(** System message data. *)
type t
-
(** Abstract type for system message data. *)
val empty : t
(** [empty] creates empty data. *)
···
val get_bool : t -> string -> bool option
(** [get_bool t key] returns the boolean value for [key], if present. *)
val to_json : t -> Ezjsonm.value
(** [to_json t] converts to JSON representation. Internal use only. *)
···
(** System message data. *)
type t
+
(** Abstract type for system message data. Contains both the raw JSON
+
and typed accessors for common fields. *)
val empty : t
(** [empty] creates empty data. *)
···
val get_bool : t -> string -> bool option
(** [get_bool t key] returns the boolean value for [key], if present. *)
+
+
val get_float : t -> string -> float option
+
(** [get_float t key] returns the float value for [key], if present. *)
+
+
val get_list : t -> string -> Ezjsonm.value list option
+
(** [get_list t key] returns the list value for [key], if present. *)
+
+
val get_field : t -> string -> Ezjsonm.value option
+
(** [get_field t key] returns the raw JSON value for [key], if present. *)
+
+
val raw_json : t -> Ezjsonm.value
+
(** [raw_json t] returns the full underlying JSON data. *)
val to_json : t -> Ezjsonm.value
(** [to_json t] converts to JSON representation. Internal use only. *)
+53 -2
claudeio/lib/options.ml
···
model : string option;
cwd : Eio.Fs.dir_ty Eio.Path.t option;
env : (string * string) list;
}
let default = {
···
model = None;
cwd = None;
env = [];
}
let create
···
?model
?cwd
?(env = [])
() =
{ allowed_tools; disallowed_tools; max_thinking_tokens;
system_prompt; append_system_prompt; permission_mode;
-
permission_callback; model; cwd; env }
let allowed_tools t = t.allowed_tools
let disallowed_tools t = t.disallowed_tools
···
let model t = t.model
let cwd t = t.cwd
let env t = t.env
let with_allowed_tools tools t = { t with allowed_tools = tools }
let with_disallowed_tools tools t = { t with disallowed_tools = tools }
···
let with_model model t = { t with model = Some model }
let with_cwd cwd t = { t with cwd = Some cwd }
let with_env env t = { t with env }
let to_json t =
let fields = [] in
···
{ allowed_tools; disallowed_tools; max_thinking_tokens;
system_prompt; append_system_prompt; permission_mode;
permission_callback = Some Permissions.default_allow_callback;
-
model; cwd = None; env }
| _ -> raise (Invalid_argument "Options.of_json: expected object")
let pp fmt t =
···
model : string option;
cwd : Eio.Fs.dir_ty Eio.Path.t option;
env : (string * string) list;
+
continue_conversation : bool;
+
resume : string option;
+
max_turns : int option;
+
permission_prompt_tool_name : string option;
+
settings : string option;
+
add_dirs : string list;
+
extra_args : (string * string option) list;
+
debug_stderr : Eio.Flow.sink_ty Eio.Flow.sink option;
}
let default = {
···
model = None;
cwd = None;
env = [];
+
continue_conversation = false;
+
resume = None;
+
max_turns = None;
+
permission_prompt_tool_name = None;
+
settings = None;
+
add_dirs = [];
+
extra_args = [];
+
debug_stderr = None;
}
let create
···
?model
?cwd
?(env = [])
+
?(continue_conversation = false)
+
?resume
+
?max_turns
+
?permission_prompt_tool_name
+
?settings
+
?(add_dirs = [])
+
?(extra_args = [])
+
?debug_stderr
() =
{ allowed_tools; disallowed_tools; max_thinking_tokens;
system_prompt; append_system_prompt; permission_mode;
+
permission_callback; model; cwd; env;
+
continue_conversation; resume; max_turns;
+
permission_prompt_tool_name; settings; add_dirs;
+
extra_args; debug_stderr }
let allowed_tools t = t.allowed_tools
let disallowed_tools t = t.disallowed_tools
···
let model t = t.model
let cwd t = t.cwd
let env t = t.env
+
let continue_conversation t = t.continue_conversation
+
let resume t = t.resume
+
let max_turns t = t.max_turns
+
let permission_prompt_tool_name t = t.permission_prompt_tool_name
+
let settings t = t.settings
+
let add_dirs t = t.add_dirs
+
let extra_args t = t.extra_args
+
let debug_stderr t = t.debug_stderr
let with_allowed_tools tools t = { t with allowed_tools = tools }
let with_disallowed_tools tools t = { t with disallowed_tools = tools }
···
let with_model model t = { t with model = Some model }
let with_cwd cwd t = { t with cwd = Some cwd }
let with_env env t = { t with env }
+
let with_continue_conversation continue t = { t with continue_conversation = continue }
+
let with_resume session_id t = { t with resume = Some session_id }
+
let with_max_turns turns t = { t with max_turns = Some turns }
+
let with_permission_prompt_tool_name tool t = { t with permission_prompt_tool_name = Some tool }
+
let with_settings path t = { t with settings = Some path }
+
let with_add_dirs dirs t = { t with add_dirs = dirs }
+
let with_extra_args args t = { t with extra_args = args }
+
let with_debug_stderr sink t = { t with debug_stderr = Some sink }
let to_json t =
let fields = [] in
···
{ allowed_tools; disallowed_tools; max_thinking_tokens;
system_prompt; append_system_prompt; permission_mode;
permission_callback = Some Permissions.default_allow_callback;
+
model; cwd = None; env;
+
continue_conversation = false;
+
resume = None;
+
max_turns = None;
+
permission_prompt_tool_name = None;
+
settings = None;
+
add_dirs = [];
+
extra_args = [];
+
debug_stderr = None }
| _ -> raise (Invalid_argument "Options.of_json: expected object")
let pp fmt t =
+68 -2
claudeio/lib/options.mli
···
?model:string ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
?env:(string * string) list ->
unit -> t
(** [create ?allowed_tools ?disallowed_tools ?max_thinking_tokens ?system_prompt
-
?append_system_prompt ?permission_mode ?permission_callback ?model ?cwd ?env ()]
creates a new configuration.
@param allowed_tools List of explicitly allowed tool names
@param disallowed_tools List of explicitly disallowed tool names
···
@param permission_callback Custom permission callback
@param model Override the default model
@param cwd Working directory for file operations
-
@param env Environment variables to set *)
(** {1 Accessors} *)
···
val env : t -> (string * string) list
(** [env t] returns the environment variables. *)
(** {1 Builders} *)
val with_allowed_tools : string list -> t -> t
···
val with_env : (string * string) list -> t -> t
(** [with_env env t] sets the environment variables. *)
(** {1 Serialization} *)
···
?model:string ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
?env:(string * string) list ->
+
?continue_conversation:bool ->
+
?resume:string ->
+
?max_turns:int ->
+
?permission_prompt_tool_name:string ->
+
?settings:string ->
+
?add_dirs:string list ->
+
?extra_args:(string * string option) list ->
+
?debug_stderr:Eio.Flow.sink_ty Eio.Flow.sink ->
unit -> t
(** [create ?allowed_tools ?disallowed_tools ?max_thinking_tokens ?system_prompt
+
?append_system_prompt ?permission_mode ?permission_callback ?model ?cwd ?env
+
?continue_conversation ?resume ?max_turns ?permission_prompt_tool_name ?settings
+
?add_dirs ?extra_args ?debug_stderr ()]
creates a new configuration.
@param allowed_tools List of explicitly allowed tool names
@param disallowed_tools List of explicitly disallowed tool names
···
@param permission_callback Custom permission callback
@param model Override the default model
@param cwd Working directory for file operations
+
@param env Environment variables to set
+
@param continue_conversation Continue an existing conversation
+
@param resume Resume from a specific session ID
+
@param max_turns Maximum number of conversation turns
+
@param permission_prompt_tool_name Tool name for permission prompts
+
@param settings Path to settings file
+
@param add_dirs Additional directories to allow access to
+
@param extra_args Additional CLI flags to pass through
+
@param debug_stderr Sink for debug output when debug-to-stderr is set *)
(** {1 Accessors} *)
···
val env : t -> (string * string) list
(** [env t] returns the environment variables. *)
+
val continue_conversation : t -> bool
+
(** [continue_conversation t] returns whether to continue an existing conversation. *)
+
+
val resume : t -> string option
+
(** [resume t] returns the optional session ID to resume. *)
+
+
val max_turns : t -> int option
+
(** [max_turns t] returns the optional maximum number of turns. *)
+
+
val permission_prompt_tool_name : t -> string option
+
(** [permission_prompt_tool_name t] returns the optional tool name for permission prompts. *)
+
+
val settings : t -> string option
+
(** [settings t] returns the optional path to settings file. *)
+
+
val add_dirs : t -> string list
+
(** [add_dirs t] returns the list of additional allowed directories. *)
+
+
val extra_args : t -> (string * string option) list
+
(** [extra_args t] returns the additional CLI flags. *)
+
+
val debug_stderr : t -> Eio.Flow.sink_ty Eio.Flow.sink option
+
(** [debug_stderr t] returns the optional debug output sink. *)
+
(** {1 Builders} *)
val with_allowed_tools : string list -> t -> t
···
val with_env : (string * string) list -> t -> t
(** [with_env env t] sets the environment variables. *)
+
+
val with_continue_conversation : bool -> t -> t
+
(** [with_continue_conversation continue t] sets whether to continue conversation. *)
+
+
val with_resume : string -> t -> t
+
(** [with_resume session_id t] sets the session ID to resume. *)
+
+
val with_max_turns : int -> t -> t
+
(** [with_max_turns turns t] sets the maximum number of turns. *)
+
+
val with_permission_prompt_tool_name : string -> t -> t
+
(** [with_permission_prompt_tool_name tool t] sets the permission prompt tool name. *)
+
+
val with_settings : string -> t -> t
+
(** [with_settings path t] sets the path to settings file. *)
+
+
val with_add_dirs : string list -> t -> t
+
(** [with_add_dirs dirs t] sets the additional allowed directories. *)
+
+
val with_extra_args : (string * string option) list -> t -> t
+
(** [with_extra_args args t] sets the additional CLI flags. *)
+
+
val with_debug_stderr : Eio.Flow.sink_ty Eio.Flow.sink -> t -> t
+
(** [with_debug_stderr sink t] sets the debug output sink. *)
(** {1 Serialization} *)
+363
claudeio/lib/sdk_control.ml
···
···
+
open Ezjsonm
+
+
let src = Logs.Src.create "claude.sdk_control" ~doc:"Claude SDK control protocol"
+
module Log = (val Logs.src_log src : Logs.LOG)
+
+
module JU = Json_utils
+
+
module Request = struct
+
type interrupt = {
+
subtype : [`Interrupt];
+
}
+
+
type permission = {
+
subtype : [`Can_use_tool];
+
tool_name : string;
+
input : value;
+
permission_suggestions : Permissions.Update.t list option;
+
blocked_path : string option;
+
}
+
+
type initialize = {
+
subtype : [`Initialize];
+
hooks : (string * value) list option;
+
}
+
+
type set_permission_mode = {
+
subtype : [`Set_permission_mode];
+
mode : Permissions.Mode.t;
+
}
+
+
type hook_callback = {
+
subtype : [`Hook_callback];
+
callback_id : string;
+
input : value;
+
tool_use_id : string option;
+
}
+
+
type mcp_message = {
+
subtype : [`Mcp_message];
+
server_name : string;
+
message : value;
+
}
+
+
type t =
+
| Interrupt of interrupt
+
| Permission of permission
+
| Initialize of initialize
+
| Set_permission_mode of set_permission_mode
+
| Hook_callback of hook_callback
+
| Mcp_message of mcp_message
+
+
let interrupt () = Interrupt { subtype = `Interrupt }
+
+
let permission ~tool_name ~input ?permission_suggestions ?blocked_path () =
+
Permission {
+
subtype = `Can_use_tool;
+
tool_name;
+
input;
+
permission_suggestions;
+
blocked_path;
+
}
+
+
let initialize ?hooks () =
+
Initialize { subtype = `Initialize; hooks }
+
+
let set_permission_mode ~mode =
+
Set_permission_mode { subtype = `Set_permission_mode; mode }
+
+
let hook_callback ~callback_id ~input ?tool_use_id () =
+
Hook_callback {
+
subtype = `Hook_callback;
+
callback_id;
+
input;
+
tool_use_id;
+
}
+
+
let mcp_message ~server_name ~message =
+
Mcp_message {
+
subtype = `Mcp_message;
+
server_name;
+
message;
+
}
+
+
let to_json = function
+
| Interrupt _ ->
+
`O [("subtype", `String "interrupt")]
+
| Permission p ->
+
let fields = [
+
("subtype", `String "can_use_tool");
+
("tool_name", `String p.tool_name);
+
("input", p.input);
+
] in
+
let fields = match p.permission_suggestions with
+
| Some suggestions ->
+
("permission_suggestions",
+
`A (List.map Permissions.Update.to_json suggestions)) :: fields
+
| None -> fields
+
in
+
let fields = match p.blocked_path with
+
| Some path -> ("blocked_path", `String path) :: fields
+
| None -> fields
+
in
+
`O fields
+
| Initialize i ->
+
let fields = [("subtype", `String "initialize")] in
+
let fields = match i.hooks with
+
| Some hooks ->
+
("hooks", `O hooks) :: fields
+
| None -> fields
+
in
+
`O fields
+
| Set_permission_mode s ->
+
`O [
+
("subtype", `String "set_permission_mode");
+
("mode", Permissions.Mode.to_json s.mode);
+
]
+
| Hook_callback h ->
+
let fields = [
+
("subtype", `String "hook_callback");
+
("callback_id", `String h.callback_id);
+
("input", h.input);
+
] in
+
let fields = match h.tool_use_id with
+
| Some id -> ("tool_use_id", `String id) :: fields
+
| None -> fields
+
in
+
`O fields
+
| Mcp_message m ->
+
`O [
+
("subtype", `String "mcp_message");
+
("server_name", `String m.server_name);
+
("message", m.message);
+
]
+
+
let of_json = function
+
| `O fields ->
+
let subtype = JU.assoc_string "subtype" fields in
+
(match subtype with
+
| "interrupt" ->
+
Interrupt { subtype = `Interrupt }
+
| "can_use_tool" ->
+
let tool_name = JU.assoc_string "tool_name" fields in
+
let input = List.assoc "input" fields in
+
let permission_suggestions =
+
match List.assoc_opt "permission_suggestions" fields with
+
| Some (`A lst) ->
+
Some (List.map Permissions.Update.of_json lst)
+
| _ -> None
+
in
+
let blocked_path = JU.assoc_string_opt "blocked_path" fields in
+
Permission {
+
subtype = `Can_use_tool;
+
tool_name;
+
input;
+
permission_suggestions;
+
blocked_path;
+
}
+
| "initialize" ->
+
let hooks =
+
match List.assoc_opt "hooks" fields with
+
| Some (`O hooks) -> Some hooks
+
| _ -> None
+
in
+
Initialize { subtype = `Initialize; hooks }
+
| "set_permission_mode" ->
+
let mode = List.assoc "mode" fields |> Permissions.Mode.of_json in
+
Set_permission_mode { subtype = `Set_permission_mode; mode }
+
| "hook_callback" ->
+
let callback_id = JU.assoc_string "callback_id" fields in
+
let input = List.assoc "input" fields in
+
let tool_use_id = JU.assoc_string_opt "tool_use_id" fields in
+
Hook_callback {
+
subtype = `Hook_callback;
+
callback_id;
+
input;
+
tool_use_id;
+
}
+
| "mcp_message" ->
+
let server_name = JU.assoc_string "server_name" fields in
+
let message = List.assoc "message" fields in
+
Mcp_message {
+
subtype = `Mcp_message;
+
server_name;
+
message;
+
}
+
| _ -> raise (Invalid_argument ("Unknown request subtype: " ^ subtype)))
+
| _ -> raise (Invalid_argument "Request.of_json: expected object")
+
+
let pp fmt = function
+
| Interrupt _ ->
+
Fmt.pf fmt "@[<2>Interrupt@]"
+
| Permission p ->
+
Fmt.pf fmt "@[<2>Permission@ { tool = %S;@ blocked_path = %a }@]"
+
p.tool_name Fmt.(option string) p.blocked_path
+
| Initialize i ->
+
Fmt.pf fmt "@[<2>Initialize@ { hooks = %s }@]"
+
(if Option.is_some i.hooks then "present" else "none")
+
| Set_permission_mode s ->
+
Fmt.pf fmt "@[<2>SetPermissionMode@ { mode = %a }@]"
+
Permissions.Mode.pp s.mode
+
| Hook_callback h ->
+
Fmt.pf fmt "@[<2>HookCallback@ { id = %S;@ tool_use_id = %a }@]"
+
h.callback_id Fmt.(option string) h.tool_use_id
+
| Mcp_message m ->
+
Fmt.pf fmt "@[<2>McpMessage@ { server = %S }@]"
+
m.server_name
+
end
+
+
module Response = struct
+
type success = {
+
subtype : [`Success];
+
request_id : string;
+
response : value option;
+
}
+
+
type error = {
+
subtype : [`Error];
+
request_id : string;
+
error : string;
+
}
+
+
type t =
+
| Success of success
+
| Error of error
+
+
let success ~request_id ?response () =
+
Success {
+
subtype = `Success;
+
request_id;
+
response;
+
}
+
+
let error ~request_id ~error =
+
Error {
+
subtype = `Error;
+
request_id;
+
error;
+
}
+
+
let to_json = function
+
| Success s ->
+
let fields = [
+
("subtype", `String "success");
+
("request_id", `String s.request_id);
+
] in
+
let fields = match s.response with
+
| Some resp -> ("response", resp) :: fields
+
| None -> fields
+
in
+
`O fields
+
| Error e ->
+
`O [
+
("subtype", `String "error");
+
("request_id", `String e.request_id);
+
("error", `String e.error);
+
]
+
+
let of_json = function
+
| `O fields ->
+
let subtype = JU.assoc_string "subtype" fields in
+
let request_id = JU.assoc_string "request_id" fields in
+
(match subtype with
+
| "success" ->
+
let response = List.assoc_opt "response" fields in
+
Success {
+
subtype = `Success;
+
request_id;
+
response;
+
}
+
| "error" ->
+
let error = JU.assoc_string "error" fields in
+
Error {
+
subtype = `Error;
+
request_id;
+
error;
+
}
+
| _ -> raise (Invalid_argument ("Unknown response subtype: " ^ subtype)))
+
| _ -> raise (Invalid_argument "Response.of_json: expected object")
+
+
let pp fmt = function
+
| Success s ->
+
Fmt.pf fmt "@[<2>Success@ { request_id = %S;@ response = %s }@]"
+
s.request_id (if Option.is_some s.response then "present" else "none")
+
| Error e ->
+
Fmt.pf fmt "@[<2>Error@ { request_id = %S;@ error = %S }@]"
+
e.request_id e.error
+
end
+
+
type control_request = {
+
type_ : [`Control_request];
+
request_id : string;
+
request : Request.t;
+
}
+
+
type control_response = {
+
type_ : [`Control_response];
+
response : Response.t;
+
}
+
+
type t =
+
| Request of control_request
+
| Response of control_response
+
+
let create_request ~request_id ~request =
+
Request {
+
type_ = `Control_request;
+
request_id;
+
request;
+
}
+
+
let create_response ~response =
+
Response {
+
type_ = `Control_response;
+
response;
+
}
+
+
let to_json = function
+
| Request r ->
+
`O [
+
("type", `String "control_request");
+
("request_id", `String r.request_id);
+
("request", Request.to_json r.request);
+
]
+
| Response r ->
+
`O [
+
("type", `String "control_response");
+
("response", Response.to_json r.response);
+
]
+
+
let of_json = function
+
| `O fields ->
+
let type_ = JU.assoc_string "type" fields in
+
(match type_ with
+
| "control_request" ->
+
let request_id = JU.assoc_string "request_id" fields in
+
let request = List.assoc "request" fields |> Request.of_json in
+
Request {
+
type_ = `Control_request;
+
request_id;
+
request;
+
}
+
| "control_response" ->
+
let response = List.assoc "response" fields |> Response.of_json in
+
Response {
+
type_ = `Control_response;
+
response;
+
}
+
| _ -> raise (Invalid_argument ("Unknown control type: " ^ type_)))
+
| _ -> raise (Invalid_argument "of_json: expected object")
+
+
let pp fmt = function
+
| Request r ->
+
Fmt.pf fmt "@[<2>ControlRequest@ { id = %S;@ request = %a }@]"
+
r.request_id Request.pp r.request
+
| Response r ->
+
Fmt.pf fmt "@[<2>ControlResponse@ { %a }@]"
+
Response.pp r.response
+
+
let log_request req =
+
Log.debug (fun m -> m "SDK control request: %a" Request.pp req)
+
+
let log_response resp =
+
Log.debug (fun m -> m "SDK control response: %a" Response.pp resp)
+188
claudeio/lib/sdk_control.mli
···
···
+
(** SDK Control Protocol for Claude.
+
+
This module defines the typed SDK control protocol for communication
+
between the SDK and Claude, including request and response types. *)
+
+
open Ezjsonm
+
+
(** The log source for SDK control operations *)
+
val src : Logs.Src.t
+
+
(** {1 Request Types} *)
+
+
module Request : sig
+
(** SDK control request types. *)
+
+
type interrupt = {
+
subtype : [`Interrupt];
+
}
+
(** Interrupt request to stop execution. *)
+
+
type permission = {
+
subtype : [`Can_use_tool];
+
tool_name : string;
+
input : value;
+
permission_suggestions : Permissions.Update.t list option;
+
blocked_path : string option;
+
}
+
(** Permission request for tool usage. *)
+
+
type initialize = {
+
subtype : [`Initialize];
+
hooks : (string * value) list option; (* Hook event to configuration *)
+
}
+
(** Initialize request with optional hook configuration. *)
+
+
type set_permission_mode = {
+
subtype : [`Set_permission_mode];
+
mode : Permissions.Mode.t;
+
}
+
(** Request to change permission mode. *)
+
+
type hook_callback = {
+
subtype : [`Hook_callback];
+
callback_id : string;
+
input : value;
+
tool_use_id : string option;
+
}
+
(** Hook callback request. *)
+
+
type mcp_message = {
+
subtype : [`Mcp_message];
+
server_name : string;
+
message : value;
+
}
+
(** MCP server message request. *)
+
+
type t =
+
| Interrupt of interrupt
+
| Permission of permission
+
| Initialize of initialize
+
| Set_permission_mode of set_permission_mode
+
| Hook_callback of hook_callback
+
| Mcp_message of mcp_message
+
(** The type of SDK control requests. *)
+
+
val interrupt : unit -> t
+
(** [interrupt ()] creates an interrupt request. *)
+
+
val permission :
+
tool_name:string ->
+
input:value ->
+
?permission_suggestions:Permissions.Update.t list ->
+
?blocked_path:string ->
+
unit -> t
+
(** [permission ~tool_name ~input ?permission_suggestions ?blocked_path ()]
+
creates a permission request. *)
+
+
val initialize : ?hooks:(string * value) list -> unit -> t
+
(** [initialize ?hooks ()] creates an initialize request. *)
+
+
val set_permission_mode : mode:Permissions.Mode.t -> t
+
(** [set_permission_mode ~mode] creates a permission mode change request. *)
+
+
val hook_callback :
+
callback_id:string ->
+
input:value ->
+
?tool_use_id:string ->
+
unit -> t
+
(** [hook_callback ~callback_id ~input ?tool_use_id ()] creates a hook callback request. *)
+
+
val mcp_message : server_name:string -> message:value -> t
+
(** [mcp_message ~server_name ~message] creates an MCP message request. *)
+
+
val to_json : t -> value
+
(** [to_json t] converts a request to JSON. *)
+
+
val of_json : value -> t
+
(** [of_json json] parses a request from JSON.
+
@raise Invalid_argument if the JSON is not a valid request. *)
+
+
val pp : Format.formatter -> t -> unit
+
(** [pp fmt t] pretty-prints the request. *)
+
end
+
+
(** {1 Response Types} *)
+
+
module Response : sig
+
(** SDK control response types. *)
+
+
type success = {
+
subtype : [`Success];
+
request_id : string;
+
response : value option;
+
}
+
(** Successful response. *)
+
+
type error = {
+
subtype : [`Error];
+
request_id : string;
+
error : string;
+
}
+
(** Error response. *)
+
+
type t =
+
| Success of success
+
| Error of error
+
(** The type of SDK control responses. *)
+
+
val success : request_id:string -> ?response:value -> unit -> t
+
(** [success ~request_id ?response ()] creates a success response. *)
+
+
val error : request_id:string -> error:string -> t
+
(** [error ~request_id ~error] creates an error response. *)
+
+
val to_json : t -> value
+
(** [to_json t] converts a response to JSON. *)
+
+
val of_json : value -> t
+
(** [of_json json] parses a response from JSON.
+
@raise Invalid_argument if the JSON is not a valid response. *)
+
+
val pp : Format.formatter -> t -> unit
+
(** [pp fmt t] pretty-prints the response. *)
+
end
+
+
(** {1 Control Messages} *)
+
+
type control_request = {
+
type_ : [`Control_request];
+
request_id : string;
+
request : Request.t;
+
}
+
(** Control request message. *)
+
+
type control_response = {
+
type_ : [`Control_response];
+
response : Response.t;
+
}
+
(** Control response message. *)
+
+
type t =
+
| Request of control_request
+
| Response of control_response
+
(** The type of SDK control messages. *)
+
+
val create_request : request_id:string -> request:Request.t -> t
+
(** [create_request ~request_id ~request] creates a control request message. *)
+
+
val create_response : response:Response.t -> t
+
(** [create_response ~response] creates a control response message. *)
+
+
val to_json : t -> value
+
(** [to_json t] converts a control message to JSON. *)
+
+
val of_json : value -> t
+
(** [of_json json] parses a control message from JSON.
+
@raise Invalid_argument if the JSON is not a valid control message. *)
+
+
val pp : Format.formatter -> t -> unit
+
(** [pp fmt t] pretty-prints the control message. *)
+
+
(** {1 Logging} *)
+
+
val log_request : Request.t -> unit
+
(** [log_request req] logs an SDK control request. *)
+
+
val log_response : Response.t -> unit
+
(** [log_response resp] logs an SDK control response. *)