Skip to main content

victauri_plugin/mcp/
compound_params.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5// ── Enums ──────────────────────────────────────────────────────────────────
6
7/// Web storage type for browser storage operations.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
9#[serde(rename_all = "snake_case")]
10pub enum StorageType {
11    /// Browser localStorage (persistent across sessions).
12    Local,
13    /// Browser sessionStorage (cleared when tab closes).
14    Session,
15}
16
17impl StorageType {
18    /// Returns the JavaScript property name for this storage type.
19    #[must_use]
20    pub fn js_property(self) -> &'static str {
21        match self {
22            Self::Local => "localStorage",
23            Self::Session => "sessionStorage",
24        }
25    }
26}
27
28impl fmt::Display for StorageType {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Self::Local => f.write_str("local"),
32            Self::Session => f.write_str("session"),
33        }
34    }
35}
36
37/// Browser dialog type for dialog response configuration.
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
39#[serde(rename_all = "snake_case")]
40pub enum DialogType {
41    /// JavaScript `alert()` dialog.
42    Alert,
43    /// JavaScript `confirm()` dialog.
44    Confirm,
45    /// JavaScript `prompt()` dialog.
46    Prompt,
47}
48
49impl DialogType {
50    /// Returns the lowercase string for JS bridge consumption.
51    #[must_use]
52    pub fn as_str(self) -> &'static str {
53        match self {
54            Self::Alert => "alert",
55            Self::Confirm => "confirm",
56            Self::Prompt => "prompt",
57        }
58    }
59}
60
61impl fmt::Display for DialogType {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        f.write_str(self.as_str())
64    }
65}
66
67/// Action to take on a browser dialog.
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
69#[serde(rename_all = "snake_case")]
70pub enum DialogAction {
71    /// Accept the dialog (click OK/Yes).
72    Accept,
73    /// Dismiss the dialog (click Cancel/No).
74    Dismiss,
75}
76
77impl DialogAction {
78    /// Returns the lowercase string for JS bridge consumption.
79    #[must_use]
80    pub fn as_str(self) -> &'static str {
81        match self {
82            Self::Accept => "accept",
83            Self::Dismiss => "dismiss",
84        }
85    }
86}
87
88impl fmt::Display for DialogAction {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        f.write_str(self.as_str())
91    }
92}
93
94// ── interact ────────────────────────────────────────────────────────────────
95
96/// Action for the compound `interact` tool.
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
98#[serde(rename_all = "snake_case")]
99pub enum InteractAction {
100    /// Click an element.
101    Click,
102    /// Double-click an element.
103    DoubleClick,
104    /// Hover over an element.
105    Hover,
106    /// Focus an element.
107    Focus,
108    /// Scroll an element into view.
109    ScrollIntoView,
110    /// Select an option in a `<select>` element.
111    SelectOption,
112}
113
114impl fmt::Display for InteractAction {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        match self {
117            Self::Click => f.write_str("click"),
118            Self::DoubleClick => f.write_str("double_click"),
119            Self::Hover => f.write_str("hover"),
120            Self::Focus => f.write_str("focus"),
121            Self::ScrollIntoView => f.write_str("scroll_into_view"),
122            Self::SelectOption => f.write_str("select_option"),
123        }
124    }
125}
126
127/// Parameters for the compound `interact` tool (click, hover, focus, scroll, select).
128#[derive(Debug, Deserialize, JsonSchema)]
129pub struct InteractParams {
130    /// Action to perform: click, `double_click`, hover, focus, `scroll_into_view`, `select_option`.
131    pub action: InteractAction,
132    /// Ref handle ID from a DOM snapshot (e.g. "e5"). Required for click, `double_click`, hover, focus, `select_option`.
133    pub ref_id: Option<String>,
134    /// Option values for `select_option` action.
135    pub values: Option<Vec<String>>,
136    /// Horizontal scroll position (pixels). Used with `scroll_into_view` when `ref_id` is null.
137    pub x: Option<f64>,
138    /// Vertical scroll position (pixels). Used with `scroll_into_view` when `ref_id` is null.
139    pub y: Option<f64>,
140    /// Target webview label.
141    pub webview_label: Option<String>,
142}
143
144// ── input ───────────────────────────────────────────────────────────────────
145
146/// Action for the compound `input` tool.
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
148#[serde(rename_all = "snake_case")]
149pub enum InputAction {
150    /// Set an input element's value directly.
151    Fill,
152    /// Type text character-by-character.
153    TypeText,
154    /// Press a keyboard key.
155    PressKey,
156}
157
158impl fmt::Display for InputAction {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        match self {
161            Self::Fill => f.write_str("fill"),
162            Self::TypeText => f.write_str("type_text"),
163            Self::PressKey => f.write_str("press_key"),
164        }
165    }
166}
167
168/// Parameters for the compound `input` tool (fill, `type_text`, `press_key`).
169#[derive(Debug, Deserialize, JsonSchema)]
170pub struct InputParams {
171    /// Action to perform: fill, `type_text`, `press_key`.
172    pub action: InputAction,
173    /// Ref handle ID of the target element. Required for fill and `type_text`.
174    pub ref_id: Option<String>,
175    /// Value to set (for fill action).
176    pub value: Option<String>,
177    /// Text to type character-by-character (for `type_text` action).
178    pub text: Option<String>,
179    /// Key to press (for `press_key` action, e.g. "Enter", "Escape", "Tab", "`ArrowDown`").
180    pub key: Option<String>,
181    /// Target webview label.
182    pub webview_label: Option<String>,
183}
184
185// ── window ──────────────────────────────────────────────────────────────────
186
187/// Action for the compound `window` tool.
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
189#[serde(rename_all = "snake_case")]
190pub enum WindowAction {
191    /// Get the current state of a window.
192    GetState,
193    /// List all window labels.
194    List,
195    /// Manage a window (minimize, maximize, close, etc.).
196    Manage,
197    /// Resize a window.
198    Resize,
199    /// Move a window to a new position.
200    MoveTo,
201    /// Set a window's title.
202    SetTitle,
203}
204
205impl fmt::Display for WindowAction {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        match self {
208            Self::GetState => f.write_str("get_state"),
209            Self::List => f.write_str("list"),
210            Self::Manage => f.write_str("manage"),
211            Self::Resize => f.write_str("resize"),
212            Self::MoveTo => f.write_str("move_to"),
213            Self::SetTitle => f.write_str("set_title"),
214        }
215    }
216}
217
218/// Window management sub-action for the `manage` action.
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
220#[serde(rename_all = "snake_case")]
221pub enum ManageAction {
222    /// Minimize the window.
223    Minimize,
224    /// Restore from minimized state.
225    Unminimize,
226    /// Maximize the window.
227    Maximize,
228    /// Restore from maximized state.
229    Unmaximize,
230    /// Close the window.
231    Close,
232    /// Focus the window.
233    Focus,
234    /// Show the window.
235    Show,
236    /// Hide the window.
237    Hide,
238    /// Enter fullscreen mode.
239    Fullscreen,
240    /// Exit fullscreen mode.
241    Unfullscreen,
242    /// Set the window to always be on top.
243    AlwaysOnTop,
244    /// Remove the always-on-top flag.
245    NotAlwaysOnTop,
246}
247
248impl ManageAction {
249    /// Returns the `snake_case` string for bridge consumption.
250    #[must_use]
251    pub fn as_str(self) -> &'static str {
252        match self {
253            Self::Minimize => "minimize",
254            Self::Unminimize => "unminimize",
255            Self::Maximize => "maximize",
256            Self::Unmaximize => "unmaximize",
257            Self::Close => "close",
258            Self::Focus => "focus",
259            Self::Show => "show",
260            Self::Hide => "hide",
261            Self::Fullscreen => "fullscreen",
262            Self::Unfullscreen => "unfullscreen",
263            Self::AlwaysOnTop => "always_on_top",
264            Self::NotAlwaysOnTop => "not_always_on_top",
265        }
266    }
267}
268
269impl fmt::Display for ManageAction {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        f.write_str(self.as_str())
272    }
273}
274
275/// Parameters for the compound `window` tool (`get_state`, list, manage, resize, move, title).
276#[derive(Debug, Deserialize, JsonSchema)]
277pub struct WindowParams {
278    /// Action to perform: `get_state`, list, manage, resize, `move_to`, `set_title`.
279    pub action: WindowAction,
280    /// Target window label.
281    pub label: Option<String>,
282    /// Window management action (for manage): minimize, unminimize, maximize, unmaximize, close, focus, show, hide, fullscreen, unfullscreen, `always_on_top`, `not_always_on_top`.
283    pub manage_action: Option<ManageAction>,
284    /// Width in logical pixels (for resize).
285    pub width: Option<u32>,
286    /// Height in logical pixels (for resize).
287    pub height: Option<u32>,
288    /// X position in logical pixels (for `move_to`).
289    pub x: Option<i32>,
290    /// Y position in logical pixels (for `move_to`).
291    pub y: Option<i32>,
292    /// New window title (for `set_title`).
293    pub title: Option<String>,
294}
295
296// ── storage ─────────────────────────────────────────────────────────────────
297
298/// Action for the compound `storage` tool.
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
300#[serde(rename_all = "snake_case")]
301pub enum StorageAction {
302    /// Read a value from storage.
303    Get,
304    /// Write a value to storage.
305    Set,
306    /// Delete a value from storage.
307    Delete,
308    /// Get all cookies.
309    GetCookies,
310}
311
312impl fmt::Display for StorageAction {
313    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314        match self {
315            Self::Get => f.write_str("get"),
316            Self::Set => f.write_str("set"),
317            Self::Delete => f.write_str("delete"),
318            Self::GetCookies => f.write_str("get_cookies"),
319        }
320    }
321}
322
323/// Parameters for the compound `storage` tool (get, set, delete, `get_cookies`).
324#[derive(Debug, Deserialize, JsonSchema)]
325pub struct StorageParams {
326    /// Action to perform: get, set, delete, `get_cookies`.
327    pub action: StorageAction,
328    /// Storage type for get/set/delete. Defaults to local if omitted.
329    pub storage_type: Option<StorageType>,
330    /// Key to read, write, or delete.
331    pub key: Option<String>,
332    /// Value to store (for set action). Will be JSON-serialized if not a string.
333    pub value: Option<serde_json::Value>,
334    /// Target webview label.
335    pub webview_label: Option<String>,
336}
337
338// ── navigate ────────────────────────────────────────────────────────────────
339
340/// Action for the compound `navigate` tool.
341#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
342#[serde(rename_all = "snake_case")]
343pub enum NavigateAction {
344    /// Navigate to a URL.
345    GoTo,
346    /// Navigate back in browser history.
347    GoBack,
348    /// Get the navigation history log.
349    GetHistory,
350    /// Set an auto-response for browser dialogs.
351    SetDialogResponse,
352    /// Get the dialog event log.
353    GetDialogLog,
354}
355
356impl fmt::Display for NavigateAction {
357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358        match self {
359            Self::GoTo => f.write_str("go_to"),
360            Self::GoBack => f.write_str("go_back"),
361            Self::GetHistory => f.write_str("get_history"),
362            Self::SetDialogResponse => f.write_str("set_dialog_response"),
363            Self::GetDialogLog => f.write_str("get_dialog_log"),
364        }
365    }
366}
367
368/// Parameters for the compound `navigate` tool (`go_to`, `go_back`, history, dialogs).
369#[derive(Debug, Deserialize, JsonSchema)]
370pub struct NavigateParams {
371    /// Action to perform: `go_to`, `go_back`, `get_history`, `set_dialog_response`, `get_dialog_log`.
372    pub action: NavigateAction,
373    /// URL to navigate to (for `go_to` action).
374    pub url: Option<String>,
375    /// Dialog type (for `set_dialog_response`).
376    pub dialog_type: Option<DialogType>,
377    /// Dialog action (for `set_dialog_response`).
378    pub dialog_action: Option<DialogAction>,
379    /// Response text for prompt dialogs (for `set_dialog_response`).
380    pub text: Option<String>,
381    /// Target webview label.
382    pub webview_label: Option<String>,
383}
384
385// ── recording ───────────────────────────────────────────────────────────────
386
387/// Action for the compound `recording` tool.
388#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
389#[serde(rename_all = "snake_case")]
390pub enum RecordingAction {
391    /// Begin recording events.
392    Start,
393    /// Stop recording and return the session.
394    Stop,
395    /// Save a state checkpoint.
396    Checkpoint,
397    /// List all checkpoints in the current session.
398    ListCheckpoints,
399    /// Get events since an index.
400    GetEvents,
401    /// Get events between two checkpoints.
402    EventsBetween,
403    /// Get an IPC replay sequence.
404    GetReplay,
405    /// Export the current session as JSON.
406    Export,
407    /// Import a previously exported session.
408    Import,
409}
410
411impl fmt::Display for RecordingAction {
412    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413        match self {
414            Self::Start => f.write_str("start"),
415            Self::Stop => f.write_str("stop"),
416            Self::Checkpoint => f.write_str("checkpoint"),
417            Self::ListCheckpoints => f.write_str("list_checkpoints"),
418            Self::GetEvents => f.write_str("get_events"),
419            Self::EventsBetween => f.write_str("events_between"),
420            Self::GetReplay => f.write_str("get_replay"),
421            Self::Export => f.write_str("export"),
422            Self::Import => f.write_str("import"),
423        }
424    }
425}
426
427/// Parameters for the compound `recording` tool (start, stop, checkpoint, replay, export, import).
428#[derive(Debug, Deserialize, JsonSchema)]
429pub struct RecordingParams {
430    /// Action to perform: start, stop, checkpoint, `list_checkpoints`, `get_events`, `events_between`, `get_replay`, export, import.
431    pub action: RecordingAction,
432    /// Session ID (for start — optional, UUID generated if omitted).
433    pub session_id: Option<String>,
434    /// Checkpoint ID (for checkpoint, required).
435    pub checkpoint_id: Option<String>,
436    /// Checkpoint label (for checkpoint, optional).
437    pub checkpoint_label: Option<String>,
438    /// State snapshot as JSON (for checkpoint).
439    pub state: Option<serde_json::Value>,
440    /// Starting checkpoint ID (for `events_between`).
441    pub from: Option<String>,
442    /// Ending checkpoint ID (for `events_between`).
443    pub to: Option<String>,
444    /// Only return events after this index (for `get_events`).
445    pub since_index: Option<usize>,
446    /// JSON string of a previously exported `RecordedSession` (for import).
447    pub session_json: Option<String>,
448}
449
450// ── inspect ─────────────────────────────────────────────────────────────────
451
452/// Action for the compound `inspect` tool.
453#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
454#[serde(rename_all = "snake_case")]
455pub enum InspectAction {
456    /// Get computed CSS styles for an element.
457    GetStyles,
458    /// Get bounding boxes for elements.
459    GetBoundingBoxes,
460    /// Add a debug highlight overlay to an element.
461    Highlight,
462    /// Remove all debug highlight overlays.
463    ClearHighlights,
464    /// Run an accessibility audit.
465    AuditAccessibility,
466    /// Get performance metrics (timing, heap, DOM).
467    GetPerformance,
468}
469
470impl fmt::Display for InspectAction {
471    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472        match self {
473            Self::GetStyles => f.write_str("get_styles"),
474            Self::GetBoundingBoxes => f.write_str("get_bounding_boxes"),
475            Self::Highlight => f.write_str("highlight"),
476            Self::ClearHighlights => f.write_str("clear_highlights"),
477            Self::AuditAccessibility => f.write_str("audit_accessibility"),
478            Self::GetPerformance => f.write_str("get_performance"),
479        }
480    }
481}
482
483/// Parameters for the compound `inspect` tool (styles, bounding boxes, highlight, a11y, perf).
484#[derive(Debug, Deserialize, JsonSchema)]
485pub struct InspectParams {
486    /// Action to perform: `get_styles`, `get_bounding_boxes`, highlight, `clear_highlights`, `audit_accessibility`, `get_performance`.
487    pub action: InspectAction,
488    /// Ref handle ID (for `get_styles`, highlight).
489    pub ref_id: Option<String>,
490    /// List of ref handle IDs (for `get_bounding_boxes`).
491    pub ref_ids: Option<Vec<String>>,
492    /// CSS property names to return (for `get_styles` — if omitted, returns key properties).
493    pub properties: Option<Vec<String>>,
494    /// CSS color for the highlight overlay (for highlight, default: "rgba(255, 0, 0, 0.3)").
495    pub color: Option<String>,
496    /// Text label displayed above the highlight (for highlight).
497    #[serde(rename = "highlight_label")]
498    pub label: Option<String>,
499    /// Target webview label.
500    pub webview_label: Option<String>,
501}
502
503// ── css ─────────────────────────────────────────────────────────────────────
504
505/// Action for the compound `css` tool.
506#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
507#[serde(rename_all = "snake_case")]
508pub enum CssAction {
509    /// Inject custom CSS into the page.
510    Inject,
511    /// Remove previously injected CSS.
512    Remove,
513}
514
515impl fmt::Display for CssAction {
516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
517        match self {
518            Self::Inject => f.write_str("inject"),
519            Self::Remove => f.write_str("remove"),
520        }
521    }
522}
523
524/// Parameters for the compound `css` tool (inject, remove).
525#[derive(Debug, Deserialize, JsonSchema)]
526pub struct CssParams {
527    /// Action to perform: inject, remove.
528    pub action: CssAction,
529    /// CSS text to inject (for inject action).
530    pub css: Option<String>,
531    /// Target webview label.
532    pub webview_label: Option<String>,
533}
534
535// ── logs ────────────────────────────────────────────────────────────────────
536
537/// Action for the compound `logs` tool.
538#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
539#[serde(rename_all = "snake_case")]
540pub enum LogsAction {
541    /// Get captured console.log/warn/error entries.
542    Console,
543    /// Get intercepted fetch/XHR network requests.
544    Network,
545    /// Get IPC call log.
546    Ipc,
547    /// Get URL change history.
548    Navigation,
549    /// Get alert/confirm/prompt dialog events.
550    Dialogs,
551    /// Get combined event stream.
552    Events,
553    /// Find slow IPC calls exceeding a threshold.
554    SlowIpc,
555}
556
557impl fmt::Display for LogsAction {
558    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
559        match self {
560            Self::Console => f.write_str("console"),
561            Self::Network => f.write_str("network"),
562            Self::Ipc => f.write_str("ipc"),
563            Self::Navigation => f.write_str("navigation"),
564            Self::Dialogs => f.write_str("dialogs"),
565            Self::Events => f.write_str("events"),
566            Self::SlowIpc => f.write_str("slow_ipc"),
567        }
568    }
569}
570
571/// Parameters for the compound `logs` tool (console, network, ipc, navigation, dialogs, events).
572#[derive(Debug, Deserialize, JsonSchema)]
573pub struct LogsParams {
574    /// Action to perform: console, network, ipc, navigation, dialogs, events, `slow_ipc`.
575    pub action: LogsAction,
576    /// Only return entries after this Unix timestamp in milliseconds (for console, events).
577    pub since: Option<f64>,
578    /// Filter by URL substring (for network).
579    pub filter: Option<String>,
580    /// Maximum number of entries to return (for ipc, network, `slow_ipc`).
581    pub limit: Option<usize>,
582    /// Threshold in milliseconds for slow IPC calls (for `slow_ipc`).
583    pub threshold_ms: Option<u64>,
584    /// When true (for ipc action), await up to 500ms for the latest IPC entry's
585    /// response body to be fully captured. Uses event-driven signaling from the
586    /// fetch interceptor rather than polling.
587    pub wait_for_capture: Option<bool>,
588    /// Target webview label.
589    pub webview_label: Option<String>,
590}