aboutsummaryrefslogtreecommitdiff
path: root/src/app/api_helpers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/api_helpers.rs')
-rw-r--r--src/app/api_helpers.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/app/api_helpers.rs b/src/app/api_helpers.rs
new file mode 100644
index 00000000..011e5ccb
--- /dev/null
+++ b/src/app/api_helpers.rs
@@ -0,0 +1,92 @@
+pub(super) fn tab_attention_priority(state: crate::detect::AgentState, seen: bool) -> u8 {
+ match (state, seen) {
+ (crate::detect::AgentState::Blocked, _) => 4,
+ (crate::detect::AgentState::Idle, false) => 3,
+ (crate::detect::AgentState::Working, _) => 2,
+ (crate::detect::AgentState::Idle, true) => 1,
+ (crate::detect::AgentState::Unknown, _) => 0,
+ }
+}
+
+fn parse_api_key(key: &str) -> Option<crossterm::event::KeyEvent> {
+ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
+
+ let normalized = key.trim();
+ match normalized {
+ "Enter" | "enter" => Some(KeyEvent::new(KeyCode::Enter, KeyModifiers::empty())),
+ "Tab" | "tab" => Some(KeyEvent::new(KeyCode::Tab, KeyModifiers::empty())),
+ "Esc" | "esc" => Some(KeyEvent::new(KeyCode::Esc, KeyModifiers::empty())),
+ "Backspace" | "backspace" => Some(KeyEvent::new(KeyCode::Backspace, KeyModifiers::empty())),
+ "Up" | "up" => Some(KeyEvent::new(KeyCode::Up, KeyModifiers::empty())),
+ "Down" | "down" => Some(KeyEvent::new(KeyCode::Down, KeyModifiers::empty())),
+ "Left" | "left" => Some(KeyEvent::new(KeyCode::Left, KeyModifiers::empty())),
+ "Right" | "right" => Some(KeyEvent::new(KeyCode::Right, KeyModifiers::empty())),
+ "C-c" | "c-c" | "ctrl+c" => Some(KeyEvent::new(KeyCode::Char('c'), KeyModifiers::CONTROL)),
+ _ if normalized.len() == 1 => normalized
+ .chars()
+ .next()
+ .map(|ch| KeyEvent::new(KeyCode::Char(ch), KeyModifiers::empty())),
+ _ => None,
+ }
+}
+
+pub(super) fn encode_api_text(runtime: &crate::pane::PaneRuntime, text: &str) -> Vec<u8> {
+ let bracketed = runtime
+ .input_state()
+ .map(|state| state.bracketed_paste)
+ .unwrap_or(false);
+ if bracketed {
+ format!("\x1b[200~{text}\x1b[201~").into_bytes()
+ } else {
+ text.as_bytes().to_vec()
+ }
+}
+
+pub(super) fn encode_api_keys(
+ runtime: &crate::pane::PaneRuntime,
+ keys: &[String],
+) -> Result<Vec<Vec<u8>>, String> {
+ let mut encoded_keys = Vec::with_capacity(keys.len());
+ for key in keys {
+ let Some(key_event) = parse_api_key(key) else {
+ return Err(key.clone());
+ };
+ encoded_keys.push(runtime.encode_terminal_key(key_event.into()));
+ }
+ Ok(encoded_keys)
+}
+
+pub(super) fn detect_state_from_api(
+ state: crate::api::schema::PaneAgentState,
+) -> crate::detect::AgentState {
+ match state {
+ crate::api::schema::PaneAgentState::Idle => crate::detect::AgentState::Idle,
+ crate::api::schema::PaneAgentState::Working => crate::detect::AgentState::Working,
+ crate::api::schema::PaneAgentState::Blocked => crate::detect::AgentState::Blocked,
+ crate::api::schema::PaneAgentState::Unknown => crate::detect::AgentState::Unknown,
+ }
+}
+
+pub(super) fn pane_agent_status(
+ state: crate::detect::AgentState,
+ seen: bool,
+) -> crate::api::schema::AgentStatus {
+ match (state, seen) {
+ (crate::detect::AgentState::Idle, false) => crate::api::schema::AgentStatus::Done,
+ (crate::detect::AgentState::Idle, true) => crate::api::schema::AgentStatus::Idle,
+ (crate::detect::AgentState::Working, _) => crate::api::schema::AgentStatus::Working,
+ (crate::detect::AgentState::Blocked, _) => crate::api::schema::AgentStatus::Blocked,
+ (crate::detect::AgentState::Unknown, _) => crate::api::schema::AgentStatus::Unknown,
+ }
+}
+
+pub(super) fn normalize_reported_agent_label(agent: &str) -> Option<String> {
+ let trimmed = agent.trim();
+ if trimmed.is_empty() {
+ return None;
+ }
+ if let Some(agent) = crate::detect::parse_agent_label(trimmed) {
+ return Some(crate::detect::agent_label(agent).to_string());
+ }
+ Some(trimmed.to_string())
+}