Skip to main content

lean_ctx/proxy/web_app/
mod.rs

1#[allow(dead_code)]
2pub(crate) mod conversation_tracker;
3#[allow(dead_code)]
4pub(crate) mod normalize;
5#[cfg(test)]
6mod proof_tests;
7
8/// Recognized web-app AI providers (domain-detected, not path-detected).
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum WebAppProvider {
11    ClaudeWeb,
12    ChatGptWeb,
13    GeminiWeb,
14}
15
16/// A web-app request normalized to the canonical messages format that
17/// the existing compression pipeline understands.
18#[derive(Debug, Clone)]
19pub struct NormalizedRequest {
20    pub provider: WebAppProvider,
21    pub messages: Vec<serde_json::Value>,
22    pub system_prompt: Option<String>,
23    pub model: Option<String>,
24    pub conversation_id: Option<String>,
25    pub parent_message_id: Option<String>,
26}
27
28pub(crate) fn detect_web_provider(host: &str, path: &str) -> Option<WebAppProvider> {
29    let _ = path;
30    let host = host
31        .trim()
32        .trim_end_matches('.')
33        .split(':')
34        .next()
35        .unwrap_or_default();
36
37    if host.eq_ignore_ascii_case("claude.ai") {
38        Some(WebAppProvider::ClaudeWeb)
39    } else if host.eq_ignore_ascii_case("chat.openai.com")
40        || host.eq_ignore_ascii_case("chatgpt.com")
41    {
42        Some(WebAppProvider::ChatGptWeb)
43    } else if host.eq_ignore_ascii_case("gemini.google.com") {
44        Some(WebAppProvider::GeminiWeb)
45    } else {
46        None
47    }
48}