feat: auto-delete old conversations, and stop a tool call that repeats
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { readSnipContext, snipDirectory } from "../lib/snip";
|
||||
import { access, mkdir, rm, utimes, writeFile } from "node:fs/promises";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { listSnipFiles, readSnipContext, removeSnipFiles, snipDirectory } from "../lib/snip";
|
||||
|
||||
/**
|
||||
* The snip handoff crosses a command boundary as a serialized launch context, so
|
||||
@@ -55,3 +56,97 @@ describe("snipDirectory", () => {
|
||||
expect(snipDirectory()).toBe("/tmp/lam-agent-support/snips");
|
||||
});
|
||||
});
|
||||
|
||||
describe("listSnipFiles", () => {
|
||||
const DIRECTORY = "/tmp/lam-agent-support/snips";
|
||||
|
||||
beforeEach(async () => {
|
||||
await rm(DIRECTORY, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(DIRECTORY, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("returns nothing before anything has been snipped", async () => {
|
||||
await expect(listSnipFiles()).resolves.toEqual([]);
|
||||
});
|
||||
|
||||
it("reports each capture with the time it was written", async () => {
|
||||
await mkdir(DIRECTORY, { recursive: true });
|
||||
const path = `${DIRECTORY}/one.png`;
|
||||
await writeFile(path, "png");
|
||||
const when = new Date(Date.now() - 60_000);
|
||||
await utimes(path, when, when);
|
||||
|
||||
const [file] = await listSnipFiles();
|
||||
|
||||
expect(file.path).toBe(path);
|
||||
expect(Date.now() - file.mtimeMs).toBeGreaterThan(30_000);
|
||||
});
|
||||
|
||||
it("ignores a subdirectory, which is not a capture", async () => {
|
||||
await mkdir(`${DIRECTORY}/nested`, { recursive: true });
|
||||
|
||||
await expect(listSnipFiles()).resolves.toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("removeSnipFiles", () => {
|
||||
const DIRECTORY = "/tmp/lam-agent-support/snips";
|
||||
const OUTSIDE = "/tmp/lam-agent-not-a-snip.png";
|
||||
|
||||
beforeEach(async () => {
|
||||
await rm(DIRECTORY, { recursive: true, force: true });
|
||||
await mkdir(DIRECTORY, { recursive: true });
|
||||
await writeFile(OUTSIDE, "do not delete me");
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(DIRECTORY, { recursive: true, force: true });
|
||||
await rm(OUTSIDE, { force: true });
|
||||
});
|
||||
|
||||
it("deletes a capture inside the snip directory", async () => {
|
||||
const path = `${DIRECTORY}/one.png`;
|
||||
await writeFile(path, "png");
|
||||
|
||||
await removeSnipFiles([path]);
|
||||
|
||||
await expect(access(path)).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("shrugs at a file that is already gone", async () => {
|
||||
await expect(removeSnipFiles([`${DIRECTORY}/never-existed.png`])).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("refuses a path outside the snip directory", async () => {
|
||||
// These paths come out of stored JSON, which is data rather than code, so
|
||||
// this must not be a general-purpose delete-any-file helper.
|
||||
await removeSnipFiles([OUTSIDE]);
|
||||
|
||||
await expect(access(OUTSIDE)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("refuses a path that climbs out of the directory", async () => {
|
||||
await removeSnipFiles([`${DIRECTORY}/../../lam-agent-not-a-snip.png`]);
|
||||
|
||||
await expect(access(OUTSIDE)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("refuses the directory itself", async () => {
|
||||
await removeSnipFiles([DIRECTORY]);
|
||||
|
||||
await expect(access(DIRECTORY)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps going when one path in the batch is refused", async () => {
|
||||
const inside = `${DIRECTORY}/one.png`;
|
||||
await writeFile(inside, "png");
|
||||
|
||||
await removeSnipFiles([OUTSIDE, inside]);
|
||||
|
||||
await expect(access(inside)).rejects.toThrow();
|
||||
await expect(access(OUTSIDE)).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user