refactor: consolidate nvim crates, extract server library, and update workspace dependencies
This commit is contained in:
1 parent
a083719cf1
commit
533adfd41b
53 files changed
+5967
-1230
No files matched your search
@@ -86,6 +86,88 @@ impl McpTool for GetActiveWorktreeContextHandler {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QueryGitDiffsHandler;
|
||||
|
||||
#[async_trait]
|
||||
impl McpTool for QueryGitDiffsHandler {
|
||||
fn name(&self) -> &'static str {
|
||||
"query_git_diffs"
|
||||
}
|
||||
|
||||
fn schema(&self) -> Value {
|
||||
crate::mcp::tool_def::<crate::tools::QueryGitDiffsTool>(
|
||||
"query_git_diffs",
|
||||
"Query recent git commit history, diffs, and change ledger entries.",
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: crate::tools::QueryGitDiffsTool =
|
||||
serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let limit = req.limit.unwrap_or(5);
|
||||
let q = req.query.to_lowercase();
|
||||
|
||||
let mut matches = Vec::new();
|
||||
|
||||
state.code.ledger.read_with(|ledger| {
|
||||
for change in ledger {
|
||||
if change.file_path.to_lowercase().contains(&q)
|
||||
|| change.description.to_lowercase().contains(&q)
|
||||
|| change.git_commit.as_ref().is_some_and(|c| c.contains(&q))
|
||||
{
|
||||
matches.push(json!({
|
||||
"file_path": change.file_path,
|
||||
"description": change.description,
|
||||
"commit": change.git_commit,
|
||||
"branch": change.git_branch,
|
||||
"timestamp": change.timestamp,
|
||||
}));
|
||||
if matches.len() >= limit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if matches.len() < limit {
|
||||
let remaining = limit - matches.len();
|
||||
let git_matches = tokio::task::spawn_blocking(move || {
|
||||
let mut results = Vec::new();
|
||||
let cwd = env::current_dir().unwrap_or_default();
|
||||
if let Ok(repo) = git2::Repository::discover(&cwd) {
|
||||
if let Ok(mut revwalk) = repo.revwalk() {
|
||||
let _ = revwalk.push_head();
|
||||
let mut count = 0;
|
||||
for oid in revwalk.flatten() {
|
||||
if count >= remaining {
|
||||
break;
|
||||
}
|
||||
if let Ok(commit) = repo.find_commit(oid) {
|
||||
let summary = commit.summary().unwrap_or("");
|
||||
if summary.to_lowercase().contains(&q) {
|
||||
count += 1;
|
||||
results.push(json!({
|
||||
"commit_id": oid.to_string(),
|
||||
"author": commit.author().name().unwrap_or("unknown"),
|
||||
"message": summary,
|
||||
"timestamp": commit.time().seconds(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
results
|
||||
})
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
matches.extend(git_matches);
|
||||
}
|
||||
|
||||
Ok(serde_json::to_string_pretty(&matches)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -110,4 +192,22 @@ mod tests {
|
||||
assert!(parsed.get("modified_files").is_some());
|
||||
assert!(parsed.get("diff").is_some());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_active_worktree_context_empty_git_repo() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let state = Arc::new(MemoryState::new(dir.path().to_str().unwrap()));
|
||||
|
||||
let handler = GetActiveWorktreeContextHandler;
|
||||
|
||||
let result = handler
|
||||
.execute(serde_json::json!({}), state)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to get worktree context: {}", e))
|
||||
.unwrap();
|
||||
|
||||
let parsed: serde_json::Value = serde_json::from_str(&result).unwrap();
|
||||
assert!(parsed.get("branch").is_some() || parsed.is_object());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user