Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions .sandcastle/context-compressor.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* Unit tests for context-compressor — the headroom-ai wrapper that shrinks
* compiled prompts before they reach the agent.
*
* All tests set / restore process.env.HEADROOM_MODE around each assertion so
* they are order-independent (getHeadroomMode() reads the env var at call time,
* not at module load time, which is what makes this possible).
*
* Run: npm test (picks up all *.test.ts files listed in the test script)
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import {
getHeadroomMode,
getCompressionCallback,
isCompressionActive,
} from "./context-compressor.ts";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function withMode(mode: string | undefined, fn: () => void): void {
const orig = process.env.HEADROOM_MODE;
if (mode === undefined) {
delete process.env.HEADROOM_MODE;
} else {
process.env.HEADROOM_MODE = mode;
}
try {
fn();
} finally {
if (orig === undefined) {
delete process.env.HEADROOM_MODE;
} else {
process.env.HEADROOM_MODE = orig;
}
}
}

// ---------------------------------------------------------------------------
// getHeadroomMode
// ---------------------------------------------------------------------------

test("getHeadroomMode returns 'off' when HEADROOM_MODE is unset", () => {
withMode(undefined, () => {
assert.equal(getHeadroomMode(), "off");
});
});

test("getHeadroomMode returns 'conservative' when HEADROOM_MODE=conservative", () => {
withMode("conservative", () => {
assert.equal(getHeadroomMode(), "conservative");
});
});

test("getHeadroomMode returns 'aggressive' when HEADROOM_MODE=aggressive", () => {
withMode("aggressive", () => {
assert.equal(getHeadroomMode(), "aggressive");
});
});

// ---------------------------------------------------------------------------
// isCompressionActive
// ---------------------------------------------------------------------------

test("isCompressionActive returns false when HEADROOM_MODE is unset (default off)", () => {
withMode(undefined, () => {
assert.equal(isCompressionActive(), false);
});
});

test("isCompressionActive returns true when HEADROOM_MODE=conservative", () => {
withMode("conservative", () => {
assert.equal(isCompressionActive(), true);
});
});

test("isCompressionActive returns true when HEADROOM_MODE=aggressive", () => {
withMode("aggressive", () => {
assert.equal(isCompressionActive(), true);
});
});

// ---------------------------------------------------------------------------
// getCompressionCallback — structural shape tests (no live headroom-ai call)
// ---------------------------------------------------------------------------

test("getCompressionCallback returns undefined when HEADROOM_MODE is off (default off)", () => {
withMode(undefined, () => {
assert.equal(getCompressionCallback(), undefined);
});
});

test("getCompressionCallback returns a function when HEADROOM_MODE=conservative", () => {
withMode("conservative", () => {
const cb = getCompressionCallback();
assert.equal(typeof cb, "function");
});
});

test("getCompressionCallback returns a function when HEADROOM_MODE=aggressive", () => {
withMode("aggressive", () => {
const cb = getCompressionCallback();
assert.equal(typeof cb, "function");
});
});

test("getCompressionCallback returns an async function (returns a Promise)", () => {
withMode("conservative", () => {
const cb = getCompressionCallback();
assert.ok(cb !== undefined);
// An async function always returns a Promise synchronously, before any
// `await` inside it (here, the dynamic `import("headroom-ai")`) resolves
// or rejects — so this holds regardless of whether headroom-ai succeeds.
const result = cb("test prompt");
assert.ok(result instanceof Promise, "callback must return a Promise");
// Consume any rejection so node:test doesn't treat it as an unhandled error.
result.catch(() => {});
});
});
25 changes: 14 additions & 11 deletions .sandcastle/context-compressor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,21 @@
/** Compression mode — off by default for safe rollout. */
export type HeadroomMode = "off" | "conservative" | "aggressive";

const HEADROOM_MODE: HeadroomMode =
(process.env.HEADROOM_MODE as HeadroomMode) || "off";

const HEADROOM_MODEL = process.env.HEADROOM_MODEL || "claude-sonnet-4-6";

/** Current headroom mode (for tests and logging). */
/** Current headroom mode — reads env var at call time so tests can set it after module load. */
export function getHeadroomMode(): HeadroomMode {
return HEADROOM_MODE;
return (process.env.HEADROOM_MODE as HeadroomMode) || "off";
}

