Skip to main content

lean_ctx/core/agents/
roles.rs

1use super::ScratchpadEntry;
2use crate::core::a2a::message::{A2AMessage, MessageCategory};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum AgentRole {
8    Coder,
9    Reviewer,
10    Planner,
11    Explorer,
12    Debugger,
13    Tester,
14    Orchestrator,
15}
16
17impl AgentRole {
18    pub fn from_str_loose(s: &str) -> Self {
19        match s.to_lowercase().as_str() {
20            "review" | "reviewer" | "code_review" => Self::Reviewer,
21            "plan" | "planner" | "architect" => Self::Planner,
22            "explore" | "explorer" | "research" => Self::Explorer,
23            "debug" | "debugger" => Self::Debugger,
24            "test" | "tester" | "qa" => Self::Tester,
25            "orchestrator" | "coordinator" | "manager" => Self::Orchestrator,
26            _ => Self::Coder,
27        }
28    }
29}
30
31#[derive(Debug, Clone)]
32pub struct ContextDepthConfig {
33    pub max_files_full: usize,
34    pub max_files_signatures: usize,
35    pub preferred_mode: &'static str,
36    pub context_budget_ratio: f64,
37}
38
39impl ContextDepthConfig {
40    pub fn for_role(role: AgentRole) -> Self {
41        match role {
42            AgentRole::Coder => Self {
43                max_files_full: 5,
44                max_files_signatures: 15,
45                preferred_mode: "full",
46                context_budget_ratio: 0.7,
47            },
48            AgentRole::Reviewer => Self {
49                max_files_full: 3,
50                max_files_signatures: 20,
51                preferred_mode: "signatures",
52                context_budget_ratio: 0.5,
53            },
54            AgentRole::Planner => Self {
55                max_files_full: 1,
56                max_files_signatures: 10,
57                preferred_mode: "map",
58                context_budget_ratio: 0.3,
59            },
60            AgentRole::Explorer => Self {
61                max_files_full: 2,
62                max_files_signatures: 8,
63                preferred_mode: "map",
64                context_budget_ratio: 0.4,
65            },
66            AgentRole::Debugger => Self {
67                max_files_full: 8,
68                max_files_signatures: 5,
69                preferred_mode: "full",
70                context_budget_ratio: 0.8,
71            },
72            AgentRole::Tester => Self {
73                max_files_full: 4,
74                max_files_signatures: 10,
75                preferred_mode: "full",
76                context_budget_ratio: 0.6,
77            },
78            AgentRole::Orchestrator => Self {
79                max_files_full: 0,
80                max_files_signatures: 5,
81                preferred_mode: "map",
82                context_budget_ratio: 0.2,
83            },
84        }
85    }
86}
87
88impl From<ScratchpadEntry> for A2AMessage {
89    fn from(entry: ScratchpadEntry) -> Self {
90        Self {
91            id: entry.id,
92            from_agent: entry.from_agent,
93            to_agent: entry.to_agent,
94            task_id: entry.task_id,
95            category: MessageCategory::parse_str(&entry.category),
96            priority: entry.priority,
97            privacy: entry.privacy,
98            content: entry.message,
99            metadata: entry.metadata,
100            project_root: entry.project_root,
101            timestamp: entry.timestamp,
102            read_by: entry.read_by,
103            expires_at: entry.expires_at,
104        }
105    }
106}
107
108impl From<A2AMessage> for ScratchpadEntry {
109    fn from(msg: A2AMessage) -> Self {
110        Self {
111            id: msg.id,
112            from_agent: msg.from_agent,
113            to_agent: msg.to_agent,
114            task_id: msg.task_id,
115            category: msg.category.to_string(),
116            priority: msg.priority,
117            privacy: msg.privacy,
118            message: msg.content,
119            metadata: msg.metadata,
120            project_root: msg.project_root,
121            timestamp: msg.timestamp,
122            read_by: msg.read_by,
123            expires_at: msg.expires_at,
124        }
125    }
126}