1use super::IntegrationResult;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct BrowserTab {
18 pub id: String,
19 pub window_id: String,
20 pub url: String,
21 pub title: String,
22 pub favicon_url: Option<String>,
23 pub is_active: bool,
24 pub is_pinned: bool,
25 pub is_muted: bool,
26 pub index: u32,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct BrowserWindow {
32 pub id: String,
33 pub tabs: Vec<BrowserTab>,
34 pub is_focused: bool,
35 pub is_incognito: bool,
36 pub bounds: Option<WindowBounds>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct WindowBounds {
41 pub x: i32,
42 pub y: i32,
43 pub width: u32,
44 pub height: u32,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct Bookmark {
50 pub id: String,
51 pub title: String,
52 pub url: Option<String>,
53 pub parent_id: Option<String>,
54 pub is_folder: bool,
55 pub children: Vec<Bookmark>,
56 pub date_added: Option<String>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct HistoryItem {
62 pub id: String,
63 pub url: String,
64 pub title: String,
65 pub visit_count: u32,
66 pub last_visit: String,
67}
68
69#[async_trait::async_trait]
71pub trait BrowserProvider: Send + Sync {
72 async fn list_tabs(&self) -> IntegrationResult;
74 async fn open_url(&self, url: &str, new_tab: bool) -> IntegrationResult;
75 async fn close_tab(&self, tab_id: &str) -> IntegrationResult;
76 async fn activate_tab(&self, tab_id: &str) -> IntegrationResult;
77 async fn reload_tab(&self, tab_id: &str) -> IntegrationResult;
78 async fn duplicate_tab(&self, tab_id: &str) -> IntegrationResult;
79 async fn pin_tab(&self, tab_id: &str, pinned: bool) -> IntegrationResult;
80 async fn mute_tab(&self, tab_id: &str, muted: bool) -> IntegrationResult;
81
82 async fn list_windows(&self) -> IntegrationResult;
84 async fn create_window(&self, url: Option<&str>, incognito: bool) -> IntegrationResult;
85 async fn close_window(&self, window_id: &str) -> IntegrationResult;
86
87 async fn get_bookmarks(&self) -> IntegrationResult;
89 async fn create_bookmark(
90 &self,
91 title: &str,
92 url: &str,
93 folder_id: Option<&str>,
94 ) -> IntegrationResult;
95 async fn delete_bookmark(&self, bookmark_id: &str) -> IntegrationResult;
96
97 async fn get_history(&self, max_results: u32) -> IntegrationResult;
99 async fn search_history(&self, query: &str, max_results: u32) -> IntegrationResult;
100 async fn delete_history(&self, url: &str) -> IntegrationResult;
101
102 async fn get_page_content(&self, tab_id: &str) -> IntegrationResult;
104 async fn execute_script(&self, tab_id: &str, script: &str) -> IntegrationResult;
105 async fn take_screenshot(&self, tab_id: &str) -> IntegrationResult;
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
114pub struct ArcSpace {
115 pub id: String,
116 pub name: String,
117 pub color: String,
118 pub icon: Option<String>,
119 pub tabs: Vec<BrowserTab>,
120}
121
122#[async_trait::async_trait]
124pub trait ArcProvider: BrowserProvider {
125 async fn list_spaces(&self) -> IntegrationResult;
126 async fn create_space(&self, name: &str, color: &str) -> IntegrationResult;
127 async fn switch_space(&self, space_id: &str) -> IntegrationResult;
128 async fn move_tab_to_space(&self, tab_id: &str, space_id: &str) -> IntegrationResult;
129 async fn get_little_arc_tabs(&self) -> IntegrationResult;
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct PageElement {
139 pub selector: String,
140 pub tag_name: String,
141 pub text: Option<String>,
142 pub attributes: HashMap<String, String>,
143 pub is_visible: bool,
144 pub bounding_box: Option<BoundingBox>,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct BoundingBox {
149 pub x: f64,
150 pub y: f64,
151 pub width: f64,
152 pub height: f64,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157#[serde(tag = "type", rename_all = "snake_case")]
158pub enum AutomationAction {
159 Navigate {
160 url: String,
161 },
162 Click {
163 selector: String,
164 },
165 DoubleClick {
166 selector: String,
167 },
168 RightClick {
169 selector: String,
170 },
171 Type {
172 selector: String,
173 text: String,
174 },
175 Clear {
176 selector: String,
177 },
178 Select {
179 selector: String,
180 value: String,
181 },
182 Check {
183 selector: String,
184 checked: bool,
185 },
186 Hover {
187 selector: String,
188 },
189 Focus {
190 selector: String,
191 },
192 Scroll {
193 x: i32,
194 y: i32,
195 },
196 ScrollTo {
197 selector: String,
198 },
199 WaitFor {
200 selector: String,
201 timeout_ms: u64,
202 },
203 WaitForNavigation {
204 timeout_ms: u64,
205 },
206 Screenshot {
207 path: String,
208 full_page: bool,
209 },
210 Pdf {
211 path: String,
212 },
213 Evaluate {
214 script: String,
215 },
216 SetViewport {
217 width: u32,
218 height: u32,
219 },
220 SetCookie {
221 name: String,
222 value: String,
223 domain: String,
224 },
225 Delay {
226 ms: u64,
227 },
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct AutomationScript {
233 pub name: String,
234 pub description: Option<String>,
235 pub start_url: String,
236 pub actions: Vec<AutomationAction>,
237 pub headless: bool,
238 pub viewport: Option<(u32, u32)>,
239 pub timeout_ms: u64,
240}
241
242#[async_trait::async_trait]
244pub trait AutomationProvider: Send + Sync {
245 async fn create_session(&self, headless: bool) -> IntegrationResult;
247 async fn close_session(&self, session_id: &str) -> IntegrationResult;
248
249 async fn navigate(&self, session_id: &str, url: &str) -> IntegrationResult;
251 async fn go_back(&self, session_id: &str) -> IntegrationResult;
252 async fn go_forward(&self, session_id: &str) -> IntegrationResult;
253 async fn reload(&self, session_id: &str) -> IntegrationResult;
254
255 async fn click(&self, session_id: &str, selector: &str) -> IntegrationResult;
257 async fn type_text(&self, session_id: &str, selector: &str, text: &str) -> IntegrationResult;
258 async fn fill(&self, session_id: &str, selector: &str, value: &str) -> IntegrationResult;
259 async fn select_option(
260 &self,
261 session_id: &str,
262 selector: &str,
263 value: &str,
264 ) -> IntegrationResult;
265 async fn check(&self, session_id: &str, selector: &str) -> IntegrationResult;
266 async fn uncheck(&self, session_id: &str, selector: &str) -> IntegrationResult;
267
268 async fn wait_for_selector(
270 &self,
271 session_id: &str,
272 selector: &str,
273 timeout_ms: u64,
274 ) -> IntegrationResult;
275 async fn wait_for_navigation(&self, session_id: &str, timeout_ms: u64) -> IntegrationResult;
276
277 async fn get_text(&self, session_id: &str, selector: &str) -> IntegrationResult;
279 async fn get_attribute(
280 &self,
281 session_id: &str,
282 selector: &str,
283 attribute: &str,
284 ) -> IntegrationResult;
285 async fn get_html(&self, session_id: &str, selector: Option<&str>) -> IntegrationResult;
286 async fn query_selector_all(&self, session_id: &str, selector: &str) -> IntegrationResult;
287
288 async fn screenshot(&self, session_id: &str, path: &str, full_page: bool) -> IntegrationResult;
290 async fn pdf(&self, session_id: &str, path: &str) -> IntegrationResult;
291
292 async fn run_script(&self, script: &AutomationScript) -> IntegrationResult;
294 async fn evaluate(&self, session_id: &str, script: &str) -> IntegrationResult;
295}
296
297#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct ScrapeConfig {
304 pub url: String,
305 pub selectors: HashMap<String, String>,
306 pub wait_for: Option<String>,
307 pub pagination: Option<PaginationConfig>,
308 pub headers: Option<HashMap<String, String>>,
309 pub cookies: Option<Vec<Cookie>>,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
313pub struct PaginationConfig {
314 pub next_selector: String,
315 pub max_pages: u32,
316 pub delay_ms: u64,
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct Cookie {
321 pub name: String,
322 pub value: String,
323 pub domain: String,
324 pub path: Option<String>,
325 pub expires: Option<i64>,
326 pub http_only: Option<bool>,
327 pub secure: Option<bool>,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct ScrapeResult {
333 pub url: String,
334 pub data: HashMap<String, Vec<String>>,
335 pub page_title: String,
336 pub scraped_at: String,
337}
338
339#[async_trait::async_trait]
341pub trait ScrapingProvider: Send + Sync {
342 async fn scrape(&self, config: &ScrapeConfig) -> IntegrationResult;
343 async fn scrape_text(&self, url: &str) -> IntegrationResult;
344 async fn scrape_links(&self, url: &str) -> IntegrationResult;
345 async fn scrape_images(&self, url: &str) -> IntegrationResult;
346 async fn scrape_tables(&self, url: &str) -> IntegrationResult;
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct SavedArticle {
356 pub id: String,
357 pub url: String,
358 pub title: String,
359 pub excerpt: Option<String>,
360 pub content: Option<String>,
361 pub author: Option<String>,
362 pub published_at: Option<String>,
363 pub saved_at: String,
364 pub reading_time: Option<u32>,
365 pub is_read: bool,
366 pub is_favorited: bool,
367 pub tags: Vec<String>,
368}
369
370#[async_trait::async_trait]
372pub trait ReadLaterProvider: Send + Sync {
373 async fn save_url(
374 &self,
375 url: &str,
376 title: Option<&str>,
377 tags: Option<&[String]>,
378 ) -> IntegrationResult;
379 async fn list_articles(&self, unread_only: bool, limit: u32) -> IntegrationResult;
380 async fn get_article(&self, article_id: &str) -> IntegrationResult;
381 async fn archive_article(&self, article_id: &str) -> IntegrationResult;
382 async fn delete_article(&self, article_id: &str) -> IntegrationResult;
383 async fn favorite_article(&self, article_id: &str, favorite: bool) -> IntegrationResult;
384 async fn tag_article(&self, article_id: &str, tags: &[String]) -> IntegrationResult;
385}