gglib_core/services/
chat_history.rs

1//! Chat history service - thin orchestrator for chat operations.
2//!
3//! This service provides a clean interface for chat history operations,
4//! delegating all persistence to the `ChatHistoryRepository` port.
5
6use std::sync::Arc;
7
8use crate::domain::chat::{Conversation, ConversationUpdate, Message, NewConversation, NewMessage};
9use crate::ports::chat_history::{ChatHistoryError, ChatHistoryRepository};
10
11/// Service for managing chat history.
12///
13/// This is a thin orchestration layer over the `ChatHistoryRepository` port.
14/// It provides a clean API and handles any business logic that doesn't
15/// belong in the repository layer.
16pub struct ChatHistoryService {
17    repo: Arc<dyn ChatHistoryRepository>,
18}
19
20impl ChatHistoryService {
21    /// Create a new chat history service.
22    pub fn new(repo: Arc<dyn ChatHistoryRepository>) -> Self {
23        Self { repo }
24    }
25
26    /// Create a new conversation.
27    pub async fn create_conversation(
28        &self,
29        title: String,
30        model_id: Option<i64>,
31        system_prompt: Option<String>,
32    ) -> Result<i64, ChatHistoryError> {
33        self.repo
34            .create_conversation(NewConversation {
35                title,
36                model_id,
37                system_prompt,
38                settings: None,
39            })
40            .await
41    }
42
43    /// Create a new conversation with session settings for resume.
44    pub async fn create_conversation_with_settings(
45        &self,
46        conv: NewConversation,
47    ) -> Result<i64, ChatHistoryError> {
48        self.repo.create_conversation(conv).await
49    }
50
51    /// List all conversations, ordered by most recently updated.
52    pub async fn list_conversations(&self) -> Result<Vec<Conversation>, ChatHistoryError> {
53        self.repo.list_conversations().await
54    }
55
56    /// Get a specific conversation by ID.
57    pub async fn get_conversation(
58        &self,
59        id: i64,
60    ) -> Result<Option<Conversation>, ChatHistoryError> {
61        self.repo.get_conversation(id).await
62    }
63
64    /// Update conversation metadata.
65    pub async fn update_conversation(
66        &self,
67        id: i64,
68        new_title: Option<String>,
69        system_prompt: Option<Option<String>>,
70    ) -> Result<(), ChatHistoryError> {
71        self.repo
72            .update_conversation(
73                id,
74                ConversationUpdate {
75                    title: new_title,
76                    system_prompt,
77                    settings: None,
78                },
79            )
80            .await
81    }
82
83    /// Delete a conversation and all its messages.
84    pub async fn delete_conversation(&self, id: i64) -> Result<(), ChatHistoryError> {
85        self.repo.delete_conversation(id).await
86    }
87
88    /// Get conversation count.
89    pub async fn get_conversation_count(&self) -> Result<i64, ChatHistoryError> {
90        self.repo.get_conversation_count().await
91    }
92
93    /// Get all messages for a conversation.
94    pub async fn get_messages(
95        &self,
96        conversation_id: i64,
97    ) -> Result<Vec<Message>, ChatHistoryError> {
98        self.repo.get_messages(conversation_id).await
99    }
100
101    /// Save a new message.
102    pub async fn save_message(&self, msg: NewMessage) -> Result<i64, ChatHistoryError> {
103        self.repo.save_message(msg).await
104    }
105
106    /// Update a message's content and optionally its metadata.
107    pub async fn update_message(
108        &self,
109        id: i64,
110        content: String,
111        metadata: Option<serde_json::Value>,
112    ) -> Result<(), ChatHistoryError> {
113        self.repo.update_message(id, content, metadata).await
114    }
115
116    /// Delete a message and all subsequent messages.
117    pub async fn delete_message_and_subsequent(&self, id: i64) -> Result<i64, ChatHistoryError> {
118        self.repo.delete_message_and_subsequent(id).await
119    }
120
121    /// Get message count for a conversation.
122    pub async fn get_message_count(&self, conversation_id: i64) -> Result<i64, ChatHistoryError> {
123        self.repo.get_message_count(conversation_id).await
124    }
125}