Skip to main content

bobby_browser_client/
state.rs

1//! Session and page runtime state returned by `/v1` endpoints.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::{ExecutionPolicy, PageId, SessionId};
7
8/// Page rendering / interaction mode.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
11pub enum PageMode {
12    Document,
13    Interactive,
14    Render,
15}
16
17/// `GET /v1/runtime` body.
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
20pub struct RuntimeInfo {
21    pub version: String,
22    pub capabilities: Vec<String>,
23    pub active_sessions: usize,
24    pub queued_jobs: usize,
25    pub uptime_ms: u64,
26    #[serde(
27        default,
28        rename = "operationalMetrics",
29        skip_serializing_if = "Option::is_none"
30    )]
31    pub operational_metrics: Option<OperationalMetricsSnapshot>,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
35#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
36#[serde(rename_all = "camelCase")]
37pub struct OperationalMetricsSnapshot {
38    pub observation_window_ms: u64,
39    pub intent: IntentMetricsSnapshot,
40    pub context: ContextMetricsSnapshot,
41    pub prefill: PrefillMetricsSnapshot,
42    pub vision: VisionMetricsSnapshot,
43    pub verification: VerificationMetricsSnapshot,
44    pub retries: RetryMetricsSnapshot,
45    pub reconciliation: ReconciliationMetricsSnapshot,
46    pub workflow_calls: WorkflowCallMetricsSnapshot,
47}
48
49macro_rules! metric_snapshot {
50    ($name:ident { $($field:ident),+ $(,)? }) => {
51        #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
52        #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
53        #[serde(rename_all = "camelCase")]
54        pub struct $name { $(pub $field: u64,)+ }
55    };
56}
57
58metric_snapshot!(IntentMetricsSnapshot {
59    total,
60    locate,
61    fill,
62    complete_form,
63    extract,
64    submit,
65    wait_for_state,
66    follow,
67    dismiss,
68    deterministic,
69    context,
70    vision_prefill,
71    vision_fallback,
72});
73metric_snapshot!(ContextMetricsSnapshot {
74    hit,
75    miss,
76    ambiguous_refusal,
77    stale_rejection,
78    error,
79});
80metric_snapshot!(PrefillMetricsSnapshot {
81    hit,
82    miss,
83    dropped_entry,
84    policy_denied,
85    provider_failure,
86});
87metric_snapshot!(ConfidenceMetricsSnapshot {
88    below_acceptance,
89    accepted,
90    high,
91    unreported,
92});
93metric_snapshot!(VerificationMetricsSnapshot {
94    accepted,
95    target_not_found,
96    target_ambiguous,
97    obstruction_persisted,
98    value_mismatch,
99    other_rejected,
100});
101metric_snapshot!(RetryMetricsSnapshot {
102    transport,
103    timeout,
104    target_detached,
105    state_conflict,
106    other,
107});
108metric_snapshot!(ReconciliationMetricsSnapshot {
109    resumed,
110    restarted,
111    needs_reconciliation,
112    failed,
113});
114metric_snapshot!(WorkflowCallMetricsSnapshot {
115    lifecycle,
116    discovery,
117    read,
118    mutation,
119    composite_workflow,
120    recovery,
121    artifact,
122    job,
123});
124
125#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
126#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
127#[serde(rename_all = "camelCase")]
128pub struct VisionMetricsSnapshot {
129    pub attempted: u64,
130    pub accepted: u64,
131    pub rejected: u64,
132    pub abstained: u64,
133    pub timed_out: u64,
134    pub failed: u64,
135    pub provider_http: u64,
136    pub provider_acp: u64,
137    pub provider_direct_local: u64,
138    pub latency_ms: LatencyHistogramSnapshot,
139    pub confidence: ConfidenceMetricsSnapshot,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
143#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
144#[serde(rename_all = "camelCase")]
145pub struct LatencyHistogramSnapshot {
146    pub buckets: Vec<LatencyBucketSnapshot>,
147    pub overflow: u64,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
151#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
152#[serde(rename_all = "camelCase")]
153pub struct LatencyBucketSnapshot {
154    pub upper_bound_ms: u64,
155    pub count: u64,
156}
157
158/// Browser session returned by session create/list endpoints.
159#[derive(Debug, Clone, Serialize, Deserialize)]
160#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
161pub struct SessionState {
162    pub id: SessionId,
163    pub profile: String,
164    pub proxy: Option<String>,
165    pub page_ids: Vec<PageId>,
166    pub created_at: DateTime<Utc>,
167    pub last_used_at: DateTime<Utc>,
168    pub execution_policy: ExecutionPolicy,
169}
170
171/// Page within a session.
172#[derive(Debug, Clone, Serialize, Deserialize)]
173#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
174pub struct PageState {
175    pub id: PageId,
176    pub session_id: SessionId,
177    pub url: Option<String>,
178    pub mode: PageMode,
179    pub ready_state: String,
180    pub pending_requests: usize,
181}
182
183/// Result of a navigation command.
184#[derive(Debug, Clone, Serialize, Deserialize)]
185#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
186pub struct NavigationResult {
187    pub page_id: PageId,
188    pub url: String,
189    pub ready_state: String,
190}
191
192/// Result of a structured extract command.
193#[derive(Debug, Clone, Serialize, Deserialize)]
194#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
195pub struct ExtractResult {
196    pub page_id: PageId,
197    pub data: serde_json::Value,
198}