browsr-types 0.4.0

Shared data models and schemas for Browsr browser automation flows.
Documentation
//! Browser step types for the /browser_step API.
//!
//! These types are shared between browsr-client and browsr server.

use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::Commands;

/// Input for browser_step execution (tool parameters).
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BrowserStepInput {
    /// Browser commands to execute
    pub commands: Vec<Commands>,
    /// Whether to run browser in headless mode
    #[serde(default)]
    pub headless: Option<bool>,
    /// Thinking/reasoning about current step
    #[serde(default)]
    pub thinking: Option<String>,
    /// Evaluation of how well the previous goal was achieved
    #[serde(default)]
    pub evaluation_previous_goal: Option<String>,
    /// Memory/context to persist across steps
    #[serde(default)]
    pub memory: Option<String>,
    /// Next goal to achieve
    #[serde(default)]
    pub next_goal: Option<String>,
}

impl BrowserStepInput {
    /// Create a new BrowserStepInput with commands only.
    pub fn new(commands: Vec<Commands>) -> Self {
        Self {
            commands,
            headless: None,
            thinking: None,
            evaluation_previous_goal: None,
            memory: None,
            next_goal: None,
        }
    }

    /// Set headless mode.
    pub fn with_headless(mut self, headless: bool) -> Self {
        self.headless = Some(headless);
        self
    }
}

/// Request payload for the /browser_step API.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BrowserStepRequest {
    /// Browser session ID (managed by server)
    #[serde(default)]
    pub session_id: String,
    /// Distri thread ID (used for sequence persistence)
    #[serde(default)]
    pub thread_id: String,
    /// Distri task ID (optional)
    #[serde(default)]
    pub task_id: Option<String>,
    /// Distri run ID (optional)
    #[serde(default)]
    pub run_id: Option<String>,
    /// Tool call ID (optional)
    #[serde(default)]
    pub tool_call_id: Option<String>,
    /// Browser commands to execute
    pub commands: Vec<Commands>,
    /// Whether to run browser in headless mode
    #[serde(default)]
    pub headless: Option<bool>,
    /// Thinking/reasoning about current step
    #[serde(default)]
    pub thinking: Option<String>,
    /// Evaluation of how well the previous goal was achieved
    #[serde(default)]
    pub evaluation_previous_goal: Option<String>,
    /// Memory/context to persist across steps
    #[serde(default)]
    pub memory: Option<String>,
    /// Next goal to achieve
    #[serde(default)]
    pub next_goal: Option<String>,
}

impl BrowserStepRequest {
    /// Create a new request from input with context.
    pub fn new(input: BrowserStepInput) -> Self {
        Self {
            session_id: String::new(),
            thread_id: String::new(),
            task_id: None,
            run_id: None,
            tool_call_id: None,
            commands: input.commands,
            headless: input.headless,
            thinking: input.thinking,
            evaluation_previous_goal: input.evaluation_previous_goal,
            memory: input.memory,
            next_goal: input.next_goal,
        }
    }

    /// Set session ID.
    pub fn with_session_id(mut self, session_id: impl Into<String>) -> Self {
        self.session_id = session_id.into();
        self
    }

    /// Set thread ID.
    pub fn with_thread_id(mut self, thread_id: impl Into<String>) -> Self {
        self.thread_id = thread_id.into();
        self
    }

    /// Set task ID.
    pub fn with_task_id(mut self, task_id: impl Into<String>) -> Self {
        self.task_id = Some(task_id.into());
        self
    }

    /// Set run ID.
    pub fn with_run_id(mut self, run_id: impl Into<String>) -> Self {
        self.run_id = Some(run_id.into());
        self
    }

    /// Set tool call ID.
    pub fn with_tool_call_id(mut self, tool_call_id: impl Into<String>) -> Self {
        self.tool_call_id = Some(tool_call_id.into());
        self
    }
}

/// Result of browser_step execution.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BrowserStepResult {
    /// Whether all commands succeeded
    pub success: bool,
    /// Browser session ID
    pub session_id: String,
    /// Summary of execution
    pub summary: Option<String>,
    /// Current URL after execution
    pub url: Option<String>,
    /// Error message if any command failed
    pub error: Option<String>,
    /// Sequence ID for persistence
    pub sequence_id: Option<String>,
    /// Extracted data from commands (e.g., ExtractStructuredContent)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<serde_json::Value>,
}

impl BrowserStepResult {
    /// Create a successful result.
    pub fn success(session_id: impl Into<String>) -> Self {
        Self {
            success: true,
            session_id: session_id.into(),
            summary: None,
            url: None,
            error: None,
            sequence_id: None,
            data: None,
        }
    }

    /// Create an error result.
    pub fn error(session_id: impl Into<String>, error: impl Into<String>) -> Self {
        Self {
            success: false,
            session_id: session_id.into(),
            summary: None,
            url: None,
            error: Some(error.into()),
            sequence_id: None,
            data: None,
        }
    }
}