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    solve_challenge,
69    detect_challenge,
70    deterministic,
71    context,
72    vision_prefill,
73    vision_fallback,
74});
75metric_snapshot!(ContextMetricsSnapshot {
76    hit,
77    miss,
78    ambiguous_refusal,
79    stale_rejection,
80    error,
81});
82metric_snapshot!(PrefillMetricsSnapshot {
83    hit,
84    miss,
85    dropped_entry,
86    policy_denied,
87    provider_failure,
88});
89metric_snapshot!(ConfidenceMetricsSnapshot {
90    below_acceptance,
91    accepted,
92    high,
93    unreported,
94});
95metric_snapshot!(VerificationMetricsSnapshot {
96    accepted,
97    target_not_found,
98    target_ambiguous,
99    obstruction_persisted,
100    value_mismatch,
101    other_rejected,
102});
103metric_snapshot!(RetryMetricsSnapshot {
104    transport,
105    timeout,
106    target_detached,
107    state_conflict,
108    other,
109});
110metric_snapshot!(ReconciliationMetricsSnapshot {
111    resumed,
112    restarted,
113    needs_reconciliation,
114    failed,
115});
116metric_snapshot!(WorkflowCallMetricsSnapshot {
117    lifecycle,
118    discovery,
119    read,
120    mutation,
121    composite_workflow,
122    recovery,
123    artifact,
124    job,
125});
126
127#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
128#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
129#[serde(rename_all = "camelCase")]
130pub struct VisionMetricsSnapshot {
131    pub attempted: u64,
132    pub accepted: u64,
133    pub rejected: u64,
134    pub abstained: u64,
135    pub timed_out: u64,
136    pub failed: u64,
137    pub provider_http: u64,
138    pub provider_acp: u64,
139    pub provider_direct_local: u64,
140    pub latency_ms: LatencyHistogramSnapshot,
141    pub confidence: ConfidenceMetricsSnapshot,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
145#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
146#[serde(rename_all = "camelCase")]
147pub struct LatencyHistogramSnapshot {
148    pub buckets: Vec<LatencyBucketSnapshot>,
149    pub overflow: u64,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
153#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
154#[serde(rename_all = "camelCase")]
155pub struct LatencyBucketSnapshot {
156    pub upper_bound_ms: u64,
157    pub count: u64,
158}
159
160/// Browser session returned by session create/list endpoints.
161#[derive(Debug, Clone, Serialize, Deserialize)]
162#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
163pub struct SessionState {
164    pub id: SessionId,
165    pub profile: String,
166    pub proxy: Option<String>,
167    pub page_ids: Vec<PageId>,
168    pub created_at: DateTime<Utc>,
169    pub last_used_at: DateTime<Utc>,
170    pub execution_policy: ExecutionPolicy,
171    /// Set at creation by `CreateSessionRequest::zigzagzig`: page-bound
172    /// commands run under the ZigZagZig recovery ladder. Recorded
173    /// separately from the policy — a hand-assembled everything-on policy
174    /// does not opt into the ladder. Absent from the wire when off, so
175    /// plain sessions carry no godmode baggage.
176    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
177    pub zigzagzig: bool,
178}
179
180/// Page within a session.
181#[derive(Debug, Clone, Serialize, Deserialize)]
182#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
183pub struct PageState {
184    pub id: PageId,
185    pub session_id: SessionId,
186    pub url: Option<String>,
187    pub mode: PageMode,
188    pub ready_state: String,
189    pub pending_requests: usize,
190}
191
192/// Result of a navigation command.
193#[derive(Debug, Clone, Serialize, Deserialize)]
194#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
195pub struct NavigationResult {
196    pub page_id: PageId,
197    pub url: String,
198    pub ready_state: String,
199}
200
201/// Result of a structured extract command.
202#[derive(Debug, Clone, Serialize, Deserialize)]
203#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
204pub struct ExtractResult {
205    pub page_id: PageId,
206    pub data: serde_json::Value,
207}