config.mojo (11134B)
1 from std.os.path import exists 2 from std.pathlib import Path 3 4 from morph.toml import from_toml 5 6 7 @fieldwise_init 8 struct HyfServiceRuntimeConfig(Defaultable, Copyable, Movable): 9 var transport: String 10 11 def __init__(out self): 12 self.transport = "stdio" 13 14 15 @fieldwise_init 16 struct HyfExecutionRuntimeConfig(Defaultable, Copyable, Movable): 17 var default_execution_mode: String 18 var allow_assisted: Bool 19 20 def __init__(out self): 21 self.default_execution_mode = "deterministic" 22 self.allow_assisted = False 23 24 25 @fieldwise_init 26 struct HyfMaxLocalProviderRuntimeConfig(Defaultable, Copyable, Movable): 27 var enabled: Bool 28 var base_url: String 29 var health_url: String 30 var model: String 31 var request_timeout_ms: Int 32 33 def __init__(out self): 34 self.enabled = False 35 self.base_url = "" 36 self.health_url = "" 37 self.model = "" 38 self.request_timeout_ms = 0 39 40 41 @fieldwise_init 42 struct HyfAssistedRuntimeConfig(Defaultable, Copyable, Movable): 43 var provider: String 44 var max_local: HyfMaxLocalProviderRuntimeConfig 45 46 def __init__(out self): 47 self.provider = "" 48 self.max_local = HyfMaxLocalProviderRuntimeConfig() 49 50 51 @fieldwise_init 52 struct HyfRuntimeConfig(Defaultable, Copyable, Movable): 53 var service: HyfServiceRuntimeConfig 54 var runtime: HyfExecutionRuntimeConfig 55 var assisted: HyfAssistedRuntimeConfig 56 57 def __init__(out self): 58 self.service = HyfServiceRuntimeConfig() 59 self.runtime = HyfExecutionRuntimeConfig() 60 self.assisted = HyfAssistedRuntimeConfig() 61 62 63 @fieldwise_init 64 struct HyfLoadedRuntimeConfig(Copyable, Movable): 65 var artifact_present: Bool 66 var loaded: Bool 67 var compiled_defaults_active: Bool 68 var load_state: String 69 var load_error: String 70 var effective: HyfRuntimeConfig 71 72 73 def default_runtime_config() -> HyfRuntimeConfig: 74 return HyfRuntimeConfig() 75 76 77 def default_loaded_runtime_config() -> HyfLoadedRuntimeConfig: 78 return HyfLoadedRuntimeConfig( 79 artifact_present=False, 80 loaded=False, 81 compiled_defaults_active=True, 82 load_state="not_found", 83 load_error="", 84 effective=default_runtime_config(), 85 ) 86 87 88 def assisted_execution_enabled(config: HyfLoadedRuntimeConfig) -> Bool: 89 return config.effective.runtime.allow_assisted 90 91 92 def assisted_runtime_configured(config: HyfLoadedRuntimeConfig) -> Bool: 93 return ( 94 config.effective.runtime.allow_assisted 95 and config.effective.assisted.provider == "max_local" 96 and config.effective.assisted.max_local.enabled 97 ) 98 99 100 def max_local_provider_configured(config: HyfLoadedRuntimeConfig) -> Bool: 101 return assisted_runtime_configured(config) 102 103 104 def load_runtime_config(path: String) -> HyfLoadedRuntimeConfig: 105 var defaults = default_runtime_config() 106 if String(path).strip() == "" or not exists(path): 107 return default_loaded_runtime_config() 108 109 try: 110 var config_text = Path(path).read_text() 111 _reject_removed_max_local_route_config(config_text) 112 var config = from_toml[HyfRuntimeConfig](config_text) 113 _validate_runtime_config(config) 114 return HyfLoadedRuntimeConfig( 115 artifact_present=True, 116 loaded=True, 117 compiled_defaults_active=False, 118 load_state="loaded", 119 load_error="", 120 effective=config^, 121 ) 122 except e: 123 return HyfLoadedRuntimeConfig( 124 artifact_present=True, 125 loaded=False, 126 compiled_defaults_active=True, 127 load_state="invalid", 128 load_error=String(e), 129 effective=defaults^, 130 ) 131 132 133 def _validate_runtime_config(config: HyfRuntimeConfig) raises: 134 if config.service.transport != "stdio": 135 raise Error("service.transport must be 'stdio'") 136 137 if config.runtime.default_execution_mode != "deterministic": 138 raise Error( 139 "runtime.default_execution_mode must be 'deterministic' in the foundation wave" 140 ) 141 142 if config.assisted.provider != "": 143 _require_no_boundary_whitespace( 144 config.assisted.provider, "assisted.provider" 145 ) 146 147 if config.runtime.allow_assisted: 148 if config.assisted.provider != "max_local": 149 raise Error( 150 "assisted.provider must be 'max_local' when runtime.allow_assisted is true" 151 ) 152 153 if config.assisted.provider != "" and config.assisted.provider != "max_local": 154 raise Error("assisted.provider must be 'max_local'") 155 156 if config.assisted.max_local.enabled: 157 if not config.runtime.allow_assisted: 158 raise Error( 159 "runtime.allow_assisted must be true when assisted.max_local.enabled is true" 160 ) 161 if config.assisted.provider != "max_local": 162 raise Error( 163 "assisted.provider must be 'max_local' when assisted.max_local.enabled is true" 164 ) 165 _validate_max_local_provider_config(config.assisted.max_local) 166 167 168 def _require_non_empty(value: String, context: String) raises: 169 if String(value).strip() == "": 170 raise Error(context + " must not be empty") 171 172 173 def _require_no_boundary_whitespace(value: String, context: String) raises: 174 if String(value) != String(value).strip(): 175 raise Error(context + " must not include leading or trailing whitespace") 176 177 178 def _require_http_url(value: String, context: String) raises: 179 if not (value.startswith("http://") or value.startswith("https://")): 180 raise Error(context + " must use http or https") 181 182 183 def _strip_toml_key_quotes(value: String) -> String: 184 var stripped = String(String(value).strip()) 185 if stripped.byte_length() < 2: 186 return stripped^ 187 188 var bytes = stripped.as_bytes() 189 var last_index = stripped.byte_length() - 1 190 if ( 191 bytes[0] == UInt8(ord('"')) 192 and bytes[last_index] == UInt8(ord('"')) 193 ): 194 return String(stripped[byte=1:last_index]) 195 if ( 196 bytes[0] == UInt8(ord("'")) 197 and bytes[last_index] == UInt8(ord("'")) 198 ): 199 return String(stripped[byte=1:last_index]) 200 return stripped^ 201 202 203 def _normalize_toml_key_path(key: String) -> String: 204 var normalized = String("") 205 for raw_part in key.split("."): 206 var part = _strip_toml_key_quotes( 207 String(String(raw_part).strip()) 208 ) 209 if normalized == "": 210 normalized = part 211 else: 212 normalized += "." + part 213 return normalized^ 214 215 216 def _toml_delimiter_index_outside_quotes( 217 text: String, delimiter: UInt8, start_index: Int 218 ) -> Int: 219 var bytes = text.as_bytes() 220 var index = start_index 221 var in_basic_string = False 222 var in_literal_string = False 223 var escaped = False 224 while index < text.byte_length(): 225 var byte = bytes[index] 226 if in_basic_string: 227 if escaped: 228 escaped = False 229 elif byte == UInt8(ord("\\")): 230 escaped = True 231 elif byte == UInt8(ord('"')): 232 in_basic_string = False 233 elif in_literal_string: 234 if byte == UInt8(ord("'")): 235 in_literal_string = False 236 else: 237 if byte == UInt8(ord('"')): 238 in_basic_string = True 239 elif byte == UInt8(ord("'")): 240 in_literal_string = True 241 elif byte == delimiter: 242 return index 243 index += 1 244 return -1 245 246 247 def _inline_table_contains_route_key(value: String) -> Bool: 248 var table = String(String(value).strip()) 249 var open_index = _toml_delimiter_index_outside_quotes( 250 table, UInt8(ord("{")), 0 251 ) 252 if open_index < 0: 253 return False 254 var close_index = _toml_delimiter_index_outside_quotes( 255 table, UInt8(ord("}")), open_index + 1 256 ) 257 if close_index < 0 or close_index <= open_index: 258 close_index = table.byte_length() 259 260 var body = String(table[byte=open_index + 1:close_index]) 261 var field_start = 0 262 while field_start <= body.byte_length(): 263 var comma_index = _toml_delimiter_index_outside_quotes( 264 body, UInt8(ord(",")), field_start 265 ) 266 var field_end = comma_index 267 if field_end < 0: 268 field_end = body.byte_length() 269 270 var field = String(String(body[byte=field_start:field_end]).strip()) 271 var equals_index = _toml_delimiter_index_outside_quotes( 272 field, UInt8(ord("=")), 0 273 ) 274 if equals_index < 0: 275 if comma_index < 0: 276 break 277 field_start = comma_index + 1 278 continue 279 else: 280 var key = String(String(field[byte=0:equals_index]).strip()) 281 if _normalize_toml_key_path(key) == "route": 282 return True 283 284 if comma_index < 0: 285 break 286 field_start = comma_index + 1 287 return False 288 289 290 def _reject_removed_max_local_route_config(config_text: String) raises: 291 var in_max_local = False 292 for raw_line in config_text.splitlines(): 293 var line = String(String(raw_line).strip()) 294 if line == "" or line.startswith("#"): 295 continue 296 if line.startswith("["): 297 var close_index = line.find("]") 298 if close_index < 0: 299 in_max_local = False 300 continue 301 var table_name = String( 302 String(line[byte=1:close_index]).strip() 303 ) 304 in_max_local = ( 305 _normalize_toml_key_path(table_name) 306 == "assisted.max_local" 307 ) 308 continue 309 var equals_index = line.find("=") 310 if equals_index < 0: 311 continue 312 var key = _normalize_toml_key_path( 313 String(String(line[byte=0:equals_index]).strip()) 314 ) 315 var value = String(String(line[byte=equals_index + 1:]).strip()) 316 if ( 317 (in_max_local and key == "route") 318 or key == "assisted.max_local.route" 319 or ( 320 key == "assisted.max_local" 321 and _inline_table_contains_route_key(value) 322 ) 323 ): 324 raise Error( 325 "assisted.max_local.route has been removed; provider route is derived by HYF" 326 ) 327 328 329 def _validate_max_local_provider_config( 330 config: HyfMaxLocalProviderRuntimeConfig 331 ) raises: 332 _require_non_empty(config.base_url, "assisted.max_local.base_url") 333 _require_no_boundary_whitespace( 334 config.base_url, "assisted.max_local.base_url" 335 ) 336 _require_http_url(config.base_url, "assisted.max_local.base_url") 337 _require_non_empty(config.health_url, "assisted.max_local.health_url") 338 _require_no_boundary_whitespace( 339 config.health_url, "assisted.max_local.health_url" 340 ) 341 _require_http_url(config.health_url, "assisted.max_local.health_url") 342 _require_non_empty(config.model, "assisted.max_local.model") 343 _require_no_boundary_whitespace( 344 config.model, "assisted.max_local.model" 345 ) 346 if config.request_timeout_ms <= 0: 347 raise Error("assisted.max_local.request_timeout_ms must be greater than zero")