multica/src/agent/profile/storage.test.ts
Jiayuan 9661226979 feat(profile): enhance templates with user.md and workspace.md
- Enrich soul.md with core truths, boundaries, and continuity guidance
  inspired by moltbot's template design
- Add user.md template for building user profile and preferences
- Add workspace.md template for workspace behavior guidelines
- Update memory.md and bootstrap.md with more structured content
- Update all related storage, types, and test files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:04:35 +08:00

250 lines
8.4 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { existsSync, mkdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
getProfileDir,
ensureProfileDir,
profileExists,
readProfileFile,
writeProfileFile,
loadProfile,
saveProfile,
} from "./storage.js";
describe("storage", () => {
const testBaseDir = join(tmpdir(), `multica-test-${Date.now()}`);
beforeEach(() => {
// Create fresh test directory
if (existsSync(testBaseDir)) {
rmSync(testBaseDir, { recursive: true });
}
mkdirSync(testBaseDir, { recursive: true });
});
afterEach(() => {
// Clean up test directory
if (existsSync(testBaseDir)) {
rmSync(testBaseDir, { recursive: true });
}
});
describe("getProfileDir", () => {
it("should return correct path with custom baseDir", () => {
const result = getProfileDir("test-profile", { baseDir: testBaseDir });
expect(result).toBe(join(testBaseDir, "test-profile"));
});
it("should handle profile IDs with special characters", () => {
const result = getProfileDir("profile-with-dashes", { baseDir: testBaseDir });
expect(result).toBe(join(testBaseDir, "profile-with-dashes"));
});
});
describe("ensureProfileDir", () => {
it("should create directory if it does not exist", () => {
const profileId = "new-profile";
const dir = ensureProfileDir(profileId, { baseDir: testBaseDir });
expect(existsSync(dir)).toBe(true);
expect(dir).toBe(join(testBaseDir, profileId));
});
it("should not fail if directory already exists", () => {
const profileId = "existing-profile";
const expectedDir = join(testBaseDir, profileId);
mkdirSync(expectedDir, { recursive: true });
const dir = ensureProfileDir(profileId, { baseDir: testBaseDir });
expect(dir).toBe(expectedDir);
expect(existsSync(dir)).toBe(true);
});
});
describe("profileExists", () => {
it("should return false for non-existent profile", () => {
const result = profileExists("non-existent", { baseDir: testBaseDir });
expect(result).toBe(false);
});
it("should return true for existing profile", () => {
const profileId = "existing";
mkdirSync(join(testBaseDir, profileId), { recursive: true });
const result = profileExists(profileId, { baseDir: testBaseDir });
expect(result).toBe(true);
});
});
describe("readProfileFile", () => {
it("should return undefined for non-existent file", () => {
const profileId = "profile";
mkdirSync(join(testBaseDir, profileId), { recursive: true });
const result = readProfileFile(profileId, "missing.md", { baseDir: testBaseDir });
expect(result).toBeUndefined();
});
it("should return file contents for existing file", () => {
const profileId = "profile";
const fileName = "test.md";
const content = "# Test Content\n\nThis is a test.";
const dir = join(testBaseDir, profileId);
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, fileName), content);
const result = readProfileFile(profileId, fileName, { baseDir: testBaseDir });
expect(result).toBe(content);
});
it("should return undefined for non-existent profile directory", () => {
const result = readProfileFile("non-existent", "file.md", { baseDir: testBaseDir });
expect(result).toBeUndefined();
});
});
describe("writeProfileFile", () => {
it("should create file in existing directory", () => {
const profileId = "profile";
const fileName = "test.md";
const content = "Test content";
writeProfileFile(profileId, fileName, content, { baseDir: testBaseDir });
const filePath = join(testBaseDir, profileId, fileName);
expect(existsSync(filePath)).toBe(true);
expect(readFileSync(filePath, "utf-8")).toBe(content);
});
it("should create directory if it does not exist", () => {
const profileId = "new-profile";
const fileName = "test.md";
const content = "Test content";
writeProfileFile(profileId, fileName, content, { baseDir: testBaseDir });
const filePath = join(testBaseDir, profileId, fileName);
expect(existsSync(filePath)).toBe(true);
});
it("should overwrite existing file", () => {
const profileId = "profile";
const fileName = "test.md";
const dir = join(testBaseDir, profileId);
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, fileName), "Original content");
writeProfileFile(profileId, fileName, "New content", { baseDir: testBaseDir });
expect(readFileSync(join(dir, fileName), "utf-8")).toBe("New content");
});
});
describe("loadProfile", () => {
it("should load all profile files", () => {
const profileId = "full-profile";
const dir = join(testBaseDir, profileId);
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, "SOUL.md"), "Soul content");
writeFileSync(join(dir, "IDENTITY.md"), "Identity content");
writeFileSync(join(dir, "USER.md"), "User content");
writeFileSync(join(dir, "WORKSPACE.md"), "Workspace content");
writeFileSync(join(dir, "MEMORY.md"), "Memory content");
writeFileSync(join(dir, "BOOTSTRAP.md"), "Bootstrap content");
const profile = loadProfile(profileId, { baseDir: testBaseDir });
expect(profile.id).toBe(profileId);
expect(profile.soul).toBe("Soul content");
expect(profile.identity).toBe("Identity content");
expect(profile.user).toBe("User content");
expect(profile.workspace).toBe("Workspace content");
expect(profile.memory).toBe("Memory content");
expect(profile.bootstrap).toBe("Bootstrap content");
});
it("should return undefined for missing files", () => {
const profileId = "partial-profile";
const dir = join(testBaseDir, profileId);
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, "SOUL.md"), "Soul only");
const profile = loadProfile(profileId, { baseDir: testBaseDir });
expect(profile.id).toBe(profileId);
expect(profile.soul).toBe("Soul only");
expect(profile.identity).toBeUndefined();
expect(profile.user).toBeUndefined();
expect(profile.workspace).toBeUndefined();
expect(profile.memory).toBeUndefined();
expect(profile.bootstrap).toBeUndefined();
});
it("should handle non-existent profile", () => {
const profile = loadProfile("non-existent", { baseDir: testBaseDir });
expect(profile.id).toBe("non-existent");
expect(profile.soul).toBeUndefined();
expect(profile.identity).toBeUndefined();
});
});
describe("saveProfile", () => {
it("should save all defined profile fields", () => {
const profile = {
id: "save-test",
soul: "Soul data",
identity: "Identity data",
user: "User data",
workspace: "Workspace data",
memory: "Memory data",
bootstrap: "Bootstrap data",
};
saveProfile(profile, { baseDir: testBaseDir });
const dir = join(testBaseDir, profile.id);
expect(readFileSync(join(dir, "SOUL.md"), "utf-8")).toBe("Soul data");
expect(readFileSync(join(dir, "IDENTITY.md"), "utf-8")).toBe("Identity data");
expect(readFileSync(join(dir, "USER.md"), "utf-8")).toBe("User data");
expect(readFileSync(join(dir, "WORKSPACE.md"), "utf-8")).toBe("Workspace data");
expect(readFileSync(join(dir, "MEMORY.md"), "utf-8")).toBe("Memory data");
expect(readFileSync(join(dir, "BOOTSTRAP.md"), "utf-8")).toBe("Bootstrap data");
});
it("should only save defined fields", () => {
const profile = {
id: "partial-save",
soul: "Soul only",
identity: undefined,
user: undefined,
workspace: undefined,
memory: undefined,
bootstrap: undefined,
};
saveProfile(profile, { baseDir: testBaseDir });
const dir = join(testBaseDir, profile.id);
expect(existsSync(join(dir, "SOUL.md"))).toBe(true);
expect(existsSync(join(dir, "IDENTITY.md"))).toBe(false);
});
it("should create profile directory if needed", () => {
const profile = {
id: "new-save-profile",
soul: "Content",
};
saveProfile(profile, { baseDir: testBaseDir });
expect(existsSync(join(testBaseDir, profile.id))).toBe(true);
});
});
});