use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct CommandPoint {
pub x: f64,
pub y: f64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum CommandType {
Action,
Extraction,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PageContentKind {
Markdown,
Html,
Json,
}
impl Default for PageContentKind {
fn default() -> Self {
PageContentKind::Markdown
}
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "command", rename_all = "snake_case", content = "data")]
pub enum Commands {
ToggleClickOverlay {
enabled: bool,
},
ToggleBoundingBoxes {
enabled: bool,
selector: Option<String>,
limit: Option<usize>,
include_html: Option<bool>,
},
NavigateTo {
url: String,
},
Refresh,
WaitForNavigation {
timeout_ms: Option<u64>,
},
WaitForElement {
selector: String,
timeout_ms: Option<u64>,
visible_only: Option<bool>,
},
Click {
selector: String,
},
ClickAt {
x: f64,
y: f64,
},
Clear {
selector: String,
},
PressKey {
selector: String,
key: String,
},
GetContent {
#[serde(default, skip_serializing_if = "Option::is_none")]
selector: Option<String>,
#[serde(default)]
kind: Option<PageContentKind>,
},
GetText {
selector: String,
},
GetAttribute {
selector: String,
attribute: String,
},
GetTitle,
ExtractStructuredContent {
query: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
schema: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
max_chars: Option<usize>,
},
Evaluate {
expression: String,
},
GetBoundingBoxes {
selector: String,
limit: Option<usize>,
include_html: Option<bool>,
},
InspectElement {
selector: String,
},
ScrollTo {
#[serde(default)]
x: Option<f64>,
#[serde(default)]
y: Option<f64>,
},
MoveMouseTo {
x: f64,
y: f64,
steps: Option<u32>,
},
Drag {
from: CommandPoint,
to: CommandPoint,
modifiers: Option<i64>,
},
ScrollIntoView {
selector: String,
},
Screenshot {
full_page: Option<bool>,
path: Option<String>,
},
ClickAdvanced {
selector: String,
button: Option<String>,
click_count: Option<u8>,
modifiers: Option<i64>,
},
TypeText {
selector: String,
text: String,
clear: Option<bool>,
},
Hover {
selector: String,
},
Focus {
selector: String,
},
Check {
selector: String,
},
SelectOption {
selector: String,
values: Vec<String>,
},
DragTo {
selector: String,
target_selector: Option<String>,
source_position: Option<CommandPoint>,
target_position: Option<CommandPoint>,
modifiers: Option<i64>,
},
EvaluateOnElement {
selector: String,
expression: String,
},
GetElementBoundingBox {
selector: String,
},
ElementScreenshot {
selector: String,
format: Option<String>,
quality: Option<u8>,
},
GetBasicInfo {
selector: String,
},
SetCookie {
name: String,
value: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
domain: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
secure: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
http_only: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
same_site: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
expires: Option<f64>,
},
SetCookies {
cookies: String,
domain: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
secure: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
http_only: Option<bool>,
},
GetCookies,
DeleteCookie {
name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
domain: Option<String>,
},
GetLocalStorage,
SetLocalStorage {
items: Vec<LocalStorageItem>,
},
ClearLocalStorage,
GetSessionStorage,
SetSessionStorage {
items: Vec<LocalStorageItem>,
},
ClearSessionStorage,
CaptureState,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct LocalStorageItem {
pub key: String,
pub value: String,
}
#[derive(serde::Deserialize)]
pub struct StepPayload {
pub commands: Vec<Commands>,
pub thinking: Option<String>,
pub evaluation_previous_goal: Option<String>,
pub memory: Option<String>,
pub next_goal: Option<String>,
}
impl Commands {
pub fn command_type(&self) -> CommandType {
match self {
Commands::GetContent { .. }
| Commands::GetText { .. }
| Commands::GetAttribute { .. }
| Commands::GetTitle
| Commands::ExtractStructuredContent { .. }
| Commands::Screenshot { .. }
| Commands::ElementScreenshot { .. }
| Commands::GetElementBoundingBox { .. }
| Commands::Evaluate { .. }
| Commands::EvaluateOnElement { .. }
| Commands::GetBoundingBoxes { .. }
| Commands::InspectElement { .. }
| Commands::GetBasicInfo { .. }
| Commands::GetCookies
| Commands::GetLocalStorage
| Commands::GetSessionStorage
| Commands::CaptureState => CommandType::Extraction,
_ => CommandType::Action,
}
}
}