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.
- package/.env.example +42 -0
- package/.github/workflows/ci.yml +30 -0
- package/.github/workflows/rust.yml +22 -0
- package/.grok/.env.example +85 -0
- package/.grok/COMPLETE_FIX_SUMMARY.md +466 -0
- package/.grok/ENV_CONFIG_GUIDE.md +173 -0
- package/.grok/QUICK_REFERENCE.md +180 -0
- package/.grok/README.md +104 -0
- package/.grok/TESTING_GUIDE.md +393 -0
- package/CHANGELOG.md +465 -0
- package/CODE_REVIEW_SUMMARY.md +414 -0
- package/COMPLETE_FIX_SUMMARY.md +415 -0
- package/CONFIGURATION.md +489 -0
- package/CONTEXT_FILES_GUIDE.md +419 -0
- package/CONTRIBUTING.md +55 -0
- package/CURSOR_POSITION_FIX.md +206 -0
- package/Cargo.toml +88 -0
- package/ERROR_HANDLING_REPORT.md +361 -0
- package/FINAL_FIX_SUMMARY.md +462 -0
- package/FIXES.md +37 -0
- package/FIXES_SUMMARY.md +87 -0
- package/GROK_API_MIGRATION_SUMMARY.md +111 -0
- package/LICENSE +22 -0
- package/MIGRATION_TO_GROK_API.md +223 -0
- package/README.md +504 -0
- package/REVIEW_COMPLETE.md +416 -0
- package/REVIEW_QUICK_REFERENCE.md +173 -0
- package/SECURITY.md +463 -0
- package/SECURITY_AUDIT.md +661 -0
- package/SETUP.md +287 -0
- package/TESTING_TOOLS.md +88 -0
- package/TESTING_TOOL_EXECUTION.md +239 -0
- package/TOOL_EXECUTION_FIX.md +491 -0
- package/VERIFICATION_CHECKLIST.md +419 -0
- package/docs/API.md +74 -0
- package/docs/CHAT_LOGGING.md +39 -0
- package/docs/CURSOR_FIX_DEMO.md +306 -0
- package/docs/ERROR_HANDLING_GUIDE.md +547 -0
- package/docs/FILE_OPERATIONS.md +449 -0
- package/docs/INTERACTIVE.md +401 -0
- package/docs/PROJECT_CREATION_GUIDE.md +570 -0
- package/docs/QUICKSTART.md +378 -0
- package/docs/QUICK_REFERENCE.md +691 -0
- package/docs/RELEASE_NOTES_0.1.2.md +240 -0
- package/docs/TOOLS.md +459 -0
- package/docs/TOOLS_QUICK_REFERENCE.md +210 -0
- package/docs/ZED_INTEGRATION.md +371 -0
- package/docs/extensions.md +464 -0
- package/docs/settings.md +293 -0
- package/examples/extensions/logging-hook/README.md +91 -0
- package/examples/extensions/logging-hook/extension.json +22 -0
- package/package.json +30 -0
- package/scripts/test_acp.py +252 -0
- package/scripts/test_acp.sh +143 -0
- package/scripts/test_acp_simple.sh +72 -0
- package/src/acp/mod.rs +741 -0
- package/src/acp/protocol.rs +323 -0
- package/src/acp/security.rs +298 -0
- package/src/acp/tools.rs +697 -0
- package/src/bin/banner_demo.rs +216 -0
- package/src/bin/docgen.rs +18 -0
- package/src/bin/installer.rs +217 -0
- package/src/cli/app.rs +310 -0
- package/src/cli/commands/acp.rs +721 -0
- package/src/cli/commands/chat.rs +485 -0
- package/src/cli/commands/code.rs +513 -0
- package/src/cli/commands/config.rs +394 -0
- package/src/cli/commands/health.rs +442 -0
- package/src/cli/commands/history.rs +421 -0
- package/src/cli/commands/mod.rs +14 -0
- package/src/cli/commands/settings.rs +1384 -0
- package/src/cli/mod.rs +166 -0
- package/src/config/mod.rs +2212 -0
- package/src/display/ascii_art.rs +139 -0
- package/src/display/banner.rs +289 -0
- package/src/display/components/input.rs +323 -0
- package/src/display/components/mod.rs +2 -0
- package/src/display/components/settings_list.rs +306 -0
- package/src/display/interactive.rs +1255 -0
- package/src/display/mod.rs +62 -0
- package/src/display/terminal.rs +42 -0
- package/src/display/tips.rs +316 -0
- package/src/grok_client_ext.rs +177 -0
- package/src/hooks/loader.rs +407 -0
- package/src/hooks/mod.rs +158 -0
- package/src/lib.rs +174 -0
- package/src/main.rs +65 -0
- package/src/mcp/client.rs +195 -0
- package/src/mcp/config.rs +20 -0
- package/src/mcp/mod.rs +6 -0
- package/src/mcp/protocol.rs +67 -0
- package/src/utils/auth.rs +41 -0
- package/src/utils/chat_logger.rs +568 -0
- package/src/utils/context.rs +390 -0
- package/src/utils/mod.rs +16 -0
- package/src/utils/network.rs +320 -0
- package/src/utils/rate_limiter.rs +166 -0
- package/src/utils/session.rs +73 -0
- package/src/utils/shell_permissions.rs +389 -0
- package/src/utils/telemetry.rs +41 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
//! Chat history viewer command
|
|
2
|
+
//!
|
|
3
|
+
//! This module provides commands to view, search, and manage chat session logs.
|
|
4
|
+
|
|
5
|
+
use anyhow::{Context, Result};
|
|
6
|
+
use colored::*;
|
|
7
|
+
use std::path::PathBuf;
|
|
8
|
+
|
|
9
|
+
use crate::cli::{print_error, print_info, print_success};
|
|
10
|
+
use crate::utils::chat_logger::{ChatLogger, ChatLoggerConfig, ChatSession};
|
|
11
|
+
|
|
12
|
+
/// Handle history-related commands
|
|
13
|
+
pub async fn handle_history_action(action: crate::HistoryAction) -> Result<()> {
|
|
14
|
+
match action {
|
|
15
|
+
crate::HistoryAction::List => list_sessions().await,
|
|
16
|
+
crate::HistoryAction::View { session_id } => view_session(&session_id).await,
|
|
17
|
+
crate::HistoryAction::Search { query } => search_sessions(&query).await,
|
|
18
|
+
crate::HistoryAction::Clear { confirm } => clear_history(confirm).await,
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// List all available chat sessions
|
|
23
|
+
async fn list_sessions() -> Result<()> {
|
|
24
|
+
let config = get_logger_config();
|
|
25
|
+
let logger =
|
|
26
|
+
ChatLogger::new(config).context("Failed to initialize chat logger for listing sessions")?;
|
|
27
|
+
|
|
28
|
+
let sessions = logger
|
|
29
|
+
.list_sessions()
|
|
30
|
+
.context("Failed to list chat sessions")?;
|
|
31
|
+
|
|
32
|
+
if sessions.is_empty() {
|
|
33
|
+
print_info("No chat sessions found.");
|
|
34
|
+
return Ok(());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
println!("\n{}", "=".repeat(80).bright_cyan());
|
|
38
|
+
println!(
|
|
39
|
+
"{}",
|
|
40
|
+
format!(" CHAT SESSIONS ({} total)", sessions.len())
|
|
41
|
+
.bright_cyan()
|
|
42
|
+
.bold()
|
|
43
|
+
);
|
|
44
|
+
println!("{}\n", "=".repeat(80).bright_cyan());
|
|
45
|
+
|
|
46
|
+
for (i, session_id) in sessions.iter().enumerate() {
|
|
47
|
+
// Try to load session metadata
|
|
48
|
+
match logger.load_session(session_id) {
|
|
49
|
+
Ok(session) => {
|
|
50
|
+
let start_time = session.start_time.format("%Y-%m-%d %H:%M:%S UTC");
|
|
51
|
+
let msg_count = session.messages.len();
|
|
52
|
+
let status = if session.end_time.is_some() {
|
|
53
|
+
"Completed".green()
|
|
54
|
+
} else {
|
|
55
|
+
"Active".yellow()
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
println!(
|
|
59
|
+
"{}. {} {}",
|
|
60
|
+
format!("{:3}", i + 1).bright_black(),
|
|
61
|
+
session_id.bright_white().bold(),
|
|
62
|
+
status
|
|
63
|
+
);
|
|
64
|
+
println!(
|
|
65
|
+
" {} {} | {} messages",
|
|
66
|
+
"Started:".bright_black(),
|
|
67
|
+
start_time.to_string().bright_white(),
|
|
68
|
+
msg_count.to_string().bright_cyan()
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if let Some(end_time) = session.end_time {
|
|
72
|
+
let duration = end_time
|
|
73
|
+
.signed_duration_since(session.start_time)
|
|
74
|
+
.num_seconds();
|
|
75
|
+
println!(
|
|
76
|
+
" {} {}",
|
|
77
|
+
"Duration:".bright_black(),
|
|
78
|
+
format!("{} seconds", duration).bright_white()
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Show first user message preview if available
|
|
83
|
+
if let Some(first_msg) = session.messages.iter().find(|m| m.role == "user") {
|
|
84
|
+
let preview = first_msg
|
|
85
|
+
.content
|
|
86
|
+
.lines()
|
|
87
|
+
.next()
|
|
88
|
+
.unwrap_or("")
|
|
89
|
+
.chars()
|
|
90
|
+
.take(60)
|
|
91
|
+
.collect::<String>();
|
|
92
|
+
if !preview.is_empty() {
|
|
93
|
+
println!(
|
|
94
|
+
" {} {}{}",
|
|
95
|
+
"Preview:".bright_black(),
|
|
96
|
+
preview.bright_white(),
|
|
97
|
+
if first_msg.content.len() > 60 {
|
|
98
|
+
"..."
|
|
99
|
+
} else {
|
|
100
|
+
""
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
println!();
|
|
106
|
+
}
|
|
107
|
+
Err(e) => {
|
|
108
|
+
println!(
|
|
109
|
+
"{}. {} {}",
|
|
110
|
+
format!("{:3}", i + 1).bright_black(),
|
|
111
|
+
session_id.bright_white().bold(),
|
|
112
|
+
"(error loading)".red()
|
|
113
|
+
);
|
|
114
|
+
println!(" Error: {}", e.to_string().red());
|
|
115
|
+
println!();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
println!("{}", "=".repeat(80).bright_cyan());
|
|
121
|
+
println!(
|
|
122
|
+
"\n{} {}",
|
|
123
|
+
"Tip:".bright_cyan().bold(),
|
|
124
|
+
"View a session with: grok history view <session-id>".bright_white()
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
Ok(())
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// View a specific chat session
|
|
131
|
+
async fn view_session(session_id: &str) -> Result<()> {
|
|
132
|
+
let config = get_logger_config();
|
|
133
|
+
let logger =
|
|
134
|
+
ChatLogger::new(config).context("Failed to initialize chat logger for viewing session")?;
|
|
135
|
+
|
|
136
|
+
let session = logger
|
|
137
|
+
.load_session(session_id)
|
|
138
|
+
.with_context(|| format!("Failed to load session: {}", session_id))?;
|
|
139
|
+
|
|
140
|
+
display_session(&session)?;
|
|
141
|
+
|
|
142
|
+
Ok(())
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Display a chat session in formatted output
|
|
146
|
+
fn display_session(session: &ChatSession) -> Result<()> {
|
|
147
|
+
println!("\n{}", "=".repeat(80).bright_cyan());
|
|
148
|
+
println!(
|
|
149
|
+
"{}",
|
|
150
|
+
format!(" CHAT SESSION: {}", session.session_id)
|
|
151
|
+
.bright_cyan()
|
|
152
|
+
.bold()
|
|
153
|
+
);
|
|
154
|
+
println!("{}\n", "=".repeat(80).bright_cyan());
|
|
155
|
+
|
|
156
|
+
// Display metadata
|
|
157
|
+
println!(
|
|
158
|
+
"{} {}",
|
|
159
|
+
"Start Time:".bright_white().bold(),
|
|
160
|
+
session.start_time.format("%Y-%m-%d %H:%M:%S UTC")
|
|
161
|
+
);
|
|
162
|
+
if let Some(end_time) = session.end_time {
|
|
163
|
+
println!(
|
|
164
|
+
"{} {}",
|
|
165
|
+
"End Time: ".bright_white().bold(),
|
|
166
|
+
end_time.format("%Y-%m-%d %H:%M:%S UTC")
|
|
167
|
+
);
|
|
168
|
+
let duration = end_time
|
|
169
|
+
.signed_duration_since(session.start_time)
|
|
170
|
+
.num_seconds();
|
|
171
|
+
println!(
|
|
172
|
+
"{} {} seconds",
|
|
173
|
+
"Duration: ".bright_white().bold(),
|
|
174
|
+
duration
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
println!(
|
|
178
|
+
"{} {}",
|
|
179
|
+
"Status: ".bright_white().bold(),
|
|
180
|
+
"Active".yellow()
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
println!(
|
|
184
|
+
"{} {}\n",
|
|
185
|
+
"Messages: ".bright_white().bold(),
|
|
186
|
+
session.messages.len()
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
println!("{}", "-".repeat(80).bright_black());
|
|
190
|
+
println!();
|
|
191
|
+
|
|
192
|
+
// Display messages
|
|
193
|
+
for (i, msg) in session.messages.iter().enumerate() {
|
|
194
|
+
let role_display = match msg.role.as_str() {
|
|
195
|
+
"user" => "USER".bright_green().bold(),
|
|
196
|
+
"assistant" => "ASSISTANT".bright_blue().bold(),
|
|
197
|
+
"system" => "SYSTEM".bright_yellow().bold(),
|
|
198
|
+
_ => msg.role.bright_white().bold(),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
let time = msg.timestamp.format("%H:%M:%S");
|
|
202
|
+
|
|
203
|
+
println!(
|
|
204
|
+
"{} {} {}",
|
|
205
|
+
format!("[{}]", i + 1).bright_black(),
|
|
206
|
+
role_display,
|
|
207
|
+
format!("({})", time).bright_black()
|
|
208
|
+
);
|
|
209
|
+
println!("{}", "-".repeat(80).bright_black());
|
|
210
|
+
|
|
211
|
+
// Print message content with proper wrapping
|
|
212
|
+
for line in msg.content.lines() {
|
|
213
|
+
println!("{}", line);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Display metadata if present
|
|
217
|
+
if let Some(metadata) = &msg.metadata {
|
|
218
|
+
println!();
|
|
219
|
+
println!("{}", "Metadata:".bright_black());
|
|
220
|
+
match serde_json::to_string_pretty(metadata) {
|
|
221
|
+
Ok(json) => {
|
|
222
|
+
for line in json.lines() {
|
|
223
|
+
println!(" {}", line.bright_black());
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
Err(_) => println!(" {}", "(error displaying metadata)".red()),
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
println!();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
println!("{}", "=".repeat(80).bright_cyan());
|
|
234
|
+
println!(
|
|
235
|
+
"{} {} messages in session {}\n",
|
|
236
|
+
"Total:".bright_cyan().bold(),
|
|
237
|
+
session.messages.len(),
|
|
238
|
+
session.session_id.bright_white()
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
Ok(())
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// Search through chat sessions for a query string
|
|
245
|
+
async fn search_sessions(query: &str) -> Result<()> {
|
|
246
|
+
let config = get_logger_config();
|
|
247
|
+
let logger = ChatLogger::new(config)
|
|
248
|
+
.context("Failed to initialize chat logger for searching sessions")?;
|
|
249
|
+
|
|
250
|
+
let sessions = logger
|
|
251
|
+
.list_sessions()
|
|
252
|
+
.context("Failed to list chat sessions")?;
|
|
253
|
+
|
|
254
|
+
if sessions.is_empty() {
|
|
255
|
+
print_info("No chat sessions found.");
|
|
256
|
+
return Ok(());
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
let query_lower = query.to_lowercase();
|
|
260
|
+
let mut matches = Vec::new();
|
|
261
|
+
|
|
262
|
+
for session_id in sessions {
|
|
263
|
+
if let Ok(session) = logger.load_session(&session_id) {
|
|
264
|
+
// Search in messages
|
|
265
|
+
for (msg_idx, msg) in session.messages.iter().enumerate() {
|
|
266
|
+
if msg.content.to_lowercase().contains(&query_lower) {
|
|
267
|
+
matches.push((session.clone(), msg_idx, msg.clone()));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if matches.is_empty() {
|
|
274
|
+
print_info(&format!("No matches found for query: '{}'", query));
|
|
275
|
+
return Ok(());
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
println!("\n{}", "=".repeat(80).bright_cyan());
|
|
279
|
+
println!(
|
|
280
|
+
"{}",
|
|
281
|
+
format!(
|
|
282
|
+
" SEARCH RESULTS: {} matches for '{}'",
|
|
283
|
+
matches.len(),
|
|
284
|
+
query
|
|
285
|
+
)
|
|
286
|
+
.bright_cyan()
|
|
287
|
+
.bold()
|
|
288
|
+
);
|
|
289
|
+
println!("{}\n", "=".repeat(80).bright_cyan());
|
|
290
|
+
|
|
291
|
+
for (i, (session, msg_idx, msg)) in matches.iter().enumerate() {
|
|
292
|
+
println!(
|
|
293
|
+
"{}. {} {}",
|
|
294
|
+
format!("{:3}", i + 1).bright_black(),
|
|
295
|
+
"Session:".bright_white().bold(),
|
|
296
|
+
session.session_id.bright_cyan()
|
|
297
|
+
);
|
|
298
|
+
println!(
|
|
299
|
+
" {} Message {} by {}",
|
|
300
|
+
"Match:".bright_black(),
|
|
301
|
+
msg_idx + 1,
|
|
302
|
+
msg.role.bright_white()
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// Show context around the match
|
|
306
|
+
let content_lines: Vec<&str> = msg.content.lines().collect();
|
|
307
|
+
let matching_lines: Vec<(usize, &str)> = content_lines
|
|
308
|
+
.iter()
|
|
309
|
+
.enumerate()
|
|
310
|
+
.filter(|(_, line)| line.to_lowercase().contains(&query_lower))
|
|
311
|
+
.map(|(idx, line)| (idx, *line))
|
|
312
|
+
.collect();
|
|
313
|
+
|
|
314
|
+
for (line_idx, line) in matching_lines.iter().take(3) {
|
|
315
|
+
// Show up to 3 matching lines
|
|
316
|
+
// Highlight the query in the line
|
|
317
|
+
let highlighted = highlight_query(line, query);
|
|
318
|
+
println!(
|
|
319
|
+
" {}: {}",
|
|
320
|
+
format!("L{}", line_idx + 1).bright_black(),
|
|
321
|
+
highlighted
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
println!();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
println!("{}", "=".repeat(80).bright_cyan());
|
|
329
|
+
println!(
|
|
330
|
+
"\n{} {}",
|
|
331
|
+
"Tip:".bright_cyan().bold(),
|
|
332
|
+
"View full session with: grok history view <session-id>".bright_white()
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
Ok(())
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/// Highlight query string in text
|
|
339
|
+
fn highlight_query(text: &str, query: &str) -> String {
|
|
340
|
+
let query_lower = query.to_lowercase();
|
|
341
|
+
let text_lower = text.to_lowercase();
|
|
342
|
+
|
|
343
|
+
if let Some(pos) = text_lower.find(&query_lower) {
|
|
344
|
+
let before = &text[..pos];
|
|
345
|
+
let matched = &text[pos..pos + query.len()];
|
|
346
|
+
let after = &text[pos + query.len()..];
|
|
347
|
+
|
|
348
|
+
format!("{}{}{}", before, matched.bright_yellow().bold(), after)
|
|
349
|
+
} else {
|
|
350
|
+
text.to_string()
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/// Clear chat history
|
|
355
|
+
async fn clear_history(confirm: bool) -> Result<()> {
|
|
356
|
+
if !confirm {
|
|
357
|
+
print_error("This will delete all chat session logs!");
|
|
358
|
+
println!(
|
|
359
|
+
"{} {}",
|
|
360
|
+
"To confirm, run:".bright_white(),
|
|
361
|
+
"grok history clear --confirm".bright_cyan()
|
|
362
|
+
);
|
|
363
|
+
return Ok(());
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
let config = get_logger_config();
|
|
367
|
+
|
|
368
|
+
if !config.log_dir.exists() {
|
|
369
|
+
print_info("No chat history to clear.");
|
|
370
|
+
return Ok(());
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Delete all log files
|
|
374
|
+
let entries = std::fs::read_dir(&config.log_dir).context("Failed to read log directory")?;
|
|
375
|
+
|
|
376
|
+
let mut deleted_count = 0;
|
|
377
|
+
for entry in entries.flatten() {
|
|
378
|
+
if entry.path().is_file() {
|
|
379
|
+
if let Err(e) = std::fs::remove_file(entry.path()) {
|
|
380
|
+
print_error(&format!(
|
|
381
|
+
"Failed to delete {}: {}",
|
|
382
|
+
entry.path().display(),
|
|
383
|
+
e
|
|
384
|
+
));
|
|
385
|
+
} else {
|
|
386
|
+
deleted_count += 1;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
print_success(&format!(
|
|
392
|
+
"Cleared chat history: {} files deleted",
|
|
393
|
+
deleted_count
|
|
394
|
+
));
|
|
395
|
+
|
|
396
|
+
Ok(())
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/// Get chat logger configuration from environment
|
|
400
|
+
fn get_logger_config() -> ChatLoggerConfig {
|
|
401
|
+
let log_dir = std::env::var("GROK_CHAT_LOG_DIR")
|
|
402
|
+
.ok()
|
|
403
|
+
.map(PathBuf::from)
|
|
404
|
+
.unwrap_or_else(|| {
|
|
405
|
+
dirs::home_dir()
|
|
406
|
+
.unwrap_or_else(|| PathBuf::from("."))
|
|
407
|
+
.join(".grok")
|
|
408
|
+
.join("logs")
|
|
409
|
+
.join("chat_sessions")
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
ChatLoggerConfig {
|
|
413
|
+
enabled: true,
|
|
414
|
+
log_dir,
|
|
415
|
+
json_format: true,
|
|
416
|
+
text_format: true,
|
|
417
|
+
max_file_size_mb: 10,
|
|
418
|
+
rotation_count: 5,
|
|
419
|
+
include_system: true,
|
|
420
|
+
}
|
|
421
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//! Command handlers for grok-cli
|
|
2
|
+
//!
|
|
3
|
+
//! This module contains all the command handler implementations for the various
|
|
4
|
+
//! CLI commands supported by grok-cli.
|
|
5
|
+
|
|
6
|
+
pub mod acp;
|
|
7
|
+
pub mod chat;
|
|
8
|
+
pub mod code;
|
|
9
|
+
pub mod config;
|
|
10
|
+
pub mod health;
|
|
11
|
+
pub mod history;
|
|
12
|
+
pub mod settings;
|
|
13
|
+
|
|
14
|
+
// Re-export all command handlers
|