Skip to main content

quantum_sdk/
session.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::chat::{ChatResponse, ChatTool};
6use crate::client::Client;
7use crate::error::Result;
8
9/// Configuration for session context management.
10#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11pub struct ContextConfig {
12    /// Maximum number of tokens to retain before compaction.
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub max_tokens: Option<i64>,
15
16    /// Whether to enable automatic context compaction.
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub auto_compact: Option<bool>,
19}
20
21/// A tool result to feed back into the session.
22#[derive(Debug, Clone, Serialize, Deserialize, Default)]
23pub struct ToolResult {
24    /// The tool_use ID this result corresponds to.
25    pub tool_call_id: String,
26
27    /// The result content.
28    pub content: String,
29
30    /// Whether this result is an error.
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub is_error: Option<bool>,
33}
34
35/// A tool execution result from the client (used in SessionChatRequest.tool_results).
36#[derive(Debug, Clone, Serialize, Deserialize, Default)]
37pub struct SessionToolResult {
38    /// References the tool_use ID from the previous response.
39    pub tool_call_id: String,
40
41    /// The tool execution result content.
42    pub content: String,
43
44    /// Whether the tool execution failed.
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub is_error: Option<bool>,
47}
48
49/// Context metadata returned in session responses (includes tools_cleared).
50#[derive(Debug, Clone, Deserialize)]
51pub struct ContextMetadata {
52    /// Total number of turns in the conversation.
53    #[serde(default)]
54    pub turn_count: i64,
55
56    /// Estimated token count of the current context.
57    #[serde(default)]
58    pub estimated_tokens: i64,
59
60    /// Whether the conversation was compacted in this request.
61    #[serde(default)]
62    pub compacted: bool,
63
64    /// Description of the compaction that occurred.
65    #[serde(default)]
66    pub compaction_note: Option<String>,
67
68    /// Number of stale tool results that were cleared.
69    #[serde(default)]
70    pub tools_cleared: Option<i32>,
71}
72
73/// Request body for session-based chat.
74#[derive(Debug, Clone, Serialize, Default)]
75pub struct SessionChatRequest {
76    /// Session identifier. Omit to create a new session.
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub session_id: Option<String>,
79
80    /// Model to use for generation.
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub model: Option<String>,
83
84    /// The user message.
85    pub message: String,
86
87    /// Tools the model can call.
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub tools: Option<Vec<ChatTool>>,
90
91    /// Results from previous tool calls.
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub tool_results: Option<Vec<ToolResult>>,
94
95    /// Enable streaming.
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub stream: Option<bool>,
98
99    /// System prompt for the session.
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub system_prompt: Option<String>,
102
103    /// Context management configuration.
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub context_config: Option<ContextConfig>,
106
107    /// Provider-specific settings.
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub provider_options: Option<HashMap<String, serde_json::Value>>,
110}
111
112/// Context metadata returned with session responses.
113#[derive(Debug, Clone, Deserialize)]
114pub struct SessionContext {
115    /// Number of conversation turns in the session.
116    pub turn_count: i64,
117
118    /// Estimated total tokens in the session context.
119    pub estimated_tokens: i64,
120
121    /// Whether context was compacted during this turn.
122    #[serde(default)]
123    pub compacted: bool,
124
125    /// Note about the compaction, if any.
126    #[serde(default)]
127    pub compaction_note: Option<String>,
128}
129
130/// Response from session-based chat.
131#[derive(Debug, Clone, Deserialize)]
132pub struct SessionChatResponse {
133    /// The session identifier (may be newly created).
134    pub session_id: String,
135
136    /// The chat response.
137    pub response: ChatResponse,
138
139    /// Session context metadata.
140    pub context: SessionContext,
141}
142
143impl Client {
144    /// Sends a message within a persistent session.
145    ///
146    /// Sessions maintain conversation history server-side with automatic
147    /// context compaction. Omit `session_id` to start a new session.
148    pub async fn chat_session(&self, req: &SessionChatRequest) -> Result<SessionChatResponse> {
149        let (resp, _meta) = self
150            .post_json::<SessionChatRequest, SessionChatResponse>("/qai/v1/chat/session", req)
151            .await?;
152        Ok(resp)
153    }
154}