- Only inject workspace.md into system prompt (not soul, user, memory)
- Add profile directory path to workspace section for on-demand file access
- Agent now reads soul.md, user.md, memory.md on first session using tools
- Reduces system prompt size and improves token efficiency
- Aligns with workspace.md template instructions ("Read soul.md first")
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
261 lines
9.8 KiB
TypeScript
261 lines
9.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { buildSystemPrompt, buildSystemPromptWithReport } from "./builder.js";
|
|
import type { SystemPromptOptions } from "./types.js";
|
|
|
|
const PROFILE = {
|
|
soul: "# Soul\nYou are a helpful coding assistant.",
|
|
user: "# User\nName: Alice",
|
|
workspace: "# Workspace\nFollow conventional commits.",
|
|
memory: "# Memory\nUser prefers TypeScript.",
|
|
config: { name: "TestAgent" },
|
|
};
|
|
|
|
const TOOLS = ["read", "write", "edit", "glob", "exec", "memory_get", "memory_set", "sessions_spawn", "web_search"];
|
|
|
|
describe("buildSystemPrompt", () => {
|
|
// ── Full mode ─────────────────────────────────────────────────────────
|
|
|
|
it("full mode includes workspace section only (progressive disclosure)", () => {
|
|
// Soul, user, memory are read on-demand by the agent
|
|
const result = buildSystemPrompt({ mode: "full", profile: PROFILE });
|
|
expect(result).not.toContain("# Soul");
|
|
expect(result).not.toContain("# User");
|
|
expect(result).toContain("# Workspace");
|
|
expect(result).not.toContain("# Memory");
|
|
});
|
|
|
|
it("full mode includes safety constitution", () => {
|
|
const result = buildSystemPrompt({ mode: "full" });
|
|
expect(result).toContain("## Safety");
|
|
expect(result).toContain("no independent goals");
|
|
});
|
|
|
|
it("full mode includes tooling summary when tools provided", () => {
|
|
const result = buildSystemPrompt({ mode: "full", tools: TOOLS });
|
|
expect(result).toContain("## Tooling");
|
|
expect(result).toContain("- read: Read file contents");
|
|
expect(result).toContain("- exec: Run shell commands");
|
|
});
|
|
|
|
it("full mode includes tool call style section", () => {
|
|
const result = buildSystemPrompt({ mode: "full", tools: TOOLS });
|
|
expect(result).toContain("## Tool Call Style");
|
|
});
|
|
|
|
it("full mode includes memory section when memory tools present", () => {
|
|
const result = buildSystemPrompt({ mode: "full", tools: ["memory_get", "memory_set"] });
|
|
expect(result).toContain("## Memory");
|
|
expect(result).toContain("search memory first");
|
|
});
|
|
|
|
it("full mode includes sub-agents section when sessions_spawn present", () => {
|
|
const result = buildSystemPrompt({ mode: "full", tools: ["sessions_spawn"] });
|
|
expect(result).toContain("## Sub-Agents");
|
|
});
|
|
|
|
it("full mode includes web access section when web tools present", () => {
|
|
const result = buildSystemPrompt({ mode: "full", tools: ["web_search"] });
|
|
expect(result).toContain("## Web Access");
|
|
});
|
|
|
|
it("full mode includes skills section when provided", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "full",
|
|
skillsPrompt: "## commit\nRun conventional commits.",
|
|
});
|
|
expect(result).toContain("## Skills (mandatory)");
|
|
expect(result).toContain("## commit");
|
|
});
|
|
|
|
it("full mode includes runtime info line", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "full",
|
|
runtime: { agentName: "test", os: "darwin", arch: "arm64", nodeVersion: "v22.0.0" },
|
|
});
|
|
expect(result).toContain("## Runtime");
|
|
expect(result).toContain("agent=test");
|
|
expect(result).toContain("os=darwin (arm64)");
|
|
});
|
|
|
|
it("full mode includes profile info in workspace section", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "full",
|
|
profileDir: "/home/user/.super-multica/agent-profiles/test",
|
|
profile: { workspace: "Workspace rules" },
|
|
});
|
|
expect(result).toContain("## Profile");
|
|
expect(result).toContain("/home/user/.super-multica/agent-profiles/test");
|
|
expect(result).toContain("soul.md");
|
|
expect(result).toContain("user.md");
|
|
expect(result).toContain("memory.md");
|
|
});
|
|
|
|
it("full mode excludes subagent section", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "full",
|
|
subagent: { requesterSessionId: "a", childSessionId: "b", task: "test" },
|
|
});
|
|
expect(result).not.toContain("## Subagent Rules");
|
|
});
|
|
|
|
// ── Minimal mode ──────────────────────────────────────────────────────
|
|
|
|
it("minimal mode excludes profile content", () => {
|
|
const result = buildSystemPrompt({ mode: "minimal", profile: PROFILE });
|
|
expect(result).not.toContain("# Soul");
|
|
expect(result).not.toContain("# User");
|
|
expect(result).not.toContain("# Workspace");
|
|
expect(result).not.toContain("# Memory");
|
|
});
|
|
|
|
it("minimal mode includes safety constitution", () => {
|
|
const result = buildSystemPrompt({ mode: "minimal" });
|
|
expect(result).toContain("## Safety");
|
|
});
|
|
|
|
it("minimal mode includes tooling summary", () => {
|
|
const result = buildSystemPrompt({ mode: "minimal", tools: ["read", "write"] });
|
|
expect(result).toContain("## Tooling");
|
|
});
|
|
|
|
it("minimal mode includes subagent context", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "minimal",
|
|
subagent: { requesterSessionId: "parent-1", childSessionId: "child-1", task: "Search for bugs" },
|
|
});
|
|
expect(result).toContain("## Subagent Rules");
|
|
expect(result).toContain("Search for bugs");
|
|
expect(result).toContain("parent-1");
|
|
});
|
|
|
|
it("minimal mode excludes skills section", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "minimal",
|
|
skillsPrompt: "## commit\nSome skill.",
|
|
});
|
|
expect(result).not.toContain("## Skills");
|
|
});
|
|
|
|
it("minimal mode excludes sub-agents section even with sessions_spawn", () => {
|
|
const result = buildSystemPrompt({ mode: "minimal", tools: ["sessions_spawn"] });
|
|
expect(result).not.toContain("## Sub-Agents");
|
|
});
|
|
|
|
// ── None mode ─────────────────────────────────────────────────────────
|
|
|
|
it("none mode includes identity line with agent name", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "none",
|
|
profile: { config: { name: "Multica" } },
|
|
});
|
|
expect(result).toContain("You are Multica, a Super Multica agent.");
|
|
});
|
|
|
|
it("none mode includes safety constitution", () => {
|
|
const result = buildSystemPrompt({ mode: "none" });
|
|
expect(result).toContain("## Safety");
|
|
});
|
|
|
|
it("none mode excludes tooling and skills", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "none",
|
|
tools: TOOLS,
|
|
skillsPrompt: "some skills",
|
|
});
|
|
expect(result).not.toContain("## Tooling");
|
|
expect(result).not.toContain("## Skills");
|
|
});
|
|
|
|
it("none mode includes subagent context", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "none",
|
|
subagent: { requesterSessionId: "a", childSessionId: "b", task: "do stuff" },
|
|
});
|
|
expect(result).toContain("## Task");
|
|
expect(result).toContain("do stuff");
|
|
});
|
|
|
|
// ── Cross-cutting ─────────────────────────────────────────────────────
|
|
|
|
it("safety can be disabled via includeSafety=false", () => {
|
|
const result = buildSystemPrompt({ mode: "full", includeSafety: false });
|
|
expect(result).not.toContain("## Safety");
|
|
});
|
|
|
|
it("extra system prompt is appended", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "full",
|
|
extraSystemPrompt: "Always respond in French.",
|
|
});
|
|
expect(result).toContain("## Additional Context");
|
|
expect(result).toContain("Always respond in French.");
|
|
});
|
|
|
|
it("extra system prompt uses subagent header in minimal mode", () => {
|
|
const result = buildSystemPrompt({
|
|
mode: "minimal",
|
|
extraSystemPrompt: "Focus on tests.",
|
|
});
|
|
expect(result).toContain("## Subagent Context");
|
|
});
|
|
|
|
it("returns empty-ish prompt when no options", () => {
|
|
const result = buildSystemPrompt({ mode: "none" });
|
|
// Should at least have identity + safety
|
|
expect(result).toContain("Super Multica agent");
|
|
expect(result).toContain("Safety");
|
|
});
|
|
|
|
it("handles unknown tools gracefully", () => {
|
|
const result = buildSystemPrompt({ mode: "full", tools: ["custom_tool", "read"] });
|
|
expect(result).toContain("- read: Read file contents");
|
|
expect(result).toContain("- custom_tool");
|
|
});
|
|
});
|
|
|
|
describe("buildSystemPromptWithReport", () => {
|
|
it("report includes accurate section counts", () => {
|
|
const { report } = buildSystemPromptWithReport({
|
|
mode: "full",
|
|
profile: PROFILE,
|
|
tools: TOOLS,
|
|
});
|
|
expect(report.mode).toBe("full");
|
|
expect(report.totalChars).toBeGreaterThan(0);
|
|
expect(report.toolCount).toBe(TOOLS.length);
|
|
expect(report.safetyIncluded).toBe(true);
|
|
|
|
const identitySection = report.sections.find((s) => s.name === "identity");
|
|
expect(identitySection?.included).toBe(true);
|
|
|
|
const subagentSection = report.sections.find((s) => s.name === "subagent");
|
|
expect(subagentSection?.included).toBe(false);
|
|
});
|
|
|
|
it("report reflects skills inclusion", () => {
|
|
const { report: withSkills } = buildSystemPromptWithReport({
|
|
mode: "full",
|
|
skillsPrompt: "some skills",
|
|
});
|
|
expect(withSkills.skillsIncluded).toBe(true);
|
|
|
|
const { report: withoutSkills } = buildSystemPromptWithReport({
|
|
mode: "full",
|
|
});
|
|
expect(withoutSkills.skillsIncluded).toBe(false);
|
|
});
|
|
|
|
it("report marks excluded sections correctly in minimal mode", () => {
|
|
const { report } = buildSystemPromptWithReport({ mode: "minimal" });
|
|
// Identity is now included in all modes (just a one-liner)
|
|
const identity = report.sections.find((s) => s.name === "identity");
|
|
expect(identity?.included).toBe(true);
|
|
|
|
// User and memory are excluded (progressive disclosure)
|
|
const user = report.sections.find((s) => s.name === "user");
|
|
expect(user?.included).toBe(false);
|
|
|
|
const safety = report.sections.find((s) => s.name === "safety");
|
|
expect(safety?.included).toBe(true);
|
|
});
|
|
});
|