From 919435eb84f9a41a0637052a5dc1234b410714f8 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Mon, 20 Jul 2026 16:11:15 +0700 Subject: [PATCH] feat(tui): integrate rich context builder into agent turn process --- apps/infrastructure/src/utils.rs | 70 ++++++++++++++++++++++++++++++++ apps/interfaces/tui/src/turn.rs | 6 ++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/apps/infrastructure/src/utils.rs b/apps/infrastructure/src/utils.rs index e3922ae..5feff50 100644 --- a/apps/infrastructure/src/utils.rs +++ b/apps/infrastructure/src/utils.rs @@ -191,3 +191,73 @@ pub fn build_workspace_tree(root: &Path, max_files: usize) -> String { tree.trim_end().to_string() } + +// --------------------------------------------------------------------------- +// Rich Context Builder +// --------------------------------------------------------------------------- + +/// Gathers essential project context (OS, Time, Git, Tech Stack, Rules) into a string. +pub fn build_rich_context(root: &Path) -> String { + use std::process::Command; + let mut ctx = String::new(); + + // 1. Time and OS + let os = std::env::consts::OS; + let arch = std::env::consts::ARCH; + let time = chrono::Local::now().to_rfc3339(); + ctx.push_str(&format!("Environment: {} ({}), Current Time: {}\n\n", os, arch, time)); + + // 2. Custom Rules + let rule_files = [".cursorrules", ".zesdexrules", "claude.md", "agent.md"]; + for file in rule_files { + let p = root.join(file); + if let Ok(content) = std::fs::read_to_string(&p) { + ctx.push_str(&format!("### Project Rules ({})\n```\n{}\n```\n\n", file, content.trim())); + } + } + + // 3. Git Status + if root.join(".git").exists() { + let branch = Command::new("git") + .arg("branch") + .arg("--show-current") + .current_dir(root) + .output() + .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string()) + .unwrap_or_default(); + + let status = Command::new("git") + .arg("status") + .arg("-s") + .current_dir(root) + .output() + .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string()) + .unwrap_or_default(); + + if !branch.is_empty() { + ctx.push_str(&format!("### Git State (branch: {})\n", branch)); + if !status.is_empty() { + ctx.push_str(&format!("Uncommitted changes:\n```\n{}\n```\n", status)); + } else { + ctx.push_str("No uncommitted changes.\n"); + } + ctx.push('\n'); + } + } + + // 4. Tech Stack (manifests) + let manifests = ["Cargo.toml", "package.json", "go.mod"]; + for file in manifests { + let p = root.join(file); + if let Ok(content) = std::fs::read_to_string(&p) { + let snippet = if content.len() > 1500 { + format!("{}\n... (truncated)", &content[..1500]) + } else { + content + }; + ctx.push_str(&format!("### Tech Stack Manifest ({})\n```\n{}\n```\n\n", file, snippet.trim())); + } + } + + ctx.trim_end().to_string() +} diff --git a/apps/interfaces/tui/src/turn.rs b/apps/interfaces/tui/src/turn.rs index a046af8..1008203 100644 --- a/apps/interfaces/tui/src/turn.rs +++ b/apps/interfaces/tui/src/turn.rs @@ -129,9 +129,13 @@ fn run_turn(params: TurnParams) { if let Some(root) = params.workspace_roots.first() { let tree = zesdex_infrastructure::utils::build_workspace_tree(root, 800); + let rich_ctx = zesdex_infrastructure::utils::build_rich_context(root); + sys_prompt.push_str("\n\nWorkspace structure:\n```\n"); sys_prompt.push_str(&tree); - sys_prompt.push_str("\n```\n"); + sys_prompt.push_str("\n```\n\n"); + + sys_prompt.push_str(&rich_ctx); } let sys_msg = ChatMessage::system(sys_prompt);