···194194195195module System = struct
196196 module Data = struct
197197- type t = value
197197+ (* Store both the raw JSON and provide typed accessors *)
198198+ type t = value (* The full JSON data *)
198199199200 let empty = `O []
200201···205206 let get_int t key = JU.get_field_int_opt t key
206207207208 let get_bool t key = JU.get_field_bool_opt t key
209209+210210+ let get_float t key = JU.get_field_float_opt t key
211211+212212+ let get_list t key =
213213+ match t with
214214+ | `O fields ->
215215+ (match List.assoc_opt key fields with
216216+ | Some (`A lst) -> Some lst
217217+ | _ -> None)
218218+ | _ -> None
219219+220220+ let get_field t key =
221221+ match t with
222222+ | `O fields -> List.assoc_opt key fields
223223+ | _ -> None
224224+225225+ let raw_json t = t
208226209227 let to_json t = t
210228 let of_json json = json
+14-1
claudeio/lib/message.mli
···112112 (** System message data. *)
113113114114 type t
115115- (** Abstract type for system message data. *)
115115+ (** Abstract type for system message data. Contains both the raw JSON
116116+ and typed accessors for common fields. *)
116117117118 val empty : t
118119 (** [empty] creates empty data. *)
···128129129130 val get_bool : t -> string -> bool option
130131 (** [get_bool t key] returns the boolean value for [key], if present. *)
132132+133133+ val get_float : t -> string -> float option
134134+ (** [get_float t key] returns the float value for [key], if present. *)
135135+136136+ val get_list : t -> string -> Ezjsonm.value list option
137137+ (** [get_list t key] returns the list value for [key], if present. *)
138138+139139+ val get_field : t -> string -> Ezjsonm.value option
140140+ (** [get_field t key] returns the raw JSON value for [key], if present. *)
141141+142142+ val raw_json : t -> Ezjsonm.value
143143+ (** [raw_json t] returns the full underlying JSON data. *)
131144132145 val to_json : t -> Ezjsonm.value
133146 (** [to_json t] converts to JSON representation. Internal use only. *)
+53-2
claudeio/lib/options.ml
···1414 model : string option;
1515 cwd : Eio.Fs.dir_ty Eio.Path.t option;
1616 env : (string * string) list;
1717+ continue_conversation : bool;
1818+ resume : string option;
1919+ max_turns : int option;
2020+ permission_prompt_tool_name : string option;
2121+ settings : string option;
2222+ add_dirs : string list;
2323+ extra_args : (string * string option) list;
2424+ debug_stderr : Eio.Flow.sink_ty Eio.Flow.sink option;
1725}
18261927let default = {
···2735 model = None;
2836 cwd = None;
2937 env = [];
3838+ continue_conversation = false;
3939+ resume = None;
4040+ max_turns = None;
4141+ permission_prompt_tool_name = None;
4242+ settings = None;
4343+ add_dirs = [];
4444+ extra_args = [];
4545+ debug_stderr = None;
3046}
31473248let create
···4056 ?model
4157 ?cwd
4258 ?(env = [])
5959+ ?(continue_conversation = false)
6060+ ?resume
6161+ ?max_turns
6262+ ?permission_prompt_tool_name
6363+ ?settings
6464+ ?(add_dirs = [])
6565+ ?(extra_args = [])
6666+ ?debug_stderr
4367 () =
4468 { allowed_tools; disallowed_tools; max_thinking_tokens;
4569 system_prompt; append_system_prompt; permission_mode;
4646- permission_callback; model; cwd; env }
7070+ permission_callback; model; cwd; env;
7171+ continue_conversation; resume; max_turns;
7272+ permission_prompt_tool_name; settings; add_dirs;
7373+ extra_args; debug_stderr }
47744875let allowed_tools t = t.allowed_tools
4976let disallowed_tools t = t.disallowed_tools
···5582let model t = t.model
5683let cwd t = t.cwd
5784let env t = t.env
8585+let continue_conversation t = t.continue_conversation
8686+let resume t = t.resume
8787+let max_turns t = t.max_turns
8888+let permission_prompt_tool_name t = t.permission_prompt_tool_name
8989+let settings t = t.settings
9090+let add_dirs t = t.add_dirs
9191+let extra_args t = t.extra_args
9292+let debug_stderr t = t.debug_stderr
58935994let with_allowed_tools tools t = { t with allowed_tools = tools }
6095let with_disallowed_tools tools t = { t with disallowed_tools = tools }
···66101let with_model model t = { t with model = Some model }
67102let with_cwd cwd t = { t with cwd = Some cwd }
68103let with_env env t = { t with env }
104104+let with_continue_conversation continue t = { t with continue_conversation = continue }
105105+let with_resume session_id t = { t with resume = Some session_id }
106106+let with_max_turns turns t = { t with max_turns = Some turns }
107107+let with_permission_prompt_tool_name tool t = { t with permission_prompt_tool_name = Some tool }
108108+let with_settings path t = { t with settings = Some path }
109109+let with_add_dirs dirs t = { t with add_dirs = dirs }
110110+let with_extra_args args t = { t with extra_args = args }
111111+let with_debug_stderr sink t = { t with debug_stderr = Some sink }
6911270113let to_json t =
71114 let fields = [] in
···148191 { allowed_tools; disallowed_tools; max_thinking_tokens;
149192 system_prompt; append_system_prompt; permission_mode;
150193 permission_callback = Some Permissions.default_allow_callback;
151151- model; cwd = None; env }
194194+ model; cwd = None; env;
195195+ continue_conversation = false;
196196+ resume = None;
197197+ max_turns = None;
198198+ permission_prompt_tool_name = None;
199199+ settings = None;
200200+ add_dirs = [];
201201+ extra_args = [];
202202+ debug_stderr = None }
152203 | _ -> raise (Invalid_argument "Options.of_json: expected object")
153204154205let pp fmt t =
+68-2
claudeio/lib/options.mli
···3030 ?model:string ->
3131 ?cwd:Eio.Fs.dir_ty Eio.Path.t ->
3232 ?env:(string * string) list ->
3333+ ?continue_conversation:bool ->
3434+ ?resume:string ->
3535+ ?max_turns:int ->
3636+ ?permission_prompt_tool_name:string ->
3737+ ?settings:string ->
3838+ ?add_dirs:string list ->
3939+ ?extra_args:(string * string option) list ->
4040+ ?debug_stderr:Eio.Flow.sink_ty Eio.Flow.sink ->
3341 unit -> t
3442(** [create ?allowed_tools ?disallowed_tools ?max_thinking_tokens ?system_prompt
3535- ?append_system_prompt ?permission_mode ?permission_callback ?model ?cwd ?env ()]
4343+ ?append_system_prompt ?permission_mode ?permission_callback ?model ?cwd ?env
4444+ ?continue_conversation ?resume ?max_turns ?permission_prompt_tool_name ?settings
4545+ ?add_dirs ?extra_args ?debug_stderr ()]
3646 creates a new configuration.
3747 @param allowed_tools List of explicitly allowed tool names
3848 @param disallowed_tools List of explicitly disallowed tool names
···4353 @param permission_callback Custom permission callback
4454 @param model Override the default model
4555 @param cwd Working directory for file operations
4646- @param env Environment variables to set *)
5656+ @param env Environment variables to set
5757+ @param continue_conversation Continue an existing conversation
5858+ @param resume Resume from a specific session ID
5959+ @param max_turns Maximum number of conversation turns
6060+ @param permission_prompt_tool_name Tool name for permission prompts
6161+ @param settings Path to settings file
6262+ @param add_dirs Additional directories to allow access to
6363+ @param extra_args Additional CLI flags to pass through
6464+ @param debug_stderr Sink for debug output when debug-to-stderr is set *)
47654866(** {1 Accessors} *)
4967···7795val env : t -> (string * string) list
7896(** [env t] returns the environment variables. *)
79979898+val continue_conversation : t -> bool
9999+(** [continue_conversation t] returns whether to continue an existing conversation. *)
100100+101101+val resume : t -> string option
102102+(** [resume t] returns the optional session ID to resume. *)
103103+104104+val max_turns : t -> int option
105105+(** [max_turns t] returns the optional maximum number of turns. *)
106106+107107+val permission_prompt_tool_name : t -> string option
108108+(** [permission_prompt_tool_name t] returns the optional tool name for permission prompts. *)
109109+110110+val settings : t -> string option
111111+(** [settings t] returns the optional path to settings file. *)
112112+113113+val add_dirs : t -> string list
114114+(** [add_dirs t] returns the list of additional allowed directories. *)
115115+116116+val extra_args : t -> (string * string option) list
117117+(** [extra_args t] returns the additional CLI flags. *)
118118+119119+val debug_stderr : t -> Eio.Flow.sink_ty Eio.Flow.sink option
120120+(** [debug_stderr t] returns the optional debug output sink. *)
121121+80122(** {1 Builders} *)
8112382124val with_allowed_tools : string list -> t -> t
···108150109151val with_env : (string * string) list -> t -> t
110152(** [with_env env t] sets the environment variables. *)
153153+154154+val with_continue_conversation : bool -> t -> t
155155+(** [with_continue_conversation continue t] sets whether to continue conversation. *)
156156+157157+val with_resume : string -> t -> t
158158+(** [with_resume session_id t] sets the session ID to resume. *)
159159+160160+val with_max_turns : int -> t -> t
161161+(** [with_max_turns turns t] sets the maximum number of turns. *)
162162+163163+val with_permission_prompt_tool_name : string -> t -> t
164164+(** [with_permission_prompt_tool_name tool t] sets the permission prompt tool name. *)
165165+166166+val with_settings : string -> t -> t
167167+(** [with_settings path t] sets the path to settings file. *)
168168+169169+val with_add_dirs : string list -> t -> t
170170+(** [with_add_dirs dirs t] sets the additional allowed directories. *)
171171+172172+val with_extra_args : (string * string option) list -> t -> t
173173+(** [with_extra_args args t] sets the additional CLI flags. *)
174174+175175+val with_debug_stderr : Eio.Flow.sink_ty Eio.Flow.sink -> t -> t
176176+(** [with_debug_stderr sink t] sets the debug output sink. *)
111177112178(** {1 Serialization} *)
113179
+363
claudeio/lib/sdk_control.ml
···11+open Ezjsonm
22+33+let src = Logs.Src.create "claude.sdk_control" ~doc:"Claude SDK control protocol"
44+module Log = (val Logs.src_log src : Logs.LOG)
55+66+module JU = Json_utils
77+88+module Request = struct
99+ type interrupt = {
1010+ subtype : [`Interrupt];
1111+ }
1212+1313+ type permission = {
1414+ subtype : [`Can_use_tool];
1515+ tool_name : string;
1616+ input : value;
1717+ permission_suggestions : Permissions.Update.t list option;
1818+ blocked_path : string option;
1919+ }
2020+2121+ type initialize = {
2222+ subtype : [`Initialize];
2323+ hooks : (string * value) list option;
2424+ }
2525+2626+ type set_permission_mode = {
2727+ subtype : [`Set_permission_mode];
2828+ mode : Permissions.Mode.t;
2929+ }
3030+3131+ type hook_callback = {
3232+ subtype : [`Hook_callback];
3333+ callback_id : string;
3434+ input : value;
3535+ tool_use_id : string option;
3636+ }
3737+3838+ type mcp_message = {
3939+ subtype : [`Mcp_message];
4040+ server_name : string;
4141+ message : value;
4242+ }
4343+4444+ type t =
4545+ | Interrupt of interrupt
4646+ | Permission of permission
4747+ | Initialize of initialize
4848+ | Set_permission_mode of set_permission_mode
4949+ | Hook_callback of hook_callback
5050+ | Mcp_message of mcp_message
5151+5252+ let interrupt () = Interrupt { subtype = `Interrupt }
5353+5454+ let permission ~tool_name ~input ?permission_suggestions ?blocked_path () =
5555+ Permission {
5656+ subtype = `Can_use_tool;
5757+ tool_name;
5858+ input;
5959+ permission_suggestions;
6060+ blocked_path;
6161+ }
6262+6363+ let initialize ?hooks () =
6464+ Initialize { subtype = `Initialize; hooks }
6565+6666+ let set_permission_mode ~mode =
6767+ Set_permission_mode { subtype = `Set_permission_mode; mode }
6868+6969+ let hook_callback ~callback_id ~input ?tool_use_id () =
7070+ Hook_callback {
7171+ subtype = `Hook_callback;
7272+ callback_id;
7373+ input;
7474+ tool_use_id;
7575+ }
7676+7777+ let mcp_message ~server_name ~message =
7878+ Mcp_message {
7979+ subtype = `Mcp_message;
8080+ server_name;
8181+ message;
8282+ }
8383+8484+ let to_json = function
8585+ | Interrupt _ ->
8686+ `O [("subtype", `String "interrupt")]
8787+ | Permission p ->
8888+ let fields = [
8989+ ("subtype", `String "can_use_tool");
9090+ ("tool_name", `String p.tool_name);
9191+ ("input", p.input);
9292+ ] in
9393+ let fields = match p.permission_suggestions with
9494+ | Some suggestions ->
9595+ ("permission_suggestions",
9696+ `A (List.map Permissions.Update.to_json suggestions)) :: fields
9797+ | None -> fields
9898+ in
9999+ let fields = match p.blocked_path with
100100+ | Some path -> ("blocked_path", `String path) :: fields
101101+ | None -> fields
102102+ in
103103+ `O fields
104104+ | Initialize i ->
105105+ let fields = [("subtype", `String "initialize")] in
106106+ let fields = match i.hooks with
107107+ | Some hooks ->
108108+ ("hooks", `O hooks) :: fields
109109+ | None -> fields
110110+ in
111111+ `O fields
112112+ | Set_permission_mode s ->
113113+ `O [
114114+ ("subtype", `String "set_permission_mode");
115115+ ("mode", Permissions.Mode.to_json s.mode);
116116+ ]
117117+ | Hook_callback h ->
118118+ let fields = [
119119+ ("subtype", `String "hook_callback");
120120+ ("callback_id", `String h.callback_id);
121121+ ("input", h.input);
122122+ ] in
123123+ let fields = match h.tool_use_id with
124124+ | Some id -> ("tool_use_id", `String id) :: fields
125125+ | None -> fields
126126+ in
127127+ `O fields
128128+ | Mcp_message m ->
129129+ `O [
130130+ ("subtype", `String "mcp_message");
131131+ ("server_name", `String m.server_name);
132132+ ("message", m.message);
133133+ ]
134134+135135+ let of_json = function
136136+ | `O fields ->
137137+ let subtype = JU.assoc_string "subtype" fields in
138138+ (match subtype with
139139+ | "interrupt" ->
140140+ Interrupt { subtype = `Interrupt }
141141+ | "can_use_tool" ->
142142+ let tool_name = JU.assoc_string "tool_name" fields in
143143+ let input = List.assoc "input" fields in
144144+ let permission_suggestions =
145145+ match List.assoc_opt "permission_suggestions" fields with
146146+ | Some (`A lst) ->
147147+ Some (List.map Permissions.Update.of_json lst)
148148+ | _ -> None
149149+ in
150150+ let blocked_path = JU.assoc_string_opt "blocked_path" fields in
151151+ Permission {
152152+ subtype = `Can_use_tool;
153153+ tool_name;
154154+ input;
155155+ permission_suggestions;
156156+ blocked_path;
157157+ }
158158+ | "initialize" ->
159159+ let hooks =
160160+ match List.assoc_opt "hooks" fields with
161161+ | Some (`O hooks) -> Some hooks
162162+ | _ -> None
163163+ in
164164+ Initialize { subtype = `Initialize; hooks }
165165+ | "set_permission_mode" ->
166166+ let mode = List.assoc "mode" fields |> Permissions.Mode.of_json in
167167+ Set_permission_mode { subtype = `Set_permission_mode; mode }
168168+ | "hook_callback" ->
169169+ let callback_id = JU.assoc_string "callback_id" fields in
170170+ let input = List.assoc "input" fields in
171171+ let tool_use_id = JU.assoc_string_opt "tool_use_id" fields in
172172+ Hook_callback {
173173+ subtype = `Hook_callback;
174174+ callback_id;
175175+ input;
176176+ tool_use_id;
177177+ }
178178+ | "mcp_message" ->
179179+ let server_name = JU.assoc_string "server_name" fields in
180180+ let message = List.assoc "message" fields in
181181+ Mcp_message {
182182+ subtype = `Mcp_message;
183183+ server_name;
184184+ message;
185185+ }
186186+ | _ -> raise (Invalid_argument ("Unknown request subtype: " ^ subtype)))
187187+ | _ -> raise (Invalid_argument "Request.of_json: expected object")
188188+189189+ let pp fmt = function
190190+ | Interrupt _ ->
191191+ Fmt.pf fmt "@[<2>Interrupt@]"
192192+ | Permission p ->
193193+ Fmt.pf fmt "@[<2>Permission@ { tool = %S;@ blocked_path = %a }@]"
194194+ p.tool_name Fmt.(option string) p.blocked_path
195195+ | Initialize i ->
196196+ Fmt.pf fmt "@[<2>Initialize@ { hooks = %s }@]"
197197+ (if Option.is_some i.hooks then "present" else "none")
198198+ | Set_permission_mode s ->
199199+ Fmt.pf fmt "@[<2>SetPermissionMode@ { mode = %a }@]"
200200+ Permissions.Mode.pp s.mode
201201+ | Hook_callback h ->
202202+ Fmt.pf fmt "@[<2>HookCallback@ { id = %S;@ tool_use_id = %a }@]"
203203+ h.callback_id Fmt.(option string) h.tool_use_id
204204+ | Mcp_message m ->
205205+ Fmt.pf fmt "@[<2>McpMessage@ { server = %S }@]"
206206+ m.server_name
207207+end
208208+209209+module Response = struct
210210+ type success = {
211211+ subtype : [`Success];
212212+ request_id : string;
213213+ response : value option;
214214+ }
215215+216216+ type error = {
217217+ subtype : [`Error];
218218+ request_id : string;
219219+ error : string;
220220+ }
221221+222222+ type t =
223223+ | Success of success
224224+ | Error of error
225225+226226+ let success ~request_id ?response () =
227227+ Success {
228228+ subtype = `Success;
229229+ request_id;
230230+ response;
231231+ }
232232+233233+ let error ~request_id ~error =
234234+ Error {
235235+ subtype = `Error;
236236+ request_id;
237237+ error;
238238+ }
239239+240240+ let to_json = function
241241+ | Success s ->
242242+ let fields = [
243243+ ("subtype", `String "success");
244244+ ("request_id", `String s.request_id);
245245+ ] in
246246+ let fields = match s.response with
247247+ | Some resp -> ("response", resp) :: fields
248248+ | None -> fields
249249+ in
250250+ `O fields
251251+ | Error e ->
252252+ `O [
253253+ ("subtype", `String "error");
254254+ ("request_id", `String e.request_id);
255255+ ("error", `String e.error);
256256+ ]
257257+258258+ let of_json = function
259259+ | `O fields ->
260260+ let subtype = JU.assoc_string "subtype" fields in
261261+ let request_id = JU.assoc_string "request_id" fields in
262262+ (match subtype with
263263+ | "success" ->
264264+ let response = List.assoc_opt "response" fields in
265265+ Success {
266266+ subtype = `Success;
267267+ request_id;
268268+ response;
269269+ }
270270+ | "error" ->
271271+ let error = JU.assoc_string "error" fields in
272272+ Error {
273273+ subtype = `Error;
274274+ request_id;
275275+ error;
276276+ }
277277+ | _ -> raise (Invalid_argument ("Unknown response subtype: " ^ subtype)))
278278+ | _ -> raise (Invalid_argument "Response.of_json: expected object")
279279+280280+ let pp fmt = function
281281+ | Success s ->
282282+ Fmt.pf fmt "@[<2>Success@ { request_id = %S;@ response = %s }@]"
283283+ s.request_id (if Option.is_some s.response then "present" else "none")
284284+ | Error e ->
285285+ Fmt.pf fmt "@[<2>Error@ { request_id = %S;@ error = %S }@]"
286286+ e.request_id e.error
287287+end
288288+289289+type control_request = {
290290+ type_ : [`Control_request];
291291+ request_id : string;
292292+ request : Request.t;
293293+}
294294+295295+type control_response = {
296296+ type_ : [`Control_response];
297297+ response : Response.t;
298298+}
299299+300300+type t =
301301+ | Request of control_request
302302+ | Response of control_response
303303+304304+let create_request ~request_id ~request =
305305+ Request {
306306+ type_ = `Control_request;
307307+ request_id;
308308+ request;
309309+ }
310310+311311+let create_response ~response =
312312+ Response {
313313+ type_ = `Control_response;
314314+ response;
315315+ }
316316+317317+let to_json = function
318318+ | Request r ->
319319+ `O [
320320+ ("type", `String "control_request");
321321+ ("request_id", `String r.request_id);
322322+ ("request", Request.to_json r.request);
323323+ ]
324324+ | Response r ->
325325+ `O [
326326+ ("type", `String "control_response");
327327+ ("response", Response.to_json r.response);
328328+ ]
329329+330330+let of_json = function
331331+ | `O fields ->
332332+ let type_ = JU.assoc_string "type" fields in
333333+ (match type_ with
334334+ | "control_request" ->
335335+ let request_id = JU.assoc_string "request_id" fields in
336336+ let request = List.assoc "request" fields |> Request.of_json in
337337+ Request {
338338+ type_ = `Control_request;
339339+ request_id;
340340+ request;
341341+ }
342342+ | "control_response" ->
343343+ let response = List.assoc "response" fields |> Response.of_json in
344344+ Response {
345345+ type_ = `Control_response;
346346+ response;
347347+ }
348348+ | _ -> raise (Invalid_argument ("Unknown control type: " ^ type_)))
349349+ | _ -> raise (Invalid_argument "of_json: expected object")
350350+351351+let pp fmt = function
352352+ | Request r ->
353353+ Fmt.pf fmt "@[<2>ControlRequest@ { id = %S;@ request = %a }@]"
354354+ r.request_id Request.pp r.request
355355+ | Response r ->
356356+ Fmt.pf fmt "@[<2>ControlResponse@ { %a }@]"
357357+ Response.pp r.response
358358+359359+let log_request req =
360360+ Log.debug (fun m -> m "SDK control request: %a" Request.pp req)
361361+362362+let log_response resp =
363363+ Log.debug (fun m -> m "SDK control response: %a" Response.pp resp)
+188
claudeio/lib/sdk_control.mli
···11+(** SDK Control Protocol for Claude.
22+33+ This module defines the typed SDK control protocol for communication
44+ between the SDK and Claude, including request and response types. *)
55+66+open Ezjsonm
77+88+(** The log source for SDK control operations *)
99+val src : Logs.Src.t
1010+1111+(** {1 Request Types} *)
1212+1313+module Request : sig
1414+ (** SDK control request types. *)
1515+1616+ type interrupt = {
1717+ subtype : [`Interrupt];
1818+ }
1919+ (** Interrupt request to stop execution. *)
2020+2121+ type permission = {
2222+ subtype : [`Can_use_tool];
2323+ tool_name : string;
2424+ input : value;
2525+ permission_suggestions : Permissions.Update.t list option;
2626+ blocked_path : string option;
2727+ }
2828+ (** Permission request for tool usage. *)
2929+3030+ type initialize = {
3131+ subtype : [`Initialize];
3232+ hooks : (string * value) list option; (* Hook event to configuration *)
3333+ }
3434+ (** Initialize request with optional hook configuration. *)
3535+3636+ type set_permission_mode = {
3737+ subtype : [`Set_permission_mode];
3838+ mode : Permissions.Mode.t;
3939+ }
4040+ (** Request to change permission mode. *)
4141+4242+ type hook_callback = {
4343+ subtype : [`Hook_callback];
4444+ callback_id : string;
4545+ input : value;
4646+ tool_use_id : string option;
4747+ }
4848+ (** Hook callback request. *)
4949+5050+ type mcp_message = {
5151+ subtype : [`Mcp_message];
5252+ server_name : string;
5353+ message : value;
5454+ }
5555+ (** MCP server message request. *)
5656+5757+ type t =
5858+ | Interrupt of interrupt
5959+ | Permission of permission
6060+ | Initialize of initialize
6161+ | Set_permission_mode of set_permission_mode
6262+ | Hook_callback of hook_callback
6363+ | Mcp_message of mcp_message
6464+ (** The type of SDK control requests. *)
6565+6666+ val interrupt : unit -> t
6767+ (** [interrupt ()] creates an interrupt request. *)
6868+6969+ val permission :
7070+ tool_name:string ->
7171+ input:value ->
7272+ ?permission_suggestions:Permissions.Update.t list ->
7373+ ?blocked_path:string ->
7474+ unit -> t
7575+ (** [permission ~tool_name ~input ?permission_suggestions ?blocked_path ()]
7676+ creates a permission request. *)
7777+7878+ val initialize : ?hooks:(string * value) list -> unit -> t
7979+ (** [initialize ?hooks ()] creates an initialize request. *)
8080+8181+ val set_permission_mode : mode:Permissions.Mode.t -> t
8282+ (** [set_permission_mode ~mode] creates a permission mode change request. *)
8383+8484+ val hook_callback :
8585+ callback_id:string ->
8686+ input:value ->
8787+ ?tool_use_id:string ->
8888+ unit -> t
8989+ (** [hook_callback ~callback_id ~input ?tool_use_id ()] creates a hook callback request. *)
9090+9191+ val mcp_message : server_name:string -> message:value -> t
9292+ (** [mcp_message ~server_name ~message] creates an MCP message request. *)
9393+9494+ val to_json : t -> value
9595+ (** [to_json t] converts a request to JSON. *)
9696+9797+ val of_json : value -> t
9898+ (** [of_json json] parses a request from JSON.
9999+ @raise Invalid_argument if the JSON is not a valid request. *)
100100+101101+ val pp : Format.formatter -> t -> unit
102102+ (** [pp fmt t] pretty-prints the request. *)
103103+end
104104+105105+(** {1 Response Types} *)
106106+107107+module Response : sig
108108+ (** SDK control response types. *)
109109+110110+ type success = {
111111+ subtype : [`Success];
112112+ request_id : string;
113113+ response : value option;
114114+ }
115115+ (** Successful response. *)
116116+117117+ type error = {
118118+ subtype : [`Error];
119119+ request_id : string;
120120+ error : string;
121121+ }
122122+ (** Error response. *)
123123+124124+ type t =
125125+ | Success of success
126126+ | Error of error
127127+ (** The type of SDK control responses. *)
128128+129129+ val success : request_id:string -> ?response:value -> unit -> t
130130+ (** [success ~request_id ?response ()] creates a success response. *)
131131+132132+ val error : request_id:string -> error:string -> t
133133+ (** [error ~request_id ~error] creates an error response. *)
134134+135135+ val to_json : t -> value
136136+ (** [to_json t] converts a response to JSON. *)
137137+138138+ val of_json : value -> t
139139+ (** [of_json json] parses a response from JSON.
140140+ @raise Invalid_argument if the JSON is not a valid response. *)
141141+142142+ val pp : Format.formatter -> t -> unit
143143+ (** [pp fmt t] pretty-prints the response. *)
144144+end
145145+146146+(** {1 Control Messages} *)
147147+148148+type control_request = {
149149+ type_ : [`Control_request];
150150+ request_id : string;
151151+ request : Request.t;
152152+}
153153+(** Control request message. *)
154154+155155+type control_response = {
156156+ type_ : [`Control_response];
157157+ response : Response.t;
158158+}
159159+(** Control response message. *)
160160+161161+type t =
162162+ | Request of control_request
163163+ | Response of control_response
164164+(** The type of SDK control messages. *)
165165+166166+val create_request : request_id:string -> request:Request.t -> t
167167+(** [create_request ~request_id ~request] creates a control request message. *)
168168+169169+val create_response : response:Response.t -> t
170170+(** [create_response ~response] creates a control response message. *)
171171+172172+val to_json : t -> value
173173+(** [to_json t] converts a control message to JSON. *)
174174+175175+val of_json : value -> t
176176+(** [of_json json] parses a control message from JSON.
177177+ @raise Invalid_argument if the JSON is not a valid control message. *)
178178+179179+val pp : Format.formatter -> t -> unit
180180+(** [pp fmt t] pretty-prints the control message. *)
181181+182182+(** {1 Logging} *)
183183+184184+val log_request : Request.t -> unit
185185+(** [log_request req] logs an SDK control request. *)
186186+187187+val log_response : Response.t -> unit
188188+(** [log_response resp] logs an SDK control response. *)