Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/cua-driver/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions libs/cua-driver/rust/crates/cua-driver-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ anyhow = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
async-trait = "0.1"
uuid = { workspace = true }
# Used by the shared `image_utils` module — pure PNG/JPEG/resize/crosshair
# helpers extracted from `platform-{macos,windows,linux}/src/capture.rs` so
# all three platforms call the same code path.
Expand Down
138 changes: 138 additions & 0 deletions libs/cua-driver/rust/crates/cua-driver-core/src/api/capabilities.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//! Conservative, explicit route capability reporting and preflight.

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

use super::contracts::Route;

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PlatformName {
Macos,
Windows,
Linux,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ActionKind {
Click,
Drag,
Scroll,
PressKey,
TypeText,
SetValue,
SelectText,
PerformSecondaryAction,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AddressingMode {
Window,
Element,
CapturedPoint,
ObservedFocus,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Framework {
AppKit,
Chromium,
Electron,
WebKit,
Catalyst,
Unknown,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WindowStateKind {
Visible,
Occluded,
Minimized,
OffSpace,
Unknown,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CapabilityKey {
pub platform: PlatformName,
pub os_version: String,
pub action: ActionKind,
pub addressing: AddressingMode,
pub framework: Framework,
pub window_state: WindowStateKind,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "decision", rename_all = "snake_case", deny_unknown_fields)]
pub enum RouteDecision {
Supported { route: Route },
Unsupported { reason: String },
}

impl RouteDecision {
pub fn route(&self) -> Option<Route> {
match self {
Self::Supported { route } => Some(*route),
Self::Unsupported { .. } => None,
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CapabilityCell {
pub key: CapabilityKey,
pub decision: RouteDecision,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CapabilityManifest {
pub platform: PlatformName,
pub driver_version: String,
pub protocol_version: String,
#[serde(default)]
pub permissions: BTreeMap<String, bool>,
#[serde(default)]
pub cells: Vec<CapabilityCell>,
}

#[derive(Debug, Default)]
pub struct CapabilityRegistry {
cells: BTreeMap<CapabilityKey, RouteDecision>,
}

impl CapabilityRegistry {
pub fn from_cells(cells: impl IntoIterator<Item = CapabilityCell>) -> Self {
let mut registry = Self::default();
for cell in cells {
assert!(
registry.cells.insert(cell.key, cell.decision).is_none(),
"platform capability source emitted a duplicate cell"
);
}
registry
}

pub fn decision(&self, key: &CapabilityKey) -> RouteDecision {
self.cells
.get(key)
.cloned()
.unwrap_or_else(|| RouteDecision::Unsupported {
reason: "capability cell has not been proven for background execution".to_owned(),
})
}

pub fn cells(&self) -> impl Iterator<Item = CapabilityCell> + '_ {
self.cells.iter().map(|(key, decision)| CapabilityCell {
key: key.clone(),
decision: decision.clone(),
})
}
}
Loading
Loading