feat: [US-003] - Add browser type definitions (DTOs and errors)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nathan Flurry 2026-03-17 04:46:47 -07:00
parent f8a220c53b
commit 7d294a7cab
3 changed files with 747 additions and 0 deletions

View file

@ -0,0 +1,167 @@
use sandbox_agent_error::ProblemDetails;
use serde_json::{Map, Value};
use crate::desktop_types::DesktopErrorInfo;
#[derive(Debug, Clone)]
pub struct BrowserProblem {
status: u16,
title: &'static str,
code: &'static str,
message: String,
}
impl BrowserProblem {
// 409 - browser is not running
pub fn not_active() -> Self {
Self::new(
409,
"Browser Not Active",
"browser/not-active",
"The browser is not running. Call POST /v1/browser/start first.",
)
}
// 409 - browser is already running
pub fn already_active() -> Self {
Self::new(
409,
"Browser Already Active",
"browser/already-active",
"The browser is already running. Stop it first with POST /v1/browser/stop.",
)
}
// 409 - desktop mode is active, cannot start browser
pub fn desktop_conflict() -> Self {
Self::new(
409,
"Desktop Conflict",
"browser/desktop-conflict",
"The desktop runtime is currently active. Browser and desktop modes are mutually exclusive.",
)
}
// 424 - missing dependencies
pub fn install_required(message: impl Into<String>) -> Self {
Self::new(
424,
"Browser Install Required",
"browser/install-required",
message,
)
}
// 500 - startup sequence failed
pub fn start_failed(message: impl Into<String>) -> Self {
Self::new(500, "Browser Start Failed", "browser/start-failed", message)
}
// 502 - CDP communication error
pub fn cdp_error(message: impl Into<String>) -> Self {
Self::new(502, "CDP Error", "browser/cdp-error", message)
}
// 504 - operation timed out
pub fn timeout(message: impl Into<String>) -> Self {
Self::new(504, "Browser Timeout", "browser/timeout", message)
}
// 404 - tab/context/element not found
pub fn not_found(message: impl Into<String>) -> Self {
Self::new(404, "Not Found", "browser/not-found", message)
}
// 400 - bad CSS selector
pub fn invalid_selector(message: impl Into<String>) -> Self {
Self::new(400, "Invalid Selector", "browser/invalid-selector", message)
}
pub fn to_problem_details(&self) -> ProblemDetails {
let mut extensions = Map::new();
extensions.insert("code".to_string(), Value::String(self.code.to_string()));
ProblemDetails {
type_: format!("tag:sandboxagent.dev,2025:{}", self.code),
title: self.title.to_string(),
status: self.status,
detail: Some(self.message.clone()),
instance: None,
extensions,
}
}
pub fn to_error_info(&self) -> DesktopErrorInfo {
DesktopErrorInfo {
code: self.code.to_string(),
message: self.message.clone(),
}
}
pub fn code(&self) -> &'static str {
self.code
}
fn new(
status: u16,
title: &'static str,
code: &'static str,
message: impl Into<String>,
) -> Self {
Self {
status,
title,
code,
message: message.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn not_active_produces_correct_problem_details() {
let problem = BrowserProblem::not_active();
let details = problem.to_problem_details();
assert_eq!(details.status, 409);
assert_eq!(
details.type_,
"tag:sandboxagent.dev,2025:browser/not-active"
);
assert_eq!(details.title, "Browser Not Active");
assert!(details.detail.unwrap().contains("not running"));
}
#[test]
fn cdp_error_includes_custom_message() {
let problem = BrowserProblem::cdp_error("connection refused");
let details = problem.to_problem_details();
assert_eq!(details.status, 502);
assert_eq!(details.detail.unwrap(), "connection refused");
assert_eq!(
details.extensions.get("code"),
Some(&Value::String("browser/cdp-error".to_string()))
);
}
#[test]
fn install_required_uses_424_status() {
let problem = BrowserProblem::install_required("chromium not found");
let details = problem.to_problem_details();
assert_eq!(details.status, 424);
assert_eq!(
details.type_,
"tag:sandboxagent.dev,2025:browser/install-required"
);
}
#[test]
fn to_error_info_returns_code_and_message() {
let problem = BrowserProblem::timeout("CDP poll timed out after 15s");
let info = problem.to_error_info();
assert_eq!(info.code, "browser/timeout");
assert_eq!(info.message, "CDP poll timed out after 15s");
}
}

View file

@ -0,0 +1,578 @@
use std::collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use utoipa::{IntoParams, ToSchema};
use crate::desktop_types::{DesktopErrorInfo, DesktopProcessInfo, DesktopResolution};
// ---------------------------------------------------------------------------
// State
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum BrowserState {
Inactive,
InstallRequired,
Starting,
Active,
Stopping,
Failed,
}
// ---------------------------------------------------------------------------
// Lifecycle
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserStartRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub width: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub height: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dpi: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub headless: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub context_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_video_codec: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_audio_codec: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_frame_rate: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub webrtc_port_range: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub recording_fps: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserStatusResponse {
pub state: BrowserState,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub display: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub resolution: Option<DesktopResolution>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cdp_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(default)]
pub missing_dependencies: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub install_command: Option<String>,
#[serde(default)]
pub processes: Vec<DesktopProcessInfo>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_error: Option<DesktopErrorInfo>,
}
// ---------------------------------------------------------------------------
// Navigation
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserNavigateRequest {
pub url: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wait_until: Option<BrowserNavigateWaitUntil>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BrowserNavigateWaitUntil {
Load,
Domcontentloaded,
Networkidle,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserPageInfo {
pub url: String,
pub title: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<u16>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserReloadRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ignore_cache: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserWaitRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selector: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timeout: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub state: Option<BrowserWaitState>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BrowserWaitState {
Visible,
Hidden,
Attached,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserWaitResponse {
pub found: bool,
}
// ---------------------------------------------------------------------------
// Tabs
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserTabInfo {
pub id: String,
pub url: String,
pub title: String,
pub active: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserTabListResponse {
pub tabs: Vec<BrowserTabInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCreateTabRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
// ---------------------------------------------------------------------------
// Screenshots & PDF
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BrowserScreenshotFormat {
Png,
Jpeg,
Webp,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserScreenshotQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub format: Option<BrowserScreenshotFormat>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quality: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub full_page: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selector: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserPdfQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub format: Option<BrowserPdfFormat>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub landscape: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub print_background: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub scale: Option<f32>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BrowserPdfFormat {
A4,
Letter,
Legal,
}
// ---------------------------------------------------------------------------
// Content extraction
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserContentQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selector: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserContentResponse {
pub html: String,
pub url: String,
pub title: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserMarkdownResponse {
pub markdown: String,
pub url: String,
pub title: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserLinkInfo {
pub href: String,
pub text: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserLinksResponse {
pub links: Vec<BrowserLinkInfo>,
pub url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserSnapshotResponse {
pub snapshot: String,
pub url: String,
pub title: String,
}
// ---------------------------------------------------------------------------
// Scrape
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserScrapeRequest {
pub selectors: HashMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserScrapeResponse {
pub data: HashMap<String, Vec<String>>,
pub url: String,
pub title: String,
}
// ---------------------------------------------------------------------------
// Execute
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserExecuteRequest {
pub expression: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub await_promise: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserExecuteResponse {
pub result: Value,
#[serde(rename = "type")]
pub type_: String,
}
// ---------------------------------------------------------------------------
// Interaction
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserClickRequest {
pub selector: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub button: Option<BrowserMouseButton>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub click_count: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timeout: Option<u64>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BrowserMouseButton {
Left,
Right,
Middle,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserTypeRequest {
pub selector: String,
pub text: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub delay: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub clear: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserSelectRequest {
pub selector: String,
pub value: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserHoverRequest {
pub selector: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserScrollRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selector: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub x: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub y: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserUploadRequest {
pub selector: String,
pub path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserDialogRequest {
pub accept: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserActionResponse {
pub ok: bool,
}
// ---------------------------------------------------------------------------
// Console monitoring
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserConsoleQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub level: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserConsoleMessage {
pub level: String,
pub text: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub line: Option<u32>,
pub timestamp: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserConsoleResponse {
pub messages: Vec<BrowserConsoleMessage>,
}
// ---------------------------------------------------------------------------
// Network monitoring
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserNetworkQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url_pattern: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserNetworkRequest {
pub url: String,
pub method: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<u16>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub response_size: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duration: Option<u64>,
pub timestamp: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserNetworkResponse {
pub requests: Vec<BrowserNetworkRequest>,
}
// ---------------------------------------------------------------------------
// Crawling
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCrawlRequest {
pub url: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_pages: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_depth: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub allowed_domains: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extract: Option<BrowserCrawlExtract>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BrowserCrawlExtract {
Markdown,
Html,
Text,
Links,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCrawlPage {
pub url: String,
pub title: String,
pub content: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub links: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<u16>,
pub depth: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCrawlResponse {
pub pages: Vec<BrowserCrawlPage>,
pub total_pages: u32,
pub truncated: bool,
}
// ---------------------------------------------------------------------------
// Contexts (persistent profiles)
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserContextInfo {
pub id: String,
pub name: String,
pub created_at: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub size_bytes: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserContextListResponse {
pub contexts: Vec<BrowserContextInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserContextCreateRequest {
pub name: String,
}
// ---------------------------------------------------------------------------
// Cookies
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCookiesQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCookie {
pub name: String,
pub value: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub expires: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub http_only: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub secure: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub same_site: Option<BrowserCookieSameSite>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)]
pub enum BrowserCookieSameSite {
Strict,
Lax,
None,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserCookiesResponse {
pub cookies: Vec<BrowserCookie>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct BrowserSetCookiesRequest {
pub cookies: Vec<BrowserCookie>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams, Default)]
#[serde(rename_all = "camelCase")]
pub struct BrowserDeleteCookiesQuery {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
}

View file

@ -1,7 +1,9 @@
//! Sandbox agent core utilities.
mod acp_proxy_runtime;
mod browser_errors;
mod browser_install;
pub mod browser_types;
pub mod cli;
pub mod daemon;
mod desktop_errors;