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
package/src/cli/app.rs ADDED
@@ -0,0 +1,310 @@
1
+ use anyhow::Result;
2
+ use clap::{Parser, Subcommand};
3
+ use std::path::PathBuf;
4
+ use tracing::{error, info};
5
+
6
+ use crate::config::{Config, ConfigSource};
7
+ use crate::display::banner::{BannerConfig, print_welcome_banner};
8
+ use crate::display::interactive::{InteractiveConfig, PromptStyle, start_interactive_mode};
9
+ use crate::utils::auth::{require_api_key, resolve_api_key};
10
+ use crate::utils::network::test_connectivity;
11
+
12
+ /// Grok CLI - Command-line interface for Grok AI
13
+ #[derive(Parser, Debug)]
14
+ #[command(author, version, about, long_about = None)]
15
+ pub struct Cli {
16
+ /// API key for authentication
17
+ #[arg(short, long, env = "GROK_API_KEY")]
18
+ pub api_key: Option<String>,
19
+
20
+ /// Config file path
21
+ #[arg(short, long)]
22
+ pub config: Option<PathBuf>,
23
+
24
+ /// Hide banner
25
+ #[arg(long)]
26
+ pub hide_banner: bool,
27
+
28
+ /// Model to use
29
+ #[arg(short, long)]
30
+ pub model: Option<String>,
31
+
32
+ #[command(subcommand)]
33
+ pub command: Option<Commands>,
34
+ }
35
+
36
+ #[derive(Subcommand, Debug)]
37
+ pub enum Commands {
38
+ /// Chat with Grok AI
39
+ Chat {
40
+ /// The message to send
41
+ #[arg(required = true)]
42
+ message: Vec<String>,
43
+
44
+ /// Start an interactive chat session
45
+ #[arg(short, long)]
46
+ interactive: bool,
47
+
48
+ /// System prompt to use
49
+ #[arg(short, long)]
50
+ system: Option<String>,
51
+
52
+ /// Temperature for response generation (0.0 to 2.0)
53
+ #[arg(short, long, default_value = "0.7")]
54
+ temperature: f32,
55
+
56
+ /// Maximum tokens in response
57
+ #[arg(long, default_value = "4096")]
58
+ max_tokens: u32,
59
+ },
60
+
61
+ /// Code-related operations
62
+ Code {
63
+ #[command(subcommand)]
64
+ action: crate::CodeAction,
65
+ },
66
+
67
+ /// ACP (Agent Client Protocol) operations for Zed integration
68
+ Acp {
69
+ #[command(subcommand)]
70
+ action: crate::AcpAction,
71
+ },
72
+
73
+ /// Interactive chat mode
74
+ Interactive,
75
+
76
+ /// Send a single query
77
+ Query {
78
+ /// The question or prompt to send
79
+ #[arg(required = true)]
80
+ prompt: Vec<String>,
81
+ },
82
+
83
+ /// Test network connectivity
84
+ TestNetwork {
85
+ /// Timeout in seconds
86
+ #[arg(short, long, default_value = "10")]
87
+ timeout: u64,
88
+ },
89
+
90
+ /// Configuration management
91
+ Config {
92
+ #[command(subcommand)]
93
+ action: crate::ConfigAction,
94
+ },
95
+
96
+ /// Settings management and configuration
97
+ Settings {
98
+ #[command(subcommand)]
99
+ action: crate::SettingsAction,
100
+ },
101
+
102
+ /// Chat history management
103
+ History {
104
+ #[command(subcommand)]
105
+ action: crate::HistoryAction,
106
+ },
107
+
108
+ /// Health check and diagnostics
109
+ Health {
110
+ /// Check API connectivity
111
+ #[arg(long)]
112
+ api: bool,
113
+
114
+ /// Check configuration
115
+ #[arg(long)]
116
+ config: bool,
117
+
118
+ /// Check all systems
119
+ #[arg(long)]
120
+ all: bool,
121
+ },
122
+ }
123
+
124
+ /// Main application entry point
125
+ pub async fn run() -> Result<()> {
126
+ let cli = Cli::parse();
127
+ let config = if let Some(config_path) = &cli.config {
128
+ // Use explicit config path if provided
129
+ let path_str = config_path
130
+ .to_str()
131
+ .ok_or_else(|| anyhow::anyhow!("Invalid config path: contains non-UTF8 characters"))?;
132
+ Config::load(Some(path_str)).await?
133
+ } else {
134
+ // Use hierarchical loading: project → system → defaults
135
+ match Config::load_hierarchical().await {
136
+ Ok(cfg) => {
137
+ info!("✓ Configuration loaded successfully");
138
+ cfg
139
+ }
140
+ Err(e) => {
141
+ error!("Failed to load hierarchical configuration: {}", e);
142
+ error!("Falling back to default configuration");
143
+ Config {
144
+ config_source: Some(ConfigSource::Default),
145
+ ..Config::default()
146
+ }
147
+ }
148
+ }
149
+ };
150
+
151
+ // Initialize telemetry
152
+ crate::utils::telemetry::init(config.telemetry.enabled, config.telemetry.log_file.clone());
153
+
154
+ // Resolve API key once
155
+ let api_key = resolve_api_key(cli.api_key.clone(), &config);
156
+
157
+ // Resolve model: CLI argument overrides config
158
+ let model = cli.model.as_deref().unwrap_or(&config.default_model);
159
+
160
+ // Show banner function
161
+ let show_banner_fn = || {
162
+ let banner_config = BannerConfig {
163
+ show_banner: true,
164
+ show_tips: true,
165
+ show_updates: true,
166
+ width: None,
167
+ };
168
+ print_welcome_banner(&banner_config);
169
+ };
170
+
171
+ match &cli.command {
172
+ Some(Commands::Chat {
173
+ message,
174
+ interactive,
175
+ system,
176
+ temperature,
177
+ max_tokens,
178
+ }) => {
179
+ let api_key = require_api_key(api_key, cli.hide_banner, show_banner_fn);
180
+ crate::cli::commands::chat::handle_chat(crate::cli::commands::chat::ChatOptions {
181
+ message: message.clone(),
182
+ interactive: *interactive,
183
+ system: system.clone(),
184
+ temperature: *temperature,
185
+ max_tokens: *max_tokens,
186
+ api_key: &api_key,
187
+ model,
188
+ timeout_secs: config.timeout_secs,
189
+ max_retries: config.max_retries,
190
+ rate_limit_config: config.rate_limits,
191
+ })
192
+ .await?;
193
+ }
194
+ Some(Commands::Code { action }) => {
195
+ let api_key = require_api_key(api_key, cli.hide_banner, show_banner_fn);
196
+ crate::cli::commands::code::handle_code_action(
197
+ action.clone(),
198
+ &api_key,
199
+ model,
200
+ config.timeout_secs,
201
+ config.max_retries,
202
+ config.rate_limits,
203
+ )
204
+ .await?;
205
+ }
206
+ Some(Commands::Acp { action }) => {
207
+ crate::cli::commands::acp::handle_acp_action(action.clone(), &config).await?;
208
+ }
209
+ Some(Commands::Interactive) => {
210
+ let api_key = require_api_key(api_key, cli.hide_banner, show_banner_fn);
211
+ let interactive_config = InteractiveConfig {
212
+ show_banner: !cli.hide_banner,
213
+ show_tips: true,
214
+ show_status: true,
215
+ auto_save_session: false,
216
+ prompt_style: PromptStyle::Rich,
217
+ check_directory: true,
218
+ };
219
+ start_interactive_mode(&api_key, model, &config, interactive_config).await?;
220
+ }
221
+ Some(Commands::Query { prompt }) => {
222
+ let api_key = require_api_key(api_key, cli.hide_banner, show_banner_fn);
223
+ let query = prompt.join(" ");
224
+
225
+ if !cli.hide_banner {
226
+ show_banner_fn();
227
+ }
228
+
229
+ info!("Sending query: {}", query);
230
+ crate::cli::commands::chat::handle_chat(crate::cli::commands::chat::ChatOptions {
231
+ message: vec![query],
232
+ interactive: false,
233
+ system: None,
234
+ temperature: 0.7,
235
+ max_tokens: 4096,
236
+ api_key: &api_key,
237
+ model,
238
+ timeout_secs: config.timeout_secs,
239
+ max_retries: config.max_retries,
240
+ rate_limit_config: config.rate_limits,
241
+ })
242
+ .await?;
243
+ }
244
+ Some(Commands::TestNetwork { timeout }) => {
245
+ if !cli.hide_banner {
246
+ show_banner_fn();
247
+ }
248
+ let timeout_duration = std::time::Duration::from_secs(*timeout);
249
+ match test_connectivity(timeout_duration).await {
250
+ Ok(duration) => {
251
+ println!("✓ Network connectivity test passed in {:?}", duration);
252
+ }
253
+ Err(e) => {
254
+ error!("Network connectivity test failed: {}", e);
255
+ return Err(e);
256
+ }
257
+ }
258
+ }
259
+ Some(Commands::Config { action }) => {
260
+ if !cli.hide_banner {
261
+ show_banner_fn();
262
+ }
263
+ crate::cli::commands::config::handle_config_action(action.clone(), &config).await?;
264
+ }
265
+ Some(Commands::Settings { action }) => {
266
+ if !cli.hide_banner {
267
+ show_banner_fn();
268
+ }
269
+ crate::cli::commands::settings::handle_settings_action(action.clone(), &config).await?;
270
+ }
271
+ Some(Commands::History { action }) => {
272
+ if !cli.hide_banner {
273
+ show_banner_fn();
274
+ }
275
+ crate::cli::commands::history::handle_history_action(action.clone()).await?;
276
+ }
277
+ Some(Commands::Health {
278
+ api,
279
+ config: check_config,
280
+ all,
281
+ }) => {
282
+ let check_api = *api || *all;
283
+ let check_cfg = *check_config || *all;
284
+ crate::cli::commands::health::handle_health_check(
285
+ check_api,
286
+ check_cfg,
287
+ api_key.as_deref(),
288
+ &config,
289
+ model,
290
+ config.timeout_secs,
291
+ )
292
+ .await?;
293
+ }
294
+ None => {
295
+ // Default to interactive mode
296
+ let api_key = require_api_key(api_key, cli.hide_banner, show_banner_fn);
297
+ let interactive_config = InteractiveConfig {
298
+ show_banner: !cli.hide_banner,
299
+ show_tips: true,
300
+ show_status: true,
301
+ auto_save_session: false,
302
+ prompt_style: PromptStyle::Rich,
303
+ check_directory: true,
304
+ };
305
+ start_interactive_mode(&api_key, model, &config, interactive_config).await?;
306
+ }
307
+ }
308
+
309
+ Ok(())
310
+ }