Skip to content

Commit 542c15c

Browse files
authored
Merge pull request #678 from phantom5099/main
pref(tool):删除无用工具
2 parents 4e575d8 + 7670fc7 commit 542c15c

28 files changed

Lines changed: 17 additions & 1737 deletions

docs/architecture/architecture-v1.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -691,11 +691,7 @@ NeoCode 在多处预留了扩展点。本节集中描述:**哪里可以扩展
691691
| `filesystem_edit` | 文件系统 | 基于字符串精确替换的原地编辑 |
692692
| `filesystem_glob` | 文件系统 | 文件名模式匹配 |
693693
| `filesystem_grep` | 文件系统 | 文件内容正则搜索 |
694-
| `filesystem_copy_file` | 文件系统 | 复制文件 |
695-
| `filesystem_move_file` | 文件系统 | 移动/重命名文件 |
696-
| `filesystem_create_dir` | 文件系统 | 创建目录 |
697694
| `filesystem_delete_file` | 文件系统 | 删除文件 |
698-
| `filesystem_remove_dir` | 文件系统 | 删除目录 |
699695
| `codebase_read` | 代码库 | 读取代码文件(含语义增强) |
700696
| `codebase_search_text` | 代码库 | 基于文本搜索代码库 |
701697
| `codebase_search_symbol` | 代码库 | 基于 Tree-sitter 的跨语言符号搜索 |

