vtcode_core/config/
constants.rs

1/// Prompt path constants to avoid hardcoding throughout the codebase
2pub mod prompts {
3    pub const DEFAULT_SYSTEM_PROMPT_PATH: &str = "prompts/system.md";
4    pub const CODER_SYSTEM_PROMPT_PATH: &str = "prompts/coder_system.md";
5}
6
7/// Model ID constants to sync with docs/models.json
8pub mod models {
9    // Google/Gemini models
10    pub mod google {
11        pub const DEFAULT_MODEL: &str = "gemini-2.5-flash-preview-05-20";
12        pub const SUPPORTED_MODELS: &[&str] = &[
13            "gemini-2.5-flash-preview-05-20",
14            "gemini-2.5-pro",
15            "gemini-2.5-flash",
16            "gemini-2.5-flash-lite",
17        ];
18
19        // Convenience constants for commonly used models
20        pub const GEMINI_2_5_FLASH_PREVIEW: &str = "gemini-2.5-flash-preview-05-20";
21        pub const GEMINI_2_5_PRO: &str = "gemini-2.5-pro";
22        pub const GEMINI_2_5_FLASH: &str = "gemini-2.5-flash";
23        pub const GEMINI_2_5_FLASH_LITE: &str = "gemini-2.5-flash-lite";
24    }
25
26    // OpenAI models (from docs/models.json)
27    pub mod openai {
28        pub const DEFAULT_MODEL: &str = "gpt-5";
29        pub const SUPPORTED_MODELS: &[&str] = &[
30            "gpt-5",
31            "gpt-5-codex",
32            "gpt-5-mini",
33            "gpt-5-nano",
34            "codex-mini-latest",
35        ];
36
37        /// Models that support the OpenAI reasoning API extensions
38        pub const REASONING_MODELS: &[&str] = &[GPT_5, GPT_5_CODEX, GPT_5_MINI, GPT_5_NANO];
39
40        /// Models that do not expose structured tool calling on the OpenAI platform
41        pub const TOOL_UNAVAILABLE_MODELS: &[&str] = &[];
42
43        // Convenience constants for commonly used models
44        pub const GPT_5: &str = "gpt-5";
45        pub const GPT_5_CODEX: &str = "gpt-5-codex";
46        pub const GPT_5_MINI: &str = "gpt-5-mini";
47        pub const GPT_5_NANO: &str = "gpt-5-nano";
48        pub const CODEX_MINI_LATEST: &str = "codex-mini-latest";
49        pub const CODEX_MINI: &str = "codex-mini";
50    }
51
52    // Z.AI models (direct API)
53    pub mod zai {
54        pub const DEFAULT_MODEL: &str = "glm-4.6";
55        pub const SUPPORTED_MODELS: &[&str] = &[
56            "glm-4.6",
57            "glm-4.5",
58            "glm-4.5-air",
59            "glm-4.5-x",
60            "glm-4.5-airx",
61            "glm-4.5-flash",
62            "glm-4-32b-0414-128k",
63        ];
64
65        pub const GLM_4_6: &str = "glm-4.6";
66        pub const GLM_4_5: &str = "glm-4.5";
67        pub const GLM_4_5_AIR: &str = "glm-4.5-air";
68        pub const GLM_4_5_X: &str = "glm-4.5-x";
69        pub const GLM_4_5_AIRX: &str = "glm-4.5-airx";
70        pub const GLM_4_5_FLASH: &str = "glm-4.5-flash";
71        pub const GLM_4_32B_0414_128K: &str = "glm-4-32b-0414-128k";
72    }
73
74    // Moonshot.ai models (direct API)
75    pub mod moonshot {
76        pub const DEFAULT_MODEL: &str = "kimi-k2-turbo-preview";
77        pub const SUPPORTED_MODELS: &[&str] = &[
78            "kimi-k2-turbo-preview",
79            "kimi-k2-0905-preview",
80            "kimi-k2-0711-preview",
81            "kimi-latest",
82            "kimi-latest-8k",
83            "kimi-latest-32k",
84            "kimi-latest-128k",
85        ];
86
87        pub const KIMI_K2_TURBO_PREVIEW: &str = "kimi-k2-turbo-preview";
88        pub const KIMI_K2_0905_PREVIEW: &str = "kimi-k2-0905-preview";
89        pub const KIMI_K2_0711_PREVIEW: &str = "kimi-k2-0711-preview";
90        pub const KIMI_LATEST: &str = "kimi-latest";
91        pub const KIMI_LATEST_8K: &str = "kimi-latest-8k";
92        pub const KIMI_LATEST_32K: &str = "kimi-latest-32k";
93        pub const KIMI_LATEST_128K: &str = "kimi-latest-128k";
94    }
95
96    // OpenRouter models (extensible via vtcode.toml)
97    pub mod openrouter {
98        pub const X_AI_GROK_CODE_FAST_1: &str = "x-ai/grok-code-fast-1";
99        pub const X_AI_GROK_4_FAST: &str = "x-ai/grok-4-fast";
100        pub const X_AI_GROK_4: &str = "x-ai/grok-4";
101        pub const Z_AI_GLM_4_5_AIR_FREE: &str = "z-ai/glm-4.5-air:free";
102        pub const Z_AI_GLM_4_6: &str = "z-ai/glm-4.6";
103        pub const MOONSHOTAI_KIMI_K2_0905: &str = "moonshotai/kimi-k2-0905";
104        pub const QWEN3_MAX: &str = "qwen/qwen3-max";
105        pub const QWEN3_235B_A22B: &str = "qwen/qwen3-235b-a22b";
106        pub const QWEN3_235B_A22B_FREE: &str = "qwen/qwen3-235b-a22b:free";
107        pub const QWEN3_235B_A22B_2507: &str = "qwen/qwen3-235b-a22b-2507";
108        pub const QWEN3_235B_A22B_THINKING_2507: &str = "qwen/qwen3-235b-a22b-thinking-2507";
109        pub const QWEN3_32B: &str = "qwen/qwen3-32b";
110        pub const QWEN3_30B_A3B: &str = "qwen/qwen3-30b-a3b";
111        pub const QWEN3_30B_A3B_FREE: &str = "qwen/qwen3-30b-a3b:free";
112        pub const QWEN3_30B_A3B_INSTRUCT_2507: &str = "qwen/qwen3-30b-a3b-instruct-2507";
113        pub const QWEN3_30B_A3B_THINKING_2507: &str = "qwen/qwen3-30b-a3b-thinking-2507";
114        pub const QWEN3_14B: &str = "qwen/qwen3-14b";
115        pub const QWEN3_14B_FREE: &str = "qwen/qwen3-14b:free";
116        pub const QWEN3_8B: &str = "qwen/qwen3-8b";
117        pub const QWEN3_8B_FREE: &str = "qwen/qwen3-8b:free";
118        pub const QWEN3_4B_FREE: &str = "qwen/qwen3-4b:free";
119        pub const QWEN3_NEXT_80B_A3B_INSTRUCT: &str = "qwen/qwen3-next-80b-a3b-instruct";
120        pub const QWEN3_NEXT_80B_A3B_THINKING: &str = "qwen/qwen3-next-80b-a3b-thinking";
121        pub const QWEN3_CODER: &str = "qwen/qwen3-coder";
122        pub const QWEN3_CODER_FREE: &str = "qwen/qwen3-coder:free";
123        pub const QWEN3_CODER_PLUS: &str = "qwen/qwen3-coder-plus";
124        pub const QWEN3_CODER_FLASH: &str = "qwen/qwen3-coder-flash";
125        pub const QWEN3_CODER_30B_A3B_INSTRUCT: &str = "qwen/qwen3-coder-30b-a3b-instruct";
126        pub const DEEPSEEK_DEEPSEEK_V3_2_EXP: &str = "deepseek/deepseek-v3.2-exp";
127        pub const DEEPSEEK_DEEPSEEK_CHAT_V3_1: &str = "deepseek/deepseek-chat-v3.1";
128        pub const DEEPSEEK_DEEPSEEK_R1: &str = "deepseek/deepseek-r1";
129        pub const OPENAI_GPT_OSS_120B: &str = "openai/gpt-oss-120b";
130        pub const OPENAI_GPT_OSS_20B: &str = "openai/gpt-oss-20b";
131        pub const OPENAI_GPT_OSS_20B_FREE: &str = "openai/gpt-oss-20b:free";
132        pub const OPENAI_GPT_5: &str = "openai/gpt-5";
133        pub const OPENAI_GPT_5_CODEX: &str = "openai/gpt-5-codex";
134        pub const OPENAI_GPT_5_CHAT: &str = "openai/gpt-5-chat";
135        pub const OPENAI_GPT_4O_SEARCH_PREVIEW: &str = "openai/gpt-4o-search-preview";
136        pub const OPENAI_GPT_4O_MINI_SEARCH_PREVIEW: &str = "openai/gpt-4o-mini-search-preview";
137        pub const OPENAI_CHATGPT_4O_LATEST: &str = "openai/chatgpt-4o-latest";
138        pub const ANTHROPIC_CLAUDE_SONNET_4_5: &str = "anthropic/claude-sonnet-4.5";
139        pub const ANTHROPIC_CLAUDE_OPUS_4_1: &str = "anthropic/claude-opus-4.1";
140
141        pub const DEFAULT_MODEL: &str = X_AI_GROK_CODE_FAST_1;
142
143        pub const SUPPORTED_MODELS: &[&str] = &[
144            X_AI_GROK_CODE_FAST_1,
145            X_AI_GROK_4_FAST,
146            X_AI_GROK_4,
147            Z_AI_GLM_4_5_AIR_FREE,
148            Z_AI_GLM_4_6,
149            MOONSHOTAI_KIMI_K2_0905,
150            QWEN3_MAX,
151            QWEN3_235B_A22B,
152            QWEN3_235B_A22B_FREE,
153            QWEN3_235B_A22B_2507,
154            QWEN3_235B_A22B_THINKING_2507,
155            QWEN3_32B,
156            QWEN3_30B_A3B,
157            QWEN3_30B_A3B_INSTRUCT_2507,
158            QWEN3_30B_A3B_THINKING_2507,
159            QWEN3_14B,
160            QWEN3_NEXT_80B_A3B_INSTRUCT,
161            QWEN3_NEXT_80B_A3B_THINKING,
162            QWEN3_CODER,
163            QWEN3_CODER_FREE,
164            QWEN3_CODER_PLUS,
165            QWEN3_CODER_FLASH,
166            QWEN3_CODER_30B_A3B_INSTRUCT,
167            QWEN3_4B_FREE,
168            DEEPSEEK_DEEPSEEK_V3_2_EXP,
169            DEEPSEEK_DEEPSEEK_CHAT_V3_1,
170            DEEPSEEK_DEEPSEEK_R1,
171            OPENAI_GPT_OSS_120B,
172            OPENAI_GPT_OSS_20B,
173            OPENAI_GPT_5,
174            OPENAI_GPT_5_CODEX,
175            ANTHROPIC_CLAUDE_SONNET_4_5,
176            ANTHROPIC_CLAUDE_OPUS_4_1,
177        ];
178
179        /// Models that expose reasoning traces via OpenRouter APIs
180        pub const REASONING_MODELS: &[&str] = &[
181            X_AI_GROK_CODE_FAST_1,
182            X_AI_GROK_4_FAST,
183            X_AI_GROK_4,
184            Z_AI_GLM_4_6,
185            QWEN3_235B_A22B,
186            QWEN3_235B_A22B_FREE,
187            QWEN3_235B_A22B_THINKING_2507,
188            QWEN3_32B,
189            QWEN3_30B_A3B,
190            QWEN3_30B_A3B_THINKING_2507,
191            QWEN3_14B,
192            QWEN3_4B_FREE,
193            QWEN3_NEXT_80B_A3B_THINKING,
194            DEEPSEEK_DEEPSEEK_V3_2_EXP,
195            DEEPSEEK_DEEPSEEK_CHAT_V3_1,
196            DEEPSEEK_DEEPSEEK_R1,
197            OPENAI_GPT_OSS_120B,
198            OPENAI_GPT_OSS_20B,
199            OPENAI_GPT_5,
200            OPENAI_GPT_5_CODEX,
201            ANTHROPIC_CLAUDE_SONNET_4_5,
202            ANTHROPIC_CLAUDE_OPUS_4_1,
203        ];
204
205        /// Models that do not expose function calling via OpenRouter
206        pub const TOOL_UNAVAILABLE_MODELS: &[&str] = &[
207            Z_AI_GLM_4_5_AIR_FREE,
208            QWEN3_30B_A3B_FREE,
209            QWEN3_14B_FREE,
210            QWEN3_8B,
211            QWEN3_8B_FREE,
212            OPENAI_GPT_OSS_20B_FREE,
213            OPENAI_GPT_5_CHAT,
214            OPENAI_GPT_4O_SEARCH_PREVIEW,
215            OPENAI_GPT_4O_MINI_SEARCH_PREVIEW,
216            OPENAI_CHATGPT_4O_LATEST,
217        ];
218    }
219
220    // DeepSeek models (native API)
221    pub mod deepseek {
222        pub const DEFAULT_MODEL: &str = "deepseek-chat";
223        pub const SUPPORTED_MODELS: &[&str] = &["deepseek-chat", "deepseek-reasoner"];
224
225        pub const DEEPSEEK_CHAT: &str = "deepseek-chat";
226        pub const DEEPSEEK_REASONER: &str = "deepseek-reasoner";
227    }
228
229    // Anthropic models (from docs/models.json) - Updated for tool use best practices
230    pub mod anthropic {
231        // Standard model for straightforward tools - Sonnet 4 preferred for most use cases
232        pub const DEFAULT_MODEL: &str = "claude-sonnet-4-5";
233        pub const SUPPORTED_MODELS: &[&str] = &[
234            "claude-opus-4-1-20250805", // Latest: Opus 4.1 (2025-08-05)
235            "claude-sonnet-4-5",        // Latest: Sonnet 4.5 (2025-09-29)
236            "claude-sonnet-4-20250514", // Previous: Sonnet 4 (2025-05-14)
237        ];
238
239        // Convenience constants for commonly used models
240        pub const CLAUDE_OPUS_4_1_20250805: &str = "claude-opus-4-1-20250805";
241        pub const CLAUDE_SONNET_4_5: &str = "claude-sonnet-4-5";
242        pub const CLAUDE_SONNET_4_20250514: &str = "claude-sonnet-4-20250514";
243    }
244
245    // xAI models
246    pub mod xai {
247        pub const DEFAULT_MODEL: &str = "grok-4";
248        pub const SUPPORTED_MODELS: &[&str] = &[
249            "grok-4",
250            "grok-4-mini",
251            "grok-4-code",
252            "grok-4-code-latest",
253            "grok-4-vision",
254        ];
255
256        pub const GROK_4: &str = "grok-4";
257        pub const GROK_4_MINI: &str = "grok-4-mini";
258        pub const GROK_4_CODE: &str = "grok-4-code";
259        pub const GROK_4_CODE_LATEST: &str = "grok-4-code-latest";
260        pub const GROK_4_VISION: &str = "grok-4-vision";
261    }
262
263    // Backwards compatibility - keep old constants working
264    pub const GEMINI_2_5_FLASH_PREVIEW: &str = google::GEMINI_2_5_FLASH_PREVIEW;
265    pub const GEMINI_2_5_FLASH: &str = google::GEMINI_2_5_FLASH;
266    pub const GEMINI_2_5_PRO: &str = google::GEMINI_2_5_PRO;
267    pub const GEMINI_2_5_FLASH_LITE: &str = google::GEMINI_2_5_FLASH_LITE;
268    pub const GPT_5: &str = openai::GPT_5;
269    pub const GPT_5_CODEX: &str = openai::GPT_5_CODEX;
270    pub const GPT_5_MINI: &str = openai::GPT_5_MINI;
271    pub const GPT_5_NANO: &str = openai::GPT_5_NANO;
272    pub const CODEX_MINI: &str = openai::CODEX_MINI;
273    pub const CODEX_MINI_LATEST: &str = openai::CODEX_MINI_LATEST;
274    pub const CLAUDE_OPUS_4_1_20250805: &str = anthropic::CLAUDE_OPUS_4_1_20250805;
275    pub const CLAUDE_SONNET_4_5: &str = anthropic::CLAUDE_SONNET_4_5;
276    pub const CLAUDE_SONNET_4_20250514: &str = anthropic::CLAUDE_SONNET_4_20250514;
277    pub const OPENROUTER_X_AI_GROK_CODE_FAST_1: &str = openrouter::X_AI_GROK_CODE_FAST_1;
278    pub const OPENROUTER_X_AI_GROK_4_FAST: &str = openrouter::X_AI_GROK_4_FAST;
279    pub const OPENROUTER_X_AI_GROK_4: &str = openrouter::X_AI_GROK_4;
280    pub const OPENROUTER_Z_AI_GLM_4_5_AIR_FREE: &str = openrouter::Z_AI_GLM_4_5_AIR_FREE;
281    pub const OPENROUTER_Z_AI_GLM_4_6: &str = openrouter::Z_AI_GLM_4_6;
282    pub const OPENROUTER_MOONSHOTAI_KIMI_K2_0905: &str = openrouter::MOONSHOTAI_KIMI_K2_0905;
283    pub const OPENROUTER_QWEN3_MAX: &str = openrouter::QWEN3_MAX;
284    pub const OPENROUTER_QWEN3_235B_A22B: &str = openrouter::QWEN3_235B_A22B;
285    pub const OPENROUTER_QWEN3_235B_A22B_FREE: &str = openrouter::QWEN3_235B_A22B_FREE;
286    pub const OPENROUTER_QWEN3_235B_A22B_2507: &str = openrouter::QWEN3_235B_A22B_2507;
287    pub const OPENROUTER_QWEN3_235B_A22B_THINKING_2507: &str =
288        openrouter::QWEN3_235B_A22B_THINKING_2507;
289    pub const OPENROUTER_QWEN3_32B: &str = openrouter::QWEN3_32B;
290    pub const OPENROUTER_QWEN3_30B_A3B: &str = openrouter::QWEN3_30B_A3B;
291    pub const OPENROUTER_QWEN3_30B_A3B_FREE: &str = openrouter::QWEN3_30B_A3B_FREE;
292    pub const OPENROUTER_QWEN3_30B_A3B_INSTRUCT_2507: &str =
293        openrouter::QWEN3_30B_A3B_INSTRUCT_2507;
294    pub const OPENROUTER_QWEN3_30B_A3B_THINKING_2507: &str =
295        openrouter::QWEN3_30B_A3B_THINKING_2507;
296    pub const OPENROUTER_QWEN3_14B: &str = openrouter::QWEN3_14B;
297    pub const OPENROUTER_QWEN3_14B_FREE: &str = openrouter::QWEN3_14B_FREE;
298    pub const OPENROUTER_QWEN3_8B: &str = openrouter::QWEN3_8B;
299    pub const OPENROUTER_QWEN3_8B_FREE: &str = openrouter::QWEN3_8B_FREE;
300    pub const OPENROUTER_QWEN3_4B_FREE: &str = openrouter::QWEN3_4B_FREE;
301    pub const OPENROUTER_QWEN3_NEXT_80B_A3B_INSTRUCT: &str =
302        openrouter::QWEN3_NEXT_80B_A3B_INSTRUCT;
303    pub const OPENROUTER_QWEN3_NEXT_80B_A3B_THINKING: &str =
304        openrouter::QWEN3_NEXT_80B_A3B_THINKING;
305    pub const OPENROUTER_QWEN3_CODER: &str = openrouter::QWEN3_CODER;
306    pub const OPENROUTER_QWEN3_CODER_FREE: &str = openrouter::QWEN3_CODER_FREE;
307    pub const OPENROUTER_QWEN3_CODER_PLUS: &str = openrouter::QWEN3_CODER_PLUS;
308    pub const OPENROUTER_QWEN3_CODER_FLASH: &str = openrouter::QWEN3_CODER_FLASH;
309    pub const OPENROUTER_QWEN3_CODER_30B_A3B_INSTRUCT: &str =
310        openrouter::QWEN3_CODER_30B_A3B_INSTRUCT;
311    pub const OPENROUTER_DEEPSEEK_V3_2_EXP: &str = openrouter::DEEPSEEK_DEEPSEEK_V3_2_EXP;
312    pub const OPENROUTER_DEEPSEEK_CHAT_V3_1: &str = openrouter::DEEPSEEK_DEEPSEEK_CHAT_V3_1;
313    pub const OPENROUTER_DEEPSEEK_R1: &str = openrouter::DEEPSEEK_DEEPSEEK_R1;
314    pub const OPENROUTER_OPENAI_GPT_OSS_120B: &str = openrouter::OPENAI_GPT_OSS_120B;
315    pub const OPENROUTER_OPENAI_GPT_OSS_20B: &str = openrouter::OPENAI_GPT_OSS_20B;
316    pub const OPENROUTER_OPENAI_GPT_OSS_20B_FREE: &str = openrouter::OPENAI_GPT_OSS_20B_FREE;
317    pub const OPENROUTER_OPENAI_GPT_5: &str = openrouter::OPENAI_GPT_5;
318    pub const OPENROUTER_OPENAI_GPT_5_CODEX: &str = openrouter::OPENAI_GPT_5_CODEX;
319    pub const OPENROUTER_OPENAI_GPT_5_CHAT: &str = openrouter::OPENAI_GPT_5_CHAT;
320    pub const OPENROUTER_OPENAI_GPT_4O_SEARCH_PREVIEW: &str =
321        openrouter::OPENAI_GPT_4O_SEARCH_PREVIEW;
322    pub const OPENROUTER_OPENAI_GPT_4O_MINI_SEARCH_PREVIEW: &str =
323        openrouter::OPENAI_GPT_4O_MINI_SEARCH_PREVIEW;
324    pub const OPENROUTER_OPENAI_CHATGPT_4O_LATEST: &str = openrouter::OPENAI_CHATGPT_4O_LATEST;
325    pub const OPENROUTER_ANTHROPIC_CLAUDE_SONNET_4_5: &str =
326        openrouter::ANTHROPIC_CLAUDE_SONNET_4_5;
327    pub const OPENROUTER_ANTHROPIC_CLAUDE_OPUS_4_1: &str = openrouter::ANTHROPIC_CLAUDE_OPUS_4_1;
328    pub const MOONSHOT_KIMI_K2_TURBO_PREVIEW: &str = moonshot::KIMI_K2_TURBO_PREVIEW;
329    pub const MOONSHOT_KIMI_K2_0905_PREVIEW: &str = moonshot::KIMI_K2_0905_PREVIEW;
330    pub const MOONSHOT_KIMI_K2_0711_PREVIEW: &str = moonshot::KIMI_K2_0711_PREVIEW;
331    pub const MOONSHOT_KIMI_LATEST: &str = moonshot::KIMI_LATEST;
332    pub const MOONSHOT_KIMI_LATEST_8K: &str = moonshot::KIMI_LATEST_8K;
333    pub const MOONSHOT_KIMI_LATEST_32K: &str = moonshot::KIMI_LATEST_32K;
334    pub const MOONSHOT_KIMI_LATEST_128K: &str = moonshot::KIMI_LATEST_128K;
335    pub const XAI_GROK_4: &str = xai::GROK_4;
336    pub const XAI_GROK_4_MINI: &str = xai::GROK_4_MINI;
337    pub const XAI_GROK_4_CODE: &str = xai::GROK_4_CODE;
338    pub const XAI_GROK_4_CODE_LATEST: &str = xai::GROK_4_CODE_LATEST;
339    pub const XAI_GROK_4_VISION: &str = xai::GROK_4_VISION;
340    pub const DEEPSEEK_CHAT: &str = deepseek::DEEPSEEK_CHAT;
341    pub const DEEPSEEK_REASONER: &str = deepseek::DEEPSEEK_REASONER;
342}
343
344/// Prompt caching defaults shared across features and providers
345pub mod prompt_cache {
346    pub const DEFAULT_ENABLED: bool = true;
347    pub const DEFAULT_CACHE_DIR: &str = ".vtcode/cache/prompts";
348    pub const DEFAULT_MAX_ENTRIES: usize = 1_000;
349    pub const DEFAULT_MAX_AGE_DAYS: u64 = 30;
350    pub const DEFAULT_AUTO_CLEANUP: bool = true;
351    pub const DEFAULT_MIN_QUALITY_THRESHOLD: f64 = 0.7;
352
353    pub const OPENAI_MIN_PREFIX_TOKENS: u32 = 1_024;
354    pub const OPENAI_IDLE_EXPIRATION_SECONDS: u64 = 60 * 60; // 1 hour max reuse window
355
356    pub const ANTHROPIC_DEFAULT_TTL_SECONDS: u64 = 5 * 60; // 5 minutes
357    pub const ANTHROPIC_EXTENDED_TTL_SECONDS: u64 = 60 * 60; // 1 hour option
358    pub const ANTHROPIC_MAX_BREAKPOINTS: u8 = 4;
359
360    pub const GEMINI_MIN_PREFIX_TOKENS: u32 = 1_024;
361    pub const GEMINI_EXPLICIT_DEFAULT_TTL_SECONDS: u64 = 60 * 60; // 1 hour default for explicit caches
362
363    pub const OPENROUTER_CACHE_DISCOUNT_ENABLED: bool = true;
364    pub const XAI_CACHE_ENABLED: bool = true;
365    pub const DEEPSEEK_CACHE_ENABLED: bool = true;
366    pub const ZAI_CACHE_ENABLED: bool = false;
367    pub const MOONSHOT_CACHE_ENABLED: bool = true;
368}
369
370/// Model validation and helper functions
371pub mod model_helpers {
372    use super::models;
373
374    /// Get supported models for a provider
375    pub fn supported_for(provider: &str) -> Option<&'static [&'static str]> {
376        match provider {
377            "google" | "gemini" => Some(models::google::SUPPORTED_MODELS),
378            "openai" => Some(models::openai::SUPPORTED_MODELS),
379            "anthropic" => Some(models::anthropic::SUPPORTED_MODELS),
380            "deepseek" => Some(models::deepseek::SUPPORTED_MODELS),
381            "openrouter" => Some(models::openrouter::SUPPORTED_MODELS),
382            "moonshot" => Some(models::moonshot::SUPPORTED_MODELS),
383            "xai" => Some(models::xai::SUPPORTED_MODELS),
384            "zai" => Some(models::zai::SUPPORTED_MODELS),
385            _ => None,
386        }
387    }
388
389    /// Get default model for a provider
390    pub fn default_for(provider: &str) -> Option<&'static str> {
391        match provider {
392            "google" | "gemini" => Some(models::google::DEFAULT_MODEL),
393            "openai" => Some(models::openai::DEFAULT_MODEL),
394            "anthropic" => Some(models::anthropic::DEFAULT_MODEL),
395            "deepseek" => Some(models::deepseek::DEFAULT_MODEL),
396            "openrouter" => Some(models::openrouter::DEFAULT_MODEL),
397            "moonshot" => Some(models::moonshot::DEFAULT_MODEL),
398            "xai" => Some(models::xai::DEFAULT_MODEL),
399            "zai" => Some(models::zai::DEFAULT_MODEL),
400            _ => None,
401        }
402    }
403
404    /// Validate if a model is supported by a provider
405    pub fn is_valid(provider: &str, model: &str) -> bool {
406        supported_for(provider)
407            .map(|list| list.iter().any(|m| *m == model))
408            .unwrap_or(false)
409    }
410}
411
412/// Environment variable names shared across the application.
413pub mod env {
414    /// Toggle automatic update checks in the onboarding banner.
415    pub const UPDATE_CHECK: &str = "VT_UPDATE_CHECK";
416
417    /// Agent Client Protocol specific environment keys
418    pub mod acp {
419        #[derive(Debug, Clone, Copy)]
420        pub enum AgentClientProtocolEnvKey {
421            Enabled,
422            ZedEnabled,
423            ZedToolsReadFileEnabled,
424            ZedToolsListFilesEnabled,
425            ZedWorkspaceTrust,
426        }
427
428        impl AgentClientProtocolEnvKey {
429            pub fn as_str(self) -> &'static str {
430                match self {
431                    Self::Enabled => "VT_ACP_ENABLED",
432                    Self::ZedEnabled => "VT_ACP_ZED_ENABLED",
433                    Self::ZedToolsReadFileEnabled => "VT_ACP_ZED_TOOLS_READ_FILE_ENABLED",
434                    Self::ZedToolsListFilesEnabled => "VT_ACP_ZED_TOOLS_LIST_FILES_ENABLED",
435                    Self::ZedWorkspaceTrust => "VT_ACP_ZED_WORKSPACE_TRUST",
436                }
437            }
438        }
439    }
440}
441
442/// Default configuration values
443pub mod defaults {
444    use super::{models, ui};
445
446    pub const DEFAULT_MODEL: &str = models::google::GEMINI_2_5_FLASH_PREVIEW;
447    pub const DEFAULT_CLI_MODEL: &str = models::google::GEMINI_2_5_FLASH_PREVIEW;
448    pub const DEFAULT_PROVIDER: &str = "gemini";
449    pub const DEFAULT_API_KEY_ENV: &str = "GEMINI_API_KEY";
450    pub const DEFAULT_THEME: &str = "ciapre-dark";
451    pub const DEFAULT_MAX_TOOL_LOOPS: usize = 100;
452    pub const ANTHROPIC_DEFAULT_MAX_TOKENS: u32 = 4_096;
453    pub const DEFAULT_PTY_STDOUT_TAIL_LINES: usize = 20;
454    pub const DEFAULT_TOOL_OUTPUT_MODE: &str = ui::TOOL_OUTPUT_MODE_COMPACT;
455}
456
457pub mod ui {
458    pub const TOOL_OUTPUT_MODE_COMPACT: &str = "compact";
459    pub const TOOL_OUTPUT_MODE_FULL: &str = "full";
460    pub const DEFAULT_INLINE_VIEWPORT_ROWS: u16 = 16;
461    pub const INLINE_SHOW_TIMELINE_PANE: bool = false;
462    pub const SLASH_SUGGESTION_LIMIT: usize = 6;
463    pub const SLASH_PALETTE_MIN_WIDTH: u16 = 40;
464    pub const SLASH_PALETTE_MIN_HEIGHT: u16 = 9;
465    pub const SLASH_PALETTE_HORIZONTAL_MARGIN: u16 = 8;
466    pub const SLASH_PALETTE_TOP_OFFSET: u16 = 3;
467    pub const SLASH_PALETTE_CONTENT_PADDING: u16 = 6;
468    pub const SLASH_PALETTE_HINT_PRIMARY: &str = "Type to filter slash commands.";
469    pub const SLASH_PALETTE_HINT_SECONDARY: &str = "Press Enter to apply • Esc to dismiss.";
470    pub const MODAL_MIN_WIDTH: u16 = 36;
471    pub const MODAL_MIN_HEIGHT: u16 = 9;
472    pub const MODAL_LIST_MIN_HEIGHT: u16 = 12;
473    pub const MODAL_WIDTH_RATIO: f32 = 0.6;
474    pub const MODAL_HEIGHT_RATIO: f32 = 0.6;
475    pub const MODAL_MAX_WIDTH_RATIO: f32 = 0.9;
476    pub const MODAL_MAX_HEIGHT_RATIO: f32 = 0.8;
477    pub const MODAL_CONTENT_HORIZONTAL_PADDING: u16 = 8;
478    pub const MODAL_CONTENT_VERTICAL_PADDING: u16 = 6;
479    pub const INLINE_HEADER_HEIGHT: u16 = 4;
480    pub const INLINE_INPUT_HEIGHT: u16 = 3;
481    pub const INLINE_NAVIGATION_PERCENT: u16 = 32;
482    pub const INLINE_NAVIGATION_MIN_WIDTH: u16 = 24;
483    pub const INLINE_CONTENT_MIN_WIDTH: u16 = 48;
484    pub const INLINE_STACKED_NAVIGATION_PERCENT: u16 = INLINE_NAVIGATION_PERCENT;
485    pub const INLINE_SCROLLBAR_EDGE_PADDING: u16 = 1;
486    pub const INLINE_TRANSCRIPT_BOTTOM_PADDING: u16 = 6;
487    pub const INLINE_PREVIEW_MAX_CHARS: usize = 56;
488    pub const INLINE_PREVIEW_ELLIPSIS: &str = "…";
489    pub const INLINE_AGENT_MESSAGE_LEFT_PADDING: &str = "  ";
490    pub const INLINE_AGENT_QUOTE_PREFIX: &str = "";
491    pub const INLINE_USER_MESSAGE_DIVIDER_SYMBOL: &str = "─";
492    pub const HEADER_VERSION_PROMPT: &str = "> ";
493    pub const HEADER_VERSION_PREFIX: &str = "VT Code";
494    pub const HEADER_VERSION_LEFT_DELIMITER: &str = "(";
495    pub const HEADER_VERSION_RIGHT_DELIMITER: &str = ")";
496    pub const HEADER_MODE_INLINE: &str = "Inline session";
497    pub const HEADER_MODE_ALTERNATE: &str = "Alternate session";
498    pub const HEADER_MODE_AUTO: &str = "Auto session";
499    pub const HEADER_MODE_FULL_AUTO_SUFFIX: &str = " (full auto)";
500    pub const HEADER_MODE_PRIMARY_SEPARATOR: &str = " | ";
501    pub const HEADER_MODE_SECONDARY_SEPARATOR: &str = " | ";
502    pub const HEADER_PROVIDER_PREFIX: &str = "Provider: ";
503    pub const HEADER_MODEL_PREFIX: &str = "Model: ";
504    pub const HEADER_REASONING_PREFIX: &str = "Reasoning: ";
505    pub const HEADER_TRUST_PREFIX: &str = "Trust: ";
506    pub const HEADER_TOOLS_PREFIX: &str = "Tools: ";
507    pub const HEADER_LANGUAGES_PREFIX: &str = "Languages: ";
508    pub const HEADER_MCP_PREFIX: &str = "MCP: ";
509    pub const HEADER_UNKNOWN_PLACEHOLDER: &str = "unavailable";
510    pub const HEADER_STATUS_LABEL: &str = "Status";
511    pub const HEADER_STATUS_ACTIVE: &str = "Active";
512    pub const HEADER_STATUS_PAUSED: &str = "Paused";
513    pub const HEADER_MESSAGES_LABEL: &str = "Messages";
514    pub const HEADER_INPUT_LABEL: &str = "Input";
515    pub const HEADER_INPUT_ENABLED: &str = "Enabled";
516    pub const HEADER_INPUT_DISABLED: &str = "Disabled";
517    pub const HEADER_SHORTCUT_HINT: &str =
518        "Shortcuts: Ctrl+Enter to submit • Esc to cancel • Ctrl+C to interrupt";
519    pub const HEADER_META_SEPARATOR: &str = "   ";
520    pub const WELCOME_TEXT_WIDTH: usize = 80;
521    pub const WELCOME_SHORTCUT_SECTION_TITLE: &str = "Keyboard Shortcuts";
522    pub const WELCOME_SHORTCUT_HINT_PREFIX: &str = "Shortcuts:";
523    pub const WELCOME_SHORTCUT_SEPARATOR: &str = "•";
524    pub const WELCOME_SHORTCUT_INDENT: &str = "  ";
525    pub const WELCOME_SLASH_COMMAND_SECTION_TITLE: &str = "Slash Commands";
526    pub const WELCOME_SLASH_COMMAND_LIMIT: usize = 6;
527    pub const WELCOME_SLASH_COMMAND_PREFIX: &str = "/";
528    pub const WELCOME_SLASH_COMMAND_INTRO: &str =
529        "To get started, describe a task or try one of these commands:";
530    pub const WELCOME_SLASH_COMMAND_INDENT: &str = "  ";
531    pub const NAVIGATION_BLOCK_TITLE: &str = "Timeline";
532    pub const NAVIGATION_EMPTY_LABEL: &str = "Waiting for activity";
533    pub const NAVIGATION_INDEX_PREFIX: &str = "#";
534    pub const NAVIGATION_LABEL_AGENT: &str = "Agent";
535    pub const NAVIGATION_LABEL_ERROR: &str = "Error";
536    pub const NAVIGATION_LABEL_INFO: &str = "Info";
537    pub const NAVIGATION_LABEL_POLICY: &str = "Policy";
538    pub const NAVIGATION_LABEL_TOOL: &str = "Tool";
539    pub const NAVIGATION_LABEL_USER: &str = "User";
540    pub const NAVIGATION_LABEL_PTY: &str = "PTY";
541    pub const SUGGESTION_BLOCK_TITLE: &str = "Slash Commands";
542}
543
544/// Reasoning effort configuration constants
545pub mod reasoning {
546    pub const LOW: &str = "low";
547    pub const MEDIUM: &str = "medium";
548    pub const HIGH: &str = "high";
549    pub const ALLOWED_LEVELS: &[&str] = &[LOW, MEDIUM, HIGH];
550    pub const LABEL_LOW: &str = "Easy";
551    pub const LABEL_MEDIUM: &str = "Medium";
552    pub const LABEL_HIGH: &str = "Hard";
553    pub const DESCRIPTION_LOW: &str = "Fast responses with lightweight reasoning.";
554    pub const DESCRIPTION_MEDIUM: &str = "Balanced depth and speed for general tasks.";
555    pub const DESCRIPTION_HIGH: &str = "Maximum reasoning depth for complex problems.";
556}
557
558/// Message role constants to avoid hardcoding strings
559pub mod message_roles {
560    pub const SYSTEM: &str = "system";
561    pub const USER: &str = "user";
562    pub const ASSISTANT: &str = "assistant";
563    pub const TOOL: &str = "tool";
564}
565
566/// URL constants for API endpoints
567pub mod urls {
568    pub const GEMINI_API_BASE: &str = "https://generativelanguage.googleapis.com/v1beta";
569    pub const OPENAI_API_BASE: &str = "https://api.openai.com/v1";
570    pub const ANTHROPIC_API_BASE: &str = "https://api.anthropic.com/v1";
571    pub const ANTHROPIC_API_VERSION: &str = "2023-06-01";
572    pub const OPENROUTER_API_BASE: &str = "https://openrouter.ai/api/v1";
573    pub const XAI_API_BASE: &str = "https://api.x.ai/v1";
574    pub const DEEPSEEK_API_BASE: &str = "https://api.deepseek.com/v1";
575    pub const Z_AI_API_BASE: &str = "https://api.z.ai/api";
576    pub const MOONSHOT_API_BASE: &str = "https://api.moonshot.cn/v1";
577}
578
579/// Tool name constants to avoid hardcoding strings throughout the codebase
580pub mod tools {
581    pub const GREP_SEARCH: &str = "grep_search";
582    pub const LIST_FILES: &str = "list_files";
583    pub const RUN_TERMINAL_CMD: &str = "run_terminal_cmd";
584    pub const READ_FILE: &str = "read_file";
585    pub const WRITE_FILE: &str = "write_file";
586    pub const EDIT_FILE: &str = "edit_file";
587    pub const DELETE_FILE: &str = "delete_file";
588    pub const CREATE_FILE: &str = "create_file";
589    pub const AST_GREP_SEARCH: &str = "ast_grep_search";
590    pub const SIMPLE_SEARCH: &str = "simple_search";
591    pub const BASH: &str = "bash";
592    pub const APPLY_PATCH: &str = "apply_patch";
593    pub const SRGN: &str = "srgn";
594    pub const CURL: &str = "curl";
595    pub const UPDATE_PLAN: &str = "update_plan";
596
597    // Explorer-specific tools
598    pub const FILE_METADATA: &str = "file_metadata";
599    pub const PROJECT_OVERVIEW: &str = "project_overview";
600    pub const TREE_SITTER_ANALYZE: &str = "tree_sitter_analyze";
601
602    // Special wildcard for full access
603    pub const WILDCARD_ALL: &str = "*";
604}
605
606pub mod mcp {
607    pub const RENDERER_CONTEXT7: &str = "context7";
608    pub const RENDERER_SEQUENTIAL_THINKING: &str = "sequential-thinking";
609}
610
611pub mod project_doc {
612    pub const DEFAULT_MAX_BYTES: usize = 16 * 1024;
613}
614
615/// Context window management defaults
616pub mod context {
617    /// Approximate character count per token when estimating context size
618    pub const CHAR_PER_TOKEN_APPROX: usize = 3;
619
620    /// Default maximum context window (in approximate tokens)
621    pub const DEFAULT_MAX_TOKENS: usize = 90_000;
622
623    /// Trim target as a percentage of the maximum token budget
624    pub const DEFAULT_TRIM_TO_PERCENT: u8 = 80;
625
626    /// Minimum allowed trim percentage (prevents overly aggressive retention)
627    pub const MIN_TRIM_RATIO_PERCENT: u8 = 60;
628
629    /// Maximum allowed trim percentage (prevents minimal trimming)
630    pub const MAX_TRIM_RATIO_PERCENT: u8 = 90;
631
632    /// Default number of recent turns to preserve verbatim
633    pub const DEFAULT_PRESERVE_RECENT_TURNS: usize = 12;
634
635    /// Minimum number of recent turns that must remain after trimming
636    pub const MIN_PRESERVE_RECENT_TURNS: usize = 6;
637
638    /// Maximum number of recent turns to keep when aggressively reducing context
639    pub const AGGRESSIVE_PRESERVE_RECENT_TURNS: usize = 8;
640
641    /// Maximum number of retry attempts when the provider signals context overflow
642    pub const CONTEXT_ERROR_RETRY_LIMIT: usize = 2;
643}
644
645/// Chunking constants for large file handling
646pub mod chunking {
647    /// Maximum lines before triggering chunking for read_file
648    pub const MAX_LINES_THRESHOLD: usize = 2_000;
649
650    /// Number of lines to read from start of file when chunking
651    pub const CHUNK_START_LINES: usize = 800;
652
653    /// Number of lines to read from end of file when chunking
654    pub const CHUNK_END_LINES: usize = 800;
655
656    /// Maximum lines for terminal command output before truncation
657    pub const MAX_TERMINAL_OUTPUT_LINES: usize = 3_000;
658
659    /// Number of lines to show from start of terminal output when truncating
660    pub const TERMINAL_OUTPUT_START_LINES: usize = 1_000;
661
662    /// Number of lines to show from end of terminal output when truncating
663    pub const TERMINAL_OUTPUT_END_LINES: usize = 1_000;
664
665    /// Maximum content size for write_file before chunking (in bytes)
666    pub const MAX_WRITE_CONTENT_SIZE: usize = 500_000; // 500KB
667
668    /// Chunk size for write operations (in bytes)
669    pub const WRITE_CHUNK_SIZE: usize = 50_000; // 50KB chunks
670}
671
672/// Diff preview controls for file operations
673pub mod diff {
674    /// Maximum number of bytes allowed in diff preview inputs
675    pub const MAX_PREVIEW_BYTES: usize = 200_000;
676
677    /// Number of context lines to include around changes in unified diff output
678    pub const CONTEXT_RADIUS: usize = 3;
679
680    /// Maximum number of diff lines to keep in preview output before condensation
681    pub const MAX_PREVIEW_LINES: usize = 160;
682
683    /// Number of leading diff lines to retain when condensing previews
684    pub const HEAD_LINE_COUNT: usize = 96;
685
686    /// Number of trailing diff lines to retain when condensing previews
687    pub const TAIL_LINE_COUNT: usize = 32;
688}