gglib_core/ports/
chat_history.rs

1//! Chat history repository port definition.
2//!
3//! This port defines the interface for persisting and retrieving chat
4//! conversations and messages.
5
6use async_trait::async_trait;
7use thiserror::Error;
8
9use crate::domain::chat::{
10    Conversation, ConversationUpdate, Message, MessageRole, NewConversation, NewMessage,
11};
12
13/// Errors that can occur in chat history operations.
14#[derive(Debug, Error)]
15pub enum ChatHistoryError {
16    #[error("Conversation not found: {0}")]
17    ConversationNotFound(i64),
18
19    #[error("Message not found: {0}")]
20    MessageNotFound(i64),
21
22    #[error("Invalid message role: {0}")]
23    InvalidRole(String),
24
25    #[error("Database error: {0}")]
26    Database(String),
27}
28
29/// Port for chat history persistence operations.
30///
31/// This trait defines the interface for storing and retrieving chat
32/// conversations and messages. Implementations handle the actual storage
33/// mechanism (`SQLite`, etc.).
34#[async_trait]
35pub trait ChatHistoryRepository: Send + Sync {
36    /// Create a new conversation.
37    async fn create_conversation(&self, conv: NewConversation) -> Result<i64, ChatHistoryError>;
38
39    /// List all conversations, ordered by most recently updated.
40    async fn list_conversations(&self) -> Result<Vec<Conversation>, ChatHistoryError>;
41
42    /// Get a specific conversation by ID.
43    async fn get_conversation(&self, id: i64) -> Result<Option<Conversation>, ChatHistoryError>;
44
45    /// Update conversation metadata.
46    async fn update_conversation(
47        &self,
48        id: i64,
49        update: ConversationUpdate,
50    ) -> Result<(), ChatHistoryError>;
51
52    /// Delete a conversation and all its messages.
53    async fn delete_conversation(&self, id: i64) -> Result<(), ChatHistoryError>;
54
55    /// Get conversation count.
56    async fn get_conversation_count(&self) -> Result<i64, ChatHistoryError>;
57
58    /// Get all messages for a conversation, ordered chronologically.
59    async fn get_messages(&self, conversation_id: i64) -> Result<Vec<Message>, ChatHistoryError>;
60
61    /// Save a new message and update conversation timestamp.
62    async fn save_message(&self, msg: NewMessage) -> Result<i64, ChatHistoryError>;
63
64    /// Update a message's content and optionally its metadata.
65    async fn update_message(
66        &self,
67        id: i64,
68        content: String,
69        metadata: Option<serde_json::Value>,
70    ) -> Result<(), ChatHistoryError>;
71
72    /// Delete a message and all subsequent messages in the same conversation.
73    /// Returns the number of messages deleted.
74    async fn delete_message_and_subsequent(&self, id: i64) -> Result<i64, ChatHistoryError>;
75
76    /// Get message count for a conversation.
77    async fn get_message_count(&self, conversation_id: i64) -> Result<i64, ChatHistoryError>;
78}
79
80/// Validate a message role string.
81pub fn validate_role(role: &str) -> Result<MessageRole, ChatHistoryError> {
82    MessageRole::parse(role).ok_or_else(|| ChatHistoryError::InvalidRole(role.to_string()))
83}