Remove legacy logs/ directory, consolidate all data under .g3/
This change removes the legacy logs/ directory and consolidates all session data, error logs, and discovery files under the .g3/ directory. New directory structure: - .g3/sessions/<session_id>/session.json - session logs - .g3/errors/ - error logs (was logs/errors/) - .g3/background_processes/ - background process logs - .g3/discovery/ - planner discovery files (was workspace/logs/) Changes: - paths.rs: Remove get_logs_dir()/logs_dir(), add get_errors_dir(), get_background_processes_dir(), get_discovery_dir() - session.rs: Anonymous sessions now use .g3/sessions/anonymous_<ts>/ - error_handling.rs: Errors now saved to .g3/errors/ - project.rs: Remove logs_dir() and ensure_logs_dir() methods - feedback_extraction.rs: Remove logs_dir field and fallback logic - planner: Use .g3/ for workspace data and .g3/discovery/ for reports - flock.rs: Look for session metrics in .g3/sessions/ - coach_feedback.rs: Remove fallback to logs/ path - Update all tests to use new paths - Update README.md and .gitignore
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,8 +23,7 @@ target
|
|||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
# Session logs directory
|
# G3 session data directory
|
||||||
logs/
|
|
||||||
.g3/
|
.g3/
|
||||||
|
|
||||||
# g3 artifacts
|
# g3 artifacts
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ G3 includes robust error handling with automatic retry logic:
|
|||||||
- **Recoverable Error Detection**: Automatically identifies recoverable errors (rate limits, network issues, server errors, timeouts)
|
- **Recoverable Error Detection**: Automatically identifies recoverable errors (rate limits, network issues, server errors, timeouts)
|
||||||
- **Exponential Backoff with Jitter**: Implements intelligent retry delays to avoid overwhelming services
|
- **Exponential Backoff with Jitter**: Implements intelligent retry delays to avoid overwhelming services
|
||||||
- **Detailed Error Logging**: Captures comprehensive error context including stack traces, request/response data, and session information
|
- **Detailed Error Logging**: Captures comprehensive error context including stack traces, request/response data, and session information
|
||||||
- **Error Persistence**: Saves detailed error logs to `logs/errors/` for post-mortem analysis
|
- **Error Persistence**: Saves detailed error logs to `.g3/errors/` for post-mortem analysis
|
||||||
- **Graceful Degradation**: Non-recoverable errors are logged with full context before terminating
|
- **Graceful Degradation**: Non-recoverable errors are logged with full context before terminating
|
||||||
|
|
||||||
### Tool Call Duplicate Detection
|
### Tool Call Duplicate Detection
|
||||||
@@ -316,12 +316,12 @@ G3 can interact with your computer's GUI for automation tasks:
|
|||||||
|
|
||||||
## Session Logs
|
## Session Logs
|
||||||
|
|
||||||
G3 automatically saves session logs for each interaction in the `logs/` directory. These logs contain:
|
G3 automatically saves session logs for each interaction in the `.g3/sessions/` directory. These logs contain:
|
||||||
- Complete conversation history
|
- Complete conversation history
|
||||||
- Token usage statistics
|
- Token usage statistics
|
||||||
- Timestamps and session status
|
- Timestamps and session status
|
||||||
|
|
||||||
The `logs/` directory is created automatically on first use and is excluded from version control.
|
The `.g3/` directory is created automatically on first use and is excluded from version control.
|
||||||
|
|
||||||
## Documentation Map
|
## Documentation Map
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ pub struct Cli {
|
|||||||
#[arg(long, value_name = "MODEL")]
|
#[arg(long, value_name = "MODEL")]
|
||||||
pub model: Option<String>,
|
pub model: Option<String>,
|
||||||
|
|
||||||
/// Disable log file creation (no logs/ directory or session logs)
|
/// Disable session log file creation (no .g3/sessions/ or error logs)
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub quiet: bool,
|
pub quiet: bool,
|
||||||
|
|
||||||
|
|||||||
@@ -54,12 +54,7 @@ pub fn extract_from_logs(
|
|||||||
|
|
||||||
/// Resolve the log file path, trying new path first then falling back to old.
|
/// Resolve the log file path, trying new path first then falling back to old.
|
||||||
fn resolve_log_path(session_id: &str) -> std::path::PathBuf {
|
fn resolve_log_path(session_id: &str) -> std::path::PathBuf {
|
||||||
let new_path = g3_core::get_session_file(session_id);
|
g3_core::get_session_file(session_id)
|
||||||
if new_path.exists() {
|
|
||||||
new_path
|
|
||||||
} else {
|
|
||||||
Path::new("logs").join(format!("g3_session_{}.json", session_id))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract feedback from a session log file.
|
/// Extract feedback from a session log file.
|
||||||
|
|||||||
@@ -4,15 +4,17 @@ use tempfile::TempDir;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_coach_feedback_with_timing_message() {
|
fn test_extract_coach_feedback_with_timing_message() {
|
||||||
// Create a temporary directory for logs
|
// Create a temporary directory for session logs
|
||||||
let temp_dir = TempDir::new().unwrap();
|
let temp_dir = TempDir::new().unwrap();
|
||||||
let logs_dir = temp_dir.path().join("logs");
|
let sessions_dir = temp_dir.path().join(".g3").join("sessions");
|
||||||
fs::create_dir(&logs_dir).unwrap();
|
fs::create_dir_all(&sessions_dir).unwrap();
|
||||||
|
|
||||||
// Create a mock session log with the problematic conversation history
|
// Create a mock session log with the problematic conversation history
|
||||||
// where timing message appears after the tool result
|
// where timing message appears after the tool result
|
||||||
let session_id = "test_session_123";
|
let session_id = "test_session_123";
|
||||||
let log_file_path = logs_dir.join(format!("g3_session_{}.json", session_id));
|
let session_dir = sessions_dir.join(session_id);
|
||||||
|
fs::create_dir_all(&session_dir).unwrap();
|
||||||
|
let log_file_path = session_dir.join("session.json");
|
||||||
|
|
||||||
let log_content = json!({
|
let log_content = json!({
|
||||||
"session_id": session_id,
|
"session_id": session_id,
|
||||||
@@ -93,11 +95,13 @@ fn test_extract_coach_feedback_with_timing_message() {
|
|||||||
fn test_extract_only_final_output_tool_results() {
|
fn test_extract_only_final_output_tool_results() {
|
||||||
// Test that we only extract tool results from final_output, not from other tools
|
// Test that we only extract tool results from final_output, not from other tools
|
||||||
let temp_dir = TempDir::new().unwrap();
|
let temp_dir = TempDir::new().unwrap();
|
||||||
let logs_dir = temp_dir.path().join("logs");
|
let sessions_dir = temp_dir.path().join(".g3").join("sessions");
|
||||||
fs::create_dir(&logs_dir).unwrap();
|
fs::create_dir_all(&sessions_dir).unwrap();
|
||||||
|
|
||||||
let session_id = "test_session_final_output_only";
|
let session_id = "test_session_final_output_only";
|
||||||
let log_file_path = logs_dir.join(format!("g3_session_{}.json", session_id));
|
let session_dir = sessions_dir.join(session_id);
|
||||||
|
fs::create_dir_all(&session_dir).unwrap();
|
||||||
|
let log_file_path = session_dir.join("session.json");
|
||||||
|
|
||||||
let log_content = json!({
|
let log_content = json!({
|
||||||
"session_id": session_id,
|
"session_id": session_id,
|
||||||
@@ -184,14 +188,16 @@ fn test_extract_only_final_output_tool_results() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_coach_feedback_without_timing_message() {
|
fn test_extract_coach_feedback_without_timing_message() {
|
||||||
// Create a temporary directory for logs
|
// Create a temporary directory for session logs
|
||||||
let temp_dir = TempDir::new().unwrap();
|
let temp_dir = TempDir::new().unwrap();
|
||||||
let logs_dir = temp_dir.path().join("logs");
|
let sessions_dir = temp_dir.path().join(".g3").join("sessions");
|
||||||
fs::create_dir(&logs_dir).unwrap();
|
fs::create_dir_all(&sessions_dir).unwrap();
|
||||||
|
|
||||||
// Test the case where there's no timing message (backward compatibility)
|
// Test the case where there's no timing message (backward compatibility)
|
||||||
let session_id = "test_session_456";
|
let session_id = "test_session_456";
|
||||||
let log_file_path = logs_dir.join(format!("g3_session_{}.json", session_id));
|
let session_dir = sessions_dir.join(session_id);
|
||||||
|
fs::create_dir_all(&session_dir).unwrap();
|
||||||
|
let log_file_path = session_dir.join("session.json");
|
||||||
|
|
||||||
let log_content = json!({
|
let log_content = json!({
|
||||||
"session_id": session_id,
|
"session_id": session_id,
|
||||||
@@ -256,11 +262,13 @@ fn test_extract_coach_feedback_without_timing_message() {
|
|||||||
fn test_extract_coach_feedback_with_multiple_tool_results() {
|
fn test_extract_coach_feedback_with_multiple_tool_results() {
|
||||||
// Test that we get the LAST tool result when there are multiple
|
// Test that we get the LAST tool result when there are multiple
|
||||||
let temp_dir = TempDir::new().unwrap();
|
let temp_dir = TempDir::new().unwrap();
|
||||||
let logs_dir = temp_dir.path().join("logs");
|
let sessions_dir = temp_dir.path().join(".g3").join("sessions");
|
||||||
fs::create_dir(&logs_dir).unwrap();
|
fs::create_dir_all(&sessions_dir).unwrap();
|
||||||
|
|
||||||
let session_id = "test_session_789";
|
let session_id = "test_session_789";
|
||||||
let log_file_path = logs_dir.join(format!("g3_session_{}.json", session_id));
|
let session_dir = sessions_dir.join(session_id);
|
||||||
|
fs::create_dir_all(&session_dir).unwrap();
|
||||||
|
let log_file_path = session_dir.join("session.json");
|
||||||
|
|
||||||
let log_content = json!({
|
let log_content = json!({
|
||||||
"session_id": session_id,
|
"session_id": session_id,
|
||||||
|
|||||||
13
crates/g3-core/logs/errors/error_1768079503_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768079503_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768081876_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768081876_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768083039_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768083039_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768085339_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768085339_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768088342_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768088342_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768088453_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768088453_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768128158_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768128158_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768128264_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768128264_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768128473_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768128473_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768128656_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768128656_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768129035_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768129035_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768129323_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768129323_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768129339_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768129339_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768129356_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768129356_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768130842_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768130842_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768131516_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768131516_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768131530_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768131530_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768131543_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768131543_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768131797_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768131797_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768131982_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768131982_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132117_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132117_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132232_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132232_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132268_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132268_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132404_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132404_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132454_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132454_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132540_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132540_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768132553_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768132553_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768133139_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768133139_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768141273_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768141273_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768141548_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768141548_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768143784_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768143784_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768143829_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768143829_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768143855_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768143855_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768143909_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768143909_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768144572_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768144572_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768145313_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768145313_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768145517_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768145517_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768146713_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768146713_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768173587_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768173587_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768175252_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768175252_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768175509_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768175509_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768184765_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768184765_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768184965_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768184965_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768193369_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768193369_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768199392_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768199392_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768200370_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768200370_unknown.json
Normal file
File diff suppressed because one or more lines are too long
13
crates/g3-core/logs/errors/error_1768209302_unknown.json
Normal file
13
crates/g3-core/logs/errors/error_1768209302_unknown.json
Normal file
File diff suppressed because one or more lines are too long
@@ -129,8 +129,7 @@ impl ErrorContext {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let base_logs_dir = crate::logs_dir();
|
let logs_dir = crate::paths::get_errors_dir();
|
||||||
let logs_dir = base_logs_dir.join("errors");
|
|
||||||
if !logs_dir.exists() {
|
if !logs_dir.exists() {
|
||||||
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
||||||
error!("Failed to create error logs directory: {}", e);
|
error!("Failed to create error logs directory: {}", e);
|
||||||
|
|||||||
@@ -8,10 +8,9 @@
|
|||||||
//!
|
//!
|
||||||
//! Used by both autonomous mode (g3-cli) and planning mode (g3-planner).
|
//! Used by both autonomous mode (g3-cli) and planning mode (g3-planner).
|
||||||
|
|
||||||
use crate::{logs_dir, Agent, TaskResult};
|
use crate::{Agent, TaskResult};
|
||||||
use crate::ui_writer::UiWriter;
|
use crate::ui_writer::UiWriter;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::path::PathBuf;
|
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
|
|
||||||
/// Result of feedback extraction with source information
|
/// Result of feedback extraction with source information
|
||||||
@@ -60,8 +59,6 @@ impl ExtractedFeedback {
|
|||||||
pub struct FeedbackExtractionConfig {
|
pub struct FeedbackExtractionConfig {
|
||||||
/// Whether to print debug information
|
/// Whether to print debug information
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
/// Custom logs directory (overrides default)
|
|
||||||
pub logs_dir: Option<PathBuf>,
|
|
||||||
/// Default feedback message if extraction fails
|
/// Default feedback message if extraction fails
|
||||||
pub default_feedback: String,
|
pub default_feedback: String,
|
||||||
}
|
}
|
||||||
@@ -70,7 +67,6 @@ impl Default for FeedbackExtractionConfig {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
verbose: false,
|
verbose: false,
|
||||||
logs_dir: None,
|
|
||||||
default_feedback: "The implementation needs review. Please ensure all requirements are met and the code compiles without errors.".to_string(),
|
default_feedback: "The implementation needs review. Please ensure all requirements are met and the code compiles without errors.".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,17 +145,10 @@ fn try_extract_last_assistant_message(
|
|||||||
session_id: &str,
|
session_id: &str,
|
||||||
config: &FeedbackExtractionConfig,
|
config: &FeedbackExtractionConfig,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
// Try new .g3/sessions/<session_id>/session.json path first
|
let _ = config; // config no longer used but kept for API compatibility
|
||||||
let log_file_path = crate::get_session_file(session_id);
|
|
||||||
|
|
||||||
// Fall back to old logs/ path if new path doesn't exist
|
// Use .g3/sessions/<session_id>/session.json path
|
||||||
let log_file_path = if log_file_path.exists() {
|
let log_file_path = crate::get_session_file(session_id);
|
||||||
log_file_path
|
|
||||||
} else {
|
|
||||||
let logs_path = config.logs_dir.clone().unwrap_or_else(logs_dir);
|
|
||||||
logs_path.join(format!("g3_session_{}.json", session_id))
|
|
||||||
};
|
|
||||||
|
|
||||||
if !log_file_path.exists() {
|
if !log_file_path.exists() {
|
||||||
debug!("Session log file not found: {:?}", log_file_path);
|
debug!("Session log file not found: {:?}", log_file_path);
|
||||||
return None;
|
return None;
|
||||||
@@ -214,17 +203,10 @@ fn try_extract_from_session_log(
|
|||||||
session_id: &str,
|
session_id: &str,
|
||||||
config: &FeedbackExtractionConfig,
|
config: &FeedbackExtractionConfig,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
// Try new .g3/sessions/<session_id>/session.json path first
|
let _ = config; // config no longer used but kept for API compatibility
|
||||||
let log_file_path = crate::get_session_file(session_id);
|
|
||||||
|
|
||||||
// Fall back to old logs/ path if new path doesn't exist
|
// Use .g3/sessions/<session_id>/session.json path
|
||||||
let log_file_path = if log_file_path.exists() {
|
let log_file_path = crate::get_session_file(session_id);
|
||||||
log_file_path
|
|
||||||
} else {
|
|
||||||
let logs_path = config.logs_dir.clone().unwrap_or_else(logs_dir);
|
|
||||||
logs_path.join(format!("g3_session_{}.json", session_id))
|
|
||||||
};
|
|
||||||
|
|
||||||
if !log_file_path.exists() {
|
if !log_file_path.exists() {
|
||||||
debug!("Session log file not found: {:?}", log_file_path);
|
debug!("Session log file not found: {:?}", log_file_path);
|
||||||
return None;
|
return None;
|
||||||
@@ -358,17 +340,10 @@ fn try_extract_from_conversation_history(
|
|||||||
session_id: &str,
|
session_id: &str,
|
||||||
config: &FeedbackExtractionConfig,
|
config: &FeedbackExtractionConfig,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
// Try new .g3/sessions/<session_id>/session.json path first
|
let _ = config; // config no longer used but kept for API compatibility
|
||||||
let log_file_path = crate::get_session_file(session_id);
|
|
||||||
|
|
||||||
// Fall back to old logs/ path if new path doesn't exist
|
// Use .g3/sessions/<session_id>/session.json path
|
||||||
let log_file_path = if log_file_path.exists() {
|
let log_file_path = crate::get_session_file(session_id);
|
||||||
log_file_path
|
|
||||||
} else {
|
|
||||||
let logs_path = config.logs_dir.clone().unwrap_or_else(logs_dir);
|
|
||||||
logs_path.join(format!("g3_session_{}.json", session_id))
|
|
||||||
};
|
|
||||||
|
|
||||||
if !log_file_path.exists() {
|
if !log_file_path.exists() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -652,7 +627,6 @@ mod tests {
|
|||||||
fn test_feedback_extraction_config_default() {
|
fn test_feedback_extraction_config_default() {
|
||||||
let config = FeedbackExtractionConfig::default();
|
let config = FeedbackExtractionConfig::default();
|
||||||
assert!(!config.verbose);
|
assert!(!config.verbose);
|
||||||
assert!(config.logs_dir.is_none());
|
|
||||||
assert!(config.default_feedback.contains("review"));
|
assert!(config.default_feedback.contains("review"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,11 @@ use std::time::{Duration, Instant};
|
|||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
// Re-export path utilities for backward compatibility
|
// Re-export path utilities
|
||||||
pub use paths::{
|
pub use paths::{
|
||||||
G3_WORKSPACE_PATH_ENV, ensure_session_dir, get_context_summary_file, get_g3_dir, get_logs_dir,
|
G3_WORKSPACE_PATH_ENV, ensure_session_dir, get_context_summary_file, get_g3_dir,
|
||||||
get_session_file, get_session_logs_dir, get_session_todo_path, get_thinned_dir, logs_dir,
|
get_session_file, get_session_logs_dir, get_session_todo_path, get_thinned_dir,
|
||||||
|
get_errors_dir, get_background_processes_dir, get_discovery_dir,
|
||||||
};
|
};
|
||||||
use paths::get_todo_path;
|
use paths::get_todo_path;
|
||||||
|
|
||||||
@@ -291,7 +292,7 @@ impl<W: UiWriter> Agent<W> {
|
|||||||
working_dir: None,
|
working_dir: None,
|
||||||
background_process_manager: std::sync::Arc::new(
|
background_process_manager: std::sync::Arc::new(
|
||||||
background_process::BackgroundProcessManager::new(
|
background_process::BackgroundProcessManager::new(
|
||||||
paths::get_logs_dir().join("background_processes")
|
paths::get_background_processes_dir()
|
||||||
)),
|
)),
|
||||||
pending_images: Vec::new(),
|
pending_images: Vec::new(),
|
||||||
is_agent_mode: false,
|
is_agent_mode: false,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! Path utilities for G3 session and workspace management.
|
//! Path utilities for G3 session and workspace management.
|
||||||
//!
|
//!
|
||||||
//! This module centralizes all path-related logic for:
|
//! This module centralizes all path-related logic for:
|
||||||
//! - TODO file location
|
//! - TODO file location
|
||||||
//! - Logs directory
|
//! - Error logs directory
|
||||||
//! - Session directories and files
|
//! - Session directories and files
|
||||||
//! - Thinned content storage
|
//! - Thinned content storage
|
||||||
|
|
||||||
@@ -33,22 +33,29 @@ pub fn get_session_todo_path(session_id: &str) -> PathBuf {
|
|||||||
get_session_logs_dir(session_id).join("todo.g3.md")
|
get_session_logs_dir(session_id).join("todo.g3.md")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the path to the logs directory.
|
/// Get the path to the errors directory.
|
||||||
///
|
///
|
||||||
/// Checks for G3_WORKSPACE_PATH environment variable first (used by planning mode),
|
/// Returns `.g3/errors/` in the workspace or current directory.
|
||||||
/// then falls back to "logs" in the current directory.
|
pub fn get_errors_dir() -> PathBuf {
|
||||||
pub fn get_logs_dir() -> PathBuf {
|
get_g3_dir().join("errors")
|
||||||
if let Ok(workspace_path) = std::env::var(G3_WORKSPACE_PATH_ENV) {
|
|
||||||
PathBuf::from(workspace_path).join("logs")
|
|
||||||
} else {
|
|
||||||
std::env::current_dir().unwrap_or_default().join("logs")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Public accessor for the logs directory path (for use by submodules).
|
/// Get the path to the background processes directory.
|
||||||
/// Alias for `get_logs_dir()` for backward compatibility.
|
///
|
||||||
pub fn logs_dir() -> PathBuf {
|
/// Returns `.g3/background_processes/` in the workspace or current directory.
|
||||||
get_logs_dir()
|
pub fn get_background_processes_dir() -> PathBuf {
|
||||||
|
get_g3_dir().join("background_processes")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the path to the discovery logs directory (for planner mode).
|
||||||
|
///
|
||||||
|
/// Returns `.g3/discovery/` in the workspace or current directory.
|
||||||
|
pub fn get_discovery_dir() -> PathBuf {
|
||||||
|
if let Ok(workspace_path) = std::env::var(G3_WORKSPACE_PATH_ENV) {
|
||||||
|
PathBuf::from(workspace_path).join(".g3").join("discovery")
|
||||||
|
} else {
|
||||||
|
get_g3_dir().join("discovery")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the base .g3 directory path.
|
/// Get the base .g3 directory path.
|
||||||
|
|||||||
@@ -127,18 +127,4 @@ impl Project {
|
|||||||
std::env::set_current_dir(&self.workspace_dir)?;
|
std::env::set_current_dir(&self.workspace_dir)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the logs directory for the project
|
|
||||||
pub fn logs_dir(&self) -> PathBuf {
|
|
||||||
self.workspace_dir.join("logs")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensure the logs directory exists
|
|
||||||
pub fn ensure_logs_dir(&self) -> Result<()> {
|
|
||||||
let logs_dir = self.logs_dir();
|
|
||||||
if !logs_dir.exists() {
|
|
||||||
std::fs::create_dir_all(&logs_dir)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
//! operations from the Agent, keeping the Agent as a thin orchestrator.
|
//! operations from the Agent, keeping the Agent as a thin orchestrator.
|
||||||
|
|
||||||
use crate::context_window::ContextWindow;
|
use crate::context_window::ContextWindow;
|
||||||
use crate::paths::{ensure_session_dir, get_context_summary_file, get_g3_dir, get_logs_dir, get_session_file};
|
use crate::paths::{ensure_session_dir, get_context_summary_file, get_g3_dir, get_session_file};
|
||||||
use g3_providers::MessageRole;
|
use g3_providers::MessageRole;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@@ -90,7 +90,7 @@ pub fn generate_session_id(description: &str, agent_name: Option<&str>) -> Strin
|
|||||||
/// Save the context window to a session file.
|
/// Save the context window to a session file.
|
||||||
///
|
///
|
||||||
/// If session_id is provided, saves to `.g3/sessions/<session_id>/session.json`.
|
/// If session_id is provided, saves to `.g3/sessions/<session_id>/session.json`.
|
||||||
/// Otherwise, falls back to `logs/g3_context_<timestamp>.json`.
|
/// Otherwise, saves to `.g3/sessions/anonymous_<timestamp>/session.json`.
|
||||||
pub fn save_context_window(
|
pub fn save_context_window(
|
||||||
session_id: Option<&str>,
|
session_id: Option<&str>,
|
||||||
context_window: &ContextWindow,
|
context_window: &ContextWindow,
|
||||||
@@ -110,13 +110,13 @@ pub fn save_context_window(
|
|||||||
}
|
}
|
||||||
get_session_file(id)
|
get_session_file(id)
|
||||||
} else {
|
} else {
|
||||||
// Fallback to old logs/ directory for sessions without ID
|
// Create anonymous session for sessions without ID
|
||||||
let logs_dir = get_logs_dir();
|
let anonymous_id = format!("anonymous_{}", timestamp);
|
||||||
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
if let Err(e) = ensure_session_dir(&anonymous_id) {
|
||||||
error!("Failed to create logs directory: {}", e);
|
error!("Failed to create anonymous session directory: {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logs_dir.join(format!("g3_context_{}.json", timestamp))
|
get_session_file(&anonymous_id)
|
||||||
};
|
};
|
||||||
|
|
||||||
let context_data = serde_json::json!({
|
let context_data = serde_json::json!({
|
||||||
@@ -252,8 +252,8 @@ pub fn log_error_to_session(
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.as_secs();
|
.as_secs();
|
||||||
|
|
||||||
let logs_dir = get_logs_dir();
|
// Use the new .g3/sessions/<session_id>/session.json path
|
||||||
let filename = logs_dir.join(format!("g3_session_{}.json", session_id));
|
let filename = get_session_file(session_id);
|
||||||
|
|
||||||
// Read existing session log
|
// Read existing session log
|
||||||
let mut session_data: serde_json::Value = if filename.exists() {
|
let mut session_data: serde_json::Value = if filename.exists() {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ echo "Done!"
|
|||||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_dir = test_dir.join("logs");
|
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||||
let manager = BackgroundProcessManager::new(log_dir);
|
let manager = BackgroundProcessManager::new(log_dir);
|
||||||
|
|
||||||
println!("\n=== Background Process Demo ===");
|
println!("\n=== Background Process Demo ===");
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ done
|
|||||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_dir = test_dir.join("logs");
|
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||||
let manager = BackgroundProcessManager::new(log_dir);
|
let manager = BackgroundProcessManager::new(log_dir);
|
||||||
|
|
||||||
// Start the process
|
// Start the process
|
||||||
@@ -116,7 +116,7 @@ sleep 30
|
|||||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_dir = test_dir.join("logs");
|
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||||
let manager = BackgroundProcessManager::new(log_dir);
|
let manager = BackgroundProcessManager::new(log_dir);
|
||||||
|
|
||||||
// Start a process
|
// Start a process
|
||||||
@@ -151,7 +151,7 @@ sleep 30
|
|||||||
let _ = fs::remove_dir_all(&test_dir);
|
let _ = fs::remove_dir_all(&test_dir);
|
||||||
fs::create_dir_all(&test_dir).unwrap();
|
fs::create_dir_all(&test_dir).unwrap();
|
||||||
|
|
||||||
let log_dir = test_dir.join("logs");
|
let log_dir = test_dir.join(".g3").join("background_processes");
|
||||||
let manager = BackgroundProcessManager::new(log_dir);
|
let manager = BackgroundProcessManager::new(log_dir);
|
||||||
|
|
||||||
// Getting a process that doesn't exist should return None
|
// Getting a process that doesn't exist should return None
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ fn test_save_and_load_continuation() {
|
|||||||
"save_load_test".to_string(),
|
"save_load_test".to_string(),
|
||||||
None,
|
None,
|
||||||
Some("Test summary content".to_string()),
|
Some("Test summary content".to_string()),
|
||||||
"/logs/g3_session_save_load_test.json".to_string(),
|
"/.g3/sessions/save_load_test/session.json".to_string(),
|
||||||
35.5,
|
35.5,
|
||||||
Some("- [ ] Pending task".to_string()),
|
Some("- [ ] Pending task".to_string()),
|
||||||
temp_dir.path().to_string_lossy().to_string(),
|
temp_dir.path().to_string_lossy().to_string(),
|
||||||
@@ -321,9 +321,9 @@ fn test_has_valid_continuation_with_existing_session_log() {
|
|||||||
let (temp_dir, original_dir) = setup_test_env();
|
let (temp_dir, original_dir) = setup_test_env();
|
||||||
|
|
||||||
// Create a fake session log file
|
// Create a fake session log file
|
||||||
let logs_dir = temp_dir.path().join("logs");
|
let session_dir = temp_dir.path().join(".g3").join("sessions").join("valid_test");
|
||||||
fs::create_dir_all(&logs_dir).expect("Failed to create logs dir");
|
fs::create_dir_all(&session_dir).expect("Failed to create session dir");
|
||||||
let session_log_path = logs_dir.join("g3_session_valid_test.json");
|
let session_log_path = session_dir.join("session.json");
|
||||||
fs::write(&session_log_path, "{}").expect("Failed to write session log");
|
fs::write(&session_log_path, "{}").expect("Failed to write session log");
|
||||||
|
|
||||||
// Create a continuation pointing to the existing session log
|
// Create a continuation pointing to the existing session log
|
||||||
|
|||||||
@@ -735,8 +735,8 @@ async fn run_segment(
|
|||||||
segment_status.errors += 1;
|
segment_status.errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to extract metrics from session log if available
|
// Try to extract metrics from session log if available (check .g3/sessions/)
|
||||||
let log_dir = segment_dir.join("logs");
|
let log_dir = segment_dir.join(".g3").join("sessions");
|
||||||
if log_dir.exists() {
|
if log_dir.exists() {
|
||||||
if let Ok(entries) = std::fs::read_dir(&log_dir) {
|
if let Ok(entries) = std::fs::read_dir(&log_dir) {
|
||||||
for entry in entries.flatten() {
|
for entry in entries.flatten() {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ pub async fn get_initial_discovery_messages(
|
|||||||
// Step 1: Run explore_codebase to get the codebase report
|
// Step 1: Run explore_codebase to get the codebase report
|
||||||
let codebase_report = explore_codebase(codebase_path);
|
let codebase_report = explore_codebase(codebase_path);
|
||||||
|
|
||||||
// Write the codebase report to logs directory
|
// Write the codebase report to discovery directory
|
||||||
write_code_report(&codebase_report)?;
|
write_code_report(&codebase_report)?;
|
||||||
|
|
||||||
// Step 2: Build the prompt with the codebase report appended
|
// Step 2: Build the prompt with the codebase report appended
|
||||||
@@ -112,7 +112,7 @@ pub async fn get_initial_discovery_messages(
|
|||||||
shell_commands.len()
|
shell_commands.len()
|
||||||
));
|
));
|
||||||
|
|
||||||
// Write the discovery commands to logs directory
|
// Write the discovery commands to discovery directory
|
||||||
write_discovery_commands(&shell_commands)?;
|
write_discovery_commands(&shell_commands)?;
|
||||||
|
|
||||||
// Step 6: Format as tool messages
|
// Step 6: Format as tool messages
|
||||||
@@ -194,21 +194,21 @@ pub fn extract_summary(response: &str) -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the codebase report to logs directory
|
/// Write the codebase report to discovery directory
|
||||||
fn write_code_report(report: &str) -> Result<()> {
|
fn write_code_report(report: &str) -> Result<()> {
|
||||||
// Get logs directory from workspace path or current dir
|
// Get discovery directory from workspace path or current dir
|
||||||
let logs_dir = if let Ok(workspace_path) = std::env::var("G3_WORKSPACE_PATH") {
|
let discovery_dir = if let Ok(workspace_path) = std::env::var("G3_WORKSPACE_PATH") {
|
||||||
std::path::PathBuf::from(workspace_path).join("logs")
|
std::path::PathBuf::from(workspace_path).join(".g3").join("discovery")
|
||||||
} else {
|
} else {
|
||||||
std::env::current_dir().unwrap_or_default().join("logs")
|
std::env::current_dir().unwrap_or_default().join(".g3").join("discovery")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure logs directory exists
|
// Ensure discovery directory exists
|
||||||
fs::create_dir_all(&logs_dir)?;
|
fs::create_dir_all(&discovery_dir)?;
|
||||||
|
|
||||||
// Generate timestamp in same format as tool_calls log
|
// Generate timestamp in same format as tool_calls log
|
||||||
let timestamp = Local::now().format("%Y%m%d_%H%M%S").to_string();
|
let timestamp = Local::now().format("%Y%m%d_%H%M%S").to_string();
|
||||||
let filename = logs_dir.join(format!("code_report_{}.log", timestamp));
|
let filename = discovery_dir.join(format!("code_report_{}.log", timestamp));
|
||||||
|
|
||||||
// Write the report to file
|
// Write the report to file
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
@@ -223,21 +223,21 @@ fn write_code_report(report: &str) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the discovery commands to logs directory
|
/// Write the discovery commands to discovery directory
|
||||||
fn write_discovery_commands(commands: &[String]) -> Result<()> {
|
fn write_discovery_commands(commands: &[String]) -> Result<()> {
|
||||||
// Get logs directory from workspace path or current dir
|
// Get discovery directory from workspace path or current dir
|
||||||
let logs_dir = if let Ok(workspace_path) = std::env::var("G3_WORKSPACE_PATH") {
|
let discovery_dir = if let Ok(workspace_path) = std::env::var("G3_WORKSPACE_PATH") {
|
||||||
std::path::PathBuf::from(workspace_path).join("logs")
|
std::path::PathBuf::from(workspace_path).join(".g3").join("discovery")
|
||||||
} else {
|
} else {
|
||||||
std::env::current_dir().unwrap_or_default().join("logs")
|
std::env::current_dir().unwrap_or_default().join(".g3").join("discovery")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure logs directory exists
|
// Ensure discovery directory exists
|
||||||
fs::create_dir_all(&logs_dir)?;
|
fs::create_dir_all(&discovery_dir)?;
|
||||||
|
|
||||||
// Generate timestamp in same format as tool_calls log
|
// Generate timestamp in same format as tool_calls log
|
||||||
let timestamp = Local::now().format("%Y%m%d_%H%M%S").to_string();
|
let timestamp = Local::now().format("%Y%m%d_%H%M%S").to_string();
|
||||||
let filename = logs_dir.join(format!("discovery_commands_{}.log", timestamp));
|
let filename = discovery_dir.join(format!("discovery_commands_{}.log", timestamp));
|
||||||
|
|
||||||
// Write the commands to file
|
// Write the commands to file
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
|
|||||||
@@ -324,15 +324,13 @@ pub async fn call_refinement_llm_with_tools(
|
|||||||
let ui_writer = PlannerUiWriter::new();
|
let ui_writer = PlannerUiWriter::new();
|
||||||
|
|
||||||
// CRITICAL FIX: Use the actual workspace directory, NOT codepath!
|
// CRITICAL FIX: Use the actual workspace directory, NOT codepath!
|
||||||
// The workspace is where logs should be written (e.g., /tmp/g3_test_workspace)
|
// The workspace is where session data should be written (e.g., /tmp/g3_test_workspace)
|
||||||
// The codepath is where the source code lives (e.g., ~/RustroverProjects/g3)
|
// The codepath is where the source code lives (e.g., ~/RustroverProjects/g3)
|
||||||
// Previous bug: was using codepath as workspace, causing logs to go to wrong location
|
|
||||||
let workspace_path = std::path::PathBuf::from(workspace);
|
let workspace_path = std::path::PathBuf::from(workspace);
|
||||||
let project = Project::new(workspace_path.clone());
|
let project = Project::new(workspace_path.clone());
|
||||||
project.ensure_workspace_exists()?;
|
project.ensure_workspace_exists()?;
|
||||||
project.enter_workspace()?;
|
project.enter_workspace()?;
|
||||||
|
|
||||||
project.ensure_logs_dir()?;
|
|
||||||
// Create agent - not autonomous mode, just regular agent with tools
|
// Create agent - not autonomous mode, just regular agent with tools
|
||||||
let mut agent = Agent::new_with_readme_and_quiet(
|
let mut agent = Agent::new_with_readme_and_quiet(
|
||||||
planner_config,
|
planner_config,
|
||||||
|
|||||||
@@ -777,13 +777,13 @@ pub async fn run_planning_mode(
|
|||||||
// Set G3_WORKSPACE_PATH environment variable EARLY for all logging
|
// Set G3_WORKSPACE_PATH environment variable EARLY for all logging
|
||||||
std::env::set_var("G3_WORKSPACE_PATH", workspace_dir.display().to_string());
|
std::env::set_var("G3_WORKSPACE_PATH", workspace_dir.display().to_string());
|
||||||
|
|
||||||
// Create logs directory and verify it exists
|
// Create .g3 directory and verify it exists
|
||||||
let logs_dir = workspace_dir.join("logs");
|
let g3_dir = workspace_dir.join(".g3");
|
||||||
if !logs_dir.exists() {
|
if !g3_dir.exists() {
|
||||||
fs::create_dir_all(&logs_dir)
|
fs::create_dir_all(&g3_dir)
|
||||||
.context("Failed to create logs directory")?;
|
.context("Failed to create .g3 directory")?;
|
||||||
}
|
}
|
||||||
print_msg(&format!("📁 Logs directory: {}", logs_dir.display()));
|
print_msg(&format!("📁 G3 directory: {}", g3_dir.display()));
|
||||||
|
|
||||||
// Create the LLM provider for planning
|
// Create the LLM provider for planning
|
||||||
print_msg("🔧 Initializing planner provider...");
|
print_msg("🔧 Initializing planner provider...");
|
||||||
|
|||||||
@@ -6,22 +6,22 @@ use std::path::Path;
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_log_files_created() {
|
fn test_log_files_created() {
|
||||||
// This test verifies that the logging functions work correctly
|
// This test verifies that the logging functions work correctly
|
||||||
// by checking that files can be created in the logs directory
|
// by checking that files can be created in the discovery directory
|
||||||
|
|
||||||
// Clean up any existing test logs
|
// Clean up any existing test discovery dir
|
||||||
let _ = fs::remove_dir_all("logs");
|
let _ = fs::remove_dir_all(".g3/discovery");
|
||||||
|
|
||||||
// Create logs directory
|
// Create discovery directory
|
||||||
fs::create_dir_all("logs").expect("Failed to create logs directory");
|
fs::create_dir_all(".g3/discovery").expect("Failed to create discovery directory");
|
||||||
|
|
||||||
// Verify directory exists
|
// Verify directory exists
|
||||||
assert!(Path::new("logs").exists());
|
assert!(Path::new(".g3/discovery").exists());
|
||||||
assert!(Path::new("logs").is_dir());
|
assert!(Path::new(".g3/discovery").is_dir());
|
||||||
|
|
||||||
// Test writing a code report
|
// Test writing a code report
|
||||||
let test_report = "Test codebase report\nLine 2\nLine 3";
|
let test_report = "Test codebase report\nLine 2\nLine 3";
|
||||||
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
|
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
|
||||||
let report_filename = format!("logs/code_report_{}.log", timestamp);
|
let report_filename = format!(".g3/discovery/code_report_{}.log", timestamp);
|
||||||
|
|
||||||
fs::write(&report_filename, test_report).expect("Failed to write code report");
|
fs::write(&report_filename, test_report).expect("Failed to write code report");
|
||||||
assert!(Path::new(&report_filename).exists());
|
assert!(Path::new(&report_filename).exists());
|
||||||
@@ -30,7 +30,7 @@ fn test_log_files_created() {
|
|||||||
assert_eq!(content, test_report);
|
assert_eq!(content, test_report);
|
||||||
|
|
||||||
// Test writing discovery commands
|
// Test writing discovery commands
|
||||||
let commands_filename = format!("logs/discovery_commands_{}.log", timestamp);
|
let commands_filename = format!(".g3/discovery/discovery_commands_{}.log", timestamp);
|
||||||
let test_commands =
|
let test_commands =
|
||||||
"# Discovery Commands\n# Generated by g3-planner\n\nls -la\ncat README.md\n";
|
"# Discovery Commands\n# Generated by g3-planner\n\nls -la\ncat README.md\n";
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ fn test_extracted_feedback_approval_detection() {
|
|||||||
fn test_feedback_extraction_config_default() {
|
fn test_feedback_extraction_config_default() {
|
||||||
let config = FeedbackExtractionConfig::default();
|
let config = FeedbackExtractionConfig::default();
|
||||||
assert!(!config.verbose);
|
assert!(!config.verbose);
|
||||||
assert!(config.logs_dir.is_none());
|
|
||||||
assert!(config.default_feedback.contains("review"));
|
assert!(config.default_feedback.contains("review"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,14 +89,9 @@ fn test_feedback_extraction_config_default() {
|
|||||||
fn test_feedback_extraction_config_custom() {
|
fn test_feedback_extraction_config_custom() {
|
||||||
let config = FeedbackExtractionConfig {
|
let config = FeedbackExtractionConfig {
|
||||||
verbose: true,
|
verbose: true,
|
||||||
logs_dir: Some(std::path::PathBuf::from("/tmp/test_logs")),
|
|
||||||
default_feedback: "Custom fallback message for testing".to_string(),
|
default_feedback: "Custom fallback message for testing".to_string(),
|
||||||
};
|
};
|
||||||
assert!(config.verbose);
|
assert!(config.verbose);
|
||||||
assert_eq!(
|
|
||||||
config.logs_dir,
|
|
||||||
Some(std::path::PathBuf::from("/tmp/test_logs"))
|
|
||||||
);
|
|
||||||
assert!(config.default_feedback.contains("Custom fallback"));
|
assert!(config.default_feedback.contains("Custom fallback"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user