Skip to content

Commit 7961063

Browse files
KonghaYaoclaude
andcommitted
fix: folder list 截断公平分配、re_inject skill 路径解析 cwd
- folder_operations: list 截断策略改为 folders 和 files 各占一半配额, 修复当 folders >= 500 时所有 files 被静默丢弃的 bug - re_inject: skill 路径现在与 file 路径一样做 cwd 相对路径解析, 避免相对路径的 skill 文件读取失败导致 compact 后 skill 丢失 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent f894929 commit 7961063

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

rust-agent-middlewares/src/tools/filesystem/folder.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ fn list_folder(resolved: &Path) -> Result<String, Box<dyn std::error::Error + Se
5555
let truncated = total > MAX_LIST_ENTRIES;
5656

5757
if truncated {
58-
folders.truncate(MAX_LIST_ENTRIES.min(folders.len()));
59-
files.truncate(MAX_LIST_ENTRIES.saturating_sub(folders.len()).min(files.len()));
58+
// 公平分配:folders 和 files 各占一半配额
59+
let half = MAX_LIST_ENTRIES / 2;
60+
folders.truncate(half.min(folders.len()));
61+
files.truncate((MAX_LIST_ENTRIES - folders.len()).min(files.len()));
6062
}
6163

6264
let mut result = format!("📁 {}\n\n", resolved.display());
@@ -240,4 +242,30 @@ mod tests {
240242
.unwrap();
241243
assert!(result.contains("file.txt"), "should list file.txt: {result}");
242244
}
245+
246+
#[tokio::test]
247+
async fn test_folder_list_truncation_keeps_files() {
248+
let dir = tempfile::tempdir().unwrap();
249+
let subdir = dir.path().join("bigdir");
250+
std::fs::create_dir(&subdir).unwrap();
251+
// 创建超过 MAX_LIST_ENTRIES 的子目录
252+
for i in 0..600 {
253+
std::fs::create_dir(subdir.join(format!("d{}", i))).unwrap();
254+
}
255+
// 同时创建一些文件
256+
for i in 0..5 {
257+
std::fs::write(subdir.join(format!("f{}.txt", i)), "x").unwrap();
258+
}
259+
let tool = FolderOperationsTool::new(dir.path().to_str().unwrap());
260+
let result = tool
261+
.invoke(serde_json::json!({"operation": "list", "folder_path": "bigdir"}))
262+
.await
263+
.unwrap();
264+
// 文件不应被全部丢弃
265+
assert!(
266+
result.contains("f0.txt") || result.contains("f1.txt"),
267+
"截断后应保留部分文件: {result}"
268+
);
269+
assert!(result.contains("truncated"), "应显示截断提示: {result}");
270+
}
243271
}

rust-create-agent/src/agent/compact/re_inject.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,20 @@ pub async fn re_inject(
158158
let mut skills_injected = 0;
159159

160160
if !skills_paths.is_empty() {
161+
let resolved_skill_paths: Vec<String> = skills_paths
162+
.iter()
163+
.map(|p| {
164+
if Path::new(p).is_absolute() {
165+
p.clone()
166+
} else {
167+
let abs = Path::new(cwd).join(p);
168+
abs.to_string_lossy().to_string()
169+
}
170+
})
171+
.collect();
172+
161173
let mut skill_futures = Vec::new();
162-
for path in &skills_paths {
174+
for path in &resolved_skill_paths {
163175
skill_futures.push(read_file_with_budget(path, config.re_inject_max_tokens_per_file));
164176
}
165177
let skill_contents: Vec<Option<String>> = futures::future::join_all(skill_futures).await;

0 commit comments

Comments
 (0)