/** Resolve the compression callback, or undefined if disabled. */
export function getCompressionCallback() {
if (HEADROOM_MODE === "off") return undefined;
const mode = getHeadroomMode();
if (mode === "off") return undefined;

const model = process.env.HEADROOM_MODEL || "claude-sonnet-4-6";
return async (prompt: string): Promise<string> => {
const { compress } = await import("headroom-ai");
const messages = [{ role: "user" as const, content: prompt }];
const result = await compress(messages, { model: HEADROOM_MODEL });
const result = await compress(messages, { model });
// CompressResult.messages is typed `any[]` (headroom preserves whatever
// format was passed in) — validate the shape at runtime rather than
// trusting it, so a proxy-side format drift degrades to uncompressed
Expand All @@ -44,11 +41,17 @@ export function getCompressionCallback() {
);
return prompt;
}
// Token savings measurement: log before/after char counts (~4 chars/token).
const saved = prompt.length - content.length;
const pct = ((saved / prompt.length) * 100).toFixed(1);
console.log(
`[context-compressor] mode=${mode} ${prompt.length}→${content.length} chars (−${saved}, −${pct}%)`,
);
return content;
};
}

/** Whether compression is active (for logging). */
/** Whether compression is active (for proxy injection and logging). */
export function isCompressionActive(): boolean {
return HEADROOM_MODE !== "off";
return getHeadroomMode() !== "off";
}
2 changes: 1 addition & 1 deletion .sandcastle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"postinstall": "patch-package",
"start": "tsx main.ts",
"typecheck": "tsc --noEmit",
"test": "node --import tsx --test reduce.test.ts sandbox-runner.test.ts reviewer-adapter.test.ts memory.test.ts memory-store.test.ts run-sh.test.ts init-sh.test.ts up-sh.test.ts afk-cmd.test.ts",
"test": "node --import tsx --test reduce.test.ts sandbox-runner.test.ts reviewer-adapter.test.ts memory.test.ts memory-store.test.ts run-sh.test.ts init-sh.test.ts up-sh.test.ts afk-cmd.test.ts context-compressor.test.ts",
"test:integration": "SANDCASTLE_INTEGRATION=1 node --import tsx --test integration.test.ts"
},
"devDependencies": {
Expand Down
38 changes: 38 additions & 0 deletions .sandcastle/sandbox-runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,41 @@ test("claude tier: no sandboxEnv override when HEADROOM_MODE is off (default)",
const input = buildAgentInput({ tier: "claude" }, STUB_ISSUE);
assert.equal(input.sandboxEnv, undefined);
});

test("claude tier agent gets ANTHROPIC_BASE_URL proxy override when HEADROOM_MODE=conservative", () => {
const orig = process.env.HEADROOM_MODE;
process.env.HEADROOM_MODE = "conservative";
try {
const input = buildAgentInput({ tier: "claude" }, STUB_ISSUE);
assert.deepEqual(input.sandboxEnv, { ANTHROPIC_BASE_URL: "http://host.docker.internal:8787" });
} finally {
if (orig === undefined) delete process.env.HEADROOM_MODE;
else process.env.HEADROOM_MODE = orig;
}
});

test("claude tier agent gets ANTHROPIC_BASE_URL proxy override when HEADROOM_MODE=aggressive", () => {
const orig = process.env.HEADROOM_MODE;
process.env.HEADROOM_MODE = "aggressive";
try {
const input = buildAgentInput({ tier: "claude" }, STUB_ISSUE);
assert.deepEqual(input.sandboxEnv, { ANTHROPIC_BASE_URL: "http://host.docker.internal:8787" });
} finally {
if (orig === undefined) delete process.env.HEADROOM_MODE;
else process.env.HEADROOM_MODE = orig;
}
});

test("local tier is never proxy-routed regardless of HEADROOM_MODE", () => {
const orig = process.env.HEADROOM_MODE;
process.env.HEADROOM_MODE = "conservative";
try {
// local tier uses opencode; ANTHROPIC_BASE_URL proxy injection only
// applies to the claudeCode agent path (sandbox-runner.ts L225 tier gate).
const input = buildAgentInput({ tier: "local" }, STUB_ISSUE);
assert.equal(input.agent.name, "opencode");
} finally {
if (orig === undefined) delete process.env.HEADROOM_MODE;
else process.env.HEADROOM_MODE = orig;
}
});
Loading