Files
openclaw/src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.e2e.test.ts
Charlie Greenman dec6859702 agents: reduce prompt token bloat from exec and context (#16539)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8e1635fa3fdfb199a58bd53e816abc41cd400d44
Co-authored-by: CharlieGreenman <8540141+CharlieGreenman@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 18:32:45 -05:00

103 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
buildBootstrapContextFiles,
DEFAULT_BOOTSTRAP_MAX_CHARS,
DEFAULT_BOOTSTRAP_TOTAL_MAX_CHARS,
} from "./pi-embedded-helpers.js";
import { DEFAULT_AGENTS_FILENAME } from "./workspace.js";
const makeFile = (overrides: Partial<WorkspaceBootstrapFile>): WorkspaceBootstrapFile => ({
name: DEFAULT_AGENTS_FILENAME,
path: "/tmp/AGENTS.md",
content: "",
missing: false,
...overrides,
});
describe("buildBootstrapContextFiles", () => {
it("keeps missing markers", () => {
const files = [makeFile({ missing: true, content: undefined })];
expect(buildBootstrapContextFiles(files)).toEqual([
{
path: "/tmp/AGENTS.md",
content: "[MISSING] Expected at: /tmp/AGENTS.md",
},
]);
});
it("skips empty or whitespace-only content", () => {
const files = [makeFile({ content: " \n " })];
expect(buildBootstrapContextFiles(files)).toEqual([]);
});
it("truncates large bootstrap content", () => {
const head = `HEAD-${"a".repeat(600)}`;
const tail = `${"b".repeat(300)}-TAIL`;
const long = `${head}${tail}`;
const files = [makeFile({ name: "TOOLS.md", content: long })];
const warnings: string[] = [];
const maxChars = 200;
const expectedTailChars = Math.floor(maxChars * 0.2);
const [result] = buildBootstrapContextFiles(files, {
maxChars,
warn: (message) => warnings.push(message),
});
expect(result?.content).toContain("[...truncated, read TOOLS.md for full content...]");
expect(result?.content.length).toBeLessThan(long.length);
expect(result?.content.startsWith(long.slice(0, 120))).toBe(true);
expect(result?.content.endsWith(long.slice(-expectedTailChars))).toBe(true);
expect(warnings).toHaveLength(1);
expect(warnings[0]).toContain("TOOLS.md");
expect(warnings[0]).toContain("limit 200");
});
it("keeps content under the default limit", () => {
const long = "a".repeat(DEFAULT_BOOTSTRAP_MAX_CHARS - 10);
const files = [makeFile({ content: long })];
const [result] = buildBootstrapContextFiles(files);
expect(result?.content).toBe(long);
expect(result?.content).not.toContain("[...truncated, read AGENTS.md for full content...]");
});
it("caps total injected bootstrap characters across files", () => {
const files = [
makeFile({ name: "AGENTS.md", content: "a".repeat(10_000) }),
makeFile({ name: "SOUL.md", path: "/tmp/SOUL.md", content: "b".repeat(10_000) }),
makeFile({ name: "USER.md", path: "/tmp/USER.md", content: "c".repeat(10_000) }),
];
const result = buildBootstrapContextFiles(files);
const totalChars = result.reduce((sum, entry) => sum + entry.content.length, 0);
expect(totalChars).toBeLessThanOrEqual(DEFAULT_BOOTSTRAP_TOTAL_MAX_CHARS);
expect(result).toHaveLength(3);
expect(result[2]?.content).toContain("[...truncated, read USER.md for full content...]");
});
it("enforces strict total cap even when truncation markers are present", () => {
const files = [
makeFile({ name: "AGENTS.md", content: "a".repeat(1_000) }),
makeFile({ name: "SOUL.md", path: "/tmp/SOUL.md", content: "b".repeat(1_000) }),
];
const result = buildBootstrapContextFiles(files, {
maxChars: 100,
totalMaxChars: 150,
});
const totalChars = result.reduce((sum, entry) => sum + entry.content.length, 0);
expect(totalChars).toBeLessThanOrEqual(150);
});
it("skips bootstrap injection when remaining total budget is too small", () => {
const files = [makeFile({ name: "AGENTS.md", content: "a".repeat(1_000) })];
const result = buildBootstrapContextFiles(files, {
maxChars: 200,
totalMaxChars: 40,
});
expect(result).toEqual([]);
});
it("keeps missing markers under small total budgets", () => {
const files = [makeFile({ missing: true, content: undefined })];
const result = buildBootstrapContextFiles(files, {
totalMaxChars: 20,
});
expect(result).toHaveLength(1);
expect(result[0]?.content.length).toBeLessThanOrEqual(20);
expect(result[0]?.content.startsWith("[MISSING]")).toBe(true);
});
});