OCaml Claude SDK using Eio and Jsont
at main 240 lines 7.9 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6let src = Logs.Src.create "claudeio.options" ~doc:"Claude configuration options" 7 8module Log = (val Logs.src_log src : Logs.LOG) 9 10type t = { 11 allowed_tools : string list; 12 disallowed_tools : string list; 13 max_thinking_tokens : int; 14 system_prompt : string option; 15 append_system_prompt : string option; 16 permission_mode : Permissions.Mode.t option; 17 permission_callback : Permissions.callback option; 18 model : Proto.Model.t option; 19 cwd : Eio.Fs.dir_ty Eio.Path.t option; 20 env : (string * string) list; 21 continue_conversation : bool; 22 resume : string option; 23 max_turns : int option; 24 permission_prompt_tool_name : string option; 25 settings : string option; 26 add_dirs : string list; 27 extra_args : (string * string option) list; 28 debug_stderr : Eio.Flow.sink_ty Eio.Flow.sink option; 29 hooks : Hooks.t option; 30 max_budget_usd : float option; 31 fallback_model : Proto.Model.t option; 32 setting_sources : Proto.Options.setting_source list option; 33 max_buffer_size : int option; 34 user : string option; 35 output_format : Proto.Structured_output.t option; 36 mcp_servers : (string * Mcp_server.t) list; 37} 38 39let default = 40 { 41 allowed_tools = []; 42 disallowed_tools = []; 43 max_thinking_tokens = 8000; 44 system_prompt = None; 45 append_system_prompt = None; 46 permission_mode = None; 47 permission_callback = Some Permissions.default_allow; 48 model = None; 49 cwd = None; 50 env = []; 51 continue_conversation = false; 52 resume = None; 53 max_turns = None; 54 permission_prompt_tool_name = None; 55 settings = None; 56 add_dirs = []; 57 extra_args = []; 58 debug_stderr = None; 59 hooks = None; 60 max_budget_usd = None; 61 fallback_model = None; 62 setting_sources = None; 63 max_buffer_size = None; 64 user = None; 65 output_format = None; 66 mcp_servers = []; 67 } 68 69(* Accessors *) 70let allowed_tools t = t.allowed_tools 71let disallowed_tools t = t.disallowed_tools 72let max_thinking_tokens t = t.max_thinking_tokens 73let system_prompt t = t.system_prompt 74let append_system_prompt t = t.append_system_prompt 75let permission_mode t = t.permission_mode 76let permission_callback t = t.permission_callback 77let model t = t.model 78let cwd t = t.cwd 79let env t = t.env 80let continue_conversation t = t.continue_conversation 81let resume t = t.resume 82let max_turns t = t.max_turns 83let permission_prompt_tool_name t = t.permission_prompt_tool_name 84let settings t = t.settings 85let add_dirs t = t.add_dirs 86let extra_args t = t.extra_args 87let debug_stderr t = t.debug_stderr 88let hooks t = t.hooks 89let max_budget_usd t = t.max_budget_usd 90let fallback_model t = t.fallback_model 91let setting_sources t = t.setting_sources 92let max_buffer_size t = t.max_buffer_size 93let user t = t.user 94let output_format t = t.output_format 95let mcp_servers t = t.mcp_servers 96 97(* Builders *) 98let with_allowed_tools tools t = { t with allowed_tools = tools } 99let with_disallowed_tools tools t = { t with disallowed_tools = tools } 100let with_max_thinking_tokens tokens t = { t with max_thinking_tokens = tokens } 101let with_system_prompt prompt t = { t with system_prompt = Some prompt } 102 103let with_append_system_prompt prompt t = 104 { t with append_system_prompt = Some prompt } 105 106let with_permission_mode mode t = { t with permission_mode = Some mode } 107 108let with_permission_callback callback t = 109 { t with permission_callback = Some callback } 110 111let with_model model t = { t with model = Some model } 112let with_cwd cwd t = { t with cwd = Some (cwd :> Eio.Fs.dir_ty Eio.Path.t) } 113let with_env env t = { t with env } 114 115let with_continue_conversation continue t = 116 { t with continue_conversation = continue } 117 118let with_resume session_id t = { t with resume = Some session_id } 119let with_max_turns turns t = { t with max_turns = Some turns } 120 121let with_permission_prompt_tool_name tool t = 122 { t with permission_prompt_tool_name = Some tool } 123 124let with_settings path t = { t with settings = Some path } 125let with_add_dirs dirs t = { t with add_dirs = dirs } 126let with_extra_args args t = { t with extra_args = args } 127 128let with_debug_stderr sink t = 129 { t with debug_stderr = Some (sink :> Eio.Flow.sink_ty Eio.Flow.sink) } 130 131let with_hooks hooks t = { t with hooks = Some hooks } 132let with_max_budget_usd budget t = { t with max_budget_usd = Some budget } 133let with_fallback_model model t = { t with fallback_model = Some model } 134let with_no_settings t = { t with setting_sources = Some [] } 135let with_max_buffer_size size t = { t with max_buffer_size = Some size } 136let with_user user t = { t with user = Some user } 137let with_output_format format t = { t with output_format = Some format } 138 139let with_mcp_server ~name server t = 140 { t with mcp_servers = (name, server) :: t.mcp_servers } 141 142let log_options t = 143 Log.debug (fun m -> 144 m "Options: model=%s fallback=%s max_thinking_tokens=%d max_budget=%s" 145 (match t.model with 146 | None -> "default" 147 | Some m -> Proto.Model.to_string m) 148 (match t.fallback_model with 149 | None -> "none" 150 | Some m -> Proto.Model.to_string m) 151 t.max_thinking_tokens 152 (match t.max_budget_usd with 153 | None -> "unlimited" 154 | Some b -> Printf.sprintf "$%.2f" b)) 155 156module Advanced = struct 157 let to_wire (t : t) : Proto.Options.t = 158 let base = Proto.Options.empty in 159 let base = Proto.Options.with_allowed_tools t.allowed_tools base in 160 let base = Proto.Options.with_disallowed_tools t.disallowed_tools base in 161 let base = 162 Proto.Options.with_max_thinking_tokens t.max_thinking_tokens base 163 in 164 let base = 165 match t.system_prompt with 166 | None -> base 167 | Some p -> Proto.Options.with_system_prompt p base 168 in 169 let base = 170 match t.append_system_prompt with 171 | None -> base 172 | Some p -> Proto.Options.with_append_system_prompt p base 173 in 174 let base = 175 match t.permission_mode with 176 | None -> base 177 | Some m -> 178 Proto.Options.with_permission_mode (Permissions.Mode.to_proto m) base 179 in 180 let base = 181 match t.model with 182 | None -> base 183 | Some m -> Proto.Options.with_model m base 184 in 185 let base = 186 Proto.Options.with_continue_conversation t.continue_conversation base 187 in 188 let base = 189 match t.resume with 190 | None -> base 191 | Some r -> Proto.Options.with_resume r base 192 in 193 let base = 194 match t.max_turns with 195 | None -> base 196 | Some turns -> Proto.Options.with_max_turns turns base 197 in 198 let base = 199 match t.permission_prompt_tool_name with 200 | None -> base 201 | Some tool -> Proto.Options.with_permission_prompt_tool_name tool base 202 in 203 let base = 204 match t.settings with 205 | None -> base 206 | Some s -> Proto.Options.with_settings s base 207 in 208 let base = Proto.Options.with_add_dirs t.add_dirs base in 209 let base = 210 match t.max_budget_usd with 211 | None -> base 212 | Some b -> Proto.Options.with_max_budget_usd b base 213 in 214 let base = 215 match t.fallback_model with 216 | None -> base 217 | Some m -> Proto.Options.with_fallback_model m base 218 in 219 let base = 220 match t.setting_sources with 221 | None -> base 222 | Some sources -> Proto.Options.with_setting_sources sources base 223 in 224 let base = 225 match t.max_buffer_size with 226 | None -> base 227 | Some size -> Proto.Options.with_max_buffer_size size base 228 in 229 let base = 230 match t.user with 231 | None -> base 232 | Some u -> Proto.Options.with_user u base 233 in 234 let base = 235 match t.output_format with 236 | None -> base 237 | Some format -> Proto.Options.with_output_format format base 238 in 239 base 240end