import { describe, expect, it } from "vitest"; import { buildContextReply } from "./commands-context-report.js"; import type { HandleCommandsParams } from "./commands-types.js"; function makeParams( commandBodyNormalized: string, truncated: boolean, options?: { omitBootstrapLimits?: boolean }, ): HandleCommandsParams { return { command: { commandBodyNormalized, channel: "telegram", senderIsOwner: true, }, sessionKey: "agent:default:main", workspaceDir: "/tmp/workspace", contextTokens: null, provider: "openai", model: "gpt-5", elevated: { allowed: false }, resolvedThinkLevel: "off", resolvedReasoningLevel: "off", sessionEntry: { totalTokens: 123, inputTokens: 100, outputTokens: 23, systemPromptReport: { source: "run", generatedAt: Date.now(), workspaceDir: "/tmp/workspace", bootstrapMaxChars: options?.omitBootstrapLimits ? undefined : 20_000, bootstrapTotalMaxChars: options?.omitBootstrapLimits ? undefined : 150_000, sandbox: { mode: "off", sandboxed: false }, preparation: { totalMs: 123, skillsMs: 11, bootstrapMs: 22, toolsMs: 33, runtimeInfoMs: 4, docsPathMs: 5, systemPromptBuildMs: 6, }, systemPrompt: { chars: 1_000, projectContextChars: 500, nonProjectContextChars: 500, }, injectedWorkspaceFiles: [ { name: "AGENTS.md", path: "/tmp/workspace/AGENTS.md", missing: false, rawChars: truncated ? 200_000 : 10_000, injectedChars: truncated ? 20_000 : 10_000, truncated, }, ], skills: { promptChars: 10, entries: [{ name: "checks", blockChars: 10 }], }, tools: { listChars: 10, schemaChars: 20, entries: [{ name: "read", summaryChars: 10, schemaChars: 20, propertiesCount: 1 }], }, }, }, cfg: {}, ctx: {}, commandBody: "", commandArgs: [], resolvedElevatedLevel: "off", } as unknown as HandleCommandsParams; } describe("buildContextReply", () => { it("shows bootstrap truncation warning in list output when context exceeds configured limits", async () => { const result = await buildContextReply(makeParams("/context list", true)); expect(result.text).toContain("Bootstrap max/total: 150,000 chars"); expect(result.text).toContain("⚠ Bootstrap context is over configured limits"); expect(result.text).toContain("Causes: 1 file(s) exceeded max/file."); }); it("does not show bootstrap truncation warning when there is no truncation", async () => { const result = await buildContextReply(makeParams("/context list", false)); expect(result.text).not.toContain("Bootstrap context is over configured limits"); }); it("falls back to config defaults when legacy reports are missing bootstrap limits", async () => { const result = await buildContextReply( makeParams("/context list", false, { omitBootstrapLimits: true, }), ); expect(result.text).toContain("Bootstrap max/file: 20,000 chars"); expect(result.text).toContain("Bootstrap max/total: 150,000 chars"); expect(result.text).not.toContain("Bootstrap max/file: ? chars"); }); it("shows prompt preparation timings in detail mode when available", async () => { const result = await buildContextReply(makeParams("/context detail", false)); expect(result.text).toContain("Prompt prep total: 123 ms"); expect(result.text).toContain("- bootstrap/context: 22 ms"); expect(result.text).toContain("- system prompt build: 6 ms"); }); });