browsr_types/
commands.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
5pub struct CommandPoint {
6    pub x: f64,
7    pub y: f64,
8}
9
10#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
11#[serde(rename_all = "snake_case")]
12pub enum CommandType {
13    Action,
14    Extraction,
15}
16
17#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
18#[serde(rename_all = "snake_case")]
19pub enum PageContentKind {
20    Markdown,
21    Html,
22    Json,
23}
24
25impl Default for PageContentKind {
26    fn default() -> Self {
27        PageContentKind::Markdown
28    }
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
32#[serde(tag = "command", rename_all = "snake_case", content = "data")]
33pub enum Commands {
34    ToggleClickOverlay {
35        enabled: bool,
36    },
37    ToggleBoundingBoxes {
38        enabled: bool,
39        selector: Option<String>,
40        limit: Option<usize>,
41        include_html: Option<bool>,
42    },
43    // Navigation commands
44    NavigateTo {
45        url: String,
46    },
47    Refresh,
48    WaitForNavigation {
49        timeout_ms: Option<u64>,
50    },
51    WaitForElement {
52        selector: String,
53        timeout_ms: Option<u64>,
54        visible_only: Option<bool>,
55    },
56
57    // Element interaction commands
58    Click {
59        selector: String,
60    },
61    ClickAt {
62        x: f64,
63        y: f64,
64    },
65    Clear {
66        selector: String,
67    },
68    PressKey {
69        selector: String,
70        key: String,
71    },
72
73    // Content extraction
74    GetContent {
75        #[serde(default, skip_serializing_if = "Option::is_none")]
76        selector: Option<String>,
77        #[serde(default)]
78        kind: Option<PageContentKind>,
79    },
80    GetText {
81        selector: String,
82    },
83    GetAttribute {
84        selector: String,
85        attribute: String,
86    },
87
88    // Page information
89    GetTitle,
90    ExtractStructuredContent {
91        query: String,
92        /// JSON schema for structured extraction - can be a string or a JSON object
93        #[serde(default, skip_serializing_if = "Option::is_none")]
94        schema: Option<serde_json::Value>,
95        #[serde(default, skip_serializing_if = "Option::is_none")]
96        max_chars: Option<usize>,
97    },
98
99    // JavaScript execution
100    Evaluate {
101        expression: String,
102    },
103    GetBoundingBoxes {
104        selector: String,
105        limit: Option<usize>,
106        include_html: Option<bool>,
107    },
108    InspectElement {
109        selector: String,
110    },
111
112    // Mouse and keyboard
113    ScrollTo {
114        x: f64,
115        y: f64,
116    },
117    Drag {
118        from: CommandPoint,
119        to: CommandPoint,
120        modifiers: Option<i64>,
121    },
122    ScrollIntoView {
123        selector: String,
124    },
125
126    // Screenshot and capture
127    Screenshot {
128        full_page: Option<bool>,
129        path: Option<String>,
130    },
131
132    // Element-focused interactions
133    ClickAdvanced {
134        selector: String,
135        button: Option<String>,
136        click_count: Option<u8>,
137        modifiers: Option<i64>,
138    },
139    TypeText {
140        selector: String,
141        text: String,
142        clear: Option<bool>,
143    },
144    Hover {
145        selector: String,
146    },
147    Focus {
148        selector: String,
149    },
150    Check {
151        selector: String,
152    },
153    SelectOption {
154        selector: String,
155        values: Vec<String>,
156    },
157    DragTo {
158        selector: String,
159        target_selector: Option<String>,
160        source_position: Option<CommandPoint>,
161        target_position: Option<CommandPoint>,
162        modifiers: Option<i64>,
163    },
164    EvaluateOnElement {
165        selector: String,
166        expression: String,
167    },
168    GetElementBoundingBox {
169        selector: String,
170    },
171    ElementScreenshot {
172        selector: String,
173        format: Option<String>,
174        quality: Option<u8>,
175    },
176    GetBasicInfo {
177        selector: String,
178    },
179}
180
181#[derive(serde::Deserialize)]
182pub struct StepPayload {
183    pub commands: Vec<Commands>,
184    pub thinking: Option<String>,
185    pub evaluation_previous_goal: Option<String>,
186    pub memory: Option<String>,
187    pub next_goal: Option<String>,
188}
189
190impl Commands {
191    pub fn command_type(&self) -> CommandType {
192        match self {
193            Commands::GetContent { .. }
194            | Commands::GetText { .. }
195            | Commands::GetAttribute { .. }
196            | Commands::GetTitle
197            | Commands::ExtractStructuredContent { .. }
198            | Commands::Screenshot { .. }
199            | Commands::ElementScreenshot { .. }
200            | Commands::GetElementBoundingBox { .. }
201            | Commands::Evaluate { .. }
202            | Commands::EvaluateOnElement { .. }
203            | Commands::GetBoundingBoxes { .. }
204            | Commands::InspectElement { .. }
205            | Commands::GetBasicInfo { .. } => CommandType::Extraction,
206            _ => CommandType::Action,
207        }
208    }
209}