OCaml Claude SDK using Eio and Jsont
at main 299 lines 9.3 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** Messages exchanged with Claude. Opaque types. 7 8 This module provides opaque message types that wrap the proto types but hide 9 the unknown fields and wire format details from the public API. *) 10 11val src : Logs.Src.t 12(** The log source for message operations *) 13 14(** {1 User Messages} *) 15 16module User : sig 17 (** Messages sent by the user. *) 18 19 type t 20 (** The type of user messages (opaque). *) 21 22 val of_string : string -> t 23 (** [of_string s] creates a user message with simple text content. *) 24 25 val of_blocks : Content_block.t list -> t 26 (** [of_blocks blocks] creates a user message with content blocks. *) 27 28 val with_tool_result : 29 tool_use_id:string -> content:Jsont.json -> ?is_error:bool -> unit -> t 30 (** [with_tool_result ~tool_use_id ~content ?is_error ()] creates a user 31 message containing a tool result. Content can be a string or array. *) 32 33 val as_text : t -> string option 34 (** [as_text t] returns the text content if the message is a simple string, 35 None otherwise. *) 36 37 val blocks : t -> Content_block.t list 38 (** [blocks t] returns the content blocks, or a single text block if it's a 39 string message. *) 40 41 (** {1 Internal - for lib use only} *) 42 43 val of_proto : Proto.Message.User.t -> t 44 (** [of_proto proto] wraps a proto user message. *) 45 46 val to_proto : t -> Proto.Message.User.t 47 (** [to_proto t] extracts the proto user message. *) 48 49 val incoming_jsont : t Jsont.t 50 (** Internal codec for parsing incoming messages. *) 51 52 val to_json : t -> Jsont.json 53 (** Internal conversion to JSON for wire format. *) 54end 55 56(** {1 Assistant Messages} *) 57 58module Assistant : sig 59 (** Messages from Claude assistant. *) 60 61 type error = 62 [ `Authentication_failed (** Authentication with Claude API failed *) 63 | `Billing_error (** Billing or account issue *) 64 | `Rate_limit (** Rate limit exceeded *) 65 | `Invalid_request (** Request was invalid *) 66 | `Server_error (** Internal server error *) 67 | `Unknown (** Unknown error type *) ] 68 (** The type of assistant message errors based on Python SDK error types. *) 69 70 type t 71 (** The type of assistant messages (opaque). *) 72 73 val content : t -> Content_block.t list 74 (** [content t] returns the content blocks of the assistant message. *) 75 76 val model : t -> string 77 (** [model t] returns the model identifier. *) 78 79 val error : t -> error option 80 (** [error t] returns the optional error that occurred during message 81 generation. *) 82 83 (** {2 Convenience accessors} *) 84 85 val text_blocks : t -> string list 86 (** [text_blocks t] extracts all text content from the message. *) 87 88 val tool_uses : t -> Content_block.Tool_use.t list 89 (** [tool_uses t] extracts all tool use blocks from the message. *) 90 91 val thinking_blocks : t -> Content_block.Thinking.t list 92 (** [thinking_blocks t] extracts all thinking blocks from the message. *) 93 94 val combined_text : t -> string 95 (** [combined_text t] concatenates all text blocks into a single string. *) 96 97 val has_tool_use : t -> bool 98 (** [has_tool_use t] returns true if the message contains any tool use blocks. 99 *) 100 101 (** {1 Internal - for lib use only} *) 102 103 val of_proto : Proto.Message.Assistant.t -> t 104 (** [of_proto proto] wraps a proto assistant message. *) 105 106 val to_proto : t -> Proto.Message.Assistant.t 107 (** [to_proto t] extracts the proto assistant message. *) 108 109 val incoming_jsont : t Jsont.t 110 (** Internal codec for parsing incoming messages. *) 111 112 val to_json : t -> Jsont.json 113 (** Internal conversion to JSON for wire format. *) 114end 115 116(** {1 System Messages} *) 117 118module System : sig 119 (** System control and status messages. *) 120 121 type t 122 (** The type of system messages (opaque). *) 123 124 val is_init : t -> bool 125 (** [is_init t] returns true if the message is an init message. *) 126 127 val is_error : t -> bool 128 (** [is_error t] returns true if the message is an error message. *) 129 130 val session_id : t -> string option 131 (** [session_id t] returns session_id from Init, None otherwise. *) 132 133 val model : t -> string option 134 (** [model t] returns model from Init, None otherwise. *) 135 136 val cwd : t -> string option 137 (** [cwd t] returns cwd from Init, None otherwise. *) 138 139 val error_message : t -> string option 140 (** [error_message t] returns error from Error, None otherwise. *) 141 142 (** {1 Internal - for lib use only} *) 143 144 val of_proto : Proto.Message.System.t -> t 145 (** [of_proto proto] wraps a proto system message. *) 146 147 val to_proto : t -> Proto.Message.System.t 148 (** [to_proto t] extracts the proto system message. *) 149 150 val jsont : t Jsont.t 151 (** Internal codec for wire format. *) 152 153 val to_json : t -> Jsont.json 154 (** Internal conversion to JSON for wire format. *) 155end 156 157(** {1 Result Messages} *) 158 159module Result : sig 160 (** Final result messages with metadata about the conversation. *) 161 162 module Usage : sig 163 (** Usage statistics for API calls. *) 164 165 type t 166 (** Type for usage statistics (opaque). *) 167 168 val input_tokens : t -> int option 169 (** [input_tokens t] returns the number of input tokens used. *) 170 171 val output_tokens : t -> int option 172 (** [output_tokens t] returns the number of output tokens generated. *) 173 174 val total_tokens : t -> int option 175 (** [total_tokens t] returns the total number of tokens. *) 176 177 val cache_creation_input_tokens : t -> int option 178 (** [cache_creation_input_tokens t] returns cache creation input tokens. *) 179 180 val cache_read_input_tokens : t -> int option 181 (** [cache_read_input_tokens t] returns cache read input tokens. *) 182 183 (** {1 Internal - for lib use only} *) 184 185 val of_proto : Proto.Message.Result.Usage.t -> t 186 (** [of_proto proto] wraps a proto usage object. *) 187 end 188 189 type t 190 (** The type of result messages (opaque). *) 191 192 val duration_ms : t -> int 193 (** [duration_ms t] returns the total duration in milliseconds. *) 194 195 val duration_api_ms : t -> int 196 (** [duration_api_ms t] returns the API duration in milliseconds. *) 197 198 val is_error : t -> bool 199 (** [is_error t] returns whether this result represents an error. *) 200 201 val num_turns : t -> int 202 (** [num_turns t] returns the number of conversation turns. *) 203 204 val session_id : t -> string 205 (** [session_id t] returns the session identifier. *) 206 207 val total_cost_usd : t -> float option 208 (** [total_cost_usd t] returns the optional total cost in USD. *) 209 210 val usage : t -> Usage.t option 211 (** [usage t] returns the optional usage statistics. *) 212 213 val result_text : t -> string option 214 (** [result_text t] returns the optional result string. *) 215 216 val structured_output : t -> Jsont.json option 217 (** [structured_output t] returns the optional structured JSON output. *) 218 219 (** {1 Internal - for lib use only} *) 220 221 val of_proto : Proto.Message.Result.t -> t 222 (** [of_proto proto] wraps a proto result message. *) 223 224 val to_proto : t -> Proto.Message.Result.t 225 (** [to_proto t] extracts the proto result message. *) 226 227 val jsont : t Jsont.t 228 (** Internal codec for wire format. *) 229 230 val to_json : t -> Jsont.json 231 (** Internal conversion to JSON for wire format. *) 232end 233 234(** {1 Message Union Type} *) 235 236type t = 237 | User of User.t 238 | Assistant of Assistant.t 239 | System of System.t 240 | Result of Result.t 241 (** The type of messages, which can be user, assistant, system, or result. 242 *) 243 244val of_proto : Proto.Message.t -> t 245(** [of_proto proto] converts a proto message to a lib message. *) 246 247val to_proto : t -> Proto.Message.t 248(** [to_proto t] converts a lib message to a proto message. *) 249 250(** {1 Internal - wire format conversion} *) 251 252val to_json : t -> Jsont.json 253(** [to_json t] converts any message to its JSON wire format representation. *) 254 255(** {1 Convenience Constructors} *) 256 257val user_string : string -> t 258(** [user_string s] creates a user message with text content. *) 259 260val user_blocks : Content_block.t list -> t 261(** [user_blocks blocks] creates a user message with content blocks. *) 262 263(** {1 Message Analysis} *) 264 265val is_user : t -> bool 266(** [is_user t] returns true if the message is from a user. *) 267 268val is_assistant : t -> bool 269(** [is_assistant t] returns true if the message is from the assistant. *) 270 271val is_system : t -> bool 272(** [is_system t] returns true if the message is a system message. *) 273 274val is_result : t -> bool 275(** [is_result t] returns true if the message is a result message. *) 276 277val is_error : t -> bool 278(** [is_error t] returns true if the message represents an error. *) 279 280val extract_text : t -> string option 281(** [extract_text t] attempts to extract text content from any message type. *) 282 283val extract_tool_uses : t -> Content_block.Tool_use.t list 284(** [extract_tool_uses t] extracts tool use blocks from assistant messages. *) 285 286val get_session_id : t -> string option 287(** [get_session_id t] extracts the session ID from system or result messages. 288*) 289 290(** {1 Logging} *) 291 292val pp : Format.formatter -> t -> unit 293(** [pp fmt t] pretty-prints any message. *) 294 295val log_received : t -> unit 296(** [log_received t] logs that a message was received. *) 297 298val log_sending : t -> unit 299(** [log_sending t] logs that a message is being sent. *)