62 lines
2.4 KiB
TypeScript
62 lines
2.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { MAX_TOOL_RUNS, recordToolRun, readToolHistory, type ToolRunMetadata } from "../src/tool-history";
|
|
|
|
function createStorage(seed: string | null = null) {
|
|
let value = seed;
|
|
return {
|
|
getItem: () => value,
|
|
setItem: (_key: string, next: string) => { value = next; },
|
|
value: () => value,
|
|
};
|
|
}
|
|
|
|
const run = (overrides: Partial<ToolRunMetadata> = {}): ToolRunMetadata => ({
|
|
tool: "gitea.pullrequest.status",
|
|
project: "ludarium",
|
|
environment: "prod",
|
|
ok: true,
|
|
traceId: "trace-123",
|
|
at: "2026-09-30T10:00:00.000Z",
|
|
...overrides,
|
|
});
|
|
|
|
describe("bounded recent tool history", () => {
|
|
it("stores only safe invocation metadata and never serializes arguments or results", () => {
|
|
const storage = createStorage();
|
|
recordToolRun({ ...run(), arguments: { token: "fixture-do-not-store" }, result: "private output" } as ToolRunMetadata, storage);
|
|
|
|
expect(JSON.parse(storage.value() ?? "null")).toEqual([run()]);
|
|
expect(storage.value()).not.toContain("fixture-do-not-store");
|
|
expect(storage.value()).not.toContain("private output");
|
|
});
|
|
|
|
it("bounds history to the newest twenty valid entries", () => {
|
|
const storage = createStorage();
|
|
for (let index = 0; index < MAX_TOOL_RUNS + 4; index += 1) {
|
|
recordToolRun(run({ traceId: `trace-${index}`, at: `2026-09-30T10:${String(index).padStart(2, "0")}:00.000Z` }), storage);
|
|
}
|
|
|
|
const history = readToolHistory(storage);
|
|
expect(history).toHaveLength(MAX_TOOL_RUNS);
|
|
expect(history[0]?.traceId).toBe(`trace-${MAX_TOOL_RUNS + 3}`);
|
|
expect(history.at(-1)?.traceId).toBe("trace-4");
|
|
});
|
|
|
|
it("drops malformed and oversized stored entries without exposing extra fields", () => {
|
|
const storage = createStorage(JSON.stringify([
|
|
{ ...run(), arguments: { apiKey: "secret" }, content: "result" },
|
|
{ ...run(), traceId: "trace\nsecret" },
|
|
{ ...run(), at: "yesterday" },
|
|
null,
|
|
]));
|
|
|
|
expect(readToolHistory(storage)).toEqual([run()]);
|
|
});
|
|
|
|
it("treats corrupt or unavailable browser storage as an empty history", () => {
|
|
expect(readToolHistory(createStorage("not-json"))).toEqual([]);
|
|
expect(() => readToolHistory({ getItem: () => { throw new Error("blocked"); }, setItem: () => undefined })).not.toThrow();
|
|
expect(() => recordToolRun(run(), { getItem: () => null, setItem: () => { throw new Error("blocked"); } })).not.toThrow();
|
|
});
|
|
});
|