1use crate::Commands;
2use async_trait::async_trait;
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7pub struct ListSequencesQuery {
8 pub limit: Option<usize>,
9 pub offset: Option<usize>,
10 pub favourites_only: Option<bool>,
11 pub search: Option<String>,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct ListSequencesResult {
16 pub sequences: Vec<BrowserSequence>,
17 pub total: usize,
18}
19
20#[async_trait]
21pub trait BrowserSequenceStore: Send + Sync + std::fmt::Debug {
22 async fn create_sequence(&self, seq: NewBrowserSequence) -> anyhow::Result<BrowserSequence>;
23 async fn append_step(&self, step: NewBrowserStep) -> anyhow::Result<BrowserStep>;
24 async fn add_observation(
25 &self,
26 obs: NewBrowserObservation,
27 ) -> anyhow::Result<BrowserObservation>;
28 async fn add_screenshot(&self, shot: NewBrowserScreenshot)
29 -> anyhow::Result<BrowserScreenshot>;
30 async fn list_steps(
31 &self,
32 sequence_id: &str,
33 limit: Option<usize>,
34 ) -> anyhow::Result<Vec<BrowserStep>>;
35 async fn list_observations(
36 &self,
37 sequence_id: &str,
38 limit: Option<usize>,
39 ) -> anyhow::Result<Vec<BrowserObservation>>;
40 async fn list_sequences(
41 &self,
42 query: ListSequencesQuery,
43 ) -> anyhow::Result<ListSequencesResult>;
44 async fn get_sequence(&self, id: &str) -> anyhow::Result<Option<BrowserSequence>>;
45 async fn delete_sequence(&self, id: &str) -> anyhow::Result<()>;
46 async fn set_favourite(&self, id: &str, favourite: bool) -> anyhow::Result<()>;
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
50pub struct BrowserSequence {
51 pub id: String,
52 pub goal: Option<String>,
53 pub task_id: Option<String>,
54 pub thread_id: Option<String>,
55 pub favourite: bool,
56 pub created_at: chrono::DateTime<chrono::Utc>,
57 pub updated_at: chrono::DateTime<chrono::Utc>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
61pub struct BrowserStep {
62 pub id: String,
63 pub browser_sequence_id: String,
64 pub commands: Vec<Commands>,
65 pub reason: Option<String>,
66 pub thread_id: Option<String>,
67 pub task_id: Option<String>,
68 pub run_id: Option<String>,
69 pub success: bool,
70 pub thinking: Option<String>,
71 pub evaluation_previous_goal: Option<String>,
72 pub memory: Option<String>,
73 pub next_goal: Option<String>,
74 pub action_result: Option<serde_json::Value>,
75 pub created_at: chrono::DateTime<chrono::Utc>,
76 pub updated_at: chrono::DateTime<chrono::Utc>,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
80pub struct BrowserObservationData {
81 pub success: bool,
82 pub state_text: Option<String>,
83 pub dom_snapshot: Option<serde_json::Value>,
84 pub screenshot: Option<serde_json::Value>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
88pub struct BrowserObservation {
89 pub id: i64,
90 pub thread_id: String,
91 pub task_id: String,
92 pub run_id: String,
93 pub sequence_id: String,
94 pub observation: BrowserObservationData,
95 pub created_at: chrono::DateTime<chrono::Utc>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
99pub struct BrowserScreenshot {
100 pub id: i64,
101 pub thread_id: String,
102 pub task_id: String,
103 pub run_id: String,
104 pub sequence_id: String,
105 pub screenshot: serde_json::Value,
106 pub created_at: chrono::DateTime<chrono::Utc>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
110pub struct NewBrowserSequence {
111 pub id: String,
112 pub goal: Option<String>,
113 pub task_id: Option<String>,
114 pub thread_id: Option<String>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
118pub struct NewBrowserStep {
119 pub id: String,
120 pub browser_sequence_id: String,
121 pub commands: Vec<Commands>,
122 pub reason: Option<String>,
123 pub thread_id: Option<String>,
124 pub task_id: Option<String>,
125 pub run_id: Option<String>,
126 pub thinking: Option<String>,
127 pub evaluation_previous_goal: Option<String>,
128 pub memory: Option<String>,
129 pub next_goal: Option<String>,
130 pub success: bool,
131 pub action_result: Option<serde_json::Value>,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
135pub struct NewBrowserObservation {
136 pub thread_id: String,
137 pub task_id: String,
138 pub run_id: String,
139 pub sequence_id: String,
140 pub observation: BrowserObservationData,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
144pub struct NewBrowserScreenshot {
145 pub thread_id: String,
146 pub task_id: String,
147 pub run_id: String,
148 pub sequence_id: String,
149 pub screenshot: serde_json::Value,
150}
151
152impl BrowserObservationData {
153 pub fn success(state_text: Option<String>, dom_snapshot: Option<serde_json::Value>) -> Self {
154 Self {
155 success: true,
156 state_text,
157 dom_snapshot,
158 screenshot: None,
159 }
160 }
161}