My agentic slop goes here. Not intended for anyone else!
1(** Messages exchanged with Claude.
2
3 This module defines the various types of messages that can be sent to and
4 received from Claude, including user input, assistant responses, system
5 messages, and result metadata. *)
6
7(** The log source for message operations *)
8val src : Logs.Src.t
9
10(** {1 User Messages} *)
11
12module User : sig
13 (** Messages sent by the user. *)
14
15 type content =
16 | String of string (** Simple text message *)
17 | Blocks of Content_block.t list (** Complex message with multiple content blocks *)
18 (** The content of a user message. *)
19
20 type t
21 (** The type of user messages. *)
22
23 val jsont : t Jsont.t
24 (** [jsont] is the Jsont codec for user messages. *)
25
26 val create_string : string -> t
27 (** [create_string s] creates a user message with simple text content. *)
28
29 val create_blocks : Content_block.t list -> t
30 (** [create_blocks blocks] creates a user message with content blocks. *)
31
32 val create_with_tool_result :
33 tool_use_id:string ->
34 content:string ->
35 ?is_error:bool ->
36 unit -> t
37 (** [create_with_tool_result ~tool_use_id ~content ?is_error ()] creates a user
38 message containing a tool result. *)
39
40 val create_mixed : text:string option -> tool_results:(string * string * bool option) list -> t
41 (** [create_mixed ?text ~tool_results] creates a user message with optional text
42 and tool results. Each tool result is (tool_use_id, content, is_error). *)
43
44 val content : t -> content
45 (** [content t] returns the content of the user message. *)
46
47 val unknown : t -> Unknown.t
48 (** [unknown t] returns the unknown fields preserved from JSON. *)
49
50 val as_text : t -> string option
51 (** [as_text t] returns the text content if the message is a simple string, None otherwise. *)
52
53 val get_blocks : t -> Content_block.t list
54 (** [get_blocks t] returns the content blocks, or a single text block if it's a string message. *)
55
56 val to_json : t -> Jsont.json
57 (** [to_json t] converts the user message to its JSON representation. *)
58
59 val of_json : Jsont.json -> t
60 (** [of_json json] parses a user message from JSON.
61 @raise Invalid_argument if the JSON is not a valid user message. *)
62
63 val pp : Format.formatter -> t -> unit
64 (** [pp fmt t] pretty-prints the user message. *)
65end
66
67(** {1 Assistant Messages} *)
68
69module Assistant : sig
70 (** Messages from Claude assistant. *)
71
72 type error = [
73 | `Authentication_failed (** Authentication with Claude API failed *)
74 | `Billing_error (** Billing or account issue *)
75 | `Rate_limit (** Rate limit exceeded *)
76 | `Invalid_request (** Request was invalid *)
77 | `Server_error (** Internal server error *)
78 | `Unknown (** Unknown error type *)
79 ]
80 (** The type of assistant message errors based on Python SDK error types. *)
81
82 val error_to_string : error -> string
83 (** [error_to_string err] converts an error to its string representation. *)
84
85 val error_of_string : string -> error
86 (** [error_of_string s] parses an error string. Unknown strings become [`Unknown]. *)
87
88 type t
89 (** The type of assistant messages. *)
90
91 val jsont : t Jsont.t
92 (** [jsont] is the Jsont codec for assistant messages. *)
93
94 val create : content:Content_block.t list -> model:string -> ?error:error -> unit -> t
95 (** [create ~content ~model ?error ()] creates an assistant message.
96 @param content List of content blocks in the response
97 @param model The model identifier used for the response
98 @param error Optional error that occurred during message generation *)
99
100 val content : t -> Content_block.t list
101 (** [content t] returns the content blocks of the assistant message. *)
102
103 val model : t -> string
104 (** [model t] returns the model identifier. *)
105
106 val error : t -> error option
107 (** [error t] returns the optional error that occurred during message generation. *)
108
109 val unknown : t -> Unknown.t
110 (** [unknown t] returns the unknown fields preserved from JSON. *)
111
112 val get_text_blocks : t -> string list
113 (** [get_text_blocks t] extracts all text content from the message. *)
114
115 val get_tool_uses : t -> Content_block.Tool_use.t list
116 (** [get_tool_uses t] extracts all tool use blocks from the message. *)
117
118 val get_thinking : t -> Content_block.Thinking.t list
119 (** [get_thinking t] extracts all thinking blocks from the message. *)
120
121 val has_tool_use : t -> bool
122 (** [has_tool_use t] returns true if the message contains any tool use blocks. *)
123
124 val combined_text : t -> string
125 (** [combined_text t] concatenates all text blocks into a single string. *)
126
127 val to_json : t -> Jsont.json
128 (** [to_json t] converts the assistant message to its JSON representation. *)
129
130 val of_json : Jsont.json -> t
131 (** [of_json json] parses an assistant message from JSON.
132 @raise Invalid_argument if the JSON is not a valid assistant message. *)
133
134 val pp : Format.formatter -> t -> unit
135 (** [pp fmt t] pretty-prints the assistant message. *)
136end
137
138(** {1 System Messages} *)
139
140module System : sig
141 (** System control and status messages.
142
143 System messages use a discriminated union on the "subtype" field:
144 - "init": Session initialization with session_id, model, cwd
145 - "error": Error messages with error string
146 - Other subtypes are preserved as [Other] *)
147
148 type init = {
149 session_id : string option;
150 model : string option;
151 cwd : string option;
152 unknown : Unknown.t;
153 }
154 (** Init message fields. *)
155
156 type error = {
157 error : string;
158 unknown : Unknown.t;
159 }
160 (** Error message fields. *)
161
162 type other = {
163 subtype : string;
164 unknown : Unknown.t;
165 }
166 (** Unknown subtype fields. *)
167
168 type t =
169 | Init of init
170 | Error of error
171 | Other of other
172 (** The type of system messages. *)
173
174 val jsont : t Jsont.t
175 (** [jsont] is the Jsont codec for system messages. *)
176
177 (** {2 Constructors} *)
178
179 val init : ?session_id:string -> ?model:string -> ?cwd:string -> unit -> t
180 (** [init ?session_id ?model ?cwd ()] creates an init message. *)
181
182 val error : error:string -> t
183 (** [error ~error] creates an error message. *)
184
185 val other : subtype:string -> t
186 (** [other ~subtype] creates a message with unknown subtype. *)
187
188 (** {2 Accessors} *)
189
190 val session_id : t -> string option
191 (** [session_id t] returns session_id from Init, None otherwise. *)
192
193 val model : t -> string option
194 (** [model t] returns model from Init, None otherwise. *)
195
196 val cwd : t -> string option
197 (** [cwd t] returns cwd from Init, None otherwise. *)
198
199 val error_msg : t -> string option
200 (** [error_msg t] returns error from Error, None otherwise. *)
201
202 val subtype : t -> string
203 (** [subtype t] returns the subtype string. *)
204
205 val unknown : t -> Unknown.t
206 (** [unknown t] returns the unknown fields. *)
207
208 (** {2 Conversion} *)
209
210 val to_json : t -> Jsont.json
211 (** [to_json t] converts to JSON representation. *)
212
213 val of_json : Jsont.json -> t
214 (** [of_json json] parses from JSON.
215 @raise Invalid_argument if invalid. *)
216
217 val pp : Format.formatter -> t -> unit
218 (** [pp fmt t] pretty-prints the message. *)
219end
220
221(** {1 Result Messages} *)
222
223module Result : sig
224 (** Final result messages with metadata about the conversation. *)
225
226 module Usage : sig
227 (** Usage statistics for API calls. *)
228
229 type t
230 (** Type for usage statistics. *)
231
232 val jsont : t Jsont.t
233 (** [jsont] is the Jsont codec for usage statistics. *)
234
235 val create :
236 ?input_tokens:int ->
237 ?output_tokens:int ->
238 ?total_tokens:int ->
239 ?cache_creation_input_tokens:int ->
240 ?cache_read_input_tokens:int ->
241 unit -> t
242 (** [create ?input_tokens ?output_tokens ?total_tokens ?cache_creation_input_tokens
243 ?cache_read_input_tokens ()] creates usage statistics. *)
244
245 val input_tokens : t -> int option
246 (** [input_tokens t] returns the number of input tokens used. *)
247
248 val output_tokens : t -> int option
249 (** [output_tokens t] returns the number of output tokens generated. *)
250
251 val total_tokens : t -> int option
252 (** [total_tokens t] returns the total number of tokens. *)
253
254 val cache_creation_input_tokens : t -> int option
255 (** [cache_creation_input_tokens t] returns cache creation input tokens. *)
256
257 val cache_read_input_tokens : t -> int option
258 (** [cache_read_input_tokens t] returns cache read input tokens. *)
259
260 val unknown : t -> Unknown.t
261 (** [unknown t] returns the unknown fields preserved from JSON. *)
262
263 val effective_input_tokens : t -> int
264 (** [effective_input_tokens t] returns input tokens minus cached tokens, or 0 if not available. *)
265
266 val total_cost_estimate : t -> input_price:float -> output_price:float -> float option
267 (** [total_cost_estimate t ~input_price ~output_price] estimates the cost based on token
268 prices per million tokens. Returns None if token counts are not available. *)
269
270 val pp : Format.formatter -> t -> unit
271 (** [pp fmt t] pretty-prints the usage statistics. *)
272
273 val to_json : t -> Jsont.json
274 (** [to_json t] converts to JSON representation. Internal use only. *)
275
276 val of_json : Jsont.json -> t
277 (** [of_json json] parses from JSON. Internal use only. *)
278 end
279
280 type t
281 (** The type of result messages. *)
282
283 val jsont : t Jsont.t
284 (** [jsont] is the Jsont codec for result messages. *)
285
286 val create :
287 subtype:string ->
288 duration_ms:int ->
289 duration_api_ms:int ->
290 is_error:bool ->
291 num_turns:int ->
292 session_id:string ->
293 ?total_cost_usd:float ->
294 ?usage:Usage.t ->
295 ?result:string ->
296 ?structured_output:Jsont.json ->
297 unit -> t
298 (** [create ~subtype ~duration_ms ~duration_api_ms ~is_error ~num_turns
299 ~session_id ?total_cost_usd ?usage ?result ()] creates a result message.
300 @param subtype The subtype of the result
301 @param duration_ms Total duration in milliseconds
302 @param duration_api_ms API duration in milliseconds
303 @param is_error Whether the result represents an error
304 @param num_turns Number of conversation turns
305 @param session_id Unique session identifier
306 @param total_cost_usd Optional total cost in USD
307 @param usage Optional usage statistics as JSON
308 @param result Optional result string
309 @param structured_output Optional structured JSON output from Claude *)
310
311 val subtype : t -> string
312 (** [subtype t] returns the subtype of the result. *)
313
314 val duration_ms : t -> int
315 (** [duration_ms t] returns the total duration in milliseconds. *)
316
317 val duration_api_ms : t -> int
318 (** [duration_api_ms t] returns the API duration in milliseconds. *)
319
320 val is_error : t -> bool
321 (** [is_error t] returns whether this result represents an error. *)
322
323 val num_turns : t -> int
324 (** [num_turns t] returns the number of conversation turns. *)
325
326 val session_id : t -> string
327 (** [session_id t] returns the session identifier. *)
328
329 val total_cost_usd : t -> float option
330 (** [total_cost_usd t] returns the optional total cost in USD. *)
331
332 val usage : t -> Usage.t option
333 (** [usage t] returns the optional usage statistics. *)
334
335 val result : t -> string option
336 (** [result t] returns the optional result string. *)
337
338 val structured_output : t -> Jsont.json option
339 (** [structured_output t] returns the optional structured JSON output. *)
340
341 val unknown : t -> Unknown.t
342 (** [unknown t] returns the unknown fields preserved from JSON. *)
343
344 val to_json : t -> Jsont.json
345 (** [to_json t] converts the result message to its JSON representation. *)
346
347 val of_json : Jsont.json -> t
348 (** [of_json json] parses a result message from JSON.
349 @raise Invalid_argument if the JSON is not a valid result message. *)
350
351 val pp : Format.formatter -> t -> unit
352 (** [pp fmt t] pretty-prints the result message. *)
353end
354
355(** {1 Message Union Type} *)
356
357type t =
358 | User of User.t
359 | Assistant of Assistant.t
360 | System of System.t
361 | Result of Result.t
362(** The type of messages, which can be user, assistant, system, or result. *)
363
364val jsont : t Jsont.t
365(** [jsont] is the Jsont codec for messages. *)
366
367val user_string : string -> t
368(** [user_string s] creates a user message with text content. *)
369
370val user_blocks : Content_block.t list -> t
371(** [user_blocks blocks] creates a user message with content blocks. *)
372
373val user_with_tool_result : tool_use_id:string -> content:string -> ?is_error:bool -> unit -> t
374(** [user_with_tool_result ~tool_use_id ~content ?is_error ()] creates a user message
375 containing a tool result. *)
376
377val assistant : content:Content_block.t list -> model:string -> ?error:Assistant.error -> unit -> t
378(** [assistant ~content ~model ?error ()] creates an assistant message. *)
379
380val assistant_text : text:string -> model:string -> ?error:Assistant.error -> unit -> t
381(** [assistant_text ~text ~model ?error ()] creates an assistant message with only text content. *)
382
383val system_init : session_id:string -> t
384(** [system_init ~session_id] creates a system init message. *)
385
386val system_error : error:string -> t
387(** [system_error ~error] creates a system error message. *)
388
389val result :
390 subtype:string ->
391 duration_ms:int ->
392 duration_api_ms:int ->
393 is_error:bool ->
394 num_turns:int ->
395 session_id:string ->
396 ?total_cost_usd:float ->
397 ?usage:Result.Usage.t ->
398 ?result:string ->
399 ?structured_output:Jsont.json ->
400 unit -> t
401(** [result ~subtype ~duration_ms ~duration_api_ms ~is_error ~num_turns
402 ~session_id ?total_cost_usd ?usage ?result ()] creates a result message. *)
403
404val to_json : t -> Jsont.json
405(** [to_json t] converts any message to its JSON representation. *)
406
407val of_json : Jsont.json -> t
408(** [of_json json] parses a message from JSON.
409 @raise Invalid_argument if the JSON is not a valid message. *)
410
411val pp : Format.formatter -> t -> unit
412(** [pp fmt t] pretty-prints any message. *)
413
414(** {1 Message Analysis} *)
415
416val is_user : t -> bool
417(** [is_user t] returns true if the message is from a user. *)
418
419val is_assistant : t -> bool
420(** [is_assistant t] returns true if the message is from the assistant. *)
421
422val is_system : t -> bool
423(** [is_system t] returns true if the message is a system message. *)
424
425val is_result : t -> bool
426(** [is_result t] returns true if the message is a result message. *)
427
428val is_error : t -> bool
429(** [is_error t] returns true if the message represents an error. *)
430
431val extract_text : t -> string option
432(** [extract_text t] attempts to extract text content from any message type. *)
433
434val extract_tool_uses : t -> Content_block.Tool_use.t list
435(** [extract_tool_uses t] extracts tool use blocks from assistant messages. *)
436
437val get_session_id : t -> string option
438(** [get_session_id t] extracts the session ID from system or result messages. *)
439
440(** {1 Logging} *)
441
442val log_received : t -> unit
443(** [log_received t] logs that a message was received. *)
444
445val log_sending : t -> unit
446(** [log_sending t] logs that a message is being sent. *)
447
448val log_error : string -> t -> unit
449(** [log_error msg t] logs an error with the given message and context. *)
450