grok-cli-acp 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.env.example +42 -0
  2. package/.github/workflows/ci.yml +30 -0
  3. package/.github/workflows/rust.yml +22 -0
  4. package/.grok/.env.example +85 -0
  5. package/.grok/COMPLETE_FIX_SUMMARY.md +466 -0
  6. package/.grok/ENV_CONFIG_GUIDE.md +173 -0
  7. package/.grok/QUICK_REFERENCE.md +180 -0
  8. package/.grok/README.md +104 -0
  9. package/.grok/TESTING_GUIDE.md +393 -0
  10. package/CHANGELOG.md +465 -0
  11. package/CODE_REVIEW_SUMMARY.md +414 -0
  12. package/COMPLETE_FIX_SUMMARY.md +415 -0
  13. package/CONFIGURATION.md +489 -0
  14. package/CONTEXT_FILES_GUIDE.md +419 -0
  15. package/CONTRIBUTING.md +55 -0
  16. package/CURSOR_POSITION_FIX.md +206 -0
  17. package/Cargo.toml +88 -0
  18. package/ERROR_HANDLING_REPORT.md +361 -0
  19. package/FINAL_FIX_SUMMARY.md +462 -0
  20. package/FIXES.md +37 -0
  21. package/FIXES_SUMMARY.md +87 -0
  22. package/GROK_API_MIGRATION_SUMMARY.md +111 -0
  23. package/LICENSE +22 -0
  24. package/MIGRATION_TO_GROK_API.md +223 -0
  25. package/README.md +504 -0
  26. package/REVIEW_COMPLETE.md +416 -0
  27. package/REVIEW_QUICK_REFERENCE.md +173 -0
  28. package/SECURITY.md +463 -0
  29. package/SECURITY_AUDIT.md +661 -0
  30. package/SETUP.md +287 -0
  31. package/TESTING_TOOLS.md +88 -0
  32. package/TESTING_TOOL_EXECUTION.md +239 -0
  33. package/TOOL_EXECUTION_FIX.md +491 -0
  34. package/VERIFICATION_CHECKLIST.md +419 -0
  35. package/docs/API.md +74 -0
  36. package/docs/CHAT_LOGGING.md +39 -0
  37. package/docs/CURSOR_FIX_DEMO.md +306 -0
  38. package/docs/ERROR_HANDLING_GUIDE.md +547 -0
  39. package/docs/FILE_OPERATIONS.md +449 -0
  40. package/docs/INTERACTIVE.md +401 -0
  41. package/docs/PROJECT_CREATION_GUIDE.md +570 -0
  42. package/docs/QUICKSTART.md +378 -0
  43. package/docs/QUICK_REFERENCE.md +691 -0
  44. package/docs/RELEASE_NOTES_0.1.2.md +240 -0
  45. package/docs/TOOLS.md +459 -0
  46. package/docs/TOOLS_QUICK_REFERENCE.md +210 -0
  47. package/docs/ZED_INTEGRATION.md +371 -0
  48. package/docs/extensions.md +464 -0
  49. package/docs/settings.md +293 -0
  50. package/examples/extensions/logging-hook/README.md +91 -0
  51. package/examples/extensions/logging-hook/extension.json +22 -0
  52. package/package.json +30 -0
  53. package/scripts/test_acp.py +252 -0
  54. package/scripts/test_acp.sh +143 -0
  55. package/scripts/test_acp_simple.sh +72 -0
  56. package/src/acp/mod.rs +741 -0
  57. package/src/acp/protocol.rs +323 -0
  58. package/src/acp/security.rs +298 -0
  59. package/src/acp/tools.rs +697 -0
  60. package/src/bin/banner_demo.rs +216 -0
  61. package/src/bin/docgen.rs +18 -0
  62. package/src/bin/installer.rs +217 -0
  63. package/src/cli/app.rs +310 -0
  64. package/src/cli/commands/acp.rs +721 -0
  65. package/src/cli/commands/chat.rs +485 -0
  66. package/src/cli/commands/code.rs +513 -0
  67. package/src/cli/commands/config.rs +394 -0
  68. package/src/cli/commands/health.rs +442 -0
  69. package/src/cli/commands/history.rs +421 -0
  70. package/src/cli/commands/mod.rs +14 -0
  71. package/src/cli/commands/settings.rs +1384 -0
  72. package/src/cli/mod.rs +166 -0
  73. package/src/config/mod.rs +2212 -0
  74. package/src/display/ascii_art.rs +139 -0
  75. package/src/display/banner.rs +289 -0
  76. package/src/display/components/input.rs +323 -0
  77. package/src/display/components/mod.rs +2 -0
  78. package/src/display/components/settings_list.rs +306 -0
  79. package/src/display/interactive.rs +1255 -0
  80. package/src/display/mod.rs +62 -0
  81. package/src/display/terminal.rs +42 -0
  82. package/src/display/tips.rs +316 -0
  83. package/src/grok_client_ext.rs +177 -0
  84. package/src/hooks/loader.rs +407 -0
  85. package/src/hooks/mod.rs +158 -0
  86. package/src/lib.rs +174 -0
  87. package/src/main.rs +65 -0
  88. package/src/mcp/client.rs +195 -0
  89. package/src/mcp/config.rs +20 -0
  90. package/src/mcp/mod.rs +6 -0
  91. package/src/mcp/protocol.rs +67 -0
  92. package/src/utils/auth.rs +41 -0
  93. package/src/utils/chat_logger.rs +568 -0
  94. package/src/utils/context.rs +390 -0
  95. package/src/utils/mod.rs +16 -0
  96. package/src/utils/network.rs +320 -0
  97. package/src/utils/rate_limiter.rs +166 -0
  98. package/src/utils/session.rs +73 -0
  99. package/src/utils/shell_permissions.rs +389 -0
  100. package/src/utils/telemetry.rs +41 -0
