1pub mod acp;
8pub mod api;
9pub mod api_keys;
10pub mod constants;
11pub mod context;
12pub mod core;
13pub mod defaults;
14pub mod hooks;
15pub mod loader;
16pub mod mcp;
17pub mod models;
18pub mod telemetry;
19pub mod types;
20pub mod validation;
21pub mod validator;
22
23pub use acp::{
24 AgentClientProtocolConfig, AgentClientProtocolTransport, AgentClientProtocolZedConfig,
25 AgentClientProtocolZedToolsConfig, AgentClientProtocolZedWorkspaceTrustMode, WorkspaceTrustLevel,
26};
27pub use api::{
28 ConfigLayerView, ConfigReadRequest, ConfigReadResponse, ConfigResetRequest, ConfigResetResponse, ConfigService,
29 ConfigWriteRequest, ConfigWriteResponse, ConfigWriteStrategy, ConfigWriteTarget, OverrideMetadata,
30};
31pub use api_keys::ApiKeySources;
32pub use context::{ContextFeaturesConfig, LedgerConfig};
33pub use core::{
34 AgentConfig, AgentOnboardingConfig, AgentPromptSuggestionsConfig, AutoPermissionConfig,
35 AutoPermissionEnvironmentConfig, AutomationConfig, CommandsConfig, EditorToolConfig, FullAutoConfig,
36 GatekeeperConfig, ModelConfig, OpenAIPromptCacheKeyMode, PermissionsConfig, PersistentMemoryConfig,
37 PromptCachingConfig, ProviderPromptCachingConfig, ScheduledTasksConfig, SecurityConfig, ToolPolicy, ToolProfile,
38 ToolsConfig, build_openai_prompt_cache_key, build_session_affinity_prompt_cache_key,
39 map_prompt_cache_key_for_provider, session_affinity_key_enabled, session_affinity_provider,
40 tool_call_delay_for_rate, tool_loop_limit_reached,
41};
42pub use core::{PluginRuntimeConfig, PluginTrustLevel};
43pub use defaults::{
44 ConfigDefaultsProvider, ContextStoreDefaults, PerformanceDefaults, ScenarioDefaults, SyntaxHighlightingDefaults,
45 WorkspacePathsDefaults, current_config_defaults, get_config_dir, get_data_dir, install_config_defaults_provider,
46 reset_to_default_config_defaults, with_config_defaults,
47};
48pub use hooks::{
49 HookCommandConfig, HookCommandKind, HookGroupConfig, HooksConfig, LifecycleHooksConfig, WorkspaceHookCommand,
50 WorkspaceLifecycleHooks,
51};
52pub use loader::{ConfigManager, SyntaxHighlightingConfig, VTCodeConfig};
53pub use mcp::{
54 McpAllowListConfig, McpAllowListRules, McpClientConfig, McpHttpServerConfig, McpProviderConfig,
55 McpStdioServerConfig, McpTransportConfig, McpUiConfig, McpUiMode,
56};
57pub use models::{ModelId, OpenRouterMetadata};
58pub use telemetry::TelemetryConfig;
59pub use types::{ReasoningEffortLevel, SystemPromptMode, ToolDocumentationMode, UiSurfacePreference, VerbosityLevel};
60pub use validation::{ValidationResult, validate_config, validate_model_exists};
61pub use validator::ConfigValidator;
62pub use vtcode_config::WebmcpConfig;
63pub use vtcode_config::root::{
64 KeyboardProtocolConfig, KeyboardProtocolMode, LayoutModeOverride, PtyConfig, ReasoningDisplayMode, ToolDisplayMode,
65 ToolOutputMode, UiConfig, UiDisplayMode, UiTranscriptReviewConfig,
66};
67pub use vtcode_config::status_line::{StatusLineConfig, StatusLineMode};
68pub use vtcode_config::terminal_title::{DEFAULT_TERMINAL_TITLE_ITEMS, TerminalTitleConfig};
69pub use vtcode_config::{
70 FileOpener, HistoryConfig, HistoryPersistence, NotificationCondition, TerminalNotificationMethod,
71 TuiAlternateScreen, TuiConfig, TuiNotificationEvent, TuiNotificationsConfig,
72};
73pub use vtcode_config::{TimeoutsConfig, resolve_timeout};
74
75#[cfg(all(test, feature = "tui"))]
76fn keyboard_protocol_to_flags_for_terminal(
77 config: &KeyboardProtocolConfig,
78 is_macos: bool,
79 term_program: Option<&str>,
80 term: Option<&str>,
81) -> crossterm::event::KeyboardEnhancementFlags {
82 use ratatui::crossterm::event::KeyboardEnhancementFlags;
83
84 if !config.enabled {
85 return KeyboardEnhancementFlags::empty();
86 }
87
88 let mut flags = match config.mode {
89 KeyboardProtocolMode::Default => {
90 KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
91 | KeyboardEnhancementFlags::REPORT_EVENT_TYPES
92 | KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
93 }
94 KeyboardProtocolMode::Full => {
95 KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
96 | KeyboardEnhancementFlags::REPORT_EVENT_TYPES
97 | KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
98 | KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES
99 }
100 KeyboardProtocolMode::Minimal => KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES,
101 KeyboardProtocolMode::Custom => {
102 let mut flags = KeyboardEnhancementFlags::empty();
103 if config.disambiguate_escape_codes {
104 flags |= KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES;
105 }
106 if config.report_event_types {
107 flags |= KeyboardEnhancementFlags::REPORT_EVENT_TYPES;
108 }
109 if config.report_alternate_keys {
110 flags |= KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS;
111 }
112 if config.report_all_keys {
113 flags |= KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES;
114 }
115 flags
116 }
117 };
118
119 if should_force_report_all_keys(config.mode, is_macos, term_program, term) {
120 flags |= KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES;
121 }
122
123 flags
124}
125
126#[cfg(all(test, feature = "tui"))]
127fn should_force_report_all_keys(
128 mode: KeyboardProtocolMode,
129 is_macos: bool,
130 term_program: Option<&str>,
131 term: Option<&str>,
132) -> bool {
133 if !is_macos || mode != KeyboardProtocolMode::Default {
134 return false;
135 }
136
137 vtcode_commons::terminal_detection::is_ghostty_terminal(term_program, term)
140}
141
142#[cfg(all(test, feature = "tui"))]
143mod keyboard_protocol_tests {
144 use super::*;
145 use ratatui::crossterm::event::KeyboardEnhancementFlags;
146
147 fn default_keyboard_protocol_config() -> KeyboardProtocolConfig {
148 KeyboardProtocolConfig {
149 enabled: true,
150 mode: KeyboardProtocolMode::Default,
151 disambiguate_escape_codes: true,
152 report_event_types: true,
153 report_alternate_keys: true,
154 report_all_keys: false,
155 }
156 }
157
158 #[test]
159 fn test_keyboard_protocol_defaults() {
160 let flags = keyboard_protocol_to_flags_for_terminal(
161 &default_keyboard_protocol_config(),
162 false,
163 Some("Ghostty"),
164 Some("xterm-ghostty"),
165 );
166
167 assert!(flags.contains(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES));
168 assert!(flags.contains(KeyboardEnhancementFlags::REPORT_EVENT_TYPES));
169 assert!(flags.contains(KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS));
170 assert!(!flags.contains(KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES));
171 }
172
173 #[test]
174 fn test_keyboard_protocol_defaults_enable_all_keys_for_ghostty_on_macos() {
175 let flags = keyboard_protocol_to_flags_for_terminal(
176 &default_keyboard_protocol_config(),
177 true,
178 Some("Ghostty"),
179 Some("xterm-ghostty"),
180 );
181
182 assert!(flags.contains(KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES));
183 }
184
185 #[test]
186 fn test_keyboard_protocol_minimal_mode() {
187 let config = KeyboardProtocolConfig {
188 enabled: true,
189 mode: KeyboardProtocolMode::Minimal,
190 disambiguate_escape_codes: true,
191 report_event_types: true,
192 report_alternate_keys: true,
193 report_all_keys: false,
194 };
195
196 let flags = keyboard_protocol_to_flags_for_terminal(&config, true, Some("Ghostty"), Some("xterm-ghostty"));
197
198 assert!(flags.contains(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES));
199 assert!(!flags.contains(KeyboardEnhancementFlags::REPORT_EVENT_TYPES));
200 assert!(!flags.contains(KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS));
201 assert!(!flags.contains(KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES));
202 }
203
204 #[test]
205 fn test_keyboard_protocol_disabled() {
206 let config = KeyboardProtocolConfig {
207 enabled: false,
208 mode: KeyboardProtocolMode::Default,
209 disambiguate_escape_codes: true,
210 report_event_types: true,
211 report_alternate_keys: true,
212 report_all_keys: false,
213 };
214
215 let flags = keyboard_protocol_to_flags_for_terminal(&config, true, Some("Ghostty"), Some("xterm-ghostty"));
216 assert!(flags.is_empty());
217 }
218
219 #[test]
220 fn test_keyboard_protocol_custom_mode() {
221 let config = KeyboardProtocolConfig {
222 enabled: true,
223 mode: KeyboardProtocolMode::Custom,
224 disambiguate_escape_codes: true,
225 report_event_types: false,
226 report_alternate_keys: true,
227 report_all_keys: false,
228 };
229
230 let flags = keyboard_protocol_to_flags_for_terminal(&config, true, Some("Ghostty"), Some("xterm-ghostty"));
231
232 assert!(flags.contains(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES));
233 assert!(!flags.contains(KeyboardEnhancementFlags::REPORT_EVENT_TYPES));
234 assert!(flags.contains(KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS));
235 assert!(!flags.contains(KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES));
236 }
237
238 #[test]
239 fn test_keyboard_protocol_validation() {
240 let config = KeyboardProtocolConfig {
241 enabled: true,
242 mode: KeyboardProtocolMode::Default,
243 disambiguate_escape_codes: true,
244 report_event_types: true,
245 report_alternate_keys: true,
246 report_all_keys: false,
247 };
248
249 config.validate().unwrap();
251 }
252}