server/bot-folder.test.ts
Rama main · réplica de lectura del repositorio original.
// Test isolation is provided by server/testing/setup.ts's per-file throwaway HOME.
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
const {
BOTS_DIR,
botFolder,
checkSoulDrift,
readSoulDrift,
removeBotFolder,
soulFile,
soulHash,
soulSystemPrompt,
writeSoulMirror,
} = await import("./bot-folder.ts");
describe("bot folder", () => {
it("lives under DATA_DIR/bots/<id>", () => {
// DATA_DIR is computed from homedir() during config.ts import
const DATA_DIR = join(homedir(), ".openmausbot");
expect(BOTS_DIR).toBe(join(DATA_DIR, "bots"));
expect(botFolder("b1")).toBe(join(BOTS_DIR, "b1"));
expect(soulFile("b1")).toBe(join(BOTS_DIR, "b1", "SOUL.md"));
});
it("writes the mirror with private modes, even when the soul is empty", () => {
writeSoulMirror("b2", "");
expect(readFileSync(soulFile("b2"), "utf8")).toBe("");
if (process.platform !== "win32") {
expect(statSync(botFolder("b2")).mode & 0o777).toBe(0o700);
expect(statSync(soulFile("b2")).mode & 0o777).toBe(0o600);
}
writeSoulMirror("b2", "# Kiwi\nFile bugs, never noise.\n");
expect(readFileSync(soulFile("b2"), "utf8")).toBe("# Kiwi\nFile bugs, never noise.\n");
});
it("hashes deterministically", () => {
expect(soulHash("a")).toBe(soulHash("a"));
expect(soulHash("a")).not.toBe(soulHash("b"));
expect(soulHash("")).toMatch(/^[0-9a-f]{64}$/);
});
it("reports no drift when the mirror matches, and re-creates a missing mirror", () => {
const soul = "Be brief.";
const hash = soulHash(soul);
expect(existsSync(soulFile("b3"))).toBe(false);
expect(checkSoulDrift("b3", soul, hash)).toEqual({ drift: false });
expect(readFileSync(soulFile("b3"), "utf8")).toBe(soul);
expect(checkSoulDrift("b3", soul, hash)).toEqual({ drift: false });
});
it("reports drift with the file text when the mirror was edited", () => {
const soul = "Be brief.";
writeSoulMirror("b4", soul);
writeFileSync(soulFile("b4"), "Be verbose.");
expect(checkSoulDrift("b4", soul, soulHash(soul))).toEqual({ drift: true, fileText: "Be verbose." });
});
it("surfaces unreadable mirrors to the editor without breaking turn dispatch", () => {
mkdirSync(soulFile("broken"), { recursive: true });
expect(() => readSoulDrift("broken", "canonical", soulHash("canonical"))).toThrow();
expect(checkSoulDrift("broken", "canonical", soulHash("canonical"))).toEqual({ drift: false });
});
it("bounds external mirror reads to the standing-instructions budget", () => {
writeSoulMirror("oversized", "🐭".repeat(6_000));
expect(readSoulDrift("oversized", "", soulHash(""))).toMatchObject({ drift: true });
writeFileSync(soulFile("oversized"), "🐭".repeat(6_001));
expect(() => readSoulDrift("oversized", "", soulHash(""))).toThrow("shorten it in your editor");
expect(checkSoulDrift("oversized", "", soulHash(""))).toEqual({ drift: false });
});
it("removes the folder, and tolerates a folder that is already gone", () => {
writeSoulMirror("b5", "x");
removeBotFolder("b5");
expect(existsSync(botFolder("b5"))).toBe(false);
expect(() => removeBotFolder("b5")).not.toThrow();
});
it("renders an empty block for an empty or whitespace soul, and a fenced block otherwise", () => {
expect(soulSystemPrompt("")).toBe("");
expect(soulSystemPrompt(" \n")).toBe("");
const block = soulSystemPrompt("Be brief.\n");
expect(block.startsWith("\n\n")).toBe(true);
expect(block).toContain("--- BEGIN STANDING INSTRUCTIONS (SOUL.md, 9 bytes) ---\nBe brief.\n--- END STANDING INSTRUCTIONS ---");
expect(block).toContain("proposed changes apply only after the user confirms");
expect(block).not.toContain("propose_profile");
});
});