chasm_cli/integrations/
productivity.rs

1// Copyright (c) 2024-2026 Nervosys LLC
2// SPDX-License-Identifier: Apache-2.0
3//! Productivity Integrations
4//!
5//! Calendar, Email, Notes, Tasks, Documents
6
7#![allow(dead_code)]
8
9use super::{AuthMethod, IntegrationResult};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12
13// =============================================================================
14// Calendar
15// =============================================================================
16
17/// Calendar event
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct CalendarEvent {
20    pub id: String,
21    pub title: String,
22    pub description: Option<String>,
23    pub start: String,
24    pub end: String,
25    pub location: Option<String>,
26    pub attendees: Vec<Attendee>,
27    pub is_all_day: bool,
28    pub recurrence: Option<String>,
29    pub status: EventStatus,
30    pub calendar_id: String,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct Attendee {
35    pub email: String,
36    pub name: Option<String>,
37    pub response: AttendeeResponse,
38}
39
40#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
41#[serde(rename_all = "snake_case")]
42pub enum AttendeeResponse {
43    Accepted,
44    Declined,
45    Tentative,
46    NeedsAction,
47}
48
49#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
50#[serde(rename_all = "snake_case")]
51pub enum EventStatus {
52    Confirmed,
53    Tentative,
54    Cancelled,
55}
56
57/// Calendar provider trait
58#[async_trait::async_trait]
59pub trait CalendarProvider: Send + Sync {
60    async fn list_calendars(&self) -> IntegrationResult;
61    async fn list_events(&self, calendar_id: &str, start: &str, end: &str) -> IntegrationResult;
62    async fn create_event(&self, calendar_id: &str, event: &CalendarEvent) -> IntegrationResult;
63    async fn update_event(&self, event_id: &str, event: &CalendarEvent) -> IntegrationResult;
64    async fn delete_event(&self, event_id: &str) -> IntegrationResult;
65    async fn find_free_time(
66        &self,
67        calendars: &[String],
68        duration_minutes: u32,
69        range_start: &str,
70        range_end: &str,
71    ) -> IntegrationResult;
72}
73
74// =============================================================================
75// Email
76// =============================================================================
77
78/// Email message
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct EmailMessage {
81    pub id: String,
82    pub thread_id: Option<String>,
83    pub from: EmailAddress,
84    pub to: Vec<EmailAddress>,
85    pub cc: Vec<EmailAddress>,
86    pub bcc: Vec<EmailAddress>,
87    pub subject: String,
88    pub body_text: Option<String>,
89    pub body_html: Option<String>,
90    pub attachments: Vec<Attachment>,
91    pub labels: Vec<String>,
92    pub is_read: bool,
93    pub is_starred: bool,
94    pub date: String,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct EmailAddress {
99    pub email: String,
100    pub name: Option<String>,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct Attachment {
105    pub id: String,
106    pub filename: String,
107    pub mime_type: String,
108    pub size: u64,
109}
110
111/// Email draft
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct EmailDraft {
114    pub to: Vec<String>,
115    pub cc: Option<Vec<String>>,
116    pub bcc: Option<Vec<String>>,
117    pub subject: String,
118    pub body: String,
119    pub is_html: bool,
120    pub attachments: Option<Vec<String>>,
121    pub reply_to: Option<String>,
122}
123
124/// Email provider trait
125#[async_trait::async_trait]
126pub trait EmailProvider: Send + Sync {
127    async fn list_emails(&self, folder: &str, limit: u32) -> IntegrationResult;
128    async fn get_email(&self, email_id: &str) -> IntegrationResult;
129    async fn send_email(&self, draft: &EmailDraft) -> IntegrationResult;
130    async fn reply_to_email(&self, email_id: &str, body: &str) -> IntegrationResult;
131    async fn forward_email(&self, email_id: &str, to: &[String]) -> IntegrationResult;
132    async fn move_email(&self, email_id: &str, folder: &str) -> IntegrationResult;
133    async fn label_email(&self, email_id: &str, labels: &[String]) -> IntegrationResult;
134    async fn search_emails(&self, query: &str, limit: u32) -> IntegrationResult;
135    async fn mark_read(&self, email_id: &str, is_read: bool) -> IntegrationResult;
136}
137
138// =============================================================================
139// Notes
140// =============================================================================
141
142/// Note
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct Note {
145    pub id: String,
146    pub title: String,
147    pub content: String,
148    pub folder: Option<String>,
149    pub tags: Vec<String>,
150    pub created_at: String,
151    pub updated_at: String,
152    pub links: Vec<String>,
153    pub backlinks: Vec<String>,
154}
155
156/// Notes provider trait
157#[async_trait::async_trait]
158pub trait NotesProvider: Send + Sync {
159    async fn list_notes(&self, folder: Option<&str>) -> IntegrationResult;
160    async fn get_note(&self, note_id: &str) -> IntegrationResult;
161    async fn create_note(
162        &self,
163        title: &str,
164        content: &str,
165        folder: Option<&str>,
166    ) -> IntegrationResult;
167    async fn update_note(&self, note_id: &str, content: &str) -> IntegrationResult;
168    async fn delete_note(&self, note_id: &str) -> IntegrationResult;
169    async fn search_notes(&self, query: &str) -> IntegrationResult;
170    async fn get_backlinks(&self, note_id: &str) -> IntegrationResult;
171}
172
173// =============================================================================
174// Tasks
175// =============================================================================
176
177/// Task
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct Task {
180    pub id: String,
181    pub title: String,
182    pub description: Option<String>,
183    pub due_date: Option<String>,
184    pub priority: TaskPriority,
185    pub status: TaskStatus,
186    pub project: Option<String>,
187    pub labels: Vec<String>,
188    pub subtasks: Vec<Task>,
189    pub created_at: String,
190    pub completed_at: Option<String>,
191}
192
193#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
194#[serde(rename_all = "snake_case")]
195pub enum TaskPriority {
196    None,
197    Low,
198    Medium,
199    High,
200    Urgent,
201}
202
203#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
204#[serde(rename_all = "snake_case")]
205pub enum TaskStatus {
206    Pending,
207    InProgress,
208    Completed,
209    Cancelled,
210}
211
212/// Tasks provider trait
213#[async_trait::async_trait]
214pub trait TasksProvider: Send + Sync {
215    async fn list_tasks(&self, project: Option<&str>, include_completed: bool)
216        -> IntegrationResult;
217    async fn get_task(&self, task_id: &str) -> IntegrationResult;
218    async fn create_task(&self, task: &Task) -> IntegrationResult;
219    async fn update_task(&self, task_id: &str, task: &Task) -> IntegrationResult;
220    async fn complete_task(&self, task_id: &str) -> IntegrationResult;
221    async fn delete_task(&self, task_id: &str) -> IntegrationResult;
222    async fn list_projects(&self) -> IntegrationResult;
223}
224
225// =============================================================================
226// Documents
227// =============================================================================
228
229/// Document
230#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct Document {
232    pub id: String,
233    pub title: String,
234    pub content: Option<String>,
235    pub mime_type: String,
236    pub folder: Option<String>,
237    pub shared_with: Vec<String>,
238    pub created_at: String,
239    pub updated_at: String,
240    pub web_url: Option<String>,
241}
242
243/// Documents provider trait
244#[async_trait::async_trait]
245pub trait DocumentsProvider: Send + Sync {
246    async fn list_documents(&self, folder: Option<&str>) -> IntegrationResult;
247    async fn get_document(&self, doc_id: &str) -> IntegrationResult;
248    async fn create_document(&self, title: &str, content: &str) -> IntegrationResult;
249    async fn update_document(&self, doc_id: &str, content: &str) -> IntegrationResult;
250    async fn share_document(&self, doc_id: &str, emails: &[String]) -> IntegrationResult;
251    async fn search_documents(&self, query: &str) -> IntegrationResult;
252}