Skip to main content

systemprompt_agent/repository/context/
mutations.rs

1use chrono::Utc;
2
3use super::ContextRepository;
4use systemprompt_identifiers::{ContextId, SessionId, UserId};
5use systemprompt_traits::RepositoryError;
6
7impl ContextRepository {
8    pub async fn create_context(
9        &self,
10        user_id: &UserId,
11        session_id: Option<&SessionId>,
12        name: &str,
13    ) -> Result<ContextId, RepositoryError> {
14        let context_id = ContextId::generate();
15        let pool = self.get_pg_pool()?;
16        let now = Utc::now();
17        let session_id_str = session_id.map(SessionId::as_str);
18
19        sqlx::query!(
20            "INSERT INTO user_contexts (context_id, user_id, session_id, name, created_at, \
21             updated_at)
22             VALUES ($1, $2, $3, $4, $5, $5)",
23            context_id.as_str(),
24            user_id.as_str(),
25            session_id_str,
26            name,
27            now
28        )
29        .execute(pool.as_ref())
30        .await
31        .map_err(|e| RepositoryError::database(e))?;
32
33        Ok(context_id)
34    }
35
36    pub async fn validate_context_ownership(
37        &self,
38        context_id: &ContextId,
39        user_id: &UserId,
40    ) -> Result<(), RepositoryError> {
41        let pool = self.get_pg_pool()?;
42
43        let result = sqlx::query_scalar!(
44            "SELECT context_id FROM user_contexts WHERE context_id = $1 AND user_id = $2",
45            context_id.as_str(),
46            user_id.as_str()
47        )
48        .fetch_optional(pool.as_ref())
49        .await
50        .map_err(|e| RepositoryError::database(e))?;
51
52        match result {
53            Some(_) => Ok(()),
54            None => Err(RepositoryError::NotFound(format!(
55                "Context {} not found or user {} does not have access",
56                context_id, user_id
57            ))),
58        }
59    }
60
61    pub async fn update_context_name(
62        &self,
63        context_id: &ContextId,
64        user_id: &UserId,
65        name: &str,
66    ) -> Result<(), RepositoryError> {
67        let pool = self.get_pg_pool()?;
68        let now = Utc::now();
69
70        let result = sqlx::query!(
71            "UPDATE user_contexts SET name = $1, updated_at = $2
72             WHERE context_id = $3 AND user_id = $4",
73            name,
74            now,
75            context_id.as_str(),
76            user_id.as_str()
77        )
78        .execute(pool.as_ref())
79        .await
80        .map_err(|e| RepositoryError::database(e))?;
81
82        if result.rows_affected() == 0 {
83            return Err(RepositoryError::NotFound(format!(
84                "Context {} not found for user {}",
85                context_id, user_id
86            )));
87        }
88
89        Ok(())
90    }
91
92    pub async fn delete_context(
93        &self,
94        context_id: &ContextId,
95        user_id: &UserId,
96    ) -> Result<(), RepositoryError> {
97        let pool = self.get_pg_pool()?;
98
99        let result = sqlx::query!(
100            "DELETE FROM user_contexts WHERE context_id = $1 AND user_id = $2",
101            context_id.as_str(),
102            user_id.as_str()
103        )
104        .execute(pool.as_ref())
105        .await
106        .map_err(|e| RepositoryError::database(e))?;
107
108        if result.rows_affected() == 0 {
109            return Err(RepositoryError::NotFound(format!(
110                "Context {} not found for user {}",
111                context_id, user_id
112            )));
113        }
114
115        Ok(())
116    }
117}