From d4b7fa6903168452eb867697b64b2254e654ac41 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Sun, 10 May 2026 17:48:30 +0530 Subject: [PATCH] test(context): cover context map media (#79867) --- CHANGELOG.md | 1 + .../reply/commands-context-report.test.ts | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac48374351d..b2167df9f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai ### Changes +- Context: add `/context map` to send a treemap image of the current session context contributors. (#79867) - Plugin SDK: deprecate public subpaths that existed for at least one month and have no bundled extension production imports, keep legacy barrel/test/zod subpath package exports for backwards compatibility, and track both sets in the SDK surface report. - Plugin SDK: deprecate public subpaths currently used by only one or two bundled plugin owners, keeping them importable while steering new plugin code to focused shared SDK seams or plugin-owned APIs. - Plugin SDK: remove the owner-specific `provider-auth-login` public subpath after moving Chutes, GitHub Copilot, and OpenAI Codex auth flows back to provider-owned modules. diff --git a/src/auto-reply/reply/commands-context-report.test.ts b/src/auto-reply/reply/commands-context-report.test.ts index 2f3a24fa2cc..0df2c9709b1 100644 --- a/src/auto-reply/reply/commands-context-report.test.ts +++ b/src/auto-reply/reply/commands-context-report.test.ts @@ -1,3 +1,4 @@ +import { readFile, unlink } from "node:fs/promises"; import { describe, expect, it } from "vitest"; import type { SessionEntry } from "../../config/sessions.js"; import { buildContextReply } from "./commands-context-report.js"; @@ -155,4 +156,30 @@ describe("buildContextReply", () => { expect(result.text).toContain("Session tokens (cached): 900 total / ctx=8,192"); expect(result.text).not.toContain("Actual context usage (cached): 111 tok"); }); + + it("renders context map as sensitive local PNG media", async () => { + const result = await buildContextReply( + makeParams("/context map", false, { + contextTokens: 8_192, + totalTokens: 900, + }), + ); + if (!result.mediaUrl) { + throw new Error("missing context map media path"); + } + try { + const png = await readFile(result.mediaUrl); + expect(result.text).toContain("Context treemap"); + expect(result.text).toContain("Source: run"); + expect(result.text).toContain("Actual cached context: 900 tok"); + expect(result.trustedLocalMedia).toBe(true); + expect(result.sensitiveMedia).toBe(true); + expect(png.subarray(0, 8)).toEqual(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])); + expect(png.subarray(12, 16).toString("ascii")).toBe("IHDR"); + expect(png.readUInt32BE(16)).toBe(1280); + expect(png.readUInt32BE(20)).toBe(860); + } finally { + await unlink(result.mediaUrl); + } + }); });