ai-agent 0.13.4

Idiomatic agent sdk inspired by the claude code source leak
Documentation
// Source: /data/home/swei/claudecode/openclaudecode/src/utils/modifiers.ts
//! Modifier key utilities.

use serde::{Deserialize, Serialize};

/// Modifier keys
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Modifier {
    Control,
    Shift,
    Alt,
    Meta,
    Command,
    Function,
}

/// Keyboard shortcut
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Shortcut {
    pub key: char,
    pub modifiers: Vec<Modifier>,
}

impl Shortcut {
    pub fn new(key: char) -> Self {
        Self {
            key,
            modifiers: Vec::new(),
        }
    }

    pub fn with_modifier(mut self, modifier: Modifier) -> Self {
        self.modifiers.push(modifier);
        self
    }

    pub fn ctrl(key: char) -> Self {
        Self::new(key).with_modifier(Modifier::Control)
    }

    pub fn shift(key: char) -> Self {
        Self::new(key).with_modifier(Modifier::Shift)
    }

    pub fn alt(key: char) -> Self {
        Self::new(key).with_modifier(Modifier::Alt)
    }

    pub fn cmd(key: char) -> Self {
        Self::new(key).with_modifier(Modifier::Command)
    }

    pub fn to_string(&self) -> String {
        let mut parts = Vec::new();

        for m in &self.modifiers {
            match m {
                Modifier::Control => parts.push("Ctrl"),
                Modifier::Shift => parts.push("Shift"),
                Modifier::Alt => parts.push("Alt"),
                Modifier::Meta => parts.push("Meta"),
                Modifier::Command => parts.push("Cmd"),
                Modifier::Function => parts.push("Fn"),
            }
        }

        let key_str = self.key.to_string();
        parts.push(&key_str);
        parts.join("+")
    }
}