(
provider: &crate::models::Provider,
model: &str,
messages: &[Value],
)
| 929 | } |
| 930 | |
| 931 | async fn generate_title_openai( |
| 932 | provider: &crate::models::Provider, |
| 933 | model: &str, |
| 934 | messages: &[Value], |
| 935 | ) -> AppResult<String> { |
| 936 | let client = http_client::request_client()?; |
| 937 | let endpoint = format!( |
| 938 | "{}/chat/completions", |
| 939 | provider.base_url.trim_end_matches('/') |
| 940 | ); |
| 941 | |
| 942 | let payload = serde_json::json!({ |
| 943 | "model": model, |
| 944 | "messages": messages, |
| 945 | "temperature": 0.3, |
| 946 | "max_tokens": 20, |
| 947 | "stream": false, |
| 948 | }); |
| 949 | |
| 950 | let mut request = client |
| 951 | .post(&endpoint) |
| 952 | .header(CONTENT_TYPE, "application/json") |
| 953 | .json(&payload); |
| 954 | |
| 955 | if let Some(key) = provider.api_key.as_deref().filter(|k| !k.trim().is_empty()) { |
| 956 | request = request.header(AUTHORIZATION, format!("Bearer {key}")); |
| 957 | } |
| 958 | |
| 959 | let response = request.send().await?; |
| 960 | if !response.status().is_success() { |
| 961 | let status = response.status(); |
| 962 | let body = response.text().await.unwrap_or_default(); |
| 963 | return Err(AppError::Http(format!("{status}: {body}"))); |
| 964 | } |
| 965 | |
| 966 | let body: Value = response.json().await?; |
| 967 | let title = body["choices"][0]["message"]["content"] |
| 968 | .as_str() |
| 969 | .unwrap_or("New Chat") |
| 970 | .to_string(); |
| 971 | |
| 972 | Ok(title) |
| 973 | } |
| 974 | |
| 975 | async fn generate_title_anthropic( |
| 976 | provider: &crate::models::Provider, |
no test coverage detected