Skip to main content

devboy_core/agents/
mod.rs

1//! Agent detection.
2//!
3//! Walks `$HOME/` looking for deterministic on-disk traces of supported AI
4//! coding agents (Claude Code, GitHub Copilot CLI, Codex CLI, Kimi Code CLI,
5//! Cursor, Gemini CLI, Antigravity), and reports a structured snapshot per
6//! agent — install status, session count, last-used timestamp, and a score
7//! used to pick a primary candidate for `devboy onboard`.
8//!
9//! Architecture: one [`AgentDetector`] implementation per agent file, plus
10//! a [`registry::detect_all`] entrypoint that runs every detector
11//! sequentially and returns a sorted [`AgentSnapshot`] vector. Each detector
12//! is bound on filesystem I/O (a handful of `read_dir` + `metadata` calls);
13//! the total wall-clock is well under a second on a real machine, so we
14//! don't add a thread pool today.
15//!
16//! See ADR-017.
17
18pub mod antigravity;
19pub mod bundles;
20pub mod claude;
21pub mod codex;
22pub mod copilot;
23pub mod cursor;
24pub mod gemini;
25pub mod kimi;
26pub mod registry;
27pub mod score;
28
29mod fs_util;
30
31use std::path::{Path, PathBuf};
32
33use chrono::{DateTime, Utc};
34use serde::Serialize;
35
36pub use registry::{detect_all, detect_all_with_home};
37pub use score::{compute_score, pick_primary};
38
39/// Whether an agent is installed on the machine.
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
41#[serde(rename_all = "lowercase")]
42pub enum InstallStatus {
43    /// The agent's install marker (config dir or binary) was found.
44    Yes,
45    /// No traces found.
46    No,
47    /// We couldn't determine — e.g. the marker exists but is empty/ambiguous.
48    Unknown,
49}
50
51/// One row in the detector's report.
52#[derive(Debug, Clone, Serialize)]
53pub struct AgentSnapshot {
54    pub id: &'static str,
55    pub display_name: &'static str,
56    pub status: InstallStatus,
57    pub sessions: Option<u64>,
58    pub last_used: Option<DateTime<Utc>>,
59    pub score: f64,
60    pub paths_checked: Vec<PathBuf>,
61}
62
63/// Trait every per-agent detector implements.
64pub trait AgentDetector: Send + Sync {
65    /// Fn.
66    fn id(&self) -> &'static str;
67    /// Fn.
68    fn display_name(&self) -> &'static str;
69
70    /// Inspect `home` (the user's home directory) and produce a snapshot.
71    /// Detectors must not panic on missing paths — `InstallStatus::No` is the
72    /// expected outcome for absent agents.
73    fn detect(&self, home: &Path) -> AgentSnapshot;
74}