Skip to main content

intent_engine/
backend.rs

1//! Backend trait abstractions for SQLite and Neo4j.
2//!
3//! These traits define the shared interface that both storage backends implement.
4//! Methods that exist only on one backend (e.g. SQLite's `spawn_subtask`, Neo4j's
5//! `delete_task_cascade`) remain on their concrete structs.
6
7use std::future::Future;
8
9use crate::db::models::{
10    DoneTaskResponse, Event, PaginatedSearchResults, PaginatedTasks, PickNextResponse,
11    StatusResponse, Task, TaskContext, TaskSortBy, TaskWithEvents,
12};
13use crate::error::Result;
14use crate::plan::{PlanRequest, PlanResult};
15use crate::tasks::TaskUpdate;
16use crate::workspace::CurrentTaskResponse;
17
18/// Task CRUD + lifecycle operations.
19pub trait TaskBackend: Send + Sync {
20    // ── Read ────────────────────────────────────────────────────────
21
22    fn get_task(&self, id: i64) -> impl Future<Output = Result<Task>> + Send;
23
24    fn get_task_with_events(&self, id: i64) -> impl Future<Output = Result<TaskWithEvents>> + Send;
25
26    fn get_task_ancestry(&self, task_id: i64) -> impl Future<Output = Result<Vec<Task>>> + Send;
27
28    fn get_task_context(&self, id: i64) -> impl Future<Output = Result<TaskContext>> + Send;
29
30    fn get_siblings(
31        &self,
32        id: i64,
33        parent_id: Option<i64>,
34    ) -> impl Future<Output = Result<Vec<Task>>> + Send;
35
36    fn get_children(&self, id: i64) -> impl Future<Output = Result<Vec<Task>>> + Send;
37
38    fn get_blocking_tasks(&self, id: i64) -> impl Future<Output = Result<Vec<Task>>> + Send;
39
40    fn get_blocked_by_tasks(&self, id: i64) -> impl Future<Output = Result<Vec<Task>>> + Send;
41
42    fn get_descendants(&self, task_id: i64) -> impl Future<Output = Result<Vec<Task>>> + Send;
43
44    fn get_status(
45        &self,
46        task_id: i64,
47        with_events: bool,
48    ) -> impl Future<Output = Result<StatusResponse>> + Send;
49
50    fn get_root_tasks(&self) -> impl Future<Output = Result<Vec<Task>>> + Send;
51
52    fn find_tasks(
53        &self,
54        status: Option<String>,
55        parent_id: Option<Option<i64>>,
56        sort_by: Option<TaskSortBy>,
57        limit: Option<i64>,
58        offset: Option<i64>,
59    ) -> impl Future<Output = Result<PaginatedTasks>> + Send;
60
61    // ── Write ───────────────────────────────────────────────────────
62
63    fn add_task(
64        &self,
65        name: String,
66        spec: Option<String>,
67        parent_id: Option<i64>,
68        owner: Option<String>,
69        priority: Option<i32>,
70        metadata: Option<String>,
71    ) -> impl Future<Output = Result<Task>> + Send;
72
73    fn update_task(
74        &self,
75        id: i64,
76        update: TaskUpdate<'_>,
77    ) -> impl Future<Output = Result<Task>> + Send;
78
79    fn delete_task(&self, id: i64) -> impl Future<Output = Result<()>> + Send;
80
81    fn delete_task_cascade(&self, id: i64) -> impl Future<Output = Result<usize>> + Send;
82
83    // ── Dependencies ──────────────────────────────────────────────
84
85    fn add_dependency(
86        &self,
87        blocking_id: i64,
88        blocked_id: i64,
89    ) -> impl Future<Output = Result<()>> + Send;
90
91    fn remove_dependency(
92        &self,
93        blocking_id: i64,
94        blocked_id: i64,
95    ) -> impl Future<Output = Result<()>> + Send;
96
97    // ── Lifecycle ───────────────────────────────────────────────────
98
99    fn start_task(
100        &self,
101        id: i64,
102        with_events: bool,
103    ) -> impl Future<Output = Result<TaskWithEvents>> + Send;
104
105    fn done_task(
106        &self,
107        is_ai_caller: bool,
108    ) -> impl Future<Output = Result<DoneTaskResponse>> + Send;
109
110    fn done_task_by_id(
111        &self,
112        id: i64,
113        is_ai_caller: bool,
114    ) -> impl Future<Output = Result<DoneTaskResponse>> + Send;
115
116    fn pick_next(&self) -> impl Future<Output = Result<PickNextResponse>> + Send;
117}
118
119/// Session/workspace focus management.
120pub trait WorkspaceBackend: Send + Sync {
121    fn get_current_task(
122        &self,
123        session_id: Option<&str>,
124    ) -> impl Future<Output = Result<CurrentTaskResponse>> + Send;
125
126    fn set_current_task(
127        &self,
128        task_id: i64,
129        session_id: Option<&str>,
130    ) -> impl Future<Output = Result<CurrentTaskResponse>> + Send;
131
132    fn clear_current_task(
133        &self,
134        session_id: Option<&str>,
135    ) -> impl Future<Output = Result<()>> + Send;
136}
137
138/// Event (decision log) operations.
139pub trait EventBackend: Send + Sync {
140    fn add_event(
141        &self,
142        task_id: i64,
143        log_type: String,
144        discussion_data: String,
145    ) -> impl Future<Output = Result<Event>> + Send;
146
147    fn list_events(
148        &self,
149        task_id: Option<i64>,
150        limit: Option<i64>,
151        log_type: Option<String>,
152        since: Option<String>,
153    ) -> impl Future<Output = Result<Vec<Event>>> + Send;
154}
155
156/// Batch plan execution.
157pub trait PlanBackend: Send + Sync {
158    fn execute(&self, request: &PlanRequest) -> impl Future<Output = Result<PlanResult>> + Send;
159}
160
161/// Full-text and status-keyword search operations.
162pub trait SearchBackend: Send + Sync {
163    /// Unified search across tasks and events.
164    fn search(
165        &self,
166        query: String,
167        include_tasks: bool,
168        include_events: bool,
169        limit: Option<i64>,
170        offset: Option<i64>,
171    ) -> impl Future<Output = Result<PaginatedSearchResults>> + Send;
172}