internal/app/bootstrap.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,7 @@ func buildToolRegistry(cfg config.Config) (*tools.Registry, func() error, error)
457457
toolRegistry.Register(filesystem.NewGrep(cfg.Workdir))
458458
toolRegistry.Register(filesystem.NewGlob(cfg.Workdir))
459459
toolRegistry.Register(filesystem.NewEdit(cfg.Workdir))
460-
toolRegistry.Register(filesystem.NewMove(cfg.Workdir))
461-
toolRegistry.Register(filesystem.NewCopy(cfg.Workdir))
462460
toolRegistry.Register(filesystem.NewDelete(cfg.Workdir))
463-
toolRegistry.Register(filesystem.NewCreateDir(cfg.Workdir))
464-
toolRegistry.Register(filesystem.NewRemoveDir(cfg.Workdir))
465461
toolRegistry.Register(bash.New(cfg.Workdir, cfg.Shell, time.Duration(cfg.ToolTimeoutSec)*time.Second))
466462
toolRegistry.Register(diagnosetool.New())
467463
toolRegistry.Register(webfetch.New(webfetch.Config{

internal/checkpoint/per_edit_snapshot_test.go

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -883,72 +883,6 @@ func TestCapturePostDelete_DirectoryTreeRecovery(t *testing.T) {
883883
}
884884
}
885885

886-
func TestRestore_RemoveDirWithNestedFiles(t *testing.T) {
887-
store, workdir := newTestStore(t)
888-
dir := filepath.Join(workdir, "foo")
889-
child := filepath.Join(dir, "bar.txt")
890-
891-
// Turn 1: create tree.
892-
writeWorkdirFile(t, workdir, "foo/bar.txt", "hello")
893-
if _, err := store.CapturePreWrite(dir); err != nil {
894-
t.Fatalf("capture dir t1: %v", err)
895-
}
896-
if _, err := store.CapturePreWrite(child); err != nil {
897-
t.Fatalf("capture child t1: %v", err)
898-
}
899-
if _, err := store.Finalize("cp1"); err != nil {
900-
t.Fatalf("finalize cp1: %v", err)
901-
}
902-
store.Reset()
903-
904-
// Turn 2: remove tree with recursive pre-capture + post-delete.
905-
if _, err := store.CapturePreWrite(dir); err != nil {
906-
t.Fatalf("capture dir t2: %v", err)
907-
}
908-
if _, err := store.CapturePreWrite(child); err != nil {
909-
t.Fatalf("capture child t2: %v", err)
910-
}
911-
if err := os.RemoveAll(dir); err != nil {
912-
t.Fatalf("removeAll: %v", err)
913-
}
914-
if err := store.CapturePostDelete([]string{dir, child}); err != nil {
915-
t.Fatalf("CapturePostDelete: %v", err)
916-
}
917-
if _, err := store.Finalize("cp2"); err != nil {
918-
t.Fatalf("finalize cp2: %v", err)
919-
}
920-
store.Reset()
921-
922-
// Turn 3: recreate tree with different content.
923-
writeWorkdirFile(t, workdir, "foo/bar.txt", "world")
924-
if _, err := store.CapturePreWrite(dir); err != nil {
925-
t.Fatalf("capture dir t3: %v", err)
926-
}
927-
if _, err := store.CapturePreWrite(child); err != nil {
928-
t.Fatalf("capture child t3: %v", err)
929-
}
930-
if _, err := store.Finalize("cp3"); err != nil {
931-
t.Fatalf("finalize cp3: %v", err)
932-
}
933-
store.Reset()
934-
935-
// Restore cp2: should delete the tree.
936-
if err := store.Restore(context.Background(), "cp2", ""); err != nil {
937-
t.Fatalf("restore cp2: %v", err)
938-
}
939-
if _, err := os.Stat(dir); !os.IsNotExist(err) {
940-
t.Fatalf("expected dir absent after restore cp2, stat err=%v", err)
941-
}
942-
943-
// Restore cp1: should recreate the tree with original content.
944-
if err := store.Restore(context.Background(), "cp1", ""); err != nil {
945-
t.Fatalf("restore cp1: %v", err)
946-
}
947-
if got := mustReadFile(t, child); got != "hello" {
948-
t.Fatalf("child want hello got %q", got)
949-
}
950-
}
951-
952886
func TestPerEditStoreHelperMethods(t *testing.T) {
953887
t.Run("availability and pending lifecycle", func(t *testing.T) {
954888
var nilStore *PerEditSnapshotStore

internal/context/microcompact_test.go

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -502,101 +502,6 @@ func TestMicroCompactMixedPinnedAndNonPinned(t *testing.T) {
502502
}
503503
}
504504

505-
func TestMicroCompactPinsCopyAndMoveUsingPersistedMetadataPaths(t *testing.T) {
506-
t.Parallel()
507-
508-
pinChecker := NewDefaultPinChecker()
509-
510-
copyMessages := []providertypes.Message{
511-
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("older user")}},
512-
{
513-
Role: providertypes.RoleAssistant,
514-
ToolCalls: []providertypes.ToolCall{
515-
{ID: "copy-call", Name: tools.ToolNameFilesystemCopyFile, Arguments: `{"source_path":"main.go","destination_path":"go.mod"}`},
516-
},
517-
},
518-
{Role: providertypes.RoleTool, ToolCallID: "copy-call", Parts: []providertypes.ContentPart{providertypes.NewTextPart("ok")}, ToolMetadata: map[string]string{
519-
"tool_name": tools.ToolNameFilesystemCopyFile,
520-
"source_path": "/project/main.go",
521-
"destination_path": "/project/go.mod",
522-
}},
523-
{
524-
Role: providertypes.RoleAssistant,
525-
ToolCalls: []providertypes.ToolCall{
526-
{ID: "recent-call", Name: tools.ToolNameBash, Arguments: "{}"},
527-
},
528-
},
529-
{Role: providertypes.RoleTool, ToolCallID: "recent-call", Parts: []providertypes.ContentPart{providertypes.NewTextPart("recent bash result")}},
530-
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("latest explicit instruction")}},
531-
}
532-
533-
copyGot := microCompactMessagesWithPolicies(copyMessages, stubMicroCompactPolicySource{}, 1, nil, pinChecker)
534-
if renderDisplayParts(copyGot[2].Parts) != "ok" {
535-
t.Fatalf("expected copy_file result touching go.mod to stay pinned, got %q", renderDisplayParts(copyGot[2].Parts))
536-
}
537-
538-
moveMessages := []providertypes.Message{
539-
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("older user")}},
540-
{
541-
Role: providertypes.RoleAssistant,
542-
ToolCalls: []providertypes.ToolCall{
543-
{ID: "move-call", Name: tools.ToolNameFilesystemMoveFile, Arguments: `{"source_path":"package.json","destination_path":"package.backup.json"}`},
544-
},
545-
},
546-
{Role: providertypes.RoleTool, ToolCallID: "move-call", Parts: []providertypes.ContentPart{providertypes.NewTextPart("ok")}, ToolMetadata: map[string]string{
547-
"tool_name": tools.ToolNameFilesystemMoveFile,
548-
"source_path": "/project/package.json",
549-
"destination_path": "/project/package.backup.json",
550-
}},
551-
{
552-
Role: providertypes.RoleAssistant,
553-
ToolCalls: []providertypes.ToolCall{
554-
{ID: "recent-call", Name: tools.ToolNameBash, Arguments: "{}"},
555-
},
556-
},
557-
{Role: providertypes.RoleTool, ToolCallID: "recent-call", Parts: []providertypes.ContentPart{providertypes.NewTextPart("recent bash result")}},
558-
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("latest explicit instruction")}},
559-
}
560-
561-
moveGot := microCompactMessagesWithPolicies(moveMessages, stubMicroCompactPolicySource{}, 1, nil, pinChecker)
562-
if renderDisplayParts(moveGot[2].Parts) != "ok" {
563-
t.Fatalf("expected move_file result touching package.json to stay pinned, got %q", renderDisplayParts(moveGot[2].Parts))
564-
}
565-
}
566-
567-
func TestMicroCompactStillCompactsCopyAndMoveWhenNoKeyFileIsTouched(t *testing.T) {
568-
t.Parallel()
569-
570-
pinChecker := NewDefaultPinChecker()
571-
messages := []providertypes.Message{
572-
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("older user")}},
573-
{
574-
Role: providertypes.RoleAssistant,
575-
ToolCalls: []providertypes.ToolCall{
576-
{ID: "move-call", Name: tools.ToolNameFilesystemMoveFile, Arguments: `{"source_path":"main.go","destination_path":"main2.go"}`},
577-
},
578-
},
579-
{Role: providertypes.RoleTool, ToolCallID: "move-call", Parts: []providertypes.ContentPart{providertypes.NewTextPart("ok")}, ToolMetadata: map[string]string{
580-
"tool_name": tools.ToolNameFilesystemMoveFile,
581-
"source_path": "/project/main.go",
582-
"destination_path": "/project/main2.go",
583-
}},
584-
{
585-
Role: providertypes.RoleAssistant,
586-
ToolCalls: []providertypes.ToolCall{
587-
{ID: "recent-call", Name: tools.ToolNameBash, Arguments: "{}"},
588-
},
589-
},
590-
{Role: providertypes.RoleTool, ToolCallID: "recent-call", Parts: []providertypes.ContentPart{providertypes.NewTextPart("recent bash result")}},
591-
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("latest explicit instruction")}},
592-
}
593-
594-
got := microCompactMessagesWithPolicies(messages, stubMicroCompactPolicySource{}, 1, nil, pinChecker)
595-
if !strings.Contains(renderDisplayParts(got[2].Parts), "[summary] filesystem_move_file") {
596-
t.Fatalf("expected non-key move_file result to still compact into summary, got %q", renderDisplayParts(got[2].Parts))
597-
}
598-
}
599-
600505
// stubMicroCompactPinChecker 实现 MicroCompactPinChecker,用于测试。
601506
type stubMicroCompactPinChecker map[string]map[string]bool
602507