@@ -0,0 +1,394 @@
1
+ //! Config command handler for grok-cli
2
+ //!
3
+ //! Handles configuration management operations including showing, setting,
4
+ //! getting, initializing, and validating configuration settings.
5
+
6
+ use anyhow::{anyhow, Result};
7
+ use colored::*;
8
+
9
+ use crate::cli::{confirm, print_error, print_info, print_success, print_warning};
10
+ use crate::config::Config;
11
+ use crate::ConfigAction;
12
+
13
+ /// Handle configuration-related commands
14
+ pub async fn handle_config_action(action: ConfigAction, config: &Config) -> Result<()> {
15
+ match action {
16
+ ConfigAction::Show => show_config(config).await,
17
+ ConfigAction::Set { key, value } => set_config_value(&key, &value).await,
18
+ ConfigAction::Get { key } => get_config_value(&key).await,
19
+ ConfigAction::Init { force } => init_config(force).await,
20
+ ConfigAction::Validate => validate_config().await,
21
+ }
22
+ }
23
+
24
+ /// Show current configuration
25
+ async fn show_config(config: &Config) -> Result<()> {
26
+ println!("{}", "⚙️ Grok CLI Configuration".cyan().bold());
27
+ println!();
28
+
29
+ // API Configuration
30
+ println!("{}", "API Configuration:".green().bold());
31
+ let api_key_display = if config.api_key.is_some() {
32
+ "✓ Set (hidden)".green()
33
+ } else {
34
+ "✗ Not set".red()
35
+ };
36
+ println!(" API Key: {}", api_key_display);
37
+ println!(" Default Model: {}", config.default_model.cyan());
38
+ println!(" Temperature: {}", config.default_temperature);
39
+ println!(" Max Tokens: {}", config.default_max_tokens);
40
+ println!(" Timeout: {}s", config.timeout_secs);
41
+ println!(" Max Retries: {}", config.max_retries);
42
+ println!();
43
+
44
+ // ACP Configuration
45
+ println!("{}", "ACP Configuration:".green().bold());
46
+ let acp_status = if config.acp.enabled {
47
+ "✓ Enabled".green()
48
+ } else {
49
+ "✗ Disabled".red()
50
+ };
51
+ println!(" Status: {}", acp_status);
52
+ println!(" Bind Host: {}", config.acp.bind_host);
53
+ let port_display = config
54
+ .acp
55
+ .default_port
56
+ .map(|p| p.to_string())
57
+ .unwrap_or_else(|| "Auto-assign".to_string());
58
+ println!(" Default Port: {}", port_display);
59
+ println!(" Protocol Version: {}", config.acp.protocol_version);
60
+ let dev_mode = if config.acp.dev_mode {
61
+ "✓ Enabled".yellow()
62
+ } else {
63
+ "✗ Disabled".dimmed()
64
+ };
65
+ println!(" Dev Mode: {}", dev_mode);
66
+ println!();
67
+
68
+ // Network Configuration
69
+ println!("{}", "Network Configuration:".green().bold());
70
+ let starlink_opt = if config.network.starlink_optimizations {
71
+ "✓ Enabled".green()
72
+ } else {
73
+ "✗ Disabled".red()
74
+ };
75
+ println!(" Starlink Optimizations: {}", starlink_opt);
76
+ println!(" Base Retry Delay: {}s", config.network.base_retry_delay);
77
+ println!(" Max Retry Delay: {}s", config.network.max_retry_delay);
78
+ let health_monitoring = if config.network.health_monitoring {
79
+ "✓ Enabled".green()
80
+ } else {
81
+ "✗ Disabled".dimmed()
82
+ };
83
+ println!(" Health Monitoring: {}", health_monitoring);
84
+ println!(" Connect Timeout: {}s", config.network.connect_timeout);
85
+ println!(" Read Timeout: {}s", config.network.read_timeout);
86
+ println!();
87
+
88
+ // UI Configuration
89
+ println!("{}", "UI Configuration:".green().bold());
90
+ let colors = if config.ui.colors {
91
+ "✓ Enabled".green()
92
+ } else {
93
+ "✗ Disabled".dimmed()
94
+ };
95
+ println!(" Colors: {}", colors);
96
+ let progress = if config.ui.progress_bars {
97
+ "✓ Enabled".green()
98
+ } else {
99
+ "✗ Disabled".dimmed()
100
+ };
101
+ println!(" Progress Bars: {}", progress);
102
+ let verbose_errors = if config.ui.verbose_errors {
103
+ "✓ Enabled".yellow()
104
+ } else {
105
+ "✗ Disabled".dimmed()
106
+ };
107
+ println!(" Verbose Errors: {}", verbose_errors);
108
+ let terminal_width = if config.ui.terminal_width == 0 {
109
+ "Auto-detect".to_string()
110
+ } else {
111
+ config.ui.terminal_width.to_string()
112
+ };
113
+ println!(" Terminal Width: {}", terminal_width);
114
+ let unicode = if config.ui.unicode {
115
+ "✓ Enabled".green()
116
+ } else {
117
+ "✗ Disabled".dimmed()
118
+ };
119
+ println!(" Unicode: {}", unicode);
120
+ println!();
121
+
122
+ // Logging Configuration
123
+ println!("{}", "Logging Configuration:".green().bold());
124
+ println!(" Level: {}", config.logging.level.cyan());
125
+ let file_logging = if config.logging.file_logging {
126
+ "✓ Enabled".green()
127
+ } else {
128
+ "✗ Disabled".dimmed()
129
+ };
130
+ println!(" File Logging: {}", file_logging);
131
+ if let Some(ref log_file) = config.logging.log_file {
132
+ println!(" Log File: {}", log_file.display());
133
+ }
134
+ println!(" Max File Size: {} MB", config.logging.max_file_size_mb);
135
+ println!(" Rotation Count: {}", config.logging.rotation_count);
136
+ println!();
137
+
138
+ // Configuration source information
139
+ println!("{}", "Configuration Source:".green().bold());
140
+ if let Some(ref source) = config.config_source {
141
+ println!(" {}", source.display());
142
+ } else {
143
+ println!(" Unknown");
144
+ }
145
+
146
+ Ok(())
147
+ }
148
+
149
+ /// Set a configuration value
150
+ async fn set_config_value(key: &str, value: &str) -> Result<()> {
151
+ print_info(&format!(
152
+ "Setting configuration: {} = {}",
153
+ key.cyan(),
154
+ value.yellow()
155
+ ));
156
+
157
+ // Load current config
158
+ let mut config = Config::load(None).await?;
159
+
160
+ // Set the value
161
+ config
162
+ .set_value(key, value)
163
+ .map_err(|e| anyhow!("Failed to set configuration value: {}", e))?;
164
+
165
+ // Validate the updated config
166
+ if let Err(e) = config.validate() {
167
+ print_error(&format!("Invalid configuration value: {}", e));
168
+ return Err(e);
169
+ }
170
+
171
+ // Save the config
172
+ config
173
+ .save(None)
174
+ .await
175
+ .map_err(|e| anyhow!("Failed to save configuration: {}", e))?;
176
+
177
+ print_success(&format!("Configuration updated: {} = {}", key, value));
178
+
179
+ // Show a relevant tip based on the key that was set
180
+ show_config_tip(key);
181
+
182
+ Ok(())
183
+ }
184
+
185
+ /// Get a configuration value
186
+ async fn get_config_value(key: &str) -> Result<()> {
187
+ print_info(&format!("Getting configuration value for: {}", key.cyan()));
188
+
189
+ // Load current config
190
+ let config = Config::load(None).await?;
191
+
192
+ // Get the value
193
+ match config.get_value(key) {
194
+ Ok(value) => {
195
+ if key == "api_key" && !value.is_empty() {
196
+ println!("{}: {}", key.cyan(), "*** (hidden) ***".dimmed());
197
+ } else {
198
+ println!("{}: {}", key.cyan(), value.yellow());
199
+ }
200
+ }
201
+ Err(e) => {
202
+ print_error(&format!("Configuration key not found: {}", e));
203
+ return Err(e);
204
+ }
205
+ }
206
+
207
+ Ok(())
208
+ }
209
+
210
+ /// Initialize configuration with defaults
211
+ async fn init_config(force: bool) -> Result<()> {
212
+ print_info("Initializing Grok CLI configuration...");
213
+
214
+ if !force {
215
+ let config_path = Config::default_config_path()?;
216
+ if config_path.exists() {
217
+ print_warning("Configuration file already exists!");
218
+ println!(" Path: {}", config_path.display());
219
+
220
+ if !confirm("Do you want to overwrite the existing configuration?")? {
221
+ print_info("Configuration initialization cancelled.");
222
+ return Ok(());
223
+ }
224
+ }
225
+ }
226
+
227
+ match Config::init(force).await {
228
+ Ok(config_path) => {
229
+ print_success("Configuration initialized successfully!");
230
+ println!(" Path: {}", config_path.display());
231
+ println!();
232
+ print_info("Next steps:");
233
+ println!(
234
+ " 1. Set your X API key: {}",
235
+ "grok config set api_key YOUR_API_KEY".yellow()
236
+ );
237
+ println!(" 2. Verify configuration: {}", "grok config show".yellow());
238
+ println!(" 3. Test connection: {}", "grok health --api".yellow());
239
+ }
240
+ Err(e) => {
241
+ print_error(&format!("Failed to initialize configuration: {}", e));
242
+ return Err(e);
243
+ }
244
+ }
245
+
246
+ Ok(())
247
+ }
248
+
249
+ /// Validate current configuration
250
+ async fn validate_config() -> Result<()> {
251
+ print_info("Validating configuration...");
252
+
253
+ let config = Config::load(None).await?;
254
+
255
+ match config.validate() {
256
+ Ok(()) => {
257
+ print_success("Configuration is valid!");
258
+
259
+ // Additional checks
260
+ let mut warnings = Vec::new();
261
+ let mut suggestions = Vec::new();
262
+
263
+ // Check API key
264
+ if config.api_key.is_none() {
265
+ warnings.push("No API key configured".to_string());
266
+ suggestions
267
+ .push("Set your X API key with: grok config set api_key YOUR_KEY".to_string());
268
+ }
269
+
270
+ // Check network settings for Starlink
271
+ if config.network.starlink_optimizations {
272
+ print_info("Starlink optimizations are enabled");
273
+ if config.network.base_retry_delay < 2 {
274
+ suggestions.push("Consider increasing base_retry_delay to 2+ seconds for satellite connections".to_string());
275
+ }
276
+ }
277
+
278
+ // Check ACP settings
279
+ if config.acp.enabled {
280
+ print_info("ACP (Zed integration) is enabled");
281
+ if let Some(port) = config.acp.default_port
282
+ && port < 1024 {
283
+ warnings.push(format!("ACP port {} may require elevated privileges", port));
284
+ }
285
+ }
286
+
287
+ // Display warnings and suggestions
288
+ if !warnings.is_empty() {
289
+ println!();
290
+ println!("{}", "⚠️ Warnings:".yellow().bold());
291
+ for warning in warnings {
292
+ println!(" • {}", warning.yellow());
293
+ }
294
+ }
295
+
296
+ if !suggestions.is_empty() {
297
+ println!();
298
+ println!("{}", "💡 Suggestions:".blue().bold());
299
+ for suggestion in suggestions {
300
+ println!(" • {}", suggestion);
301
+ }
302
+ }
303
+ }
304
+ Err(e) => {
305
+ print_error(&format!("Configuration validation failed: {}", e));
306
+
307
+ println!();
308
+ print_info("To fix configuration issues:");
309
+ println!(" 1. Check values with: {}", "grok config show".yellow());
310
+ println!(
311
+ " 2. Reset to defaults: {}",
312
+ "grok config init --force".yellow()
313
+ );
314
+ println!(
315
+ " 3. Set values manually: {}",
316
+ "grok config set <key> <value>".yellow()
317
+ );
318
+
319
+ return Err(e);
320
+ }
321
+ }
322
+
323
+ Ok(())
324
+ }
325
+
326
+ /// Show a helpful tip based on the configuration key that was set
327
+ fn show_config_tip(key: &str) {
328
+ match key {
329
+ "api_key" => {
330
+ print_info("💡 Test your API key with: grok health --api");
331
+ }
332
+ "acp.enabled" => {
333
+ print_info("💡 Start ACP server for Zed integration with: grok acp server");
334
+ }
335
+ "network.starlink_optimizations" => {
336
+ print_info("💡 Starlink optimizations help with satellite network instability");
337
+ }
338
+ "default_model" => {
339
+ print_info("💡 Available models: grok-2-latest, grok-2, grok-1");
340
+ }
341
+ "logging.level" => {
342
+ print_info("💡 Valid log levels: trace, debug, info, warn, error");
343
+ }
344
+ _ => {}
345
+ }
346
+ }
347
+
348
+ /// List all available configuration keys
349
+ pub fn list_config_keys() -> Vec<(&'static str, &'static str)> {
350
+ vec![
351
+ ("api_key", "X API key for Grok access"),
352
+ ("default_model", "Default model to use"),
353
+ ("default_temperature", "Default temperature (0.0-2.0)"),
354
+ ("default_max_tokens", "Default maximum tokens"),
355
+ ("timeout_secs", "Request timeout in seconds"),
356
+ ("max_retries", "Maximum retry attempts"),
357
+ ("acp.enabled", "Enable ACP functionality"),
358
+ ("acp.bind_host", "ACP server bind host"),
359
+ (
360
+ "network.starlink_optimizations",
361
+ "Enable Starlink optimizations",
362
+ ),
363
+ ("ui.colors", "Enable colored output"),
364
+ ("ui.progress_bars", "Enable progress bars"),
365
+ ("ui.verbose_errors", "Show detailed errors"),
366
+ ("ui.unicode", "Enable Unicode characters"),
367
+ ("logging.level", "Log level (trace/debug/info/warn/error)"),
368
+ ("logging.file_logging", "Enable file logging"),
369
+ ]
370
+ }
371
+
372
+ #[cfg(test)]
373
+ mod tests {
374
+ use super::*;
375
+
376
+ #[test]
377
+ fn test_list_config_keys() {
378
+ let keys = list_config_keys();
379
+ assert!(!keys.is_empty());
380
+
381
+ // Check that we have the essential keys
382
+ assert!(keys.iter().any(|(key, _)| *key == "api_key"));
383
+ assert!(keys.iter().any(|(key, _)| *key == "default_model"));
384
+ assert!(keys.iter().any(|(key, _)| *key == "acp.enabled"));
385
+ }
386
+
387
+ #[test]
388
+ fn test_config_tip_coverage() {
389
+ // Test that show_config_tip doesn't panic for various keys
390
+ show_config_tip("api_key");
391
+ show_config_tip("unknown_key");
392
+ show_config_tip("acp.enabled");
393
+ }
394
+ }