systemprompt-oauth 0.1.22

OAuth 2.0 authentication and authorization module for systemprompt.io OS
Documentation
use serde::{Deserialize, Serialize};
use systemprompt_identifiers::{ClientId, ClientType};

#[derive(Debug, Clone, sqlx::FromRow)]
pub struct ClientAnalyticsRow {
    pub client_id: String,
    pub session_count: i64,
    pub unique_users: i64,
    pub total_requests: i64,
    pub total_tokens: i64,
    pub total_cost_microdollars: i64,
    pub avg_session_duration_seconds: f64,
    pub avg_response_time_ms: f64,
    pub first_seen: chrono::DateTime<chrono::Utc>,
    pub last_seen: chrono::DateTime<chrono::Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientAnalytics {
    pub client_id: ClientId,
    pub client_type: ClientType,
    pub session_count: i64,
    pub unique_users: i64,
    pub total_requests: i64,
    pub total_tokens: i64,
    pub total_cost_microdollars: i64,
    pub avg_session_duration_seconds: f64,
    pub avg_response_time_ms: f64,
    pub first_seen: String,
    pub last_seen: String,
}

#[derive(Debug, Clone, sqlx::FromRow)]
pub struct ClientErrorAnalyticsRow {
    pub client_id: String,
    pub error_count: i64,
    pub affected_sessions: i64,
    pub last_error: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientErrorAnalytics {
    pub client_id: ClientId,
    pub error_count: i64,
    pub affected_sessions: i64,
    pub last_error: String,
}

impl From<ClientAnalyticsRow> for ClientAnalytics {
    fn from(row: ClientAnalyticsRow) -> Self {
        let client_id = ClientId::new(&row.client_id);
        let client_type = client_id.client_type();
        Self {
            client_id,
            client_type,
            session_count: row.session_count,
            unique_users: row.unique_users,
            total_requests: row.total_requests,
            total_tokens: row.total_tokens,
            total_cost_microdollars: row.total_cost_microdollars,
            avg_session_duration_seconds: row.avg_session_duration_seconds,
            avg_response_time_ms: row.avg_response_time_ms,
            first_seen: row.first_seen.to_rfc3339(),
            last_seen: row.last_seen.to_rfc3339(),
        }
    }
}

impl From<ClientErrorAnalyticsRow> for ClientErrorAnalytics {
    fn from(row: ClientErrorAnalyticsRow) -> Self {
        Self {
            client_id: ClientId::new(&row.client_id),
            error_count: row.error_count,
            affected_sessions: row.affected_sessions,
            last_error: row.last_error.unwrap_or_else(String::new),
        }
    }
}