Adding edit tool basically cloned from opencode

This commit is contained in:
2026-04-29 06:42:51 -05:00
parent 1854a3fb9b
commit 46a98ebcfd
4 changed files with 103 additions and 0 deletions
+1
View File
@@ -14,6 +14,7 @@ add_library(drharness_lib
src/harness.cpp
tools/shell_tool.cpp
tools/agent_tool.cpp
tools/edit_tool.cpp
)
target_include_directories(drharness_lib PUBLIC include tools)
target_link_libraries(drharness_lib
+3
View File
@@ -4,6 +4,7 @@
#include "agent_profile.hpp"
#include "shell_tool.hpp"
#include "agent_tool.hpp"
#include "edit_tool.hpp"
#include <cstdlib>
#include <iostream>
#include <fstream>
@@ -24,6 +25,7 @@ static const std::vector<AgentProfile> profiles = {
static const std::vector<std::string> default_tools =
{
"run_shell",
"edit",
};
@@ -36,6 +38,7 @@ int main(int argc, char** argv) {
ToolRegistry master_registery;
ToolRegistry agent_tools;
master_registery.register_tool(make_shell_tool());
master_registery.register_tool(make_edit_tool());
// Add more base tools here:
// registry.register_tool(make_file_read_tool());
+95
View File
@@ -0,0 +1,95 @@
#include "edit_tool.hpp"
#include <fstream>
#include <sstream>
static int countOccurrences(const std::string& text, const std::string& target) {
int count = 0;
size_t pos = text.find(target);
while (pos != std::string::npos) {
++count;
pos = text.find(target, pos + target.length());
}
return count;
}
Tool make_edit_tool() {
return Tool{
.name = "edit",
.description = ""
"Performs exact string replacements in files.\n"
"\n"
"Usage:\n"
"- When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: line number + colon + space (e.g., `1: `). Everything after that space is the actual file content to match. Never include any part of the line number prefix in the oldString or newString.\n"
// "- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.\n"
"- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.\n"
"- The edit will FAIL if `oldString` is not found in the file with an error \"oldString not found in content\".\n"
"- The edit will FAIL if `oldString` is found multiple times in the file with an error \"Found multiple matches for oldString. Provide more surrounding lines in oldString to identify the correct match.\"",// Either provide a larger string with more surrounding context to make it unique or use `replaceAll` to change every instance of `oldString`. \n"
// "- Use `replaceAll` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.",
.parameters_schema = {
{"type", "object"},
{"properties", {
{"filePath", {
{"type", "string"},
{"description", "The absolute path to the file to modify"}
}},
{"oldString", {
{"type", "string"},
{"description", "The text to replace"}
}},
{"newString", {
{"type", "string"},
{"description", "The text to replace it with (must be different from oldString)"}
}},
#if 0
{"replaceAll", {
{"type", "bool"},
{"description", "Replace all occurrences of oldString (default false)"}
}},
#endif
}},
{"required", {"filePath", "oldString", "newString"}}
},
.execute = [](const nlohmann::json& args) -> std::string {
if (!args.contains("filePath") || !args["filePath"].is_string())
return "Error: missing required parameter 'filePath'";
if (!args.contains("oldString") || !args["oldString"].is_string())
return "Error: missing required parameter 'oldString'";
if (!args.contains("newString") || !args["newString"].is_string())
return "Error: missing required parameter 'newString'";
std::string oldString = args["oldString"];
std::ifstream in(args["filePath"]);
if (!in)
return "Error: Could not open file '" + std::string(args["filePath"]) + "'";
std::ostringstream sstr;
sstr << in.rdbuf();
std::string file_string = sstr.str(); // Contents of the file
auto count = countOccurrences(file_string, oldString);
if (count == 0)
return "Error: oldString not found in content";
if (count > 1)
return "Error: Found multiple matches for oldString. Provide more surrounding lines in oldString to identify the correct match.";
file_string = file_string.replace(
file_string.find(oldString),
oldString.length(),
(std::string)args["newString"]);
std::ofstream output(args["filePath"]);
output << file_string;
return "Successfully edited file";
}
};
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include "tool.hpp"
Tool make_edit_tool();