OCaml Claude SDK using Eio and Jsont

fix tool callbacks

+29 -23
+7 -6
lib/client.mli
··· 81 81 {!Advanced.send_message} instead. *) 82 82 83 83 val respond_to_tool : 84 - t -> tool_use_id:string -> content:string -> ?is_error:bool -> unit -> unit 84 + t -> tool_use_id:string -> content:Jsont.json -> ?is_error:bool -> unit -> unit 85 85 (** [respond_to_tool t ~tool_use_id ~content ?is_error ()] responds to a tool 86 86 use request. 87 87 88 88 @param tool_use_id The ID from the {!Response.Tool_use.t} event 89 - @param content The result content (can be any string) 89 + @param content The result content (can be a string or array of content blocks) 90 90 @param is_error Whether this is an error response (default: false) *) 91 91 92 - val respond_to_tools : t -> (string * string * bool option) list -> unit 92 + val respond_to_tools : t -> (string * Jsont.json * bool option) list -> unit 93 93 (** [respond_to_tools t responses] responds to multiple tool use requests at 94 94 once. 95 95 96 - Each tuple is [(tool_use_id, content, is_error option)]. 96 + Each tuple is [(tool_use_id, content, is_error option)] where content 97 + can be a string or array of content blocks. 97 98 98 99 Example: 99 100 {[ 100 101 Client.respond_to_tools client 101 102 [ 102 - ("tool_use_123", "Success", None); 103 - ("tool_use_456", "Error occurred", Some true); 103 + ("tool_use_123", Jsont.string "Success", None); 104 + ("tool_use_456", Jsont.string "Error occurred", Some true); 104 105 ] 105 106 ]} *) 106 107
+4 -4
lib/content_block.mli
··· 68 68 val tool_use_id : t -> string 69 69 (** [tool_use_id t] returns the ID of the corresponding tool use. *) 70 70 71 - val content : t -> string option 72 - (** [content t] returns the optional result content. *) 71 + val content : t -> Jsont.json option 72 + (** [content t] returns the optional result content as raw JSON. *) 73 73 74 74 val is_error : t -> bool option 75 75 (** [is_error t] returns whether this result represents an error. *) ··· 125 125 (** [tool_use ~id ~name ~input] creates a tool use content block. *) 126 126 127 127 val tool_result : 128 - tool_use_id:string -> ?content:string -> ?is_error:bool -> unit -> t 128 + tool_use_id:string -> ?content:Jsont.json -> ?is_error:bool -> unit -> t 129 129 (** [tool_result ~tool_use_id ?content ?is_error ()] creates a tool result 130 - content block. *) 130 + content block. Content can be a string or array. *) 131 131 132 132 val thinking : thinking:string -> signature:string -> t 133 133 (** [thinking ~thinking ~signature] creates a thinking content block. *)
+2 -2
lib/message.mli
··· 26 26 (** [of_blocks blocks] creates a user message with content blocks. *) 27 27 28 28 val with_tool_result : 29 - tool_use_id:string -> content:string -> ?is_error:bool -> unit -> t 29 + tool_use_id:string -> content:Jsont.json -> ?is_error:bool -> unit -> t 30 30 (** [with_tool_result ~tool_use_id ~content ?is_error ()] creates a user 31 - message containing a tool result. *) 31 + message containing a tool result. Content can be a string or array. *) 32 32 33 33 val as_text : t -> string option 34 34 (** [as_text t] returns the text content if the message is a simple string,
+2 -2
proto/content_block.ml
··· 40 40 module Tool_result = struct 41 41 type t = { 42 42 tool_use_id : string; 43 - content : string option; 43 + content : Jsont.json option; 44 44 is_error : bool option; 45 45 unknown : Unknown.t; 46 46 } ··· 59 59 let jsont : t Jsont.t = 60 60 Jsont.Object.map ~kind:"Tool_result" make 61 61 |> Jsont.Object.mem "tool_use_id" Jsont.string ~enc:tool_use_id 62 - |> Jsont.Object.opt_mem "content" Jsont.string ~enc:content 62 + |> Jsont.Object.opt_mem "content" Jsont.json ~enc:content 63 63 |> Jsont.Object.opt_mem "is_error" Jsont.bool ~enc:is_error 64 64 |> Jsont.Object.keep_unknown Unknown.mems ~enc:unknown 65 65 |> Jsont.Object.finish
+6 -6
proto/content_block.mli
··· 78 78 Use [Jsont.pp_value jsont ()] for pretty-printing. *) 79 79 80 80 val create : 81 - tool_use_id:string -> ?content:string -> ?is_error:bool -> unit -> t 81 + tool_use_id:string -> ?content:Jsont.json -> ?is_error:bool -> unit -> t 82 82 (** [create ~tool_use_id ?content ?is_error ()] creates a new tool result 83 83 block. 84 84 @param tool_use_id The ID of the corresponding tool use block 85 - @param content Optional result content 85 + @param content Optional result content (can be string or array of content blocks) 86 86 @param is_error Whether the tool execution resulted in an error *) 87 87 88 88 val tool_use_id : t -> string 89 89 (** [tool_use_id t] returns the ID of the corresponding tool use. *) 90 90 91 - val content : t -> string option 92 - (** [content t] returns the optional result content. *) 91 + val content : t -> Jsont.json option 92 + (** [content t] returns the optional result content as raw JSON. *) 93 93 94 94 val is_error : t -> bool option 95 95 (** [is_error t] returns whether this result represents an error. *) ··· 148 148 (** [tool_use ~id ~name ~input] creates a tool use content block. *) 149 149 150 150 val tool_result : 151 - tool_use_id:string -> ?content:string -> ?is_error:bool -> unit -> t 151 + tool_use_id:string -> ?content:Jsont.json -> ?is_error:bool -> unit -> t 152 152 (** [tool_result ~tool_use_id ?content ?is_error ()] creates a tool result 153 - content block. *) 153 + content block. Content can be a string or an array of content blocks. *) 154 154 155 155 val thinking : thinking:string -> signature:string -> t 156 156 (** [thinking ~thinking ~signature] creates a thinking content block. *)
+2 -2
proto/message.mli
··· 42 42 (** [create_blocks blocks] creates a user message with content blocks. *) 43 43 44 44 val create_with_tool_result : 45 - tool_use_id:string -> content:string -> ?is_error:bool -> unit -> t 45 + tool_use_id:string -> content:Jsont.json -> ?is_error:bool -> unit -> t 46 46 (** [create_with_tool_result ~tool_use_id ~content ?is_error ()] creates a 47 - user message containing a tool result. *) 47 + user message containing a tool result. Content can be a string or array. *) 48 48 49 49 val content : t -> content 50 50 (** [content t] returns the content of the user message. *)
+6 -1
test/simple_permission_test.ml
··· 66 66 if is_error then begin 67 67 Log.app (fun m -> m "\n⚠️ Tool result error for %s:" tool_use_id); 68 68 match Claude.Content_block.Tool_result.content r with 69 - | Some s -> Log.app (fun m -> m " %s" s) 69 + | Some json -> 70 + let s = match Jsont_bytesrw.encode_string' Jsont.json json with 71 + | Ok str -> str 72 + | Error _ -> "<encoding error>" 73 + in 74 + Log.app (fun m -> m " %s" s) 70 75 | None -> () 71 76 end 72 77 | Claude.Response.Complete result ->