agent_chain_core/
chat_sessions.rs

1//! **Chat Sessions** are a collection of messages and function calls.
2//!
3//! This module provides the [`ChatSession`] type for representing a single
4//! conversation, channel, or other group of messages.
5//!
6//! Mirrors `langchain_core.chat_sessions`.
7
8use serde::{Deserialize, Serialize};
9
10use crate::messages::BaseMessage;
11
12/// Chat Session.
13///
14/// A Chat Session represents a single conversation, channel, or other group of messages.
15///
16/// # Example
17///
18/// ```ignore
19/// use agent_chain_core::chat_sessions::ChatSession;
20/// use agent_chain_core::messages::{BaseMessage, HumanMessage, AIMessage};
21///
22/// let session = ChatSession {
23///     messages: Some(vec![
24///         BaseMessage::Human(HumanMessage::new("Hello!")),
25///         BaseMessage::AI(AIMessage::new("Hi there!")),
26///     ]),
27///     functions: None,
28/// };
29/// ```
30#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
31pub struct ChatSession {
32    /// A sequence of the LangChain chat messages loaded from the source.
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub messages: Option<Vec<BaseMessage>>,
35
36    /// A sequence of the function calling specs for the messages.
37    #[serde(default, skip_serializing_if = "Option::is_none")]
38    pub functions: Option<Vec<serde_json::Value>>,
39}
40
41impl ChatSession {
42    /// Create a new empty chat session.
43    pub fn new() -> Self {
44        Self::default()
45    }
46
47    /// Create a chat session with the given messages.
48    pub fn with_messages(messages: Vec<BaseMessage>) -> Self {
49        Self {
50            messages: Some(messages),
51            functions: None,
52        }
53    }
54
55    /// Create a chat session with the given messages and functions.
56    pub fn with_messages_and_functions(
57        messages: Vec<BaseMessage>,
58        functions: Vec<serde_json::Value>,
59    ) -> Self {
60        Self {
61            messages: Some(messages),
62            functions: Some(functions),
63        }
64    }
65
66    /// Get the messages in this session, or an empty slice if none.
67    pub fn messages(&self) -> &[BaseMessage] {
68        self.messages.as_deref().unwrap_or(&[])
69    }
70
71    /// Get the functions in this session, or an empty slice if none.
72    pub fn functions(&self) -> &[serde_json::Value] {
73        self.functions.as_deref().unwrap_or(&[])
74    }
75
76    /// Check if this session has any messages.
77    pub fn has_messages(&self) -> bool {
78        self.messages.as_ref().is_some_and(|m| !m.is_empty())
79    }
80
81    /// Check if this session has any functions.
82    pub fn has_functions(&self) -> bool {
83        self.functions.as_ref().is_some_and(|f| !f.is_empty())
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90    use crate::messages::{AIMessage, HumanMessage};
91
92    #[test]
93    fn test_chat_session_new() {
94        let session = ChatSession::new();
95        assert!(session.messages.is_none());
96        assert!(session.functions.is_none());
97        assert!(!session.has_messages());
98        assert!(!session.has_functions());
99    }
100
101    #[test]
102    fn test_chat_session_with_messages() {
103        let messages = vec![
104            BaseMessage::Human(HumanMessage::new("Hello")),
105            BaseMessage::AI(AIMessage::new("Hi")),
106        ];
107        let session = ChatSession::with_messages(messages);
108
109        assert!(session.has_messages());
110        assert!(!session.has_functions());
111        assert_eq!(session.messages().len(), 2);
112    }
113
114    #[test]
115    fn test_chat_session_with_messages_and_functions() {
116        let messages = vec![BaseMessage::Human(HumanMessage::new("Hello"))];
117        let functions = vec![serde_json::json!({
118            "name": "get_weather",
119            "parameters": {}
120        })];
121
122        let session = ChatSession::with_messages_and_functions(messages, functions);
123
124        assert!(session.has_messages());
125        assert!(session.has_functions());
126        assert_eq!(session.messages().len(), 1);
127        assert_eq!(session.functions().len(), 1);
128    }
129
130    #[test]
131    fn test_chat_session_messages_accessor() {
132        let session = ChatSession::new();
133        assert!(session.messages().is_empty());
134
135        let session_with_messages =
136            ChatSession::with_messages(vec![BaseMessage::Human(HumanMessage::new("Hello"))]);
137        assert_eq!(session_with_messages.messages().len(), 1);
138    }
139
140    #[test]
141    fn test_chat_session_functions_accessor() {
142        let session = ChatSession::new();
143        assert!(session.functions().is_empty());
144
145        let session_with_functions = ChatSession {
146            messages: None,
147            functions: Some(vec![serde_json::json!({"name": "test"})]),
148        };
149        assert_eq!(session_with_functions.functions().len(), 1);
150    }
151
152    #[test]
153    fn test_chat_session_serialization() {
154        let messages = vec![BaseMessage::Human(HumanMessage::new("Hello"))];
155        let session = ChatSession::with_messages(messages);
156
157        let serialized = serde_json::to_string(&session).expect("serialization should work");
158        assert!(serialized.contains("messages"));
159
160        let deserialized: ChatSession =
161            serde_json::from_str(&serialized).expect("deserialization should work");
162        assert!(deserialized.has_messages());
163    }
164}