fix(fctool): 修复 git tools 中的类型不匹配问题

- blob.rs: 修复 resolve_oid 返回 commit OID 而非 blob OID 的问题
- tree.rs: 修复 git_tree_ls_exec 直接传递 commit OID 给 tree_list 的问题
- 所有修改使类型合约与 git domain API 匹配
This commit is contained in:
ZhenYi 2026-04-28 19:58:52 +08:00
parent d1ade2c3c3
commit 13523762aa
3 changed files with 21 additions and 40 deletions

View File

@ -16,8 +16,8 @@ async fn git_blob_info_exec(
let oid = p.get("oid").and_then(|v| v.as_str()).ok_or("missing oid")?;
let domain = ctx.open_repo(project_name, repo_name).await?;
let commit_oid = resolve_oid(&domain, oid)?;
let info = domain.blob_get(&commit_oid).map_err(|e| e.to_string())?;
let blob_oid = git::commit::types::CommitOid::new(oid);
let info = domain.blob_get(&blob_oid).map_err(|e| e.to_string())?;
Ok(serde_json::json!({
"oid": info.oid.to_string(),
@ -37,10 +37,10 @@ async fn git_blob_exists_exec(
let oid = p.get("oid").and_then(|v| v.as_str()).ok_or("missing oid")?;
let domain = ctx.open_repo(project_name, repo_name).await?;
let commit_oid = resolve_oid(&domain, oid)?;
let exists = domain.blob_exists(&commit_oid);
let blob_oid = git::commit::types::CommitOid::new(oid);
let exists = domain.blob_exists(&blob_oid);
Ok(serde_json::json!({ "oid": commit_oid.to_string(), "exists": exists }))
Ok(serde_json::json!({ "oid": blob_oid.to_string(), "exists": exists }))
}
async fn git_blob_content_exec(
@ -55,8 +55,8 @@ async fn git_blob_content_exec(
let max_size = p.get("max_size").and_then(|v| v.as_u64()).unwrap_or(1_048_576) as usize; // 1MB default
let domain = ctx.open_repo(project_name, repo_name).await?;
let commit_oid = resolve_oid(&domain, oid)?;
let blob = domain.blob_content(&commit_oid).map_err(|e| e.to_string())?;
let blob_oid = git::commit::types::CommitOid::new(oid);
let blob = domain.blob_content(&blob_oid).map_err(|e| e.to_string())?;
if blob.size > max_size {
return Err(format!(
@ -109,18 +109,6 @@ async fn git_blob_create_exec(
}))
}
fn resolve_oid(
domain: &git::GitDomain,
rev: &str,
) -> Result<git::commit::types::CommitOid, String> {
if rev.len() == 40 && rev.chars().all(|c| c.is_ascii_hexdigit()) {
Ok(git::commit::types::CommitOid::new(rev))
} else if let Ok(Some(oid)) = domain.ref_target(rev) {
Ok(oid)
} else {
domain.commit_get_prefix(rev).map_err(|e| e.to_string()).map(|m| m.oid)
}
}
pub fn register_git_tools(registry: &mut ToolRegistry) {
// git_blob_info

View File

@ -47,16 +47,11 @@ async fn git_log_exec(ctx: GitToolCtx, args: serde_json::Value) -> Result<serde_
Ok(serde_json::to_value(result).map_err(|e| e.to_string())?)
}
/// Resolve a rev string to commit metadata. Tries full OID first (exactly 40 hex chars),
/// then reference name resolution (branch, tag, HEAD), then hex prefix lookup.
/// Resolve a rev string to commit metadata using the full rev-parse machinery
/// (branch names, tags, HEAD, hex prefixes, etc.).
fn resolve_commit(domain: &git::GitDomain, rev: &str) -> Result<git::commit::types::CommitMeta, String> {
if rev.len() == 40 && rev.chars().all(|c| c.is_ascii_hexdigit()) {
domain.commit_get(&git::commit::types::CommitOid::new(rev)).map_err(|e| e.to_string())
} else if let Ok(Some(oid)) = domain.ref_target(rev) {
domain.commit_get(&oid).map_err(|e| e.to_string())
} else {
domain.commit_get_prefix(rev).map_err(|e| e.to_string())
}
let oid = domain.resolve_rev(rev).map_err(|e| e.to_string())?;
domain.commit_get(&oid).map_err(|e| e.to_string())
}
async fn git_show_exec(ctx: GitToolCtx, args: serde_json::Value) -> Result<serde_json::Value, String> {

View File

@ -5,16 +5,10 @@ use agent::{ToolDefinition, ToolHandler, ToolParam, ToolRegistry, ToolSchema};
use base64::Engine;
use std::collections::HashMap;
/// Resolve a rev string to a commit OID. Tries full OID first (exactly 40 hex chars),
/// then reference name resolution (branch, tag, HEAD), then hex prefix lookup.
/// Resolve a rev string to a commit OID using the full rev-parse machinery
/// (branch names, tags, HEAD, hex prefixes, etc.).
fn resolve_commit_oid(domain: &git::GitDomain, rev: &str) -> Result<git::commit::types::CommitOid, String> {
if rev.len() == 40 && rev.chars().all(|c| c.is_ascii_hexdigit()) {
Ok(git::commit::types::CommitOid::new(rev))
} else if let Ok(Some(oid)) = domain.ref_target(rev) {
Ok(oid)
} else {
domain.commit_get_prefix(rev).map_err(|e| e.to_string()).map(|m| m.oid)
}
domain.resolve_rev(rev).map_err(|e| e.to_string())
}
async fn git_file_content_exec(ctx: GitToolCtx, args: serde_json::Value) -> Result<serde_json::Value, String> {
@ -54,14 +48,18 @@ async fn git_tree_ls_exec(ctx: GitToolCtx, args: serde_json::Value) -> Result<se
let rev = p.get("rev").and_then(|v| v.as_str()).map(|s| s.to_string()).unwrap_or_else(|| "HEAD".to_string());
let domain = ctx.open_repo(project_name, repo_name).await?;
let commit_oid = resolve_commit_oid(&domain, &rev).map_err(|e| e.to_string())?;
let commit_oid = resolve_commit_oid(&domain, &rev)?;
// Get tree OID from commit
let commit_meta = domain.commit_get(&commit_oid).map_err(|e| e.to_string())?;
let tree_oid = &commit_meta.tree_id;
let entries = match dir_path {
Some(ref dp) => {
let entry = domain.tree_entry_by_path(&commit_oid, dp).map_err(|e| e.to_string())?;
let entry = domain.tree_entry_by_path(tree_oid, dp).map_err(|e| e.to_string())?;
domain.tree_list(&entry.oid).map_err(|e| e.to_string())?
}
None => domain.tree_list(&commit_oid).map_err(|e| e.to_string())?,
None => domain.tree_list(tree_oid).map_err(|e| e.to_string())?,
};
let result: Vec<_> = entries.iter().map(|e| {