(&self, request: LlmRequest)
| 188 | } |
| 189 | |
| 190 | async fn complete(&self, request: LlmRequest) -> GraphBitResult<LlmResponse> { |
| 191 | let url = format!("{}/chat/completions", self.base_url); |
| 192 | |
| 193 | let messages: Vec<OpenRouterMessage> = |
| 194 | request.messages.iter().map(Self::convert_message).collect(); |
| 195 | |
| 196 | let tools: Option<Vec<OpenRouterTool>> = if request.tools.is_empty() { |
| 197 | None |
| 198 | } else { |
| 199 | Some(request.tools.iter().map(Self::convert_tool).collect()) |
| 200 | }; |
| 201 | |
| 202 | let body = OpenRouterRequest { |
| 203 | model: self.model.clone(), |
| 204 | messages, |
| 205 | max_tokens: request.max_tokens, |
| 206 | temperature: request.temperature, |
| 207 | top_p: request.top_p, |
| 208 | tools: tools.clone(), |
| 209 | tool_choice: if tools.is_some() { |
| 210 | Some("auto".to_string()) |
| 211 | } else { |
| 212 | None |
| 213 | }, |
| 214 | }; |
| 215 | |
| 216 | // Add extra parameters |
| 217 | let mut request_json = serde_json::to_value(&body)?; |
| 218 | if let serde_json::Value::Object(ref mut map) = request_json { |
| 219 | for (key, value) in request.extra_params { |
| 220 | map.insert(key, value); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | let mut request_builder = self |
| 225 | .client |
| 226 | .post(&url) |
| 227 | .header("Authorization", format!("Bearer {}", self.api_key)) |
| 228 | .header("Content-Type", "application/json"); |
| 229 | |
| 230 | // Add optional site information for `OpenRouter` rankings |
| 231 | if let Some(ref site_url) = self.site_url { |
| 232 | request_builder = request_builder.header("HTTP-Referer", site_url); |
| 233 | } |
| 234 | if let Some(ref site_name) = self.site_name { |
| 235 | request_builder = request_builder.header("X-Title", site_name); |
| 236 | } |
| 237 | |
| 238 | let response = request_builder |
| 239 | .json(&request_json) |
| 240 | .send() |
| 241 | .await |
| 242 | .map_err(|e| { |
| 243 | GraphBitError::llm_provider("openrouter", format!("Request failed: {e}")) |
| 244 | })?; |
| 245 | |
| 246 | if !response.status().is_success() { |
| 247 | let error_text = response |
nothing calls this directly
no test coverage detected