winx-code-agent 0.2.309

High-performance Rust implementation of WCGW for LLM code agents
Documentation
use crate::errors::Result;
use std::fmt::Write as FmtWrite;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

const MAX_DEPTH: usize = 10;
const MAX_CONTEXT_FILES: usize = 160;
const MAX_RECENT_FILES: usize = 30;

const IMPORTANT_NAMES: &[&str] = &[
    "Cargo.toml",
    "README.md",
    "AGENTS.md",
    "package.json",
    "pnpm-workspace.yaml",
    "pyproject.toml",
    "go.mod",
    "Dockerfile",
    "docker-compose.yml",
    ".github/workflows/ci.yml",
];

const SKIP_DIRS: &[&str] =
    &[".git", "target", "node_modules", ".next", "dist", "build", ".venv", "__pycache__"];

#[derive(Debug, Clone)]
pub struct RepoContext {
    pub root: PathBuf,
    pub is_git_repo: bool,
    pub project_summary: String,
    pub recent_files: Vec<String>,
    pub important_files: Vec<String>,
    pub project_files: Vec<String>,
}

pub struct RepoContextAnalyzer;

impl RepoContextAnalyzer {
    pub fn analyze(path: &Path) -> Result<RepoContext> {
        let root = workspace_root(path);
        let is_git_repo = root.join(".git").exists();
        let mut project_files = collect_project_files(&root)?;
        project_files.sort_by_key(|path| (path_score(path), path.clone()));
        project_files.truncate(MAX_CONTEXT_FILES);

        let recent_files = if is_git_repo { recent_git_files(&root) } else { Vec::new() };
        let important_files = important_files(&project_files);
        let project_summary = project_summary(&root, is_git_repo, project_files.len());

        Ok(RepoContext {
            root,
            is_git_repo,
            project_summary,
            recent_files,
            important_files,
            project_files,
        })
    }
}

pub fn get_repo_context(path: &Path) -> Result<(String, Vec<String>)> {
    let context = RepoContextAnalyzer::analyze(path)?;
    let mut output = String::new();

    let _ = writeln!(output, "Project root: {}", context.root.display());
    let _ = writeln!(output, "Git repository: {}", if context.is_git_repo { "yes" } else { "no" });
    let _ = writeln!(output, "{}", context.project_summary);

    if !context.important_files.is_empty() {
        output.push_str("\nImportant files:\n");
        for file in &context.important_files {
            let _ = writeln!(output, "- {file}");
        }
    }

    if !context.recent_files.is_empty() {
        output.push_str("\nRecent git files:\n");
        for file in &context.recent_files {
            let _ = writeln!(output, "- {file}");
        }
    }

    output.push_str("\nWorkspace files:\n");
    for file in &context.project_files {
        let _ = writeln!(output, "- {file}");
    }

    Ok((output, context.project_files))
}

fn workspace_root(path: &Path) -> PathBuf {
    if path.is_file() {
        path.parent().unwrap_or(path).to_path_buf()
    } else {
        path.to_path_buf()
    }
}

fn collect_project_files(root: &Path) -> Result<Vec<String>> {
    let mut files = Vec::new();
    collect_files(root, root, 0, &mut files)?;
    Ok(files)
}

fn collect_files(root: &Path, current: &Path, depth: usize, files: &mut Vec<String>) -> Result<()> {
    if depth > MAX_DEPTH {
        return Ok(());
    }

    let mut entries = fs::read_dir(current)?.collect::<std::result::Result<Vec<_>, _>>()?;
    entries.sort_by_key(std::fs::DirEntry::path);

    for entry in entries {
        let path = entry.path();
        let name = entry.file_name();
        let name = name.to_string_lossy();
        if path.is_dir() {
            if !SKIP_DIRS.contains(&name.as_ref()) {
                collect_files(root, &path, depth + 1, files)?;
            }
        } else if path.is_file() {
            if let Ok(relative) = path.strip_prefix(root) {
                files.push(relative.to_string_lossy().to_string());
            }
        }
    }

    Ok(())
}

fn important_files(files: &[String]) -> Vec<String> {
    files.iter().filter(|file| IMPORTANT_NAMES.contains(&file.as_str())).cloned().collect()
}

fn recent_git_files(root: &Path) -> Vec<String> {
    let output = Command::new("git")
        .args(["-C"])
        .arg(root)
        .args(["log", "--name-only", "--pretty=format:", "-n", "50"])
        .output();

    let Ok(output) = output else {
        return Vec::new();
    };
    if !output.status.success() {
        return Vec::new();
    }

    let mut recent = Vec::new();
    for line in String::from_utf8_lossy(&output.stdout).lines().map(str::trim) {
        if !line.is_empty() && !recent.iter().any(|existing| existing == line) {
            recent.push(line.to_string());
        }
        if recent.len() >= MAX_RECENT_FILES {
            break;
        }
    }
    recent
}

fn project_summary(root: &Path, is_git_repo: bool, file_count: usize) -> String {
    let manifest = if root.join("Cargo.toml").exists() {
        "Rust/Cargo"
    } else if root.join("package.json").exists() {
        "Node.js"
    } else if root.join("pyproject.toml").exists() {
        "Python"
    } else {
        "generic"
    };
    format!("Detected {manifest} workspace with {file_count} indexed files; git={is_git_repo}.")
}

fn path_score(path: &str) -> usize {
    let important = usize::from(!IMPORTANT_NAMES.contains(&path));
    let depth = path.matches('/').count();
    let test_penalty = usize::from(path.contains("test") || path.contains("spec"));
    important * 10 + depth + test_penalty
}

#[cfg(test)]
mod tests {
    use super::get_repo_context;
    use crate::errors::Result;
    use tempfile::TempDir;

    #[test]
    fn builds_repo_context_from_files() -> Result<()> {
        let temp_dir = TempDir::new()?;
        std::fs::write(temp_dir.path().join("Cargo.toml"), "[package]\nname='x'\n")?;
        std::fs::create_dir(temp_dir.path().join("src"))?;
        std::fs::write(temp_dir.path().join("src/lib.rs"), "pub fn x() {}\n")?;

        let (context, files) = get_repo_context(temp_dir.path())?;
        assert!(context.contains("Cargo.toml"));
        assert!(files.iter().any(|file| file == "src/lib.rs"));
        Ok(())
    }
}