internal/context/pin_checker.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ var defaultPinPatterns = []string{
2323
var defaultPinToolNames = map[string]struct{}{
2424
tools.ToolNameFilesystemWriteFile: {},
2525
tools.ToolNameFilesystemEdit: {},
26-
tools.ToolNameFilesystemCopyFile: {},
27-
tools.ToolNameFilesystemMoveFile: {},
2826
}
2927

3028
// pinChecker 基于文件路径 glob 模式判断工具结果是否应钉住。

internal/context/pin_checker_test.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ func TestDefaultPinCheckerMatchesKeyArtifacts(t *testing.T) {
3939
{toolName: "filesystem_write_file", path: "utils.py", expected: false},
4040
{toolName: "filesystem_write_file", path: "style.css", expected: false},
4141
{toolName: "filesystem_edit", path: "README.md", expected: true},
42-
{toolName: "filesystem_copy_file", path: "go.mod", expected: true},
43-
{toolName: "filesystem_move_file", path: "package.json", expected: true},
4442
{toolName: "filesystem_read_file", path: "README.md", expected: false},
4543
{toolName: "bash", path: "README.md", expected: false},
4644
}
@@ -80,34 +78,6 @@ func TestDefaultPinCheckerFallsBackToPath(t *testing.T) {
8078
}
8179
}
8280

83-
func TestDefaultPinCheckerSupportsCopyAndMoveMetadataFields(t *testing.T) {
84-
t.Parallel()
85-
86-
checker := NewDefaultPinChecker()
87-
88-
copyPinned := checker.ShouldPin("filesystem_copy_file", map[string]string{
89-
"destination_path": "/project/go.mod",
90-
})
91-
if !copyPinned {
92-
t.Error("expected destination_path match for copy_file go.mod")
93-
}
94-
95-
movePinned := checker.ShouldPin("filesystem_move_file", map[string]string{
96-
"source_path": "/project/package.json",
97-
})
98-
if !movePinned {
99-
t.Error("expected source_path match for move_file package.json")
100-
}
101-
102-
notPinned := checker.ShouldPin("filesystem_move_file", map[string]string{
103-
"source_path": "/project/main.go",
104-
"destination_path": "/project/main2.go",
105-
})
106-
if notPinned {
107-
t.Error("expected non-key source/destination paths to remain unpinned")
108-
}
109-
}
110-
11181
func TestDefaultPinCheckerNoPathReturnsFalse(t *testing.T) {
11282
t.Parallel()
11383

internal/promptasset/templates/core/tool_usage.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@ For general file operations outside of codebase exploration, use `filesystem_*`
3232
- For simple create/overwrite tasks, prefer `filesystem_write_file` with `verify_after_write=true` so one call can emit write + verification facts.
3333
- Do not use `bash` to edit files when the filesystem tools can make the change safely.
3434
- For file system structure changes inside the workspace, prefer the dedicated tools over `bash`:
35-
- rename/move: `filesystem_move_file` (not `bash mv`)
36-
- copy: `filesystem_copy_file` (not `bash cp`)
3735
- delete file: `filesystem_delete_file` (not `bash rm`)
38-
- create directory: `filesystem_create_dir` (not `bash mkdir`)
39-
- remove directory: `filesystem_remove_dir` (not `bash rmdir` / `rm -rf`)
4036
These tools record their changes for checkpoint/rollback; equivalent `bash` commands produce reduced rollback coverage.
4137
- For multi-step implementation, debugging, refactoring, or long-running work, keep task state explicit via `todo_write` (plan/add/update/set_status/claim/complete/fail) when that tool is available and the current mode permits execution todo updates.
4238
- Create todos that map to real acceptance work, not vague activity.

internal/runner/runner.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,7 @@ func New(cfg Config) (*Runner, error) {
104104
toolMgr.Register(filesystem.NewGrep(workdir))
105105
toolMgr.Register(filesystem.NewGlob(workdir))
106106
toolMgr.Register(filesystem.NewEdit(workdir))
107-
toolMgr.Register(filesystem.NewMove(workdir))
108-
toolMgr.Register(filesystem.NewCopy(workdir))
109107
toolMgr.Register(filesystem.NewDelete(workdir))
110-
toolMgr.Register(filesystem.NewCreateDir(workdir))
111-
toolMgr.Register(filesystem.NewRemoveDir(workdir))
112108
toolMgr.Register(bash.New(workdir, shell, cfg.RequestTimeout))
113109
toolMgr.Register(webfetch.New(webfetch.Config{Timeout: cfg.RequestTimeout}))
114110
toolMgr.Register(diagnosetool.New())

internal/runtime/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ func (s *Service) emitToolDiffs(ctx context.Context, state *runState, summary to
839839
}
840840

841841
// buildToolDiffPayload 将工具结果 metadata 中的 diff 信息组装成 ToolDiffPayload。
842-
// 多文件工具(filesystem_move_file 等)使用 Files+Diffs 多路径字段
842+
// 使用 Files+Diffs 或 FilePath/Diff/WasNew 字段
843843
// 其他写工具继续填充兼容字段 FilePath/Diff/WasNew,保持现有消费者不破。
844844
// FileChange.Kind 优先取 entry.Kind(toolexec 收集层填充),缺失时回退到 WasNew 二分以兼容旧 metadata。
845845
func buildToolDiffPayload(result tools.ToolResult) (ToolDiffPayload, bool) {

internal/runtime/tool_diff_helpers_test.go

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func TestBuildToolDiffPayload(t *testing.T) {
3333

3434
t.Run("multi file payload", func(t *testing.T) {
3535
result := tools.ToolResult{
36-
Name: tools.ToolNameFilesystemMoveFile,
36+
Name: tools.ToolNameFilesystemWriteFile,
3737
ToolCallID: "call-2",
3838
Metadata: map[string]any{
3939
"tool_diffs": []map[string]any{
@@ -61,7 +61,7 @@ func TestBuildToolDiffPayload(t *testing.T) {
6161

6262
t.Run("multi file kind from metadata wins over WasNew fallback", func(t *testing.T) {
6363
result := tools.ToolResult{
64-
Name: tools.ToolNameFilesystemMoveFile,
64+
Name: tools.ToolNameFilesystemWriteFile,
6565
ToolCallID: "call-move",
6666
Metadata: map[string]any{
6767
"tool_diffs": []map[string]any{
@@ -88,7 +88,7 @@ func TestBuildToolDiffPayload(t *testing.T) {
8888

8989
t.Run("multi file filters unchanged copy source", func(t *testing.T) {
9090
result := tools.ToolResult{
91-
Name: tools.ToolNameFilesystemCopyFile,
91+
Name: tools.ToolNameFilesystemWriteFile,
9292
ToolCallID: "call-copy",
9393
Metadata: map[string]any{
9494
"tool_diffs": []map[string]any{
@@ -112,7 +112,7 @@ func TestBuildToolDiffPayload(t *testing.T) {
112112

113113
t.Run("multi file delete metadata preserves deleted kind", func(t *testing.T) {
114114
result := tools.ToolResult{
115-
Name: tools.ToolNameFilesystemRemoveDir,
115+
Name: tools.ToolNameFilesystemWriteFile,
116116
ToolCallID: "call-rm",
117117
Metadata: map[string]any{
118118
"tool_diffs": []map[string]any{
@@ -144,7 +144,7 @@ func TestBuildToolDiffPayload(t *testing.T) {
144144
}
145145

146146
func TestToolExecutionHelperFunctions(t *testing.T) {
147-
t.Run("toolCallTouchedPaths covers write and move payloads", func(t *testing.T) {
147+
t.Run("toolCallTouchedPaths extracts path", func(t *testing.T) {
148148
writePaths := toolCallTouchedPaths(providertypes.ToolCall{
149149
Name: tools.ToolNameFilesystemWriteFile,
150150
Arguments: `{"path":" docs/readme.md "}`,
@@ -153,16 +153,8 @@ func TestToolExecutionHelperFunctions(t *testing.T) {
153153
t.Fatalf("write toolCallTouchedPaths() = %#v", writePaths)
154154
}
155155

156-
movePaths := toolCallTouchedPaths(providertypes.ToolCall{
157-
Name: tools.ToolNameFilesystemMoveFile,
158-
Arguments: `{"source_path":"src/a.txt","destination_path":" /tmp/b.txt "}`,
159-
}, "/repo")
160-
if len(movePaths) != 2 || movePaths[0] != "/repo/src/a.txt" || movePaths[1] != "/tmp/b.txt" {
161-
t.Fatalf("move toolCallTouchedPaths() = %#v", movePaths)
162-
}
163-
164156
if got := toolCallTouchedPaths(providertypes.ToolCall{
165-
Name: tools.ToolNameFilesystemCopyFile,
157+
Name: tools.ToolNameFilesystemWriteFile,
166158
Arguments: `{invalid`,
167159
}, "/repo"); got != nil {
168160
t.Fatalf("malformed toolCallTouchedPaths() = %#v, want nil", got)

0 commit comments

Comments
 (0)