OCaml client library for Claude Code
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-claude: enable MDX on lib/handler.mli

Run mdx on lib/handler.mli so the four {[ ... ]} odoc blocks now
type-check.

Replaced placeholder-comment bodies (`(* required *)`,
`(* must implement *)`) with real bodies that show what each
handler method receives and prints. The `on_init` example threads
through `Option.value` since `Response.Init.session_id` returns
`string option`. The `dispatch` and `dispatch_all` blocks are now
named functions (`print_text response`, `drain_all client handler`)
so the example doesn't depend on free `client` / `response` /
`handler` / `responses` bindings.

Switched all printers from Printf to Fmt.pr "%a@." and qualified
references to `Claude.Response.X` / `Claude.Content_block.X` so the
toploop resolves them through the `claude` package.

Trimmed the second prose block describing the abstract class --
the inline `(* required *)` placeholder snippet won't compile, and
the surrounding text already explains the type-error guarantee.

+47 -37
+1 -1
lib/dune
··· 4 4 (libraries eio eio_main fmt logs nox-json)) 5 5 6 6 (mdx 7 - (files mcp_server.mli client.mli claude.mli hooks.mli) 7 + (files mcp_server.mli client.mli claude.mli hooks.mli handler.mli) 8 8 (libraries claude nox-json logs fmt eio eio.core eio.unix eio_main))
+46 -36
lib/handler.mli
··· 19 19 let my_handler = 20 20 object 21 21 inherit Claude.Handler.default 22 - method! on_text t = print_endline (Response.Text.content t) 22 + method! on_text t = print_endline (Claude.Response.Text.content t) 23 23 24 24 method! on_complete c = 25 - Printf.printf "Done! Cost: $%.4f\n" 26 - (Option.value ~default:0.0 (Response.Complete.total_cost_usd c)) 25 + Fmt.pr "Done! Cost: $%.4f@." 26 + (Option.value ~default:0.0 27 + (Claude.Response.Complete.total_cost_usd c)) 27 28 end 28 29 ]} 29 30 30 31 For compile-time guarantees that all events are handled, inherit from 31 - {!abstract}: 32 + {!abstract} -- omitting any method is a type error. 32 33 33 34 {[ 34 - let complete_handler = object 35 + let trace_handler = 36 + object 35 37 inherit Claude.Handler.abstract 36 - method on_text t = (* must implement *) 37 - method on_tool_use t = (* must implement *) 38 - method on_tool_result t = (* must implement *) 39 - method on_thinking t = (* must implement *) 40 - method on_init t = (* must implement *) 41 - method on_error t = (* must implement *) 42 - method on_complete t = (* must implement *) 38 + method on_text t = Fmt.pr "text: %s@." (Claude.Response.Text.content t) 39 + 40 + method on_tool_use t = 41 + Fmt.pr "tool_use: %s@." (Claude.Response.Tool_use.name t) 42 + 43 + method on_tool_result t = 44 + Fmt.pr "tool_result: %s@." 45 + (Claude.Content_block.Tool_result.tool_use_id t) 46 + 47 + method on_thinking t = 48 + Fmt.pr "thinking: %s@." (Claude.Response.Thinking.content t) 49 + 50 + method on_init t = 51 + Fmt.pr "init session: %s@." 52 + (Option.value ~default:"<no session>" 53 + (Claude.Response.Init.session_id t)) 54 + 55 + method on_error t = 56 + Fmt.pr "error: %s@." (Claude.Response.Error.message t) 57 + 58 + method on_complete c = 59 + Fmt.pr "complete: $%.4f@." 60 + (Option.value ~default:0.0 61 + (Claude.Response.Complete.total_cost_usd c)) 43 62 end 44 63 ]} *) 45 64 ··· 90 109 let handler = 91 110 object 92 111 inherit Claude.Handler.default 93 - method! on_text t = Printf.printf "Text: %s\n" (Response.Text.content t) 112 + method! on_text t = Fmt.pr "Text: %s@." (Claude.Response.Text.content t) 94 113 end 95 114 ]} 96 115 ··· 99 118 100 119 (** Abstract handler requiring all methods to be implemented. 101 120 102 - Use this when you want compile-time guarantees that all events are handled: 103 - 104 - {[ 105 - let handler = object 106 - inherit Claude.Handler.abstract 107 - method on_text t = (* required *) 108 - method on_tool_use t = (* required *) 109 - method on_tool_result t = (* required *) 110 - method on_thinking t = (* required *) 111 - method on_init t = (* required *) 112 - method on_error t = (* required *) 113 - method on_complete t = (* required *) 114 - end 115 - ]} 121 + Use this when you want compile-time guarantees that all events are handled. 122 + Every method is virtual and the compiler will refuse to instantiate the 123 + class until each one has a concrete body. 116 124 117 125 The compiler will enforce that you implement all methods, ensuring no events 118 126 are silently ignored. *) ··· 147 155 148 156 Example: 149 157 {[ 150 - let handler = 151 - object 152 - inherit Claude.Handler.default 153 - method! on_text t = print_endline (Response.Text.content t) 154 - end 155 - in 156 - dispatch handler (Response.Text text_event) 158 + let print_text response = 159 + let handler = 160 + object 161 + inherit Claude.Handler.default 162 + method! on_text t = print_endline (Claude.Response.Text.content t) 163 + end 164 + in 165 + Claude.Handler.dispatch handler response 157 166 ]} *) 158 167 159 168 val dispatch_all : #handler -> Response.t list -> unit ··· 164 173 may be more convenient: 165 174 166 175 {[ 167 - let responses = Client.receive_all client in 168 - dispatch_all handler responses 176 + let drain_all client handler = 177 + let responses = Claude.Client.receive_all client in 178 + Claude.Handler.dispatch_all handler responses 169 179 ]} *)