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#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11pub struct ContextConfig {
12 #[serde(skip_serializing_if = "Option::is_none")]
14 pub max_tokens: Option<i64>,
15
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub auto_compact: Option<bool>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, Default)]
23pub struct ToolResult {
24 pub tool_call_id: String,
26
27 pub content: String,
29
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub is_error: Option<bool>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, Default)]
37pub struct SessionToolResult {
38 pub tool_call_id: String,
40
41 pub content: String,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub is_error: Option<bool>,
47}
48
49#[derive(Debug, Clone, Deserialize)]
51pub struct ContextMetadata {
52 #[serde(default)]
54 pub turn_count: i64,
55
56 #[serde(default)]
58 pub estimated_tokens: i64,
59
60 #[serde(default)]
62 pub compacted: bool,
63
64 #[serde(default)]
66 pub compaction_note: Option<String>,
67
68 #[serde(default)]
70 pub tools_cleared: Option<i32>,
71}
72
73#[derive(Debug, Clone, Serialize, Default)]
75pub struct SessionChatRequest {
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub session_id: Option<String>,
79
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub model: Option<String>,
83
84 pub message: String,
86
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub tools: Option<Vec<ChatTool>>,
90
91 #[serde(skip_serializing_if = "Option::is_none")]
93 pub tool_results: Option<Vec<ToolResult>>,
94
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub stream: Option<bool>,
98
99 #[serde(skip_serializing_if = "Option::is_none")]
101 pub system_prompt: Option<String>,
102
103 #[serde(skip_serializing_if = "Option::is_none")]
105 pub context_config: Option<ContextConfig>,
106
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub provider_options: Option<HashMap<String, serde_json::Value>>,
110}
111
112#[derive(Debug, Clone, Deserialize)]
114pub struct SessionContext {
115 pub turn_count: i64,
117
118 pub estimated_tokens: i64,
120
121 #[serde(default)]
123 pub compacted: bool,
124
125 #[serde(default)]
127 pub compaction_note: Option<String>,
128}
129
130#[derive(Debug, Clone, Deserialize)]
132pub struct SessionChatResponse {
133 pub session_id: String,
135
136 pub response: ChatResponse,
138
139 pub context: SessionContext,
141}
142
143impl Client {
144 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}