Skip to main content

systemprompt_analytics/services/
ai_provider.rs

1//! `AiSessionProvider` implementation backed by analytics session rows.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use async_trait::async_trait;
7use systemprompt_database::DbPool;
8use systemprompt_identifiers::SessionId;
9use systemprompt_traits::{
10    AiProviderError, AiProviderResult, AiSessionProvider, CreateAiSessionParams,
11};
12
13use crate::repository::{CreateSessionParams, SessionRepository};
14
15#[derive(Debug)]
16pub struct AnalyticsAiSessionProvider {
17    session_repo: SessionRepository,
18}
19
20impl AnalyticsAiSessionProvider {
21    pub fn new(pool: &DbPool) -> crate::Result<Self> {
22        Ok(Self {
23            session_repo: SessionRepository::new(pool)?,
24        })
25    }
26
27    pub const fn from_repository(session_repo: SessionRepository) -> Self {
28        Self { session_repo }
29    }
30}
31
32#[async_trait]
33impl AiSessionProvider for AnalyticsAiSessionProvider {
34    async fn create_session(&self, params: CreateAiSessionParams<'_>) -> AiProviderResult<()> {
35        let full_params = CreateSessionParams {
36            session_id: params.session_id,
37            user_id: params.user_id,
38            session_source: params.session_source,
39            fingerprint_hash: None,
40            ip_address: None,
41            user_agent: None,
42            device_type: None,
43            browser: None,
44            os: None,
45            country: None,
46            region: None,
47            city: None,
48            preferred_locale: None,
49            referrer_source: None,
50            referrer_url: None,
51            landing_page: None,
52            entry_url: None,
53            utm_source: None,
54            utm_medium: None,
55            utm_campaign: None,
56            utm_content: None,
57            utm_term: None,
58            is_bot: false,
59            is_ai_crawler: false,
60            expires_at: params.expires_at,
61        };
62
63        self.session_repo
64            .create_session(&full_params)
65            .await
66            .map_err(|e| AiProviderError::Internal(e.to_string()))
67    }
68
69    async fn increment_ai_usage(
70        &self,
71        session_id: &SessionId,
72        tokens: i32,
73        cost_microdollars: i64,
74    ) -> AiProviderResult<()> {
75        self.session_repo
76            .increment_ai_usage(session_id, tokens, cost_microdollars)
77            .await
78            .map_err(|e| AiProviderError::Internal(e.to_string()))
79    }
80}