mirror of
https://github.com/bendtherules/opencode-plugin-compaction-prompt.git
synced 2026-08-18 21:52:46 +00:00
153 lines
4.6 KiB
TypeScript
153 lines
4.6 KiB
TypeScript
import { afterEach, describe, expect, test } from "bun:test";
|
|
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { CompactionPromptPlugin } from "../src/index.js";
|
|
|
|
const temporaryDirectories: string[] = [];
|
|
|
|
afterEach(async (): Promise<void> => {
|
|
await Promise.all(
|
|
temporaryDirectories
|
|
.splice(0)
|
|
.map((directory) => rm(directory, { recursive: true })),
|
|
);
|
|
});
|
|
|
|
async function createContext(): Promise<{
|
|
worktree: string;
|
|
logs: Array<unknown>;
|
|
client: { app: { log: (input: unknown) => Promise<void> } };
|
|
}> {
|
|
const worktree = await mkdtemp(
|
|
path.join(os.tmpdir(), "opencode-compaction-"),
|
|
);
|
|
temporaryDirectories.push(worktree);
|
|
const logs: Array<unknown> = [];
|
|
|
|
return {
|
|
worktree,
|
|
logs,
|
|
client: {
|
|
app: {
|
|
log: async (input: unknown): Promise<void> => {
|
|
logs.push(input);
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("CompactionPromptPlugin", () => {
|
|
test("appends instructions and memory by default", async () => {
|
|
const context = await createContext();
|
|
await mkdir(path.join(context.worktree, ".opencode"));
|
|
await writeFile(
|
|
path.join(context.worktree, ".opencode/compaction.md"),
|
|
"Keep the active hypothesis.",
|
|
);
|
|
const hooks = await CompactionPromptPlugin(context as never);
|
|
const output = { context: [] as string[] };
|
|
|
|
await hooks["experimental.session.compacting"]?.(
|
|
{ sessionID: "test" },
|
|
output,
|
|
);
|
|
|
|
expect(output.context[0]).toContain("Keep the active hypothesis.");
|
|
expect(output.context[0]).toContain("Custom compaction request honored.");
|
|
});
|
|
|
|
test("combines custom instructions with a configured memory file", async () => {
|
|
const context = await createContext();
|
|
await writeFile(
|
|
path.join(context.worktree, "project-memory.md"),
|
|
"Preserve the active hypothesis.",
|
|
);
|
|
const hooks = await CompactionPromptPlugin(context as never, {
|
|
memoryFile: "project-memory.md",
|
|
prompt: "Keep exact file paths.",
|
|
completionMarker: "Compaction complete.",
|
|
});
|
|
const output = { context: ["Existing context"] };
|
|
|
|
await hooks["experimental.session.compacting"]?.(
|
|
{ sessionID: "test" },
|
|
output,
|
|
);
|
|
|
|
expect(output.context).toHaveLength(2);
|
|
expect(output.context[0]).toBe("Existing context");
|
|
expect(output.context[1]).toContain("Keep exact file paths.");
|
|
expect(output.context[1]).toContain("Preserve the active hypothesis.");
|
|
expect(output.context[1]).toContain("Compaction complete.");
|
|
});
|
|
|
|
test("supports replacing the default prompt", async () => {
|
|
const context = await createContext();
|
|
const hooks = await CompactionPromptPlugin(context as never, {
|
|
mode: "replace",
|
|
prompt: "Preserve the current implementation plan.",
|
|
});
|
|
const output: { context: string[]; prompt?: string } = { context: [] };
|
|
|
|
await hooks["experimental.session.compacting"]?.(
|
|
{ sessionID: "test" },
|
|
output,
|
|
);
|
|
|
|
expect(output.prompt).toContain("User Compaction Instructions");
|
|
expect(output.prompt).toContain(
|
|
"Preserve the current implementation plan.",
|
|
);
|
|
expect(output.context).toHaveLength(0);
|
|
});
|
|
|
|
test("ignores a missing memory file", async () => {
|
|
const context = await createContext();
|
|
const hooks = await CompactionPromptPlugin(context as never);
|
|
const output = { context: [] as string[] };
|
|
|
|
await hooks["experimental.session.compacting"]?.(
|
|
{ sessionID: "test" },
|
|
output,
|
|
);
|
|
|
|
expect(context.logs).toHaveLength(0);
|
|
expect(output.context).toHaveLength(0);
|
|
});
|
|
|
|
test("does not modify compaction when no instructions are provided", async () => {
|
|
const context = await createContext();
|
|
const hooks = await CompactionPromptPlugin(context as never);
|
|
const output: { context: string[]; prompt?: string } = {
|
|
context: ["Existing context"],
|
|
};
|
|
|
|
await hooks["experimental.session.compacting"]?.(
|
|
{ sessionID: "test" },
|
|
output,
|
|
);
|
|
|
|
expect(output.context).toEqual(["Existing context"]);
|
|
expect(output.prompt).toBeUndefined();
|
|
});
|
|
|
|
test("logs non-missing memory file errors without failing compaction", async () => {
|
|
const context = await createContext();
|
|
await writeFile(path.join(context.worktree, "memory"), "not a directory");
|
|
const hooks = await CompactionPromptPlugin(context as never, {
|
|
memoryFile: "memory/file.md",
|
|
});
|
|
const output = { context: [] as string[] };
|
|
|
|
await hooks["experimental.session.compacting"]?.(
|
|
{ sessionID: "test" },
|
|
output,
|
|
);
|
|
|
|
expect(context.logs).toHaveLength(1);
|
|
expect(output.context).toHaveLength(0);
|
|
});
|
|
});
|