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:
@@ -129,8 +129,7 @@ impl ErrorContext {
|
||||
return;
|
||||
}
|
||||
|
||||
let base_logs_dir = crate::logs_dir();
|
||||
let logs_dir = base_logs_dir.join("errors");
|
||||
let logs_dir = crate::paths::get_errors_dir();
|
||||
if !logs_dir.exists() {
|
||||
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
||||
error!("Failed to create error logs directory: {}", e);
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
//!
|
||||
//! 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 serde_json::Value;
|
||||
use std::path::PathBuf;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
/// Result of feedback extraction with source information
|
||||
@@ -60,8 +59,6 @@ impl ExtractedFeedback {
|
||||
pub struct FeedbackExtractionConfig {
|
||||
/// Whether to print debug information
|
||||
pub verbose: bool,
|
||||
/// Custom logs directory (overrides default)
|
||||
pub logs_dir: Option<PathBuf>,
|
||||
/// Default feedback message if extraction fails
|
||||
pub default_feedback: String,
|
||||
}
|
||||
@@ -70,7 +67,6 @@ impl Default for FeedbackExtractionConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
@@ -149,17 +145,10 @@ fn try_extract_last_assistant_message(
|
||||
session_id: &str,
|
||||
config: &FeedbackExtractionConfig,
|
||||
) -> Option<String> {
|
||||
// Try new .g3/sessions/<session_id>/session.json path first
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
let _ = config; // config no longer used but kept for API compatibility
|
||||
|
||||
// Fall back to old logs/ path if new path doesn't exist
|
||||
let log_file_path = if log_file_path.exists() {
|
||||
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))
|
||||
};
|
||||
|
||||
// Use .g3/sessions/<session_id>/session.json path
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
if !log_file_path.exists() {
|
||||
debug!("Session log file not found: {:?}", log_file_path);
|
||||
return None;
|
||||
@@ -214,17 +203,10 @@ fn try_extract_from_session_log(
|
||||
session_id: &str,
|
||||
config: &FeedbackExtractionConfig,
|
||||
) -> Option<String> {
|
||||
// Try new .g3/sessions/<session_id>/session.json path first
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
let _ = config; // config no longer used but kept for API compatibility
|
||||
|
||||
// Fall back to old logs/ path if new path doesn't exist
|
||||
let log_file_path = if log_file_path.exists() {
|
||||
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))
|
||||
};
|
||||
|
||||
// Use .g3/sessions/<session_id>/session.json path
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
if !log_file_path.exists() {
|
||||
debug!("Session log file not found: {:?}", log_file_path);
|
||||
return None;
|
||||
@@ -358,17 +340,10 @@ fn try_extract_from_conversation_history(
|
||||
session_id: &str,
|
||||
config: &FeedbackExtractionConfig,
|
||||
) -> Option<String> {
|
||||
// Try new .g3/sessions/<session_id>/session.json path first
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
let _ = config; // config no longer used but kept for API compatibility
|
||||
|
||||
// Fall back to old logs/ path if new path doesn't exist
|
||||
let log_file_path = if log_file_path.exists() {
|
||||
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))
|
||||
};
|
||||
|
||||
// Use .g3/sessions/<session_id>/session.json path
|
||||
let log_file_path = crate::get_session_file(session_id);
|
||||
if !log_file_path.exists() {
|
||||
return None;
|
||||
}
|
||||
@@ -652,7 +627,6 @@ mod tests {
|
||||
fn test_feedback_extraction_config_default() {
|
||||
let config = FeedbackExtractionConfig::default();
|
||||
assert!(!config.verbose);
|
||||
assert!(config.logs_dir.is_none());
|
||||
assert!(config.default_feedback.contains("review"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,11 @@ use std::time::{Duration, Instant};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{debug, error, warn};
|
||||
|
||||
// Re-export path utilities for backward compatibility
|
||||
// Re-export path utilities
|
||||
pub use paths::{
|
||||
G3_WORKSPACE_PATH_ENV, ensure_session_dir, get_context_summary_file, get_g3_dir, get_logs_dir,
|
||||
get_session_file, get_session_logs_dir, get_session_todo_path, get_thinned_dir, 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,
|
||||
get_errors_dir, get_background_processes_dir, get_discovery_dir,
|
||||
};
|
||||
use paths::get_todo_path;
|
||||
|
||||
@@ -291,7 +292,7 @@ impl<W: UiWriter> Agent<W> {
|
||||
working_dir: None,
|
||||
background_process_manager: std::sync::Arc::new(
|
||||
background_process::BackgroundProcessManager::new(
|
||||
paths::get_logs_dir().join("background_processes")
|
||||
paths::get_background_processes_dir()
|
||||
)),
|
||||
pending_images: Vec::new(),
|
||||
is_agent_mode: false,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! Path utilities for G3 session and workspace management.
|
||||
//!
|
||||
//! This module centralizes all path-related logic for:
|
||||
//! - TODO file location
|
||||
//! - Logs directory
|
||||
//! - TODO file location
|
||||
//! - Error logs directory
|
||||
//! - Session directories and files
|
||||
//! - 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 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),
|
||||
/// then falls back to "logs" in the current directory.
|
||||
pub fn get_logs_dir() -> PathBuf {
|
||||
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")
|
||||
}
|
||||
/// Returns `.g3/errors/` in the workspace or current directory.
|
||||
pub fn get_errors_dir() -> PathBuf {
|
||||
get_g3_dir().join("errors")
|
||||
}
|
||||
|
||||
/// Public accessor for the logs directory path (for use by submodules).
|
||||
/// Alias for `get_logs_dir()` for backward compatibility.
|
||||
pub fn logs_dir() -> PathBuf {
|
||||
get_logs_dir()
|
||||
/// Get the path to the background processes directory.
|
||||
///
|
||||
/// Returns `.g3/background_processes/` in the workspace or current directory.
|
||||
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.
|
||||
|
||||
@@ -127,18 +127,4 @@ impl Project {
|
||||
std::env::set_current_dir(&self.workspace_dir)?;
|
||||
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.
|
||||
|
||||
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 std::collections::hash_map::DefaultHasher;
|
||||
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.
|
||||
///
|
||||
/// 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(
|
||||
session_id: Option<&str>,
|
||||
context_window: &ContextWindow,
|
||||
@@ -110,13 +110,13 @@ pub fn save_context_window(
|
||||
}
|
||||
get_session_file(id)
|
||||
} else {
|
||||
// Fallback to old logs/ directory for sessions without ID
|
||||
let logs_dir = get_logs_dir();
|
||||
if let Err(e) = std::fs::create_dir_all(&logs_dir) {
|
||||
error!("Failed to create logs directory: {}", e);
|
||||
// Create anonymous session for sessions without ID
|
||||
let anonymous_id = format!("anonymous_{}", timestamp);
|
||||
if let Err(e) = ensure_session_dir(&anonymous_id) {
|
||||
error!("Failed to create anonymous session directory: {}", e);
|
||||
return;
|
||||
}
|
||||
logs_dir.join(format!("g3_context_{}.json", timestamp))
|
||||
get_session_file(&anonymous_id)
|
||||
};
|
||||
|
||||
let context_data = serde_json::json!({
|
||||
@@ -252,8 +252,8 @@ pub fn log_error_to_session(
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
|
||||
let logs_dir = get_logs_dir();
|
||||
let filename = logs_dir.join(format!("g3_session_{}.json", session_id));
|
||||
// Use the new .g3/sessions/<session_id>/session.json path
|
||||
let filename = get_session_file(session_id);
|
||||
|
||||
// Read existing session log
|
||||
let mut session_data: serde_json::Value = if filename.exists() {
|
||||
|
||||
Reference in New Issue
Block a user