fix: add parameter validation to all tools to prevent undefined insertions (#14)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2025-10-27 16:25:33 -07:00
committed by GitHub
parent 43483c77a5
commit 78ddbd499d
21 changed files with 194 additions and 0 deletions

View File

@@ -78,4 +78,10 @@ describe("Bash tool", () => {
expect(result.content).toBeDefined();
expect(result.content[0].text).toBeDefined();
});
test("throws error when command is missing", async () => {
await expect(bash({} as any)).rejects.toThrow(
/missing required parameter.*command/,
);
});
});

View File

@@ -65,4 +65,50 @@ describe("Edit tool", () => {
expect(readFileSync(file, "utf-8")).toBe("qux bar qux baz qux");
expect(result.replacements).toBe(3);
});
test("throws error when file_path is missing", async () => {
await expect(
edit({
old_string: "foo",
new_string: "bar",
} as any),
).rejects.toThrow(/missing required parameter.*file_path/);
});
test("throws error when old_string is missing", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "Hello, World!");
await expect(
edit({
file_path: file,
new_string: "bar",
} as any),
).rejects.toThrow(/missing required parameter.*old_string/);
});
test("throws error when new_string is missing", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "Hello, World!");
await expect(
edit({
file_path: file,
old_string: "foo",
} as any),
).rejects.toThrow(/missing required parameter.*new_string/);
});
test("throws error when using typo'd parameter name (new_str instead of new_string)", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "Hello, World!");
await expect(
edit({
file_path: file,
old_string: "World",
new_str: "Bun",
} as any),
).rejects.toThrow(/missing required parameter.*new_string/);
});
});

View File

@@ -56,4 +56,10 @@ describe("Grep tool", () => {
}
}
});
test("throws error when pattern is missing", async () => {
await expect(grep({} as any)).rejects.toThrow(
/missing required parameter.*pattern/,
);
});
});

View File

@@ -45,4 +45,10 @@ describe("LS tool", () => {
await expect(ls({ path: file })).rejects.toThrow(/Not a directory/);
});
test("throws error when path is missing", async () => {
await expect(ls({} as any)).rejects.toThrow(
/missing required parameter.*path/,
);
});
});

View File

@@ -40,4 +40,59 @@ describe("MultiEdit tool", () => {
expect(readFileSync(file, "utf-8")).toBe("xxx yyy");
expect(result.edits_applied).toBe(2);
});
test("throws error when file_path is missing", async () => {
await expect(
multi_edit({
edits: [{ old_string: "foo", new_string: "bar" }],
} as any),
).rejects.toThrow(/missing required parameter.*file_path/);
});
test("throws error when edits is missing", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "foo bar");
await expect(
multi_edit({
file_path: file,
} as any),
).rejects.toThrow(/missing required parameter.*edits/);
});
test("throws error when an edit is missing old_string", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "foo bar");
await expect(
multi_edit({
file_path: file,
edits: [{ new_string: "bar" } as any],
}),
).rejects.toThrow(/missing required parameter.*old_string/);
});
test("throws error when an edit is missing new_string", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "foo bar");
await expect(
multi_edit({
file_path: file,
edits: [{ old_string: "foo" } as any],
}),
).rejects.toThrow(/missing required parameter.*new_string/);
});
test("throws error when using typo'd parameter in edit (new_str instead of new_string)", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "foo bar");
await expect(
multi_edit({
file_path: file,
edits: [{ old_string: "foo", new_str: "baz" } as any],
}),
).rejects.toThrow(/missing required parameter.*new_string/);
});
});

View File

@@ -102,4 +102,10 @@ export default box;
expect(result.content).toContain("│ Header │");
expect(result.content).toContain("TypeScript file");
});
test("throws error when file_path is missing", async () => {
await expect(read({} as any)).rejects.toThrow(
/missing required parameter.*file_path/,
);
});
});

View File

@@ -48,4 +48,23 @@ describe("Write tool", () => {
expect(readFileSync(filePath, "utf-8")).toBe(content);
});
test("throws error when file_path is missing", async () => {
await expect(
write({
content: "Hello",
} as any),
).rejects.toThrow(/missing required parameter.*file_path/);
});
test("throws error when content is missing", async () => {
testDir = new TestDirectory();
const filePath = testDir.resolve("test.txt");
await expect(
write({
file_path: filePath,
} as any),
).rejects.toThrow(/missing required parameter.*content/);
});
});