1use super::helpers::parse_csv_items;
4use crate::domain::{
5 ContextBundle, MemoryScope, OutputFormat, RouteInput, TargetTool, WakeupPacket, WakeupProfile,
6};
7use crate::lifecycle_service::{LifecycleAction, LifecycleWorkbenchSnapshot};
8use crate::lifecycle_store::{
9 LedgerEntry, ProposeMemoryRequest, RecordMemoryRequest, TransitionMetadata,
10};
11use serde::{Deserialize, Serialize};
12use serde_json::Value;
13use std::path::PathBuf;
14use ts_rs::TS;
15
16#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
19#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
20pub struct DesktopRouteRequest {
21 #[ts(type = "string")]
22 pub config_path: PathBuf,
23 #[ts(type = "string | null")]
24 pub vault_root_override: Option<PathBuf>,
25 #[ts(type = "string")]
26 pub cwd: PathBuf,
27 pub task: String,
28 pub files: Vec<String>,
29 pub target: TargetTool,
30 pub format: OutputFormat,
31}
32
33#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
34#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
35pub struct DesktopWakeupRequest {
36 #[ts(type = "string")]
37 pub config_path: PathBuf,
38 #[ts(type = "string | null")]
39 pub vault_root_override: Option<PathBuf>,
40 #[ts(type = "string")]
41 pub cwd: PathBuf,
42 pub task: String,
43 pub files: Vec<String>,
44 pub target: TargetTool,
45 pub profile: WakeupProfile,
46}
47
48#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
49#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
50pub struct DesktopPromptOptimizeRequest {
51 #[ts(type = "string")]
52 pub config_path: PathBuf,
53 #[ts(type = "string | null")]
54 pub vault_root_override: Option<PathBuf>,
55 #[ts(type = "string")]
56 pub cwd: PathBuf,
57 pub task: String,
58 pub files: Vec<String>,
59 pub target: TargetTool,
60 pub profile: WakeupProfile,
61 pub provider: Option<String>,
62 pub session_id: Option<String>,
63}
64
65#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
66#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
67pub struct DesktopWorkbenchRequest {
68 #[ts(type = "string")]
69 pub config_path: PathBuf,
70 pub daemon: Option<DesktopDaemonRequest>,
71}
72
73#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
74#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
75pub struct DesktopRecordLookupRequest {
76 #[ts(type = "string")]
77 pub config_path: PathBuf,
78 pub record_id: String,
79 pub daemon: Option<DesktopDaemonRequest>,
80}
81
82#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
83#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
84pub struct DesktopSessionBrowserRequest {
85 #[ts(type = "string")]
86 pub config_path: PathBuf,
87 pub page: usize,
88 pub per_page: usize,
89 pub provider: Option<String>,
90}
91
92#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
93#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
94pub struct DesktopSessionDetailRequest {
95 #[ts(type = "string")]
96 pub config_path: PathBuf,
97 pub session_id: String,
98 pub message_offset: Option<usize>,
99 pub message_limit: Option<usize>,
100}
101
102#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
103#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
104pub struct DesktopSessionActionRequest {
105 #[ts(type = "string")]
106 pub config_path: PathBuf,
107 pub session_id: String,
108}
109
110#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
111#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
112pub struct DesktopStatusRequest {
113 #[ts(type = "string")]
114 pub config_path: PathBuf,
115 #[ts(type = "string | null")]
116 pub vault_root_override: Option<PathBuf>,
117 #[ts(type = "string")]
118 pub cwd: PathBuf,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
122#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
123pub struct DesktopWikiLintRequest {
124 #[ts(type = "string")]
125 pub config_path: PathBuf,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
129#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
130pub struct DesktopWikiIndexRequest {
131 #[ts(type = "string")]
132 pub config_path: PathBuf,
133 #[serde(default)]
134 pub project_id: Option<String>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
138#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
139pub struct DesktopImportSessionRequest {
140 #[ts(type = "string")]
141 pub config_path: PathBuf,
142 pub provider: String,
143 pub session_id: String,
144 #[serde(default)]
145 pub apply: bool,
146 #[serde(default)]
147 pub actor: Option<String>,
148}
149
150pub type DesktopImportSessionResponse = crate::memory_importer::ImportSessionResponse;
151
152#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
153#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
154pub struct DesktopMemoryDraftRequest {
155 #[ts(type = "string")]
156 pub config_path: PathBuf,
157 pub title: String,
158 pub summary: String,
159 pub memory_type: String,
160 pub scope: MemoryScope,
161 pub source_ref: String,
162 pub project_id: Option<String>,
163 pub user_id: Option<String>,
164 pub sensitivity: Option<String>,
165 pub metadata: DesktopMetadataDto,
166 #[serde(default)]
168 pub entities: Vec<String>,
169 #[serde(default)]
170 pub tags: Vec<String>,
171 #[serde(default)]
172 pub triggers: Vec<String>,
173 #[serde(default)]
174 pub related_files: Vec<String>,
175 #[serde(default)]
176 pub related_records: Vec<String>,
177 #[serde(default)]
178 pub supersedes: Option<String>,
179 #[serde(default)]
180 pub applies_to: Vec<String>,
181 #[serde(default)]
182 pub valid_until: Option<String>,
183}
184
185#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
186#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
187pub struct DesktopMemoryActionRequest {
188 #[ts(type = "string")]
189 pub config_path: PathBuf,
190 pub record_id: String,
191 pub action: DesktopLifecycleActionDto,
192 pub metadata: DesktopMetadataDto,
193}
194
195#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
196#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
197pub struct DesktopDaemonRequest {
198 pub enabled: bool,
199 #[ts(type = "string | null")]
200 pub daemon_bin: Option<PathBuf>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TS)]
204#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
205pub struct DesktopMetadataDto {
206 pub actor: Option<String>,
207 pub reason: Option<String>,
208 pub evidence_refs: Vec<String>,
209}
210
211#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ts_rs::TS)]
212#[serde(rename_all = "snake_case")]
213#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
214pub enum DesktopLifecycleActionDto {
215 Accept,
216 Promote,
217 Archive,
218}
219
220#[derive(Debug, Clone, Serialize, TS)]
223#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
224pub struct DesktopContextResponse {
225 pub rendered: String,
226 pub explain: String,
227 pub used_format: OutputFormat,
228 #[ts(type = "string")]
229 pub used_vault_root: PathBuf,
230 pub bundle: ContextBundle,
231}
232
233#[derive(Debug, Clone, Serialize, TS)]
234#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
235pub struct DesktopWakeupResponse {
236 #[ts(type = "string")]
237 pub used_vault_root: PathBuf,
238 pub bundle: ContextBundle,
239 pub packet: WakeupPacket,
240}
241
242pub type DesktopPromptOptimizeResponse = crate::memory_gateway::PromptOptimizeResponse;
243
244#[derive(Debug, Clone, Serialize, TS)]
245#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
246pub struct DesktopWorkbenchResponse {
247 pub snapshot: LifecycleWorkbenchSnapshot,
248 #[ts(type = "unknown")]
249 pub payload: Value,
250}
251
252#[derive(Debug, Clone, Serialize, TS)]
253#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
254pub struct DesktopRecordResponse {
255 pub record: LedgerEntry,
256 #[ts(type = "unknown")]
257 pub payload: Value,
258 pub rendered: String,
259 pub available_actions: Vec<DesktopLifecycleActionDto>,
260}
261
262#[derive(Debug, Clone, Serialize, TS)]
263#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
264pub struct DesktopHistoryResponse {
265 pub record_id: String,
266 pub history: Vec<LedgerEntry>,
267 #[ts(type = "unknown")]
268 pub payload: Value,
269 pub rendered: String,
270}
271
272#[derive(Debug, Clone, Serialize, TS)]
273#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
274pub struct DesktopWriteResponse {
275 pub entry: LedgerEntry,
276 #[ts(type = "unknown")]
277 pub payload: Value,
278}
279
280#[derive(Debug, Clone, Serialize, TS)]
281#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
282pub struct DesktopSessionItem {
283 pub provider: String,
284 pub session_id: String,
285 pub title: String,
286 pub summary: Option<String>,
287 pub prompt_preview: Option<String>,
288 pub cwd: Option<String>,
289 pub source_path: Option<String>,
290 pub project_path: Option<String>,
291 pub updated_at: String,
292 pub record_count: usize,
293 pub pending_review_count: usize,
294 pub wakeup_ready_count: usize,
295 pub titles: Vec<String>,
296 pub memory_types: Vec<String>,
297}
298
299#[derive(Debug, Clone, Serialize, TS)]
300#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
301pub struct DesktopSessionBrowserResponse {
302 pub sessions: Vec<DesktopSessionItem>,
303 pub page: usize,
304 pub per_page: usize,
305 pub total: usize,
306 pub has_more: bool,
307}
308
309#[derive(Debug, Clone, Serialize, TS)]
310#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
311pub struct DesktopSessionMessage {
312 pub role: String,
313 pub timestamp: String,
314 pub content: String,
315 pub truncated: bool,
316}
317
318#[derive(Debug, Clone, Serialize, TS)]
319#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
320pub struct DesktopSessionDetailResponse {
321 pub session: DesktopSessionItem,
322 pub records: Vec<LedgerEntry>,
323 pub messages: Vec<DesktopSessionMessage>,
324 pub total_messages: usize,
325 pub showing_recent_messages: usize,
326 pub has_more_messages: bool,
327 pub latest_user_message: Option<String>,
328}
329
330#[derive(Debug, Clone, Serialize, TS)]
331#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
332pub struct DesktopSessionActionResponse {
333 pub session_id: String,
334 pub provider: String,
335 pub command: Option<String>,
336 pub message: String,
337}
338
339#[derive(Debug, Clone, Serialize, TS)]
340#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
341pub struct DesktopWikiLintResponse {
342 #[ts(type = "string")]
343 pub used_vault_root: PathBuf,
344 pub report: crate::wiki_lint::LintReport,
345 pub markdown: String,
346}
347
348#[derive(Debug, Clone, Serialize, TS)]
349#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
350pub struct DesktopWikiIndexResponse {
351 #[ts(type = "string")]
352 pub used_vault_root: PathBuf,
353 pub markdown: Option<String>,
354}
355
356impl DesktopRouteRequest {
359 pub(super) fn to_route_input(&self) -> RouteInput {
360 RouteInput {
361 task: self.task.clone(),
362 cwd: self.cwd.clone(),
363 files: self.files.clone(),
364 target: self.target,
365 format: self.format,
366 }
367 }
368}
369
370impl DesktopWakeupRequest {
371 pub(super) fn to_route_input(&self) -> RouteInput {
372 RouteInput {
373 task: self.task.clone(),
374 cwd: self.cwd.clone(),
375 files: self.files.clone(),
376 target: self.target,
377 format: OutputFormat::Json,
378 }
379 }
380}
381
382impl DesktopPromptOptimizeRequest {
383 pub(super) fn to_route_input(&self) -> RouteInput {
384 RouteInput {
385 task: self.task.clone(),
386 cwd: self.cwd.clone(),
387 files: self.files.clone(),
388 target: self.target,
389 format: OutputFormat::Prompt,
390 }
391 }
392}
393
394impl DesktopMemoryDraftRequest {
395 pub(super) fn to_record_request(&self) -> RecordMemoryRequest {
396 RecordMemoryRequest {
397 title: self.title.clone(),
398 summary: self.summary.clone(),
399 memory_type: self.memory_type.clone(),
400 scope: self.scope,
401 source_ref: self.source_ref.clone(),
402 project_id: self.project_id.clone(),
403 user_id: self.user_id.clone(),
404 sensitivity: self.sensitivity.clone(),
405 metadata: self.metadata.clone().into_transition_metadata(),
406 entities: self.entities.clone(),
407 tags: self.tags.clone(),
408 triggers: self.triggers.clone(),
409 related_files: self.related_files.clone(),
410 related_records: self.related_records.clone(),
411 supersedes: self.supersedes.clone(),
412 applies_to: self.applies_to.clone(),
413 valid_until: self.valid_until.clone(),
414 }
415 }
416
417 pub(super) fn to_propose_request(&self) -> ProposeMemoryRequest {
418 ProposeMemoryRequest {
419 title: self.title.clone(),
420 summary: self.summary.clone(),
421 memory_type: self.memory_type.clone(),
422 scope: self.scope,
423 source_ref: self.source_ref.clone(),
424 project_id: self.project_id.clone(),
425 user_id: self.user_id.clone(),
426 sensitivity: self.sensitivity.clone(),
427 metadata: self.metadata.clone().into_transition_metadata(),
428 entities: self.entities.clone(),
429 tags: self.tags.clone(),
430 triggers: self.triggers.clone(),
431 related_files: self.related_files.clone(),
432 related_records: self.related_records.clone(),
433 supersedes: self.supersedes.clone(),
434 applies_to: self.applies_to.clone(),
435 valid_until: self.valid_until.clone(),
436 }
437 }
438}
439
440impl DesktopMetadataDto {
441 pub fn from_evidence_csv(value: &str) -> Self {
442 Self {
443 actor: None,
444 reason: None,
445 evidence_refs: parse_csv_items(value),
446 }
447 }
448
449 pub(super) fn into_transition_metadata(self) -> TransitionMetadata {
450 TransitionMetadata {
451 actor: self.actor,
452 reason: self.reason,
453 evidence_refs: self.evidence_refs,
454 }
455 }
456}
457
458impl DesktopLifecycleActionDto {
459 pub(super) fn from_lifecycle_action(action: LifecycleAction) -> Self {
460 match action {
461 LifecycleAction::Accept => Self::Accept,
462 LifecycleAction::PromoteToCanonical => Self::Promote,
463 LifecycleAction::Archive => Self::Archive,
464 }
465 }
466
467 pub(super) fn into_lifecycle_action(self) -> LifecycleAction {
468 match self {
469 Self::Accept => LifecycleAction::Accept,
470 Self::Promote => LifecycleAction::PromoteToCanonical,
471 Self::Archive => LifecycleAction::Archive,
472 }
473 }
474}