1use serde::{Deserialize, Deserializer, Serialize};
2use std::collections::BTreeMap;
3
4fn deserialize_explicit_nullable_string<'de, D>(
5 deserializer: D,
6) -> Result<Option<Option<String>>, D::Error>
7where
8 D: Deserializer<'de>,
9{
10 let value = serde_json::Value::deserialize(deserializer)?;
11 match value {
12 serde_json::Value::Null => Ok(Some(None)),
13 serde_json::Value::String(value) => Ok(Some(Some(value))),
14 other => Err(serde::de::Error::custom(format!(
15 "expected string or null, received {other}"
16 ))),
17 }
18}
19
20#[derive(Debug, Serialize)]
22#[serde(rename_all = "camelCase")]
23pub struct TaskArtifactSummary {
24 pub total: usize,
25 pub by_type: BTreeMap<String, usize>,
26 pub required_satisfied: bool,
27 pub missing_required: Vec<String>,
28}
29
30#[derive(Debug, Serialize)]
32#[serde(rename_all = "camelCase")]
33pub struct TaskVerificationSummary {
34 pub has_verdict: bool,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub verdict: Option<String>,
37 pub has_report: bool,
38}
39
40#[derive(Debug, Serialize)]
42#[serde(rename_all = "camelCase")]
43pub struct TaskCompletionSummary {
44 pub has_summary: bool,
45}
46
47#[derive(Debug, Serialize)]
49#[serde(rename_all = "camelCase")]
50pub struct TaskRunSummary {
51 pub total: usize,
52 pub latest_status: String,
53}
54
55#[derive(Debug, Serialize)]
57#[serde(rename_all = "camelCase")]
58pub struct TaskEvidenceSummary {
59 pub artifact: TaskArtifactSummary,
60 pub verification: TaskVerificationSummary,
61 pub completion: TaskCompletionSummary,
62 pub runs: TaskRunSummary,
63}
64
65#[derive(Debug, Serialize)]
67#[serde(rename_all = "camelCase")]
68pub struct TaskRunResumeTarget {
69 pub r#type: String,
70 pub id: String,
71}
72
73#[derive(Debug, Serialize)]
75#[serde(rename_all = "camelCase")]
76pub struct TaskRunLedgerEntry {
77 pub id: String,
78 pub kind: String,
79 pub status: String,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub session_id: Option<String>,
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub external_task_id: Option<String>,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub context_id: Option<String>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub column_id: Option<String>,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub step_id: Option<String>,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub step_name: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub provider: Option<String>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub specialist_name: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub started_at: Option<String>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub completed_at: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub owner_instance_id: Option<String>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub resume_target: Option<TaskRunResumeTarget>,
104}
105
106#[derive(Debug, Deserialize)]
108#[serde(rename_all = "camelCase")]
109pub struct CreateTaskArtifactRequest {
110 pub agent_id: Option<String>,
111 #[serde(rename = "type")]
112 pub artifact_type: Option<String>,
113 pub content: Option<String>,
114 pub context: Option<String>,
115 pub request_id: Option<String>,
116 pub metadata: Option<std::collections::BTreeMap<String, String>>,
117}
118
119#[derive(Debug, Deserialize)]
121#[serde(rename_all = "camelCase")]
122pub struct ListTasksQuery {
123 pub workspace_id: Option<String>,
124 pub session_id: Option<String>,
125 pub status: Option<String>,
126 pub assigned_to: Option<String>,
127}
128
129#[derive(Debug, Deserialize)]
131pub struct TaskChangeFileQuery {
132 pub path: Option<String>,
133 pub status: Option<String>,
134 #[serde(rename = "previousPath")]
135 pub previous_path: Option<String>,
136}
137
138#[derive(Debug, Deserialize)]
140pub struct TaskChangeCommitQuery {
141 pub sha: Option<String>,
142}
143
144#[derive(Debug, Deserialize)]
146pub struct TaskChangeStatsQuery {
147 pub paths: Option<String>,
148 pub statuses: Option<String>,
149}
150
151#[derive(Debug, Deserialize)]
153pub struct UpdateStatusRequest {
154 pub status: String,
155}
156
157#[derive(Debug, Deserialize)]
159#[serde(rename_all = "camelCase")]
160pub struct CreateTaskRequest {
161 pub title: String,
162 pub objective: String,
163 pub workspace_id: Option<String>,
164 pub session_id: Option<String>,
165 pub scope: Option<String>,
166 pub acceptance_criteria: Option<Vec<String>>,
167 pub verification_commands: Option<Vec<String>>,
168 pub test_cases: Option<Vec<String>>,
169 pub dependencies: Option<Vec<String>>,
170 pub parallel_group: Option<String>,
171 pub board_id: Option<String>,
172 pub column_id: Option<String>,
173 pub position: Option<i64>,
174 pub priority: Option<String>,
175 pub labels: Option<Vec<String>>,
176 pub assignee: Option<String>,
177 pub assigned_provider: Option<String>,
178 pub assigned_role: Option<String>,
179 pub assigned_specialist_id: Option<String>,
180 pub assigned_specialist_name: Option<String>,
181 pub create_github_issue: Option<bool>,
182 pub repo_path: Option<String>,
183 pub codebase_ids: Option<Vec<String>>,
184 pub worktree_id: Option<serde_json::Value>,
185 pub github_id: Option<String>,
186 pub github_number: Option<i64>,
187 pub github_url: Option<String>,
188 pub github_repo: Option<String>,
189 pub github_state: Option<String>,
190}
191
192#[derive(Debug, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub struct UpdateTaskRequest {
196 pub title: Option<String>,
197 pub objective: Option<String>,
198 pub comment: Option<String>,
199 pub scope: Option<String>,
200 pub acceptance_criteria: Option<Vec<String>>,
201 pub verification_commands: Option<Vec<String>>,
202 pub test_cases: Option<Vec<String>>,
203 pub assigned_to: Option<String>,
204 pub status: Option<String>,
205 pub board_id: Option<String>,
206 pub column_id: Option<String>,
207 pub position: Option<i64>,
208 pub priority: Option<String>,
209 pub labels: Option<Vec<String>>,
210 pub assignee: Option<String>,
211 pub assigned_provider: Option<String>,
212 pub assigned_role: Option<String>,
213 pub assigned_specialist_id: Option<String>,
214 pub assigned_specialist_name: Option<String>,
215 pub trigger_session_id: Option<String>,
216 pub codebase_ids: Option<Vec<String>>,
217 pub verification_plan: Option<String>,
218 pub verification_verdict: Option<String>,
219 pub github_id: Option<String>,
220 pub github_number: Option<i64>,
221 pub github_url: Option<String>,
222 pub github_repo: Option<String>,
223 pub github_state: Option<String>,
224 pub last_sync_error: Option<String>,
225 pub dependencies: Option<Vec<String>>,
226 pub parallel_group: Option<String>,
227 pub completion_summary: Option<String>,
228 pub verification_report: Option<String>,
229 pub sync_to_github: Option<bool>,
230 pub retry_trigger: Option<bool>,
231 pub repo_path: Option<String>,
232 #[serde(default, deserialize_with = "deserialize_explicit_nullable_string")]
233 pub worktree_id: Option<Option<String>>,
234}