1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::{HostRuntimeContext, Message, ModelSpec};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct SessionTime {
9 pub created: DateTime<Utc>,
10 pub updated: DateTime<Utc>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Session {
15 pub id: String,
16 pub slug: Option<String>,
17 pub version: Option<String>,
18 pub project_id: Option<String>,
19 pub title: String,
20 pub directory: String,
21 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub workspace_root: Option<String>,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub origin_workspace_root: Option<String>,
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub attached_from_workspace: Option<String>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub attached_to_workspace: Option<String>,
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub attach_timestamp_ms: Option<u64>,
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub attach_reason: Option<String>,
33 pub time: SessionTime,
34 pub model: Option<ModelSpec>,
35 pub provider: Option<String>,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 pub environment: Option<HostRuntimeContext>,
38 #[serde(default)]
39 pub messages: Vec<Message>,
40}
41
42impl Session {
43 pub fn new(title: Option<String>, directory: Option<String>) -> Self {
44 let now = Utc::now();
45 Self {
46 id: Uuid::new_v4().to_string(),
47 slug: None,
48 version: Some("v1".to_string()),
49 project_id: None,
50 title: title.unwrap_or_else(|| "New session".to_string()),
51 directory: directory.unwrap_or_else(|| ".".to_string()),
52 workspace_root: None,
53 origin_workspace_root: None,
54 attached_from_workspace: None,
55 attached_to_workspace: None,
56 attach_timestamp_ms: None,
57 attach_reason: None,
58 time: SessionTime {
59 created: now,
60 updated: now,
61 },
62 model: None,
63 provider: None,
64 environment: None,
65 messages: Vec::new(),
66 }
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct CreateSessionRequest {
72 pub parent_id: Option<String>,
73 pub title: Option<String>,
74 pub directory: Option<String>,
75 pub workspace_root: Option<String>,
76 pub project_id: Option<String>,
77 pub model: Option<ModelSpec>,
78 pub provider: Option<String>,
79 pub permission: Option<Vec<serde_json::Value>>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct SendMessageRequest {
84 #[serde(default)]
85 pub parts: Vec<crate::MessagePartInput>,
86 pub model: Option<ModelSpec>,
87 pub agent: Option<String>,
88 #[serde(default, alias = "toolMode", alias = "tool_mode")]
89 pub tool_mode: Option<ToolMode>,
90 #[serde(default, alias = "toolAllowlist", alias = "tool_allowlist")]
91 pub tool_allowlist: Option<Vec<String>>,
92 #[serde(default, alias = "contextMode", alias = "context_mode")]
93 pub context_mode: Option<ContextMode>,
94 #[serde(default, alias = "writeRequired", alias = "write_required")]
95 pub write_required: Option<bool>,
96 #[serde(
97 default,
98 alias = "prewriteRequirements",
99 alias = "prewrite_requirements"
100 )]
101 pub prewrite_requirements: Option<PrewriteRequirements>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize, Default)]
105pub struct PrewriteRequirements {
106 #[serde(
107 default,
108 alias = "workspaceInspectionRequired",
109 alias = "workspace_inspection_required"
110 )]
111 pub workspace_inspection_required: bool,
112 #[serde(
113 default,
114 alias = "webResearchRequired",
115 alias = "web_research_required"
116 )]
117 pub web_research_required: bool,
118 #[serde(
119 default,
120 alias = "concreteReadRequired",
121 alias = "concrete_read_required"
122 )]
123 pub concrete_read_required: bool,
124 #[serde(
125 default,
126 alias = "successfulWebResearchRequired",
127 alias = "successful_web_research_required"
128 )]
129 pub successful_web_research_required: bool,
130 #[serde(
131 default,
132 alias = "repairOnUnmetRequirements",
133 alias = "repair_on_unmet_requirements"
134 )]
135 pub repair_on_unmet_requirements: bool,
136 #[serde(default, alias = "coverageMode", alias = "coverage_mode")]
137 pub coverage_mode: PrewriteCoverageMode,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
141#[serde(rename_all = "snake_case")]
142pub enum PrewriteCoverageMode {
143 #[default]
144 None,
145 FilesReviewedBacked,
146 ResearchCorpus,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
150#[serde(rename_all = "snake_case")]
151pub enum ToolMode {
152 Auto,
153 None,
154 Required,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
158#[serde(rename_all = "snake_case")]
159pub enum ContextMode {
160 Auto,
161 Compact,
162 Full,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct TodoItem {
167 pub id: String,
168 pub content: String,
169 pub status: String,
170}