| use sha2::{Sha256, Digest}; |
| use crate::proxy::mappers::claude::models::{ClaudeRequest, MessageContent}; |
| use crate::proxy::mappers::openai::models::{OpenAIRequest, OpenAIContent}; |
| use serde_json::Value; |
|
|
| |
| pub struct SessionManager; |
|
|
| impl SessionManager { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub fn extract_session_id(request: &ClaudeRequest) -> String { |
| |
| if let Some(metadata) = &request.metadata { |
| if let Some(user_id) = &metadata.user_id { |
| if !user_id.is_empty() && !user_id.contains("session-") { |
| tracing::debug!("[SessionManager] Using explicit user_id: {}", user_id); |
| return user_id.clone(); |
| } |
| } |
| } |
|
|
| |
| let mut hasher = Sha256::new(); |
|
|
| let mut content_found = false; |
| for msg in &request.messages { |
| if msg.role != "user" { continue; } |
| |
| let text = match &msg.content { |
| MessageContent::String(s) => s.clone(), |
| MessageContent::Array(blocks) => { |
| blocks.iter() |
| .filter_map(|block| match block { |
| crate::proxy::mappers::claude::models::ContentBlock::Text { text } => Some(text.as_str()), |
| _ => None, |
| }) |
| .collect::<Vec<_>>() |
| .join(" ") |
| } |
| }; |
|
|
| let clean_text = text.trim(); |
| |
| |
| if clean_text.len() >= 3 && !clean_text.contains("<system-reminder>") && !clean_text.contains("[System") { |
| hasher.update(clean_text.as_bytes()); |
| content_found = true; |
| break; |
| } |
| } |
|
|
| if !content_found { |
| |
| if let Some(last_msg) = request.messages.last() { |
| hasher.update(format!("{:?}", last_msg.content).as_bytes()); |
| } |
| } |
|
|
| let hash = format!("{:x}", hasher.finalize()); |
| let sid = format!("sid-{}", &hash[..16]); |
| |
| tracing::debug!( |
| "[SessionManager] Generated session_id: {} (content_found: {}, model: {})", |
| sid, |
| content_found, |
| request.model |
| ); |
| sid |
| } |
|
|
| |
| pub fn extract_openai_session_id(request: &OpenAIRequest) -> String { |
| let mut hasher = Sha256::new(); |
|
|
| let mut content_found = false; |
| for msg in &request.messages { |
| if msg.role != "user" { continue; } |
| if let Some(content) = &msg.content { |
| let text = match content { |
| OpenAIContent::String(s) => s.clone(), |
| OpenAIContent::Array(blocks) => { |
| blocks.iter() |
| .filter_map(|block| match block { |
| crate::proxy::mappers::openai::models::OpenAIContentBlock::Text { text } => Some(text.as_str()), |
| _ => None, |
| }) |
| .collect::<Vec<_>>() |
| .join(" ") |
| } |
| }; |
|
|
| let clean_text = text.trim(); |
| if clean_text.len() > 10 && !clean_text.contains("<system-reminder>") { |
| hasher.update(clean_text.as_bytes()); |
| content_found = true; |
| break; |
| } |
| } |
| } |
|
|
| if !content_found { |
| if let Some(last_msg) = request.messages.last() { |
| hasher.update(format!("{:?}", last_msg.content).as_bytes()); |
| } |
| } |
|
|
| let hash = format!("{:x}", hasher.finalize()); |
| let sid = format!("sid-{}", &hash[..16]); |
| tracing::debug!("[SessionManager-OpenAI] Generated fingerprint: {}", sid); |
| sid |
| } |
|
|
| |
| pub fn extract_gemini_session_id(request: &Value, _model_name: &str) -> String { |
| let mut hasher = Sha256::new(); |
|
|
| let mut content_found = false; |
| if let Some(contents) = request.get("contents").and_then(|v| v.as_array()) { |
| for content in contents { |
| if content.get("role").and_then(|v| v.as_str()) != Some("user") { continue; } |
| |
| if let Some(parts) = content.get("parts").and_then(|v| v.as_array()) { |
| let mut text_parts = Vec::new(); |
| for part in parts { |
| if let Some(text) = part.get("text").and_then(|v| v.as_str()) { |
| text_parts.push(text); |
| } |
| } |
| |
| let combined_text = text_parts.join(" "); |
| let clean_text = combined_text.trim(); |
| if clean_text.len() > 10 && !clean_text.contains("<system-reminder>") { |
| hasher.update(clean_text.as_bytes()); |
| content_found = true; |
| break; |
| } |
| } |
| } |
| } |
|
|
| if !content_found { |
| |
| hasher.update(request.to_string().as_bytes()); |
| } |
|
|
| let hash = format!("{:x}", hasher.finalize()); |
| let sid = format!("sid-{}", &hash[..16]); |
| tracing::debug!("[SessionManager-Gemini] Generated fingerprint: {}", sid); |
| sid |
| } |
| } |
|
|