aboutsummaryrefslogtreecommitdiff
path: root/src/detect
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-17 23:55:08 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-17 23:59:56 +0300
commite0758c32118f2aa006db3d8fa4b41833fe6e7ead (patch)
tree2b29dd61ebf870db8d0ac95cc0b4515178c834c4 /src/detect
parent040956531f673c8fb7720037494ed4e61b123c6c (diff)
feat: harden named agent cli workflows
refs #1525
Diffstat (limited to 'src/detect')
-rw-r--r--src/detect/mod.rs108
1 files changed, 83 insertions, 25 deletions
diff --git a/src/detect/mod.rs b/src/detect/mod.rs
index 5c220b52..53c3213a 100644
--- a/src/detect/mod.rs
+++ b/src/detect/mod.rs
@@ -65,6 +65,31 @@ pub enum Agent {
}
impl Agent {
+ #[cfg(test)]
+ pub const ALL: [Self; 21] = [
+ Self::Pi,
+ Self::Claude,
+ Self::Codex,
+ Self::Gemini,
+ Self::Cursor,
+ Self::Devin,
+ Self::Antigravity,
+ Self::Cline,
+ Self::Omp,
+ Self::Mastracode,
+ Self::OpenCode,
+ Self::GithubCopilot,
+ Self::Kimi,
+ Self::Kiro,
+ Self::Droid,
+ Self::Amp,
+ Self::Grok,
+ Self::Hermes,
+ Self::Kilo,
+ Self::Qodercli,
+ Self::Maki,
+ ];
+
pub const SCREEN_MANIFEST_AGENTS: [Self; 19] = [
Self::Pi,
Self::Claude,
@@ -114,6 +139,32 @@ pub fn agent_label(agent: Agent) -> &'static str {
}
}
+pub fn interactive_agent_executable(agent: Agent) -> &'static str {
+ match agent {
+ Agent::Pi => "pi",
+ Agent::Claude => "claude",
+ Agent::Codex => "codex",
+ Agent::Gemini => "gemini",
+ Agent::Cursor => "cursor-agent",
+ Agent::Devin => "devin",
+ Agent::Antigravity => "agy",
+ Agent::Cline => "cline",
+ Agent::Omp => "omp",
+ Agent::Mastracode => "mastracode",
+ Agent::OpenCode => "opencode",
+ Agent::GithubCopilot => "copilot",
+ Agent::Kimi => "kimi",
+ Agent::Kiro => "kiro-cli",
+ Agent::Droid => "droid",
+ Agent::Amp => "amp",
+ Agent::Grok => "grok",
+ Agent::Hermes => "hermes",
+ Agent::Kilo => "kilo",
+ Agent::Qodercli => "qodercli",
+ Agent::Maki => "maki",
+ }
+}
+
pub fn parse_agent_label(agent: &str) -> Option<Agent> {
let name = normalized_agent_lookup_name(agent);
parse_canonical_agent_label(&name).or_else(|| lookup_agent(&name))
@@ -662,31 +713,7 @@ mod tests {
#[test]
fn every_agent_label_round_trips_through_canonical_and_alias_parsers() {
- let agents = [
- Agent::Pi,
- Agent::Claude,
- Agent::Codex,
- Agent::Gemini,
- Agent::Cursor,
- Agent::Devin,
- Agent::Antigravity,
- Agent::Cline,
- Agent::Omp,
- Agent::Mastracode,
- Agent::OpenCode,
- Agent::GithubCopilot,
- Agent::Kimi,
- Agent::Kiro,
- Agent::Droid,
- Agent::Amp,
- Agent::Grok,
- Agent::Hermes,
- Agent::Kilo,
- Agent::Qodercli,
- Agent::Maki,
- ];
-
- for agent in agents {
+ for agent in Agent::ALL {
let label = agent_label(agent);
assert_eq!(parse_canonical_agent_label(label), Some(agent));
assert_eq!(parse_agent_label(label), Some(agent));
@@ -694,6 +721,37 @@ mod tests {
}
#[test]
+ fn every_agent_has_a_canonical_interactive_executable() {
+ let expected = [
+ (Agent::Pi, "pi"),
+ (Agent::Claude, "claude"),
+ (Agent::Codex, "codex"),
+ (Agent::Gemini, "gemini"),
+ (Agent::Cursor, "cursor-agent"),
+ (Agent::Devin, "devin"),
+ (Agent::Antigravity, "agy"),
+ (Agent::Cline, "cline"),
+ (Agent::Omp, "omp"),
+ (Agent::Mastracode, "mastracode"),
+ (Agent::OpenCode, "opencode"),
+ (Agent::GithubCopilot, "copilot"),
+ (Agent::Kimi, "kimi"),
+ (Agent::Kiro, "kiro-cli"),
+ (Agent::Droid, "droid"),
+ (Agent::Amp, "amp"),
+ (Agent::Grok, "grok"),
+ (Agent::Hermes, "hermes"),
+ (Agent::Kilo, "kilo"),
+ (Agent::Qodercli, "qodercli"),
+ (Agent::Maki, "maki"),
+ ];
+ assert_eq!(expected.len(), Agent::ALL.len());
+ for (agent, executable) in expected {
+ assert_eq!(interactive_agent_executable(agent), executable);
+ }
+ }
+
+ #[test]
fn canonical_agent_labels_are_strict() {
assert_eq!(parse_canonical_agent_label("claude-code"), None);
assert_eq!(parse_canonical_agent_label("Pi"), None);