rust_genai/
computer_use.rs1use serde::{Deserialize, Serialize};
4
5use rust_genai_types::tool::FunctionDeclaration;
6
7pub const COMPUTER_USE_ACTIONS: &[&str] = &[
9 "open_web_browser",
10 "wait_5_seconds",
11 "go_back",
12 "go_forward",
13 "search",
14 "navigate",
15 "click_at",
16 "hover_at",
17 "type_text_at",
18 "key_combination",
19 "scroll_document",
20 "scroll_at",
21 "drag_and_drop",
22];
23
24#[must_use]
26pub fn computer_use_function_declarations() -> Vec<FunctionDeclaration> {
27 COMPUTER_USE_ACTIONS
28 .iter()
29 .map(|name| FunctionDeclaration {
30 name: (*name).to_string(),
31 description: None,
32 parameters: None,
33 parameters_json_schema: None,
34 response: None,
35 response_json_schema: None,
36 behavior: None,
37 })
38 .collect()
39}
40
41#[must_use]
43pub fn normalize_coordinate(pixel: i32, screen_dimension: i32) -> i32 {
44 if screen_dimension <= 0 {
45 return 0;
46 }
47 let numerator = i64::from(pixel) * 1000;
48 let denominator = i64::from(screen_dimension);
49 let value = numerator / denominator;
50 i32::try_from(value).unwrap_or(if value < 0 { i32::MIN } else { i32::MAX })
51}
52
53#[must_use]
55pub fn denormalize_coordinate(normalized: i32, screen_dimension: i32) -> i32 {
56 if screen_dimension <= 0 {
57 return 0;
58 }
59 let numerator = i64::from(normalized) * i64::from(screen_dimension);
60 let value = numerator / 1000;
61 i32::try_from(value).unwrap_or(if value < 0 { i32::MIN } else { i32::MAX })
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
66#[serde(rename_all = "snake_case")]
67pub struct SafetyDecision {
68 pub decision: SafetyDecisionType,
69 pub explanation: String,
70}
71
72#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
73#[serde(rename_all = "snake_case")]
74pub enum SafetyDecisionType {
75 RequireConfirmation,
76 Regular,
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_computer_use_coordinate_normalization() {
85 assert_eq!(normalize_coordinate(720, 1440), 500);
86 assert_eq!(denormalize_coordinate(500, 1440), 720);
87 }
88
89 #[test]
90 fn test_computer_use_actions_and_zero_dimension() {
91 let declarations = computer_use_function_declarations();
92 assert_eq!(declarations.len(), COMPUTER_USE_ACTIONS.len());
93 assert_eq!(declarations[0].name, COMPUTER_USE_ACTIONS[0]);
94 assert_eq!(normalize_coordinate(10, 0), 0);
95 assert_eq!(denormalize_coordinate(10, -1), 0);
96 }
97}