import { describe, expect, it } from "vitest"; import { buildAgentSystemPrompt } from "./system-prompt.js"; describe("buildAgentSystemPrompt", () => { it("includes owner numbers when provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", ownerNumbers: ["+123", " +456 ", ""], }); expect(prompt).toContain("## User Identity"); expect(prompt).toContain( "Owner numbers: +123, +456. Treat messages from these numbers as the user.", ); }); it("omits owner section when numbers are missing", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", }); expect(prompt).not.toContain("## User Identity"); expect(prompt).not.toContain("Owner numbers:"); }); it("omits extended sections in minimal prompt mode", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", promptMode: "minimal", ownerNumbers: ["+123"], skillsPrompt: "\n \n demo\n \n", heartbeatPrompt: "ping", toolNames: ["message", "memory_search"], docsPath: "/tmp/clawd/docs", extraSystemPrompt: "Subagent details", }); expect(prompt).not.toContain("## User Identity"); expect(prompt).not.toContain("## Skills"); expect(prompt).not.toContain("## Memory Recall"); expect(prompt).not.toContain("## Documentation"); expect(prompt).not.toContain("## Reply Tags"); expect(prompt).not.toContain("## Messaging"); expect(prompt).not.toContain("## Silent Replies"); expect(prompt).not.toContain("## Heartbeats"); expect(prompt).toContain("## Subagent Context"); expect(prompt).not.toContain("## Group Chat Context"); expect(prompt).toContain("Subagent details"); }); it("adds reasoning tag hint when enabled", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", reasoningTagHint: true, }); expect(prompt).toContain("## Reasoning Format"); expect(prompt).toContain("..."); expect(prompt).toContain("..."); }); it("includes a CLI quick reference section", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", }); expect(prompt).toContain("## Clawdbot CLI Quick Reference"); expect(prompt).toContain("clawdbot daemon restart"); expect(prompt).toContain("Do not invent commands"); }); it("lists available tools when provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", toolNames: ["exec", "sessions_list", "sessions_history", "sessions_send"], }); expect(prompt).toContain("Tool availability (filtered by policy):"); expect(prompt).toContain("sessions_list"); expect(prompt).toContain("sessions_history"); expect(prompt).toContain("sessions_send"); }); it("preserves tool casing in the prompt", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", toolNames: ["Read", "Exec", "process"], skillsPrompt: "\n \n demo\n \n", docsPath: "/tmp/clawd/docs", }); expect(prompt).toContain("- Read: Read file contents"); expect(prompt).toContain("- Exec: Run shell commands"); expect(prompt).toContain( "Use `Read` to load the SKILL.md at the location listed for that skill.", ); expect(prompt).toContain("Clawdbot docs: /tmp/clawd/docs"); expect(prompt).toContain("read the docs first using `Read`"); }); it("includes docs guidance when docsPath is provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", docsPath: "/tmp/clawd/docs", }); expect(prompt).toContain("## Documentation"); expect(prompt).toContain("Clawdbot docs: /tmp/clawd/docs"); expect(prompt).toContain( "When a user asks about Clawdbot behavior, commands, config, or architecture", ); }); it("includes user time when provided (12-hour)", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", userTimezone: "America/Chicago", userTime: "Monday, January 5th, 2026 — 3:26 PM", userTimeFormat: "12", }); expect(prompt).toContain("## Current Date & Time"); expect(prompt).toContain("Monday, January 5th, 2026 — 3:26 PM (America/Chicago)"); expect(prompt).toContain("Time format: 12-hour"); }); it("includes user time when provided (24-hour)", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", userTimezone: "America/Chicago", userTime: "Monday, January 5th, 2026 — 15:26", userTimeFormat: "24", }); expect(prompt).toContain("## Current Date & Time"); expect(prompt).toContain("Monday, January 5th, 2026 — 15:26 (America/Chicago)"); expect(prompt).toContain("Time format: 24-hour"); }); it("shows UTC fallback when only timezone is provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", userTimezone: "America/Chicago", userTimeFormat: "24", }); expect(prompt).toContain("## Current Date & Time"); expect(prompt).toContain( "Time zone: America/Chicago. Current time unknown; assume UTC for date/time references.", ); }); it("includes model alias guidance when aliases are provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", modelAliasLines: [ "- Opus: anthropic/claude-opus-4-5", "- Sonnet: anthropic/claude-sonnet-4-5", ], }); expect(prompt).toContain("## Model Aliases"); expect(prompt).toContain("Prefer aliases when specifying model overrides"); expect(prompt).toContain("- Opus: anthropic/claude-opus-4-5"); }); it("adds ClaudeBot self-update guidance when gateway tool is available", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", toolNames: ["gateway", "exec"], }); expect(prompt).toContain("## Clawdbot Self-Update"); expect(prompt).toContain("config.apply"); expect(prompt).toContain("update.run"); }); it("includes skills guidance when skills prompt is present", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", skillsPrompt: "\n \n demo\n \n", }); expect(prompt).toContain("## Skills"); expect(prompt).toContain( "Use `read` to load the SKILL.md at the location listed for that skill.", ); }); it("appends available skills when provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", skillsPrompt: "\n \n demo\n \n", }); expect(prompt).toContain(""); expect(prompt).toContain("demo"); }); it("omits skills section when no skills prompt is provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", }); expect(prompt).not.toContain("## Skills"); expect(prompt).not.toContain(""); }); it("renders project context files when provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", contextFiles: [ { path: "AGENTS.md", content: "Alpha" }, { path: "IDENTITY.md", content: "Bravo" }, ], }); expect(prompt).toContain("# Project Context"); expect(prompt).toContain("## AGENTS.md"); expect(prompt).toContain("Alpha"); expect(prompt).toContain("## IDENTITY.md"); expect(prompt).toContain("Bravo"); }); it("summarizes the message tool when available", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", toolNames: ["message"], }); expect(prompt).toContain("message: Send messages and channel actions"); expect(prompt).toContain("### message tool"); expect(prompt).toContain("respond with ONLY: NO_REPLY"); }); it("includes runtime provider capabilities when present", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", runtimeInfo: { channel: "telegram", capabilities: ["inlineButtons"], }, }); expect(prompt).toContain("channel=telegram"); expect(prompt).toContain("capabilities=inlineButtons"); }); it("includes reasoning visibility hint", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", reasoningLevel: "off", }); expect(prompt).toContain("Reasoning: off"); expect(prompt).toContain("/reasoning"); expect(prompt).toContain("/status shows Reasoning"); }); it("describes sandboxed runtime and elevated when allowed", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", sandboxInfo: { enabled: true, workspaceDir: "/tmp/sandbox", workspaceAccess: "ro", agentWorkspaceMount: "/agent", elevated: { allowed: true, defaultLevel: "on" }, }, }); expect(prompt).toContain("You are running in a sandboxed runtime"); expect(prompt).toContain("Sub-agents stay sandboxed"); expect(prompt).toContain("User can toggle with /elevated on|off."); expect(prompt).toContain("Current elevated level: on"); }); it("includes reaction guidance when provided", () => { const prompt = buildAgentSystemPrompt({ workspaceDir: "/tmp/clawd", reactionGuidance: { level: "minimal", channel: "Telegram", }, }); expect(prompt).toContain("## Reactions"); expect(prompt).toContain("Reactions are enabled for Telegram in MINIMAL mode."); }); });