SPB Git

spb/khaelor Public

KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.

TypeScript 82.9% HTML 14.9% CSS 1.1% JavaScript 0.7%
3.2 KB · 92 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: tests/context/budget.test.ts4 * Description: ContextBudget tests — real-usage accounting, thresholds, config-driven windows.5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import { describe, expect, it } from "vitest";11import {12  ContextBudget,13  DEFAULT_CONTEXT_WINDOW,14  resolveContextWindow,15} from "../../src/context/index.js";1617describe("resolveContextWindow", () => {18  it("falls back to the default window when nothing is configured", () => {19    expect(resolveContextWindow("any-model")).toBe(DEFAULT_CONTEXT_WINDOW);20  });2122  it("uses a configured default window", () => {23    expect(resolveContextWindow("any-model", { defaultWindow: 500_000 })).toBe(500_000);24  });2526  it("prefers an exact per-model override from config", () => {27    const config = { defaultWindow: 200_000, byModel: { "big-model": 1_000_000 } };28    expect(resolveContextWindow("big-model", config)).toBe(1_000_000);29    expect(resolveContextWindow("other-model", config)).toBe(200_000);30  });3132  it("ignores invalid overrides", () => {33    expect(resolveContextWindow("m", { byModel: { m: -5 }, defaultWindow: 0 })).toBe(34      DEFAULT_CONTEXT_WINDOW,35    );36  });37});3839describe("ContextBudget", () => {40  const budget = () =>41    new ContextBudget({42      model: "m",43      reservedOutputTokens: 1_000,44      contextWindow: { defaultWindow: 10_000 },45      compactionBufferTokens: 1_000,46      pruneThresholdRatio: 0.5,47    });4849  it("computes usableWindow = window − reservedOutput − compactionBuffer", () => {50    expect(budget().usableWindow).toBe(8_000);51  });5253  it("starts with no observed usage and zero pressure", () => {54    const b = budget();55    expect(b.hasObservedUsage).toBe(false);56    expect(b.lastTotalTokens).toBe(0);57    expect(b.pressure()).toBe(0);58    expect(b.level()).toBe("ok");59  });6061  it("records real usage including cache reads and writes", () => {62    const b = budget();63    b.onUsage({ inputTokens: 1_000, outputTokens: 500, cacheReadTokens: 6_000, cacheWriteTokens: 1_000 });64    expect(b.lastTotalTokens).toBe(8_500);65    expect(b.hasObservedUsage).toBe(true);66  });6768  it("levels: ok → prune → compact as fake usage crosses thresholds", () => {69    const b = budget();70    b.onUsage({ inputTokens: 3_000, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 });71    expect(b.level()).toBe("ok");72    expect(b.shouldCompact()).toBe(false);7374    b.onUsage({ inputTokens: 4_500, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 });75    expect(b.level()).toBe("prune"); // ≥ 50% of 800076    expect(b.shouldCompact()).toBe(false);7778    b.onUsage({ inputTokens: 8_000, outputTokens: 100, cacheReadTokens: 0, cacheWriteTokens: 0 });79    expect(b.level()).toBe("compact");80    expect(b.shouldCompact()).toBe(true);81    expect(b.pressure()).toBeGreaterThanOrEqual(1);82  });8384  it("tracks only the LAST turn's usage (context footprint, not a running sum)", () => {85    const b = budget();86    b.onUsage({ inputTokens: 7_900, outputTokens: 200, cacheReadTokens: 0, cacheWriteTokens: 0 });87    expect(b.level()).toBe("compact");88    b.onUsage({ inputTokens: 100, outputTokens: 10, cacheReadTokens: 0, cacheWriteTokens: 0 });89    expect(b.level()).toBe("ok");90  });91});92