Skip to main content

imp_core/
roles.rs

1use imp_llm::ThinkingLevel;
2use serde::{Deserialize, Serialize};
3
4/// Role definition from config.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct RoleDef {
7    pub model: Option<String>,
8    pub thinking: Option<ThinkingLevel>,
9    pub tools: Option<Vec<String>>,
10    #[serde(default)]
11    pub readonly: bool,
12    pub instructions: Option<String>,
13    pub max_turns: Option<u32>,
14}
15
16/// Resolved role ready for use.
17#[derive(Debug, Clone)]
18pub struct Role {
19    pub name: String,
20    pub model: Option<String>,
21    pub thinking_level: Option<ThinkingLevel>,
22    pub tool_set: ToolSet,
23    pub readonly: bool,
24    pub instructions: Option<String>,
25    pub max_turns: Option<u32>,
26}
27
28#[derive(Debug, Clone)]
29pub enum ToolSet {
30    All,
31    Only(Vec<String>),
32}
33
34impl Role {
35    /// Create a role from a definition.
36    pub fn from_def(name: &str, def: &RoleDef) -> Self {
37        let tool_set = match &def.tools {
38            Some(tools) => ToolSet::Only(tools.clone()),
39            None if def.readonly => ToolSet::Only(vec![
40                "read".into(),
41                "scan".into(),
42                "web".into(),
43                "recall".into(),
44            ]),
45            None => ToolSet::All,
46        };
47
48        Self {
49            name: name.to_string(),
50            model: def.model.clone(),
51            thinking_level: def.thinking,
52            tool_set,
53            readonly: def.readonly,
54            instructions: def.instructions.clone(),
55            max_turns: def.max_turns,
56        }
57    }
58}
59
60/// Built-in role definitions.
61pub fn builtin_roles() -> Vec<(&'static str, RoleDef)> {
62    vec![
63        (
64            "worker",
65            RoleDef {
66                model: None,
67                thinking: Some(ThinkingLevel::Medium),
68                tools: None,
69                readonly: false,
70                instructions: None,
71                max_turns: None,
72            },
73        ),
74        (
75            "explorer",
76            RoleDef {
77                model: Some("haiku".into()),
78                thinking: Some(ThinkingLevel::Off),
79                tools: Some(vec![
80                    "read".into(),
81                    "scan".into(),
82                    "web".into(),
83                    "recall".into(),
84                ]),
85                readonly: true,
86                instructions: Some("Explore and summarize. Do not modify files.".into()),
87                max_turns: Some(20),
88            },
89        ),
90        (
91            "reviewer",
92            RoleDef {
93                model: Some("sonnet".into()),
94                thinking: Some(ThinkingLevel::High),
95                tools: None,
96                readonly: true,
97                instructions: None,
98                max_turns: Some(10),
99            },
100        ),
101    ]
102}