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 include_graph: bool,
37 pub include_knowledge: bool,
38 pub include_gotchas: bool,
39 pub context_budget_ratio: f64,
40}
41
42impl ContextDepthConfig {
43 pub fn for_role(role: AgentRole) -> Self {
44 match role {
45 AgentRole::Coder => Self {
46 max_files_full: 5,
47 max_files_signatures: 15,
48 preferred_mode: "full",
49 include_graph: true,
50 include_knowledge: true,
51 include_gotchas: true,
52 context_budget_ratio: 0.7,
53 },
54 AgentRole::Reviewer => Self {
55 max_files_full: 3,
56 max_files_signatures: 20,
57 preferred_mode: "signatures",
58 include_graph: true,
59 include_knowledge: true,
60 include_gotchas: true,
61 context_budget_ratio: 0.5,
62 },
63 AgentRole::Planner => Self {
64 max_files_full: 1,
65 max_files_signatures: 10,
66 preferred_mode: "map",
67 include_graph: true,
68 include_knowledge: true,
69 include_gotchas: false,
70 context_budget_ratio: 0.3,
71 },
72 AgentRole::Explorer => Self {
73 max_files_full: 2,
74 max_files_signatures: 8,
75 preferred_mode: "map",
76 include_graph: true,
77 include_knowledge: false,
78 include_gotchas: false,
79 context_budget_ratio: 0.4,
80 },
81 AgentRole::Debugger => Self {
82 max_files_full: 8,
83 max_files_signatures: 5,
84 preferred_mode: "full",
85 include_graph: false,
86 include_knowledge: true,
87 include_gotchas: true,
88 context_budget_ratio: 0.8,
89 },
90 AgentRole::Tester => Self {
91 max_files_full: 4,
92 max_files_signatures: 10,
93 preferred_mode: "full",
94 include_graph: false,
95 include_knowledge: false,
96 include_gotchas: true,
97 context_budget_ratio: 0.6,
98 },
99 AgentRole::Orchestrator => Self {
100 max_files_full: 0,
101 max_files_signatures: 5,
102 preferred_mode: "map",
103 include_graph: true,
104 include_knowledge: true,
105 include_gotchas: false,
106 context_budget_ratio: 0.2,
107 },
108 }
109 }
110
111 pub fn mode_for_rank(&self, rank: usize) -> &'static str {
112 if rank < self.max_files_full {
113 "full"
114 } else if rank < self.max_files_full + self.max_files_signatures {
115 "signatures"
116 } else {
117 "map"
118 }
119 }
120}
121
122impl From<ScratchpadEntry> for A2AMessage {
123 fn from(entry: ScratchpadEntry) -> Self {
124 Self {
125 id: entry.id,
126 from_agent: entry.from_agent,
127 to_agent: entry.to_agent,
128 task_id: entry.task_id,
129 category: MessageCategory::parse_str(&entry.category),
130 priority: entry.priority,
131 privacy: entry.privacy,
132 content: entry.message,
133 metadata: entry.metadata,
134 project_root: entry.project_root,
135 timestamp: entry.timestamp,
136 read_by: entry.read_by,
137 expires_at: entry.expires_at,
138 }
139 }
140}
141
142impl From<A2AMessage> for ScratchpadEntry {
143 fn from(msg: A2AMessage) -> Self {
144 Self {
145 id: msg.id,
146 from_agent: msg.from_agent,
147 to_agent: msg.to_agent,
148 task_id: msg.task_id,
149 category: msg.category.to_string(),
150 priority: msg.priority,
151 privacy: msg.privacy,
152 message: msg.content,
153 metadata: msg.metadata,
154 project_root: msg.project_root,
155 timestamp: msg.timestamp,
156 read_by: msg.read_by,
157 expires_at: msg.expires_at,
158 }
159 }
160}