(request: &ChatRequest)
| 509 | } |
| 510 | |
| 511 | fn build_request_body(request: &ChatRequest) -> Result<Value, ProviderError> { |
| 512 | let mut value = serde_json::to_value(request) |
| 513 | .map_err(|e| ProviderError::InvalidRequest(e.to_string()))?; |
| 514 | |
| 515 | if let Value::Object(obj) = &mut value { |
| 516 | // Merge provider_options into the top-level body (matching TS SDK behavior). |
| 517 | // The TS SDK spreads provider options directly into the request body so that |
| 518 | // provider-specific fields like `thinking`, `enable_thinking`, etc. are sent |
| 519 | // as top-level keys rather than nested under `provider_options`. |
| 520 | if let Some(Value::Object(opts)) = obj.remove("provider_options") { |
| 521 | for (k, v) in opts { |
| 522 | obj.entry(k).or_insert(v); |
| 523 | } |
| 524 | } |
| 525 | |
| 526 | let effort = openai_reasoning_effort(&request.model, request.variant.as_deref()); |
| 527 | if let Some(effort) = effort { |
| 528 | obj.insert( |
| 529 | "reasoning_effort".to_string(), |
| 530 | Value::String(effort.to_string()), |
| 531 | ); |
| 532 | } |
| 533 | } |
| 534 | |
| 535 | Ok(value) |
| 536 | } |
| 537 | |
| 538 | fn responses_url(base_url: Option<&str>, path: &str) -> String { |
| 539 | let path = path.trim_start_matches('/'); |
nothing calls this directly
no test coverage detected