use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
pub const DEFAULT_INCLUDE_ATTRIBUTES: &[&str] = &[
"title",
"type",
"checked",
"id",
"name",
"role",
"value",
"placeholder",
"data-date-format",
"alt",
"aria-label",
"aria-expanded",
"data-state",
"aria-checked",
"aria-valuemin",
"aria-valuemax",
"aria-valuenow",
"aria-placeholder",
"pattern",
"min",
"max",
"minlength",
"maxlength",
"step",
"accept",
"multiple",
"inputmode",
"autocomplete",
"data-mask",
"data-inputmask",
"data-datepicker",
"format",
"expected_format",
"contenteditable",
"pseudo",
"selected",
"expanded",
"pressed",
"disabled",
"invalid",
"valuemin",
"valuemax",
"valuenow",
"keyshortcuts",
"haspopup",
"multiselectable",
"required",
"valuetext",
"level",
"busy",
"live",
"ax_name",
];
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DOMInteractedElement {
pub index: u32,
pub backend_node_id: Option<u32>,
pub tag: String,
pub text: Option<String>,
pub attributes: HashMap<String, String>,
pub selector: Option<String>,
}
impl DOMInteractedElement {
pub fn to_dict(&self) -> HashMap<String, serde_json::Value> {
serde_json::from_value(serde_json::to_value(self).unwrap()).unwrap()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializedDOMState {
pub html: Option<String>,
pub text: Option<String>,
pub markdown: Option<String>,
pub elements: Vec<DOMElement>,
pub selector_map: HashMap<u32, DOMInteractedElement>,
}
impl SerializedDOMState {
pub fn llm_representation(&self, _include_attributes: Option<&[&str]>) -> Option<String> {
if let Some(ref markdown) = self.markdown {
return Some(markdown.clone());
}
if let Some(ref text) = self.text {
return Some(text.clone());
}
if let Some(ref html) = self.html {
return Some(html.clone());
}
None
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DOMElement {
pub index: u32,
pub tag: String,
pub text: Option<String>,
pub attributes: HashMap<String, String>,
pub children: Vec<DOMElement>,
}
pub type DOMSelectorMap = HashMap<u32, DOMInteractedElement>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum NodeType {
ElementNode = 1,
AttributeNode = 2,
TextNode = 3,
CdataSectionNode = 4,
EntityReferenceNode = 5,
EntityNode = 6,
ProcessingInstructionNode = 7,
CommentNode = 8,
DocumentNode = 9,
DocumentTypeNode = 10,
DocumentFragmentNode = 11,
NotationNode = 12,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct DOMRect {
pub x: f64,
pub y: f64,
pub width: f64,
pub height: f64,
}
impl DOMRect {
pub fn new(x: f64, y: f64, width: f64, height: f64) -> Self {
Self {
x,
y,
width,
height,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedAXProperty {
pub name: String,
pub value: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedAXNode {
pub ax_node_id: String,
pub ignored: bool,
pub role: Option<String>,
pub name: Option<String>,
pub description: Option<String>,
pub properties: Option<Vec<EnhancedAXProperty>>,
pub child_ids: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedSnapshotNode {
pub is_clickable: Option<bool>,
pub cursor_style: Option<String>,
pub bounds: Option<DOMRect>,
pub client_rects: Option<DOMRect>,
pub scroll_rects: Option<DOMRect>,
pub computed_styles: Option<HashMap<String, String>>,
pub paint_order: Option<i32>,
pub stacking_contexts: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedDOMTreeNode {
pub node_id: u64,
pub backend_node_id: u64,
pub node_type: NodeType,
pub node_name: String,
pub node_value: String,
pub attributes: HashMap<String, String>,
pub is_scrollable: Option<bool>,
pub is_visible: Option<bool>,
pub absolute_position: Option<DOMRect>,
pub target_id: String,
pub frame_id: Option<String>,
pub session_id: Option<String>,
pub content_document: Option<Box<EnhancedDOMTreeNode>>,
pub shadow_root_type: Option<String>,
pub shadow_roots: Option<Vec<EnhancedDOMTreeNode>>,
pub parent_node: Option<Box<EnhancedDOMTreeNode>>,
pub children_nodes: Option<Vec<EnhancedDOMTreeNode>>,
pub ax_node: Option<EnhancedAXNode>,
pub snapshot_node: Option<EnhancedSnapshotNode>,
pub uuid: String,
}
impl EnhancedDOMTreeNode {
pub fn new(
node_id: u64,
backend_node_id: u64,
node_type: NodeType,
node_name: String,
node_value: String,
target_id: String,
) -> Self {
Self {
node_id,
backend_node_id,
node_type,
node_name,
node_value,
attributes: HashMap::new(),
is_scrollable: None,
is_visible: None,
absolute_position: None,
target_id,
frame_id: None,
session_id: None,
content_document: None,
shadow_root_type: None,
shadow_roots: None,
parent_node: None,
children_nodes: None,
ax_node: None,
snapshot_node: None,
uuid: Uuid::now_v7().to_string(),
}
}
pub fn tag_name(&self) -> String {
self.node_name.to_lowercase()
}
}