mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-05 18:52:13 +00:00
feat: Implement write file tool (#2)
* feat: Implement write file tool * cr
This commit is contained in:
parent
0830c9c3e8
commit
5f95ff2a01
3 changed files with 136 additions and 21 deletions
|
|
@ -1,21 +0,0 @@
|
||||||
import { tool } from "@langchain/core/tools";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { applyPatch } from "diff";
|
|
||||||
|
|
||||||
const applyDiffToolSchema = z.object({
|
|
||||||
diff: z.string().describe("The diff to apply"),
|
|
||||||
file_path: z.string().describe("The file path to apply the diff to"),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const applyDiffTool = tool(
|
|
||||||
(input) => {
|
|
||||||
const { diff, file_path } = input;
|
|
||||||
const res = applyPatch(file_path, diff);
|
|
||||||
return `Successfully applied diff to \`${file_path}\``;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "apply_diff",
|
|
||||||
description: "Applies a diff to a file.",
|
|
||||||
schema: applyDiffToolSchema,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
52
src/tools/write-file.ts
Normal file
52
src/tools/write-file.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { tool } from "@langchain/core/tools";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { applyPatch } from "diff";
|
||||||
|
import { GraphConfig } from "../types.js";
|
||||||
|
import { Sandbox } from "@e2b/code-interpreter";
|
||||||
|
import { readFile, writeFile } from "../utils/read-write.js";
|
||||||
|
|
||||||
|
const writeFileToolSchema = z.object({
|
||||||
|
diff: z.string().describe("The diff to apply"),
|
||||||
|
file_path: z.string().describe("The file path to apply the diff to"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const writeFileTool = tool(
|
||||||
|
async (input, config: GraphConfig) => {
|
||||||
|
const { diff, file_path } = input;
|
||||||
|
const sessionId = config.configurable?.sandbox_session_id;
|
||||||
|
if (!sessionId) {
|
||||||
|
return "FAILED TO RUN COMMAND: No sandbox session ID provided";
|
||||||
|
}
|
||||||
|
|
||||||
|
const sandbox = await Sandbox.connect(sessionId);
|
||||||
|
|
||||||
|
const { success: readFileSuccess, output: readFileOutput } = await readFile(
|
||||||
|
sandbox,
|
||||||
|
file_path,
|
||||||
|
);
|
||||||
|
if (!readFileSuccess) {
|
||||||
|
return readFileOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
const patchedContent = applyPatch(readFileOutput, diff);
|
||||||
|
|
||||||
|
if (patchedContent === false) {
|
||||||
|
return `FAILED TO APPLY PATCH: The diff could not be applied to file '${file_path}'. This may be due to an invalid diff format or conflicting changes with the file's current content. Original content length: ${readFileOutput.length}, Diff: ${diff.substring(0, 100)}...`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should we be committing every time we apply a diff?
|
||||||
|
const { success: writeFileSuccess, output: writeFileOutput } =
|
||||||
|
await writeFile(sandbox, file_path, patchedContent);
|
||||||
|
if (!writeFileSuccess) {
|
||||||
|
return writeFileOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `Successfully applied diff to \`${file_path}\` and saved changes.`;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "write_file",
|
||||||
|
description:
|
||||||
|
"Writes a file given a file path and diff content. Can be used to create or update files.",
|
||||||
|
schema: writeFileToolSchema,
|
||||||
|
},
|
||||||
|
);
|
||||||
84
src/utils/read-write.ts
Normal file
84
src/utils/read-write.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { Sandbox } from "@e2b/code-interpreter";
|
||||||
|
|
||||||
|
export async function readFile(
|
||||||
|
sandbox: Sandbox,
|
||||||
|
filePath: string,
|
||||||
|
): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
output: string;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
const readOutput = await sandbox.commands.run(`cat "${filePath}"`);
|
||||||
|
if (readOutput.exitCode !== 0) {
|
||||||
|
console.error(
|
||||||
|
`Error reading file '${filePath}' from sandbox via cat:`,
|
||||||
|
readOutput,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
output: `FAILED TO READ FILE from sandbox '${filePath}'. Exit code: ${readOutput.exitCode}.\nStderr: ${readOutput.stderr}.\nStdout: ${readOutput.stdout}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (readOutput.stderr) {
|
||||||
|
console.warn(
|
||||||
|
`Stderr while reading file '${filePath}' from sandbox via cat: ${readOutput.stderr}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
output: readOutput.stdout,
|
||||||
|
};
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error(
|
||||||
|
`Exception while trying to read file '${filePath}' from sandbox via cat:`,
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
output: `FAILED TO EXECUTE READ COMMAND for sandbox '${filePath}'. Error: ${(e as Error).message || String(e)}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function writeFile(
|
||||||
|
sandbox: Sandbox,
|
||||||
|
filePath: string,
|
||||||
|
content: string,
|
||||||
|
): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
output: string;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
const writeCommand = `printf '%s' '${content}' > "${filePath}"`;
|
||||||
|
const writeOutput = await sandbox.commands.run(writeCommand);
|
||||||
|
|
||||||
|
if (writeOutput.exitCode !== 0) {
|
||||||
|
console.error(
|
||||||
|
`Error writing file '${filePath}' to sandbox via printf:`,
|
||||||
|
writeOutput,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
output: `FAILED TO WRITE FILE to sandbox '${filePath}'. Exit code: ${writeOutput.exitCode}. Stderr: ${writeOutput.stderr}. Stdout: ${writeOutput.stdout}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (writeOutput.stderr) {
|
||||||
|
console.warn(
|
||||||
|
`Stderr while writing file '${filePath}' to sandbox via printf: ${writeOutput.stderr}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
output: `Successfully wrote file '${filePath}' to sandbox via printf.`,
|
||||||
|
};
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error(
|
||||||
|
`Exception while trying to write file '${filePath}' to sandbox via printf:`,
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
output: `FAILED TO EXECUTE WRITE COMMAND for sandbox '${filePath}'. Error: ${(e as Error).message || String(e)}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue