| 92 | } |
| 93 | |
| 94 | pub fn process_request( |
| 95 | config: &Value, |
| 96 | path: &str, |
| 97 | headers: &[(String, String)], |
| 98 | body: Value, |
| 99 | ) -> std::result::Result<RequestPlan, RequestProcessError> { |
| 100 | let mut plan = RequestPlan { |
| 101 | source_format: None, |
| 102 | target_format: None, |
| 103 | passthrough: false, |
| 104 | moderation_text: None, |
| 105 | stream: body.get("stream").and_then(Value::as_bool).unwrap_or(false), |
| 106 | body, |
| 107 | path: path.to_string(), |
| 108 | }; |
| 109 | |
| 110 | let transform_cfg = config |
| 111 | .get("format_transform") |
| 112 | .and_then(Value::as_object) |
| 113 | .cloned() |
| 114 | .unwrap_or_default(); |
| 115 | let transform_enabled = transform_cfg |
| 116 | .get("enabled") |
| 117 | .and_then(Value::as_bool) |
| 118 | .unwrap_or(false); |
| 119 | |
| 120 | if !transform_enabled { |
| 121 | return Ok(plan); |
| 122 | } |
| 123 | |
| 124 | let strict_parse = transform_cfg |
| 125 | .get("strict_parse") |
| 126 | .and_then(Value::as_bool) |
| 127 | .unwrap_or(false); |
| 128 | let disable_tools = transform_cfg |
| 129 | .get("disable_tools") |
| 130 | .and_then(Value::as_bool) |
| 131 | .unwrap_or(false); |
| 132 | let from_cfg = transform_cfg.get("from"); |
| 133 | let candidates = configured_candidates(from_cfg); |
| 134 | let detectable = detect_formats_from_candidates(&candidates, path, headers, &plan.body); |
| 135 | let mut parse_errors = Vec::new(); |
| 136 | let mut parsed = None; |
| 137 | |
| 138 | for source in detectable.iter().copied() { |
| 139 | match parse_request(source, &plan.body, path) { |
| 140 | Ok(internal) => { |
| 141 | parsed = Some((source, internal)); |
| 142 | break; |
| 143 | } |
| 144 | Err(error) => parse_errors.push(format!("{}: {error}", source.as_str())), |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | if parsed.is_none() { |
| 149 | if strict_parse { |
| 150 | let excluded = all_request_formats() |
| 151 | .into_iter() |