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            "o4-mini",
36            "o4-mini-deep-research",
37            "o3",
38            "o1",
39            "o1-mini",
40            "o1-preview",
41            "o1-pro",
42        ];
43
44        /// Models that support the OpenAI reasoning API extensions
45        pub const REASONING_MODELS: &[&str] = &[
46            O4_MINI,
47            O4_MINI_DEEP_RESEARCH,
48            O3,
49            O1,
50            O1_PRO,
51            O1_PREVIEW,
52            O1_MINI,
53        ];
54
55        // Convenience constants for commonly used models
56        pub const GPT_5: &str = "gpt-5";
57        pub const GPT_5_CODEX: &str = "gpt-5-codex";
58        pub const GPT_5_MINI: &str = "gpt-5-mini";
59        pub const GPT_5_NANO: &str = "gpt-5-nano";
60        pub const CODEX_MINI_LATEST: &str = "codex-mini-latest";
61        pub const CODEX_MINI: &str = "codex-mini";
62        pub const O4_MINI: &str = "o4-mini";
63        pub const O4_MINI_DEEP_RESEARCH: &str = "o4-mini-deep-research";
64        pub const O3: &str = "o3";
65        pub const O1: &str = "o1";
66        pub const O1_PRO: &str = "o1-pro";
67        pub const O1_PREVIEW: &str = "o1-preview";
68        pub const O1_MINI: &str = "o1-mini";
69    }
70
71    // OpenRouter models (extensible via vtcode.toml)
72    pub mod openrouter {
73        pub const DEFAULT_MODEL: &str = "x-ai/grok-code-fast-1";
74        pub const SUPPORTED_MODELS: &[&str] = &[
75            "x-ai/grok-code-fast-1",
76            "x-ai/grok-4-fast:free",
77            "qwen/qwen3-coder",
78            "deepseek/deepseek-chat-v3.1",
79            "openai/gpt-5",
80            "openai/gpt-5-codex",
81            "anthropic/claude-sonnet-4.5",
82            "anthropic/claude-sonnet-4",
83        ];
84
85        /// Models that expose reasoning traces via OpenRouter APIs
86        pub const REASONING_MODELS: &[&str] = &[
87            X_AI_GROK_4_FAST_FREE,
88            OPENAI_GPT_5,
89            OPENAI_GPT_5_CODEX,
90            ANTHROPIC_CLAUDE_SONNET_4_5,
91            ANTHROPIC_CLAUDE_SONNET_4,
92        ];
93
94        /// Models that do not expose function calling via OpenRouter
95        pub const TOOL_UNAVAILABLE_MODELS: &[&str] = &[OPENAI_GPT_OSS_20B_FREE];
96
97        pub const X_AI_GROK_CODE_FAST_1: &str = "x-ai/grok-code-fast-1";
98        pub const X_AI_GROK_4_FAST_FREE: &str = "x-ai/grok-4-fast:free";
99        pub const QWEN3_CODER: &str = "qwen/qwen3-coder";
100        pub const DEEPSEEK_DEEPSEEK_CHAT_V3_1: &str = "deepseek/deepseek-chat-v3.1";
101        pub const OPENAI_GPT_5: &str = "openai/gpt-5";
102        pub const OPENAI_GPT_5_CODEX: &str = "openai/gpt-5-codex";
103        pub const ANTHROPIC_CLAUDE_SONNET_4_5: &str = "anthropic/claude-sonnet-4.5";
104        pub const ANTHROPIC_CLAUDE_SONNET_4: &str = "anthropic/claude-sonnet-4";
105        pub const OPENAI_GPT_OSS_20B_FREE: &str = "openai/gpt-oss-20b:free";
106    }
107
108    // DeepSeek models (native API)
109    pub mod deepseek {
110        pub const DEFAULT_MODEL: &str = "deepseek-chat";
111        pub const SUPPORTED_MODELS: &[&str] = &["deepseek-chat", "deepseek-reasoner"];
112
113        pub const DEEPSEEK_CHAT: &str = "deepseek-chat";
114        pub const DEEPSEEK_REASONER: &str = "deepseek-reasoner";
115    }
116
117    // Anthropic models (from docs/models.json) - Updated for tool use best practices
118    pub mod anthropic {
119        // Standard model for straightforward tools - Sonnet 4 preferred for most use cases
120        pub const DEFAULT_MODEL: &str = "claude-sonnet-4-5";
121        pub const SUPPORTED_MODELS: &[&str] = &[
122            "claude-opus-4-1-20250805", // Latest: Opus 4.1 (2025-08-05)
123            "claude-sonnet-4-5",        // Latest: Sonnet 4.5 (2025-09-29)
124            "claude-sonnet-4-20250514", // Previous: Sonnet 4 (2025-05-14)
125        ];
126
127        // Convenience constants for commonly used models
128        pub const CLAUDE_OPUS_4_1_20250805: &str = "claude-opus-4-1-20250805";
129        pub const CLAUDE_SONNET_4_5: &str = "claude-sonnet-4-5";
130        pub const CLAUDE_SONNET_4_20250514: &str = "claude-sonnet-4-20250514";
131    }
132
133    // xAI models
134    pub mod xai {
135        pub const DEFAULT_MODEL: &str = "grok-2-latest";
136        pub const SUPPORTED_MODELS: &[&str] = &[
137            "grok-2-latest",
138            "grok-2",
139            "grok-2-mini",
140            "grok-2-reasoning",
141            "grok-2-vision",
142        ];
143
144        pub const GROK_2_LATEST: &str = "grok-2-latest";
145        pub const GROK_2: &str = "grok-2";
146        pub const GROK_2_MINI: &str = "grok-2-mini";
147        pub const GROK_2_REASONING: &str = "grok-2-reasoning";
148        pub const GROK_2_VISION: &str = "grok-2-vision";
149    }
150
151    // Backwards compatibility - keep old constants working
152    pub const GEMINI_2_5_FLASH_PREVIEW: &str = google::GEMINI_2_5_FLASH_PREVIEW;
153    pub const GEMINI_2_5_FLASH: &str = google::GEMINI_2_5_FLASH;
154    pub const GEMINI_2_5_PRO: &str = google::GEMINI_2_5_PRO;
155    pub const GEMINI_2_5_FLASH_LITE: &str = google::GEMINI_2_5_FLASH_LITE;
156    pub const GPT_5: &str = openai::GPT_5;
157    pub const GPT_5_CODEX: &str = openai::GPT_5_CODEX;
158    pub const GPT_5_MINI: &str = openai::GPT_5_MINI;
159    pub const GPT_5_NANO: &str = openai::GPT_5_NANO;
160    pub const CODEX_MINI: &str = openai::CODEX_MINI;
161    pub const CODEX_MINI_LATEST: &str = openai::CODEX_MINI_LATEST;
162    pub const CLAUDE_OPUS_4_1_20250805: &str = anthropic::CLAUDE_OPUS_4_1_20250805;
163    pub const CLAUDE_SONNET_4_5: &str = anthropic::CLAUDE_SONNET_4_5;
164    pub const CLAUDE_SONNET_4_20250514: &str = anthropic::CLAUDE_SONNET_4_20250514;
165    pub const OPENROUTER_X_AI_GROK_CODE_FAST_1: &str = openrouter::X_AI_GROK_CODE_FAST_1;
166    pub const OPENROUTER_X_AI_GROK_4_FAST_FREE: &str = openrouter::X_AI_GROK_4_FAST_FREE;
167    pub const OPENROUTER_QWEN3_CODER: &str = openrouter::QWEN3_CODER;
168    pub const OPENROUTER_DEEPSEEK_CHAT_V3_1: &str = openrouter::DEEPSEEK_DEEPSEEK_CHAT_V3_1;
169    pub const OPENROUTER_OPENAI_GPT_5: &str = openrouter::OPENAI_GPT_5;
170    pub const OPENROUTER_OPENAI_GPT_5_CODEX: &str = openrouter::OPENAI_GPT_5_CODEX;
171    pub const OPENROUTER_ANTHROPIC_CLAUDE_SONNET_4_5: &str =
172        openrouter::ANTHROPIC_CLAUDE_SONNET_4_5;
173    pub const OPENROUTER_ANTHROPIC_CLAUDE_SONNET_4: &str = openrouter::ANTHROPIC_CLAUDE_SONNET_4;
174    pub const XAI_GROK_2_LATEST: &str = xai::GROK_2_LATEST;
175    pub const XAI_GROK_2: &str = xai::GROK_2;
176    pub const XAI_GROK_2_MINI: &str = xai::GROK_2_MINI;
177    pub const XAI_GROK_2_REASONING: &str = xai::GROK_2_REASONING;
178    pub const XAI_GROK_2_VISION: &str = xai::GROK_2_VISION;
179    pub const DEEPSEEK_CHAT: &str = deepseek::DEEPSEEK_CHAT;
180    pub const DEEPSEEK_REASONER: &str = deepseek::DEEPSEEK_REASONER;
181}
182
183/// Prompt caching defaults shared across features and providers
184pub mod prompt_cache {
185    pub const DEFAULT_ENABLED: bool = true;
186    pub const DEFAULT_CACHE_DIR: &str = ".vtcode/cache/prompts";
187    pub const DEFAULT_MAX_ENTRIES: usize = 1_000;
188    pub const DEFAULT_MAX_AGE_DAYS: u64 = 30;
189    pub const DEFAULT_AUTO_CLEANUP: bool = true;
190    pub const DEFAULT_MIN_QUALITY_THRESHOLD: f64 = 0.7;
191
192    pub const OPENAI_MIN_PREFIX_TOKENS: u32 = 1_024;
193    pub const OPENAI_IDLE_EXPIRATION_SECONDS: u64 = 60 * 60; // 1 hour max reuse window
194
195    pub const ANTHROPIC_DEFAULT_TTL_SECONDS: u64 = 5 * 60; // 5 minutes
196    pub const ANTHROPIC_EXTENDED_TTL_SECONDS: u64 = 60 * 60; // 1 hour option
197    pub const ANTHROPIC_MAX_BREAKPOINTS: u8 = 4;
198
199    pub const GEMINI_MIN_PREFIX_TOKENS: u32 = 1_024;
200    pub const GEMINI_EXPLICIT_DEFAULT_TTL_SECONDS: u64 = 60 * 60; // 1 hour default for explicit caches
201
202    pub const OPENROUTER_CACHE_DISCOUNT_ENABLED: bool = true;
203    pub const XAI_CACHE_ENABLED: bool = true;
204    pub const DEEPSEEK_CACHE_ENABLED: bool = true;
205}
206
207/// Model validation and helper functions
208pub mod model_helpers {
209    use super::models;
210
211    /// Get supported models for a provider
212    pub fn supported_for(provider: &str) -> Option<&'static [&'static str]> {
213        match provider {
214            "google" | "gemini" => Some(models::google::SUPPORTED_MODELS),
215            "openai" => Some(models::openai::SUPPORTED_MODELS),
216            "anthropic" => Some(models::anthropic::SUPPORTED_MODELS),
217            "deepseek" => Some(models::deepseek::SUPPORTED_MODELS),
218            "openrouter" => Some(models::openrouter::SUPPORTED_MODELS),
219            "xai" => Some(models::xai::SUPPORTED_MODELS),
220            _ => None,
221        }
222    }
223
224    /// Get default model for a provider
225    pub fn default_for(provider: &str) -> Option<&'static str> {
226        match provider {
227            "google" | "gemini" => Some(models::google::DEFAULT_MODEL),
228            "openai" => Some(models::openai::DEFAULT_MODEL),
229            "anthropic" => Some(models::anthropic::DEFAULT_MODEL),
230            "deepseek" => Some(models::deepseek::DEFAULT_MODEL),
231            "openrouter" => Some(models::openrouter::DEFAULT_MODEL),
232            "xai" => Some(models::xai::DEFAULT_MODEL),
233            _ => None,
234        }
235    }
236
237    /// Validate if a model is supported by a provider
238    pub fn is_valid(provider: &str, model: &str) -> bool {
239        supported_for(provider)
240            .map(|list| list.iter().any(|m| *m == model))
241            .unwrap_or(false)
242    }
243}
244
245/// Environment variable names shared across the application.
246pub mod env {
247    /// Toggle automatic update checks in the onboarding banner.
248    pub const UPDATE_CHECK: &str = "VT_UPDATE_CHECK";
249
250    /// Agent Client Protocol specific environment keys
251    pub mod acp {
252        #[derive(Debug, Clone, Copy)]
253        pub enum AgentClientProtocolEnvKey {
254            Enabled,
255            ZedEnabled,
256            ZedToolsReadFileEnabled,
257            ZedToolsListFilesEnabled,
258            ZedWorkspaceTrust,
259        }
260
261        impl AgentClientProtocolEnvKey {
262            pub fn as_str(self) -> &'static str {
263                match self {
264                    Self::Enabled => "VT_ACP_ENABLED",
265                    Self::ZedEnabled => "VT_ACP_ZED_ENABLED",
266                    Self::ZedToolsReadFileEnabled => "VT_ACP_ZED_TOOLS_READ_FILE_ENABLED",
267                    Self::ZedToolsListFilesEnabled => "VT_ACP_ZED_TOOLS_LIST_FILES_ENABLED",
268                    Self::ZedWorkspaceTrust => "VT_ACP_ZED_WORKSPACE_TRUST",
269                }
270            }
271        }
272    }
273}
274
275/// Default configuration values
276pub mod defaults {
277    use super::{models, ui};
278
279    pub const DEFAULT_MODEL: &str = models::google::GEMINI_2_5_FLASH_PREVIEW;
280    pub const DEFAULT_CLI_MODEL: &str = models::google::GEMINI_2_5_FLASH_PREVIEW;
281    pub const DEFAULT_PROVIDER: &str = "gemini";
282    pub const DEFAULT_API_KEY_ENV: &str = "GEMINI_API_KEY";
283    pub const DEFAULT_THEME: &str = "ciapre-dark";
284    pub const DEFAULT_MAX_TOOL_LOOPS: usize = 100;
285    pub const ANTHROPIC_DEFAULT_MAX_TOKENS: u32 = 4_096;
286    pub const DEFAULT_PTY_STDOUT_TAIL_LINES: usize = 20;
287    pub const DEFAULT_TOOL_OUTPUT_MODE: &str = ui::TOOL_OUTPUT_MODE_COMPACT;
288}
289
290pub mod ui {
291    pub const TOOL_OUTPUT_MODE_COMPACT: &str = "compact";
292    pub const TOOL_OUTPUT_MODE_FULL: &str = "full";
293    pub const DEFAULT_INLINE_VIEWPORT_ROWS: u16 = 16;
294    pub const INLINE_SHOW_TIMELINE_PANE: bool = false;
295    pub const SLASH_SUGGESTION_LIMIT: usize = 6;
296    pub const INLINE_HEADER_HEIGHT: u16 = 4;
297    pub const INLINE_INPUT_HEIGHT: u16 = 3;
298    pub const INLINE_NAVIGATION_PERCENT: u16 = 32;
299    pub const INLINE_NAVIGATION_MIN_WIDTH: u16 = 24;
300    pub const INLINE_CONTENT_MIN_WIDTH: u16 = 48;
301    pub const INLINE_STACKED_NAVIGATION_PERCENT: u16 = INLINE_NAVIGATION_PERCENT;
302    pub const INLINE_SCROLLBAR_EDGE_PADDING: u16 = 1;
303    pub const INLINE_TRANSCRIPT_BOTTOM_PADDING: u16 = 2;
304    pub const INLINE_PREVIEW_MAX_CHARS: usize = 56;
305    pub const INLINE_PREVIEW_ELLIPSIS: &str = "…";
306    pub const INLINE_AGENT_MESSAGE_LEFT_PADDING: &str = "  ";
307    pub const INLINE_AGENT_QUOTE_PREFIX: &str = "";
308    pub const INLINE_USER_MESSAGE_DIVIDER_SYMBOL: &str = "─";
309    pub const HEADER_VERSION_PROMPT: &str = "> ";
310    pub const HEADER_VERSION_PREFIX: &str = "VT Code";
311    pub const HEADER_VERSION_LEFT_DELIMITER: &str = "(";
312    pub const HEADER_VERSION_RIGHT_DELIMITER: &str = ")";
313    pub const HEADER_MODE_INLINE: &str = "Inline session";
314    pub const HEADER_MODE_ALTERNATE: &str = "Alternate session";
315    pub const HEADER_MODE_AUTO: &str = "Auto session";
316    pub const HEADER_MODE_FULL_AUTO_SUFFIX: &str = " (full auto)";
317    pub const HEADER_MODE_PRIMARY_SEPARATOR: &str = " | ";
318    pub const HEADER_MODE_SECONDARY_SEPARATOR: &str = " | ";
319    pub const HEADER_PROVIDER_PREFIX: &str = "Provider: ";
320    pub const HEADER_MODEL_PREFIX: &str = "Model: ";
321    pub const HEADER_REASONING_PREFIX: &str = "Reasoning: ";
322    pub const HEADER_TRUST_PREFIX: &str = "Trust: ";
323    pub const HEADER_TOOLS_PREFIX: &str = "Tools: ";
324    pub const HEADER_LANGUAGES_PREFIX: &str = "Languages: ";
325    pub const HEADER_MCP_PREFIX: &str = "MCP: ";
326    pub const HEADER_UNKNOWN_PLACEHOLDER: &str = "unavailable";
327    pub const HEADER_STATUS_LABEL: &str = "Status";
328    pub const HEADER_STATUS_ACTIVE: &str = "Active";
329    pub const HEADER_STATUS_PAUSED: &str = "Paused";
330    pub const HEADER_MESSAGES_LABEL: &str = "Messages";
331    pub const HEADER_INPUT_LABEL: &str = "Input";
332    pub const HEADER_INPUT_ENABLED: &str = "Enabled";
333    pub const HEADER_INPUT_DISABLED: &str = "Disabled";
334    pub const HEADER_SHORTCUT_HINT: &str =
335        "Shortcuts: Ctrl+Enter to submit • Esc to cancel • Ctrl+C to interrupt";
336    pub const HEADER_META_SEPARATOR: &str = "   ";
337    pub const NAVIGATION_BLOCK_TITLE: &str = "Timeline";
338    pub const NAVIGATION_EMPTY_LABEL: &str = "Waiting for activity";
339    pub const NAVIGATION_INDEX_PREFIX: &str = "#";
340    pub const NAVIGATION_LABEL_AGENT: &str = "Agent";
341    pub const NAVIGATION_LABEL_ERROR: &str = "Error";
342    pub const NAVIGATION_LABEL_INFO: &str = "Info";
343    pub const NAVIGATION_LABEL_POLICY: &str = "Policy";
344    pub const NAVIGATION_LABEL_TOOL: &str = "Tool";
345    pub const NAVIGATION_LABEL_USER: &str = "User";
346    pub const NAVIGATION_LABEL_PTY: &str = "PTY";
347    pub const SUGGESTION_BLOCK_TITLE: &str = "Slash Commands";
348}
349
350/// Reasoning effort configuration constants
351pub mod reasoning {
352    pub const LOW: &str = "low";
353    pub const MEDIUM: &str = "medium";
354    pub const HIGH: &str = "high";
355    pub const ALLOWED_LEVELS: &[&str] = &[LOW, MEDIUM, HIGH];
356}
357
358/// Message role constants to avoid hardcoding strings
359pub mod message_roles {
360    pub const SYSTEM: &str = "system";
361    pub const USER: &str = "user";
362    pub const ASSISTANT: &str = "assistant";
363    pub const TOOL: &str = "tool";
364}
365
366/// URL constants for API endpoints
367pub mod urls {
368    pub const GEMINI_API_BASE: &str = "https://generativelanguage.googleapis.com/v1beta";
369    pub const OPENAI_API_BASE: &str = "https://api.openai.com/v1";
370    pub const ANTHROPIC_API_BASE: &str = "https://api.anthropic.com/v1";
371    pub const ANTHROPIC_API_VERSION: &str = "2023-06-01";
372    pub const OPENROUTER_API_BASE: &str = "https://openrouter.ai/api/v1";
373    pub const XAI_API_BASE: &str = "https://api.x.ai/v1";
374    pub const DEEPSEEK_API_BASE: &str = "https://api.deepseek.com/v1";
375}
376
377/// Tool name constants to avoid hardcoding strings throughout the codebase
378pub mod tools {
379    pub const GREP_SEARCH: &str = "grep_search";
380    pub const LIST_FILES: &str = "list_files";
381    pub const RUN_TERMINAL_CMD: &str = "run_terminal_cmd";
382    pub const READ_FILE: &str = "read_file";
383    pub const WRITE_FILE: &str = "write_file";
384    pub const EDIT_FILE: &str = "edit_file";
385    pub const DELETE_FILE: &str = "delete_file";
386    pub const CREATE_FILE: &str = "create_file";
387    pub const AST_GREP_SEARCH: &str = "ast_grep_search";
388    pub const SIMPLE_SEARCH: &str = "simple_search";
389    pub const BASH: &str = "bash";
390    pub const APPLY_PATCH: &str = "apply_patch";
391    pub const SRGN: &str = "srgn";
392    pub const CURL: &str = "curl";
393    pub const UPDATE_PLAN: &str = "update_plan";
394
395    // Explorer-specific tools
396    pub const FILE_METADATA: &str = "file_metadata";
397    pub const PROJECT_OVERVIEW: &str = "project_overview";
398    pub const TREE_SITTER_ANALYZE: &str = "tree_sitter_analyze";
399
400    // Special wildcard for full access
401    pub const WILDCARD_ALL: &str = "*";
402}
403
404pub mod project_doc {
405    pub const DEFAULT_MAX_BYTES: usize = 16 * 1024;
406}
407
408/// Context window management defaults
409pub mod context {
410    /// Approximate character count per token when estimating context size
411    pub const CHAR_PER_TOKEN_APPROX: usize = 3;
412
413    /// Default maximum context window (in approximate tokens)
414    pub const DEFAULT_MAX_TOKENS: usize = 90_000;
415
416    /// Trim target as a percentage of the maximum token budget
417    pub const DEFAULT_TRIM_TO_PERCENT: u8 = 80;
418
419    /// Minimum allowed trim percentage (prevents overly aggressive retention)
420    pub const MIN_TRIM_RATIO_PERCENT: u8 = 60;
421
422    /// Maximum allowed trim percentage (prevents minimal trimming)
423    pub const MAX_TRIM_RATIO_PERCENT: u8 = 90;
424
425    /// Default number of recent turns to preserve verbatim
426    pub const DEFAULT_PRESERVE_RECENT_TURNS: usize = 12;
427
428    /// Minimum number of recent turns that must remain after trimming
429    pub const MIN_PRESERVE_RECENT_TURNS: usize = 6;
430
431    /// Maximum number of recent turns to keep when aggressively reducing context
432    pub const AGGRESSIVE_PRESERVE_RECENT_TURNS: usize = 8;
433
434    /// Maximum number of retry attempts when the provider signals context overflow
435    pub const CONTEXT_ERROR_RETRY_LIMIT: usize = 2;
436}
437
438/// Chunking constants for large file handling
439pub mod chunking {
440    /// Maximum lines before triggering chunking for read_file
441    pub const MAX_LINES_THRESHOLD: usize = 2_000;
442
443    /// Number of lines to read from start of file when chunking
444    pub const CHUNK_START_LINES: usize = 800;
445
446    /// Number of lines to read from end of file when chunking
447    pub const CHUNK_END_LINES: usize = 800;
448
449    /// Maximum lines for terminal command output before truncation
450    pub const MAX_TERMINAL_OUTPUT_LINES: usize = 3_000;
451
452    /// Number of lines to show from start of terminal output when truncating
453    pub const TERMINAL_OUTPUT_START_LINES: usize = 1_000;
454
455    /// Number of lines to show from end of terminal output when truncating
456    pub const TERMINAL_OUTPUT_END_LINES: usize = 1_000;
457
458    /// Maximum content size for write_file before chunking (in bytes)
459    pub const MAX_WRITE_CONTENT_SIZE: usize = 500_000; // 500KB
460
461    /// Chunk size for write operations (in bytes)
462    pub const WRITE_CHUNK_SIZE: usize = 50_000; // 50KB chunks
463}
464
465/// Diff preview controls for file operations
466pub mod diff {
467    /// Maximum number of bytes allowed in diff preview inputs
468    pub const MAX_PREVIEW_BYTES: usize = 200_000;
469
470    /// Number of context lines to include around changes in unified diff output
471    pub const CONTEXT_RADIUS: usize = 3;
472
473    /// Maximum number of diff lines to keep in preview output before condensation
474    pub const MAX_PREVIEW_LINES: usize = 160;
475
476    /// Number of leading diff lines to retain when condensing previews
477    pub const HEAD_LINE_COUNT: usize = 96;
478
479    /// Number of trailing diff lines to retain when condensing previews
480    pub const TAIL_LINE_COUNT: usize = 32;
481}