vtcode_core/config/core/
agent.rs

1use crate::config::constants::{defaults, project_doc};
2use crate::config::types::{ReasoningEffortLevel, UiSurfacePreference};
3use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6/// Agent-wide configuration
7#[derive(Debug, Clone, Deserialize, Serialize)]
8pub struct AgentConfig {
9    /// AI provider for single agent mode (gemini, openai, anthropic, openrouter, xai, zai)
10    #[serde(default = "default_provider")]
11    pub provider: String,
12
13    /// Environment variable that stores the API key for the active provider
14    #[serde(default = "default_api_key_env")]
15    pub api_key_env: String,
16
17    /// Default model to use
18    #[serde(default = "default_model")]
19    pub default_model: String,
20
21    /// UI theme identifier controlling ANSI styling
22    #[serde(default = "default_theme")]
23    pub theme: String,
24
25    /// Enable TODO planning workflow integrations (update_plan tool, onboarding hints)
26    #[serde(default = "default_todo_planning_mode")]
27    pub todo_planning_mode: bool,
28
29    /// Preferred rendering surface for the interactive chat UI (auto, alternate, inline)
30    #[serde(default)]
31    pub ui_surface: UiSurfacePreference,
32
33    /// Maximum number of conversation turns before auto-termination
34    #[serde(default = "default_max_conversation_turns")]
35    pub max_conversation_turns: usize,
36
37    /// Reasoning effort level for models that support it (low, medium, high)
38    /// Applies to: Claude, GPT-5, Gemini, Qwen3, DeepSeek with reasoning capability
39    #[serde(default = "default_reasoning_effort")]
40    pub reasoning_effort: ReasoningEffortLevel,
41
42    /// Enable an extra self-review pass to refine final responses
43    #[serde(default = "default_enable_self_review")]
44    pub enable_self_review: bool,
45
46    /// Maximum number of self-review passes
47    #[serde(default = "default_max_review_passes")]
48    pub max_review_passes: usize,
49
50    /// Enable prompt refinement pass before sending to LLM
51    #[serde(default = "default_refine_prompts_enabled")]
52    pub refine_prompts_enabled: bool,
53
54    /// Max refinement passes for prompt writing
55    #[serde(default = "default_refine_max_passes")]
56    pub refine_prompts_max_passes: usize,
57
58    /// Optional model override for the refiner (empty = auto pick efficient sibling)
59    #[serde(default)]
60    pub refine_prompts_model: String,
61
62    /// Session onboarding and welcome message configuration
63    #[serde(default)]
64    pub onboarding: AgentOnboardingConfig,
65
66    /// Maximum bytes of AGENTS.md content to load from project hierarchy
67    #[serde(default = "default_project_doc_max_bytes")]
68    pub project_doc_max_bytes: usize,
69
70    /// Provider-specific API keys captured from interactive configuration flows
71    #[serde(default)]
72    pub custom_api_keys: BTreeMap<String, String>,
73}
74
75impl Default for AgentConfig {
76    fn default() -> Self {
77        Self {
78            provider: default_provider(),
79            api_key_env: default_api_key_env(),
80            default_model: default_model(),
81            theme: default_theme(),
82            todo_planning_mode: default_todo_planning_mode(),
83            ui_surface: UiSurfacePreference::default(),
84            max_conversation_turns: default_max_conversation_turns(),
85            reasoning_effort: default_reasoning_effort(),
86            enable_self_review: default_enable_self_review(),
87            max_review_passes: default_max_review_passes(),
88            refine_prompts_enabled: default_refine_prompts_enabled(),
89            refine_prompts_max_passes: default_refine_max_passes(),
90            refine_prompts_model: String::new(),
91            onboarding: AgentOnboardingConfig::default(),
92            project_doc_max_bytes: default_project_doc_max_bytes(),
93            custom_api_keys: BTreeMap::new(),
94        }
95    }
96}
97
98fn default_provider() -> String {
99    defaults::DEFAULT_PROVIDER.to_string()
100}
101
102fn default_api_key_env() -> String {
103    defaults::DEFAULT_API_KEY_ENV.to_string()
104}
105fn default_model() -> String {
106    defaults::DEFAULT_MODEL.to_string()
107}
108fn default_theme() -> String {
109    defaults::DEFAULT_THEME.to_string()
110}
111
112fn default_todo_planning_mode() -> bool {
113    true
114}
115fn default_max_conversation_turns() -> usize {
116    150
117}
118fn default_reasoning_effort() -> ReasoningEffortLevel {
119    ReasoningEffortLevel::default()
120}
121
122fn default_enable_self_review() -> bool {
123    false
124}
125
126fn default_max_review_passes() -> usize {
127    1
128}
129
130fn default_refine_prompts_enabled() -> bool {
131    false
132}
133
134fn default_refine_max_passes() -> usize {
135    1
136}
137
138fn default_project_doc_max_bytes() -> usize {
139    project_doc::DEFAULT_MAX_BYTES
140}
141
142#[derive(Debug, Clone, Deserialize, Serialize)]
143pub struct AgentOnboardingConfig {
144    /// Toggle onboarding message rendering
145    #[serde(default = "default_onboarding_enabled")]
146    pub enabled: bool,
147
148    /// Introductory text shown at session start
149    #[serde(default = "default_intro_text")]
150    pub intro_text: String,
151
152    /// Whether to include project overview in onboarding message
153    #[serde(default = "default_show_project_overview")]
154    pub include_project_overview: bool,
155
156    /// Whether to include language summary in onboarding message
157    #[serde(default = "default_show_language_summary")]
158    pub include_language_summary: bool,
159
160    /// Whether to include AGENTS.md highlights in onboarding message
161    #[serde(default = "default_show_guideline_highlights")]
162    pub include_guideline_highlights: bool,
163
164    /// Whether to surface usage tips inside the welcome text banner
165    #[serde(default = "default_show_usage_tips_in_welcome")]
166    pub include_usage_tips_in_welcome: bool,
167
168    /// Whether to surface suggested actions inside the welcome text banner
169    #[serde(default = "default_show_recommended_actions_in_welcome")]
170    pub include_recommended_actions_in_welcome: bool,
171
172    /// Maximum number of guideline bullets to surface
173    #[serde(default = "default_guideline_highlight_limit")]
174    pub guideline_highlight_limit: usize,
175
176    /// Tips for collaborating with the agent effectively
177    #[serde(default = "default_usage_tips")]
178    pub usage_tips: Vec<String>,
179
180    /// Recommended follow-up actions to display
181    #[serde(default = "default_recommended_actions")]
182    pub recommended_actions: Vec<String>,
183
184    /// Placeholder suggestion for the chat input bar
185    #[serde(default)]
186    pub chat_placeholder: Option<String>,
187}
188
189impl Default for AgentOnboardingConfig {
190    fn default() -> Self {
191        Self {
192            enabled: default_onboarding_enabled(),
193            intro_text: default_intro_text(),
194            include_project_overview: default_show_project_overview(),
195            include_language_summary: default_show_language_summary(),
196            include_guideline_highlights: default_show_guideline_highlights(),
197            include_usage_tips_in_welcome: default_show_usage_tips_in_welcome(),
198            include_recommended_actions_in_welcome: default_show_recommended_actions_in_welcome(),
199            guideline_highlight_limit: default_guideline_highlight_limit(),
200            usage_tips: default_usage_tips(),
201            recommended_actions: default_recommended_actions(),
202            chat_placeholder: None,
203        }
204    }
205}
206
207fn default_onboarding_enabled() -> bool {
208    true
209}
210
211fn default_intro_text() -> String {
212    "Let's get oriented. I preloaded workspace context so we can move fast.".to_string()
213}
214
215fn default_show_project_overview() -> bool {
216    true
217}
218
219fn default_show_language_summary() -> bool {
220    false
221}
222
223fn default_show_guideline_highlights() -> bool {
224    true
225}
226
227fn default_show_usage_tips_in_welcome() -> bool {
228    false
229}
230
231fn default_show_recommended_actions_in_welcome() -> bool {
232    false
233}
234
235fn default_guideline_highlight_limit() -> usize {
236    3
237}
238
239fn default_usage_tips() -> Vec<String> {
240    vec![
241        "Describe your current coding goal or ask for a quick status overview.".to_string(),
242        "Reference AGENTS.md guidelines when proposing changes.".to_string(),
243        "Draft or refresh your TODO list with update_plan before coding.".to_string(),
244        "Prefer asking for targeted file reads or diffs before editing.".to_string(),
245    ]
246}
247
248fn default_recommended_actions() -> Vec<String> {
249    vec![
250        "Start the session by outlining a 3–6 step TODO plan via update_plan.".to_string(),
251        "Review the highlighted guidelines and share the task you want to tackle.".to_string(),
252        "Ask for a workspace tour if you need more context.".to_string(),
253    ]
254}