feat(compression): context-budget adaptive compression (Phase 4C) [stacked on #4707] (#4716)

Phase 4C: adaptive context-budget compression. Integrated into release/v3.8.35.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-23 08:13:27 -03:00
committed by GitHub
parent fdbc000b85
commit 98fc576a42
15 changed files with 668 additions and 6 deletions

View File

@@ -136,7 +136,7 @@
"open-sse/services/claudeCodeCompatible.ts": 1202,
"_rebaseline_pr4592_exclude_exhausted_auto": "Reconcile #4592 already-merged growth: combo.ts 2991->3036 (+45, terminal-status quota-cutoff exclusion in buildAutoCandidates + opt-in gate). Fast-gate PR->release does not run check:file-size.",
"open-sse/services/combo.ts": 3036,
"open-sse/services/compression/strategySelector.ts": 818,
"open-sse/services/compression/strategySelector.ts": 848,
"open-sse/services/rateLimitManager.ts": 1035,
"open-sse/services/tokenRefresh.ts": 1997,
"open-sse/services/usage.ts": 3450,
@@ -304,5 +304,6 @@
"_rebaseline_2026_06_19_4293_codex_spark_scope": "PR #4293 (isolate Codex Spark quota scope) own growth, MEASURED on the actual merged tree (release/v3.8.30 + #4293). Production: auth.ts 2219->2279 (+60) threads requestedModel into Codex quota-policy/headroom/preflight/P2C scoring so normal Codex and GPT-5.3-Codex-Spark windows are evaluated independently; chatCore.ts 5116->5125 (+9) passes the failing model scope into Codex 429 failover (markCodexScopeRateLimited) instead of a connection-wide rateLimitedUntil write; accountFallback.ts 1727->1731 (+4) scopes Codex model-lock keys to codex vs spark. Heavy parsing/display logic lives in new leaf helpers under the cap (codexQuotaScopes.ts, codexUsageQuotas.ts, codexFailover.ts). Tests: account-fallback-service 1544->1569, executor-codex 1336->1339, sse-auth 1527->1553, usage-service-hardening 1612->1633 (added Spark-scope regression coverage). Cohesive wiring at existing selection/failover lockout boundaries; not extractable.",
"_rebaseline_2026_06_20_4447_openai_gpt41mini_o_mini_pricing": "PR #4447 own growth: pricing.ts 1592->1620 (+28 = pure-data pricing rows closing the null/$0 gap for registry-exposed OpenAI ids gpt-4.1-mini, gpt-4.1-nano, o3-mini, o4-mini that tripped the catalog pricing gate; getPricingForModel does an exact lookup, so a missing key resolves to null. Official OpenAI per-1M prices + the table's derived-field convention (reasoning=output*1.5, cache_creation=input, cached=official). Restore-green for a pre-existing release/v3.8.32 red surfaced by #4432's __RUN_ALL__ run. Cohesive data; not extractable.",
"_rebaseline_2026_06_20_web_cookie_validator_shadow_fix": "validation.ts 4518->4522 (+4 = move the generic web-cookie validateWebCookieProvider dispatch from the TOP of validateProviderApiKey to a FALLBACK after SPECIALTY_VALIDATORS, plus a comment, so #4023's generic AUTH_007 ping no longer shadows the rich per-provider validators (grok-web #3474 IP-reputation/Cloudflare, chatgpt-web cf-mitigated, claude/gemini/copilot/qwen/t3-web). Restores provider-validation-specialty.test.ts (112/112) while keeping web-cookie-auth007 (5/5). Behavior fix at an existing dispatch boundary; not extractable.",
"_rebaseline_2026_06_22_phase4b_slm_tier_ultra": "Compression Phase 4 (B) SLM tier own growth: open-sse/services/compression/strategySelector.ts 783->818 (+35 at the existing applyUltraAsync chokepoint). The no-modelPath ultra branch (previously a one-line passthrough to the sync applyCompression) now runs the two-tier resolver: it adapts the body, builds the ultraConfig (threading config.ultraEngine + preserveSystemPrompt), awaits the now-async ultraCompress (SLM Tier-B when ultraEngine===slm and the worker backend is available, else fail-open to the Tier-A heuristic), and threads result.stats.ultraTier into the returned CompressionStats so the resolved tier reaches the D0 telemetry persister. The sync applyCompression ultra branch is also re-pointed to the new pure ultraCompressHeuristic. The two-tier resolver + the pure heuristic live in open-sse/services/compression/ultra.ts and the thin SLM entry in engines/llmlingua/ultraEntry.ts (both <cap, fully unit-tested); strategySelector.ts is cohesive dispatch wiring at the existing ultra chokepoint, not extractable without hiding the dispatch boundary. Covered by tests/unit/compression/ultra-slm-tier.test.ts (applyCompressionAsync ultraTier:slm) + ultra.test.ts (39 regression) + the integration suites. Structural shrink of this file tracked in #3501."
"_rebaseline_2026_06_22_phase4b_slm_tier_ultra": "Compression Phase 4 (B) SLM tier own growth: open-sse/services/compression/strategySelector.ts 783->818 (+35 at the existing applyUltraAsync chokepoint). The no-modelPath ultra branch (previously a one-line passthrough to the sync applyCompression) now runs the two-tier resolver: it adapts the body, builds the ultraConfig (threading config.ultraEngine + preserveSystemPrompt), awaits the now-async ultraCompress (SLM Tier-B when ultraEngine===slm and the worker backend is available, else fail-open to the Tier-A heuristic), and threads result.stats.ultraTier into the returned CompressionStats so the resolved tier reaches the D0 telemetry persister. The sync applyCompression ultra branch is also re-pointed to the new pure ultraCompressHeuristic. The two-tier resolver + the pure heuristic live in open-sse/services/compression/ultra.ts and the thin SLM entry in engines/llmlingua/ultraEntry.ts (both <cap, fully unit-tested); strategySelector.ts is cohesive dispatch wiring at the existing ultra chokepoint, not extractable without hiding the dispatch boundary. Covered by tests/unit/compression/ultra-slm-tier.test.ts (applyCompressionAsync ultraTier:slm) + ultra.test.ts (39 regression) + the integration suites. Structural shrink of this file tracked in #3501.",
"_rebaseline_2026_06_22_phase4c_adaptive_context_budget": "Compression Phase 4 (C) adaptive context-budget wiring own growth: open-sse/services/compression/strategySelector.ts 818->848 (+30 at the existing selectCompressionPlan dispatch chokepoint). selectCompressionPlan gains an 8th optional `adaptiveOptions` param (modelContextLimit/requestMaxTokens/onAdaptive sink) and, after resolveBasePlan and before the caching-aware pass, runs the PURE resolveAdaptivePlan when config.contextBudget.mode is floor|replace-autotrigger; the new adaptiveEnabled(config) helper also gates the legacy shouldAutoTrigger branch inside resolveBasePlan off when adaptive owns automatic-by-size escalation (D-C4). The escalation ladder, target computation, and the resolver itself live in open-sse/services/compression/adaptiveCompression/{computeTarget,ladder,resolveAdaptivePlan,types}.ts (all <cap, fully unit-tested by Tasks 1-4). strategySelector.ts is cohesive dispatch wiring at the existing compression chokepoint, not extractable without hiding the dispatch boundary, mirroring the prior compression rebaselines (#4217/#4210/phase4b). Covered by tests/unit/compression/adaptive-select-plan-wiring.test.ts (4 tests) + adaptive-chatcore-source-guard.test.ts (2). chatCore.ts also grows ~30 lines at the same call site (threads getTokenLimit(provider,effectiveModel) + request max_tokens into adaptiveOptions and records the adaptive telemetry block onto compression.completed) but stays under its frozen cap. Structural shrink of this file tracked in #3501."
}

View File

@@ -1162,6 +1162,15 @@ export async function handleChatCore({
}
}
const compressionInputBody = body as Record<string, unknown>;
// Adaptive context-budget (Sub-project C): model context window + request max_tokens drive
// the budget target. getTokenLimit is already imported; provider/effectiveModel resolved above.
const adaptiveModelContextLimit =
provider && effectiveModel ? getTokenLimit(provider, effectiveModel) : null;
const requestMaxTokens =
typeof (compressionInputBody as Record<string, unknown>)?.max_tokens === "number"
? ((compressionInputBody as Record<string, unknown>).max_tokens as number)
: null;
let adaptiveTelemetry: import("../services/compression/adaptiveCompression/types.ts").AdaptiveTelemetry | null = null;
const compressionPlan = selectCompressionPlan(
config,
compressionComboKey,
@@ -1169,9 +1178,20 @@ export async function handleChatCore({
compressionInputBody,
{ provider, targetFormat, model: effectiveModel },
namedCombos,
compressionHeader
compressionHeader,
{
modelContextLimit: adaptiveModelContextLimit,
requestMaxTokens: requestMaxTokens,
onAdaptive: (t) => { adaptiveTelemetry = t; },
}
);
const mode = compressionPlan.mode as CompressionConfig["defaultMode"];
if (adaptiveTelemetry && adaptiveTelemetry.fit === false) {
log?.warn?.(
"COMPRESSION",
`adaptive budget-exceeded: target=${adaptiveTelemetry.target} headroomAfter=${adaptiveTelemetry.headroomAfter} stages=${adaptiveTelemetry.stagesApplied.join(",")} (best-effort plan sent, content preserved)`
);
}
compressionResponseMeta = formatCompressionMeta(compressionPlan);
// When the per-engine toggle map derives a stacked pipeline (and no named/routing
// combo already set config.stackedPipeline), feed that derived pipeline through so
@@ -1252,6 +1272,7 @@ export async function handleChatCore({
engineBreakdown: ensureEngineBreakdown(result.stats),
validationWarnings: result.stats.validationWarnings,
fallbackApplied: result.stats.fallbackApplied,
...(adaptiveTelemetry ? { adaptive: adaptiveTelemetry } : {}),
timestamp: Date.now(),
};
emit("compression.completed", compressionCompletedPayload);

View File

@@ -0,0 +1,31 @@
import type { ContextBudgetConfig, ContextBudgetPolicy } from "./types.ts";
/**
* Pure target-token computation (design D-C1). No clock, no DB, no tokenizer.
*
* @param policy active target policy
* @param modelContextLimit the resolved upstream model's context window (impure caller looks it up)
* @param requestMaxTokens request.max_tokens, if the client sent one (reserve-output only)
* @param config reserves / margin / pct / absoluteBudget
* @returns the maximum prompt-token target the compressed request should fit within
*/
export function computeTarget(
policy: ContextBudgetPolicy,
modelContextLimit: number,
requestMaxTokens: number | null,
config: Pick<ContextBudgetConfig, "outputReserve" | "safetyMargin" | "pct" | "absoluteBudget">
): number {
if (policy === "absolute") {
return Math.max(0, Math.floor(config.absoluteBudget));
}
if (policy === "percentage") {
const pct = config.pct > 0 && config.pct <= 1 ? config.pct : 1;
return Math.max(0, Math.floor(modelContextLimit * pct));
}
// reserve-output (default): limit output reservation safety margin.
const reserve =
typeof requestMaxTokens === "number" && requestMaxTokens > 0
? requestMaxTokens
: config.outputReserve;
return Math.max(0, Math.floor(modelContextLimit - reserve - config.safetyMargin));
}

View File

@@ -0,0 +1,59 @@
import type { LadderStage } from "./types.ts";
/**
* Default escalation ladder (design D-C2): cheapest/most-lossless → most aggressive.
* Ordered by the engine catalog's stackPriority. `ccr` and `llmlingua` are intentionally
* excluded from the AUTOMATIC ladder (ccr = retrieval markers, llmlingua = optional ONNX
* SLM tier wired through `ultra`); an operator can still add them via ladderOverride.
*/
export const DEFAULT_LADDER: LadderStage[] = [
{ engine: "session-dedup" }, // lossless cross-turn dedup (catalog pri 3)
{ engine: "rtk", intensity: "standard" }, // command-output filtering (pri 10)
{ engine: "headroom" }, // tabular JSON compaction (pri 15)
{ engine: "lite" }, // whitespace/format cleanup (pri 5, but cheap prose pass)
{ engine: "caveman", intensity: "full" }, // rule-based prose (pri 20)
{ engine: "aggressive" }, // summarize + age old turns (pri 30)
{ engine: "ultra" }, // heuristic token pruning + optional SLM (pri 40)
];
/**
* Aggressiveness rank used to know where a base plan sits so `floor` mode escalates
* BEYOND it (design §4.2). Keyed by engine id AND by the equivalent CompressionMode name
* ("standard" === caveman) so a base plan's `mode` string maps cleanly.
*/
const AGGRESSIVENESS: Record<string, number> = {
off: 0,
"session-dedup": 1,
rtk: 2,
headroom: 3,
lite: 4,
caveman: 5,
standard: 5, // mode-name alias for caveman
stacked: 5, // a derived/stacked base plan sits at the prose tier; floor escalates past it
aggressive: 6,
ultra: 7,
};
export function aggressivenessOf(engineOrMode: string): number {
return AGGRESSIVENESS[engineOrMode] ?? 0;
}
/**
* Cheap per-engine EXPECTED reduction factor (output/input). Used by the default injected
* estimator to model "apply this stage" WITHOUT a dry-run (design §9: no per-stage dry-run
* in the hot path). Conservative, monotonic with aggressiveness; never 0 (content preserved).
*/
const REDUCTION_FACTOR: Record<string, number> = {
"session-dedup": 0.95,
rtk: 0.85,
headroom: 0.8,
lite: 0.92,
caveman: 0.7,
standard: 0.7,
aggressive: 0.55,
ultra: 0.4,
};
export function expectedReductionFactor(engine: string): number {
return REDUCTION_FACTOR[engine] ?? 0.9;
}

View File

@@ -0,0 +1,104 @@
import type { DerivedPlan } from "../deriveDefaultPlan.ts";
import type { AdaptiveTelemetry, ContextBudgetConfig, LadderStage } from "./types.ts";
import { DEFAULT_LADDER, aggressivenessOf, expectedReductionFactor } from "./ladder.ts";
import { computeTarget } from "./computeTarget.ts";
export interface ResolveAdaptiveInput {
basePlan: DerivedPlan;
estimatedTokens: number;
modelContextLimit: number | null;
requestMaxTokens: number | null;
config: ContextBudgetConfig;
/**
* Injected per-stage estimator (design §4.1/§9). Returns the NEW token estimate after a
* stage is applied to a prompt of `priorTokens`. Default models it with the cheap
* per-engine expected-reduction factor (no dry-run, no real tokenizer).
*/
estimate?: (priorTokens: number, stage: LadderStage) => number;
}
export interface ResolveAdaptiveResult {
plan: DerivedPlan;
telemetry: AdaptiveTelemetry | null;
}
const defaultEstimate = (prior: number, stage: LadderStage): number =>
Math.round(prior * expectedReductionFactor(stage.engine));
/**
* Pure adaptive resolver (design §4.2). Floors/escalates a base plan so the (estimated)
* compressed prompt fits the context budget. Never drops content: if the ladder is
* exhausted while still over target, returns the best-effort plan with fit=false.
*
* Returns telemetry=null only when there is no usable target (unknown model limit) — the
* caller then skips adaptive entirely (design §6: skip, never throw).
*/
export function resolveAdaptivePlan(input: ResolveAdaptiveInput): ResolveAdaptiveResult {
const { basePlan, estimatedTokens, modelContextLimit, requestMaxTokens, config } = input;
const estimate = input.estimate ?? defaultEstimate;
if (config.mode === "off") return { plan: basePlan, telemetry: null };
if (!modelContextLimit || modelContextLimit <= 0) {
return { plan: basePlan, telemetry: null }; // unknown limit → skip (D-C / §6)
}
const target = computeTarget(config.policy, modelContextLimit, requestMaxTokens, config);
const headroomBefore = target - estimatedTokens;
// replace-autotrigger only acts on a bare Default/off base plan; an explicit choice wins.
const baseRank = aggressivenessOf(basePlan.mode);
if (config.mode === "replace-autotrigger" && baseRank > aggressivenessOf("off")) {
return {
plan: basePlan,
telemetry: { policy: config.policy, target, headroomBefore, stagesApplied: [], headroomAfter: headroomBefore, fit: headroomBefore >= 0 },
};
}
// Already fits → never over-compress (D-C2).
if (headroomBefore >= 0) {
return {
plan: basePlan,
telemetry: { policy: config.policy, target, headroomBefore, stagesApplied: [], headroomAfter: headroomBefore, fit: true },
};
}
// Escalation: start just ABOVE the base plan's aggressiveness (floor escalates beyond it).
const ladder = config.ladderOverride && config.ladderOverride.length > 0 ? config.ladderOverride : DEFAULT_LADDER;
const startTier = config.mode === "floor" ? baseRank : aggressivenessOf("off");
const stages = ladder.filter((s) => aggressivenessOf(s.engine) > startTier);
let current = estimatedTokens;
const applied: LadderStage[] = [];
for (const stage of stages) {
current = estimate(current, stage);
applied.push(stage);
if (current <= target) break;
}
const headroomAfter = target - current;
const fit = headroomAfter >= 0;
return {
plan: planFromStages(basePlan, applied),
telemetry: {
policy: config.policy,
target,
headroomBefore,
stagesApplied: applied.map((s) => s.engine),
headroomAfter,
fit,
},
};
}
/**
* Turn the applied ladder stages into a DerivedPlan. A single applied stage that is a
* single-mode engine collapses to that engine's mode; otherwise a stacked pipeline.
* The base plan's own pipeline is preserved as the prefix (floor escalates AFTER the base).
*/
function planFromStages(basePlan: DerivedPlan, applied: LadderStage[]): DerivedPlan {
if (applied.length === 0) return basePlan;
const basePipeline =
basePlan.mode === "stacked" ? basePlan.stackedPipeline : [];
const stackedPipeline = [...basePipeline, ...applied];
return { mode: "stacked", stackedPipeline };
}

View File

@@ -0,0 +1,61 @@
/**
* Context-budget adaptive compression — shared types.
*
* Naming note: "adaptiveCompression"/"contextBudget" — NOT "headroom" (which is an
* unrelated existing engine). "headroom" here = the budget signal (target prompt tokens).
*/
/** Target-derivation policy (design D-C1). */
export type ContextBudgetPolicy = "reserve-output" | "percentage" | "absolute";
/**
* Adaptive mode (design D-C3/C4):
* - "floor" : guarantee fit; escalate BEYOND any base plan.
* - "replace-autotrigger" : only acts when the base plan is bare Default/off (an explicit
* operator/client choice always wins, even if it overflows).
* - "off" : legacy binary auto-trigger (full backward-compat).
*/
export type ContextBudgetMode = "floor" | "replace-autotrigger" | "off";
/** One escalation stage = an engine id applied at an optional intensity. */
export interface LadderStage {
engine: string;
intensity?: string;
}
/** Persisted adaptive settings (design §4.4). All optional with safe defaults in computeTarget. */
export interface ContextBudgetConfig {
mode: ContextBudgetMode;
policy: ContextBudgetPolicy;
/** reserve-output: tokens reserved for the model's output when request.max_tokens is absent. */
outputReserve: number;
/** reserve-output: extra tokens shaved off the limit as a safety buffer. */
safetyMargin: number;
/** percentage policy: fraction of the model context window to target (0 < pct <= 1). */
pct: number;
/** absolute policy: a model-independent token budget. */
absoluteBudget: number;
/** Operator override of the default escalation ladder (cheapest → most aggressive). */
ladderOverride?: LadderStage[];
}
/** The `adaptive` block of the shared CompressionRunTelemetry contract (roadmap overview). */
export interface AdaptiveTelemetry {
policy: ContextBudgetPolicy;
target: number;
headroomBefore: number;
stagesApplied: string[];
headroomAfter: number;
/** false => budget-exceeded (best-effort plan sent as-is; content never dropped). */
fit: boolean;
}
/** Safe defaults applied when a field is absent (design §4.4 / §6). */
export const DEFAULT_CONTEXT_BUDGET: ContextBudgetConfig = {
mode: "off",
policy: "reserve-output",
outputReserve: 4096,
safetyMargin: 1024,
pct: 0.85,
absoluteBudget: 0,
};

View File

@@ -29,6 +29,8 @@ import {
deriveDefaultPlanFromConfig,
buildNamedComboLookup,
} from "./planResolution.ts";
import { resolveAdaptivePlan } from "./adaptiveCompression/resolveAdaptivePlan.ts";
import type { AdaptiveTelemetry } from "./adaptiveCompression/types.ts";
// Re-export so existing importers (resolver test + chatCore dynamic import) keep resolving.
export { planFromHeader, formatCompressionMeta, buildNamedComboLookup };
@@ -68,6 +70,12 @@ export function shouldAutoTrigger(config: CompressionConfig, estimatedTokens: nu
* `combos` defaults to `{}` so Phase-1 callers are unchanged; when supplied, chatCore passes
* its DB-loaded named-combo map so the active profile can resolve here purely (no DB import).
*/
/** True when the adaptive resolver owns automatic-by-size escalation (D-C4). */
function adaptiveEnabled(config: CompressionConfig): boolean {
const mode = config.contextBudget?.mode;
return mode === "floor" || mode === "replace-autotrigger";
}
function resolveBasePlan(
config: CompressionConfig,
comboId: string | null,
@@ -101,7 +109,7 @@ function resolveBasePlan(
);
}
if (shouldAutoTrigger(config, estimatedTokens)) {
if (!adaptiveEnabled(config) && shouldAutoTrigger(config, estimatedTokens)) {
const mode = config.autoTriggerMode ?? "lite";
return withSource(
mode === "stacked"
@@ -154,6 +162,13 @@ export function getEffectiveMode(
* The caching-aware mode adjustment is applied to `mode` exactly as in
* {@link selectCompressionStrategy}.
*/
/** Adaptive (Sub-project C) inputs + telemetry sink for selectCompressionPlan. */
export interface AdaptiveSelectOptions {
modelContextLimit?: number | null;
requestMaxTokens?: number | null;
onAdaptive?: (telemetry: AdaptiveTelemetry) => void;
}
export function selectCompressionPlan(
config: CompressionConfig,
comboId: string | null,
@@ -161,9 +176,24 @@ export function selectCompressionPlan(
body?: Record<string, unknown>,
context?: CachingDetectionContext,
combos: NamedCombos = {},
header: string | null = null
header: string | null = null,
adaptiveOptions?: AdaptiveSelectOptions
): DerivedPlan {
const plan = resolveBasePlan(config, comboId, estimatedTokens, combos, header);
let plan = resolveBasePlan(config, comboId, estimatedTokens, combos, header);
// Adaptive context-budget floor/escalation (D-C4): after the base plan, replacing the
// (now-bypassed) auto-trigger branch. Pure resolver; chatCore supplies the model limit.
if (adaptiveEnabled(config) && config.contextBudget) {
const { plan: adaptivePlan, telemetry } = resolveAdaptivePlan({
basePlan: plan,
estimatedTokens,
modelContextLimit: adaptiveOptions?.modelContextLimit ?? null,
requestMaxTokens: adaptiveOptions?.requestMaxTokens ?? null,
config: config.contextBudget,
});
plan = adaptivePlan;
if (telemetry && adaptiveOptions?.onAdaptive) adaptiveOptions.onAdaptive(telemetry);
}
// Apply caching-aware adjustments to the mode if body is provided
if (body) {

View File

@@ -10,6 +10,7 @@
*/
import { ENGINE_IDS } from "./engineCatalog.ts";
import type { ContextBudgetConfig } from "./adaptiveCompression/types.ts";
// Re-export so consumers that already import from this module (e.g. src/lib/db/compression.ts)
// can get ENGINE_IDS without a second bare `@omniroute/open-sse/...engineCatalog.ts` specifier.
@@ -161,6 +162,13 @@ export interface CompressionConfig {
* change for installs that predate the panel). Set by `getCompressionSettings`.
*/
enginesExplicit?: boolean;
/**
* Context-budget adaptive compression (Sub-project C). Absent / mode:"off" = legacy
* binary auto-trigger (byte-identical). When mode is "floor" or "replace-autotrigger"
* the adaptive resolver owns automatic-by-size escalation and the legacy
* shouldAutoTrigger branch is bypassed.
*/
contextBudget?: ContextBudgetConfig;
/**
* Phase 4 (B): which tier the `ultra` mode uses.
* "heuristic" = Tier-A token pruner (`pruneByScore`, default, byte-identical to pre-B).

View File

@@ -28,6 +28,11 @@ import {
outputStyleMeta,
} from "../../../../../../open-sse/services/compression/outputStyles/catalog.ts";
import { deriveDefaultPlan } from "../../../../../../open-sse/services/compression/deriveDefaultPlan.ts";
import {
DEFAULT_CONTEXT_BUDGET,
type ContextBudgetConfig,
} from "../../../../../../open-sse/services/compression/adaptiveCompression/types.ts";
import { formatAdaptiveTarget } from "./adaptiveTargetLabel.ts";
type CavemanIntensity = "lite" | "full" | "ultra";
@@ -56,6 +61,10 @@ interface CompressionConfig {
ultraEngine?: "heuristic" | "slm";
// Best-effort pre-warm of the SLM model on enable / cold restart. Default false.
ultraSlmPrewarm?: boolean;
// Phase 4 (C): adaptive context-budget. Absent / mode:"off" = legacy auto-trigger.
// The panel currently surfaces the computed target read-only; mode/policy editors are a
// follow-up (the load/save path does not yet populate this field).
contextBudget?: ContextBudgetConfig;
}
const CAVEMAN_OUTPUT_LEVELS: CavemanIntensity[] = ["lite", "full", "ultra"];
@@ -248,6 +257,14 @@ export default function CompressionPanel() {
<span className="font-medium text-text-main">Effective pipeline:</span> {derivedText}
</div>
{/* Adaptive context-budget — read-only computed target (Phase 4C, D-C1 transparency) */}
<div
data-testid="adaptive-target-preview"
className="mb-4 rounded-md border border-border/60 bg-bg-subtle px-3 py-2 text-xs text-text-muted"
>
{formatAdaptiveTarget(config.contextBudget ?? DEFAULT_CONTEXT_BUDGET, 200000)}
</div>
{/* Engine grid */}
<div className={`divide-y divide-border ${config.enabled ? "" : "opacity-60"}`}>
{ENGINE_IDS.map((id) => {

View File

@@ -0,0 +1,17 @@
import { computeTarget } from "../../../../../../open-sse/services/compression/adaptiveCompression/computeTarget.ts";
import type { ContextBudgetConfig } from "../../../../../../open-sse/services/compression/adaptiveCompression/types.ts";
/**
* Read-only label for the compression panel (design D-C1 transparency). Shows the active
* policy and the computed token target for a representative model context window. PURE —
* imports only the pure computeTarget leaf, no DB, no clock. The panel renders this string
* as an informational/diagnostic line, mirroring the derived-pipeline preview.
*/
export function formatAdaptiveTarget(
config: ContextBudgetConfig,
representativeModelContextLimit: number
): string {
if (config.mode === "off") return "Adaptive context budget: off (legacy auto-trigger)";
const target = computeTarget(config.policy, representativeModelContextLimit, null, config);
return `Adaptive (${config.mode}, policy: ${config.policy}) — target ≈ ${target.toLocaleString()} tokens (for a ${representativeModelContextLimit.toLocaleString()}-token window)`;
}

View File

@@ -0,0 +1,20 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
const chatCore = readFileSync(
fileURLToPath(new URL("../../../open-sse/handlers/chatCore.ts", import.meta.url)),
"utf8"
);
test("chatCore threads modelContextLimit + requestMaxTokens into selectCompressionPlan", () => {
// the adaptive options object literal must reference both inputs
assert.match(chatCore, /modelContextLimit:/);
assert.match(chatCore, /requestMaxTokens:/);
});
test("chatCore emits the adaptive telemetry block via onAdaptive", () => {
assert.match(chatCore, /onAdaptive/);
assert.match(chatCore, /adaptiveTelemetry/);
});

View File

@@ -0,0 +1,30 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { computeTarget } from "@omniroute/open-sse/services/compression/adaptiveCompression/computeTarget.ts";
import { DEFAULT_CONTEXT_BUDGET } from "@omniroute/open-sse/services/compression/adaptiveCompression/types.ts";
const base = { ...DEFAULT_CONTEXT_BUDGET, outputReserve: 4096, safetyMargin: 1024 };
test("reserve-output: request.max_tokens wins over outputReserve default", () => {
// 200000 8000 (request max_tokens) 1024 (safetyMargin) = 190976
const t = computeTarget("reserve-output", 200000, 8000, base);
assert.equal(t, 190976);
});
test("reserve-output: falls back to outputReserve when no max_tokens", () => {
// 200000 4096 (outputReserve) 1024 (safetyMargin) = 194880
assert.equal(computeTarget("reserve-output", 200000, null, base), 194880);
assert.equal(computeTarget("reserve-output", 200000, 0, base), 194880); // 0 is not a positive reserve
});
test("percentage policy: limit × pct, floored", () => {
assert.equal(computeTarget("percentage", 200000, null, { ...base, pct: 0.7 }), 140000);
// invalid pct (out of (0,1]) → treated as 1.0 (no shrink)
assert.equal(computeTarget("percentage", 200000, null, { ...base, pct: 0 }), 200000);
assert.equal(computeTarget("percentage", 200000, null, { ...base, pct: 1.5 }), 200000);
});
test("absolute policy: model-independent budget", () => {
assert.equal(computeTarget("absolute", 200000, 8000, { ...base, absoluteBudget: 50000 }), 50000);
assert.equal(computeTarget("absolute", 8000, null, { ...base, absoluteBudget: 50000 }), 50000);
});

View File

@@ -0,0 +1,31 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { formatAdaptiveTarget } from "../../../src/app/(dashboard)/dashboard/context/settings/adaptiveTargetLabel.ts";
test("formatAdaptiveTarget shows policy + computed target for reserve-output", () => {
const label = formatAdaptiveTarget(
{ mode: "floor", policy: "reserve-output", outputReserve: 4096, safetyMargin: 1024, pct: 0.85, absoluteBudget: 0 },
200000
);
assert.match(label, /reserve-output/);
// 200000 4096 1024 = 194880; tolerate any digit-group separator (locale-dependent toLocaleString).
assert.match(label, /194[.,\s ]?880|194880/);
});
test("formatAdaptiveTarget shows off when disabled", () => {
const label = formatAdaptiveTarget(
{ mode: "off", policy: "reserve-output", outputReserve: 4096, safetyMargin: 1024, pct: 0.85, absoluteBudget: 0 },
200000
);
assert.match(label, /off|disabled/i);
});
test("formatAdaptiveTarget reflects percentage policy target", () => {
const label = formatAdaptiveTarget(
{ mode: "floor", policy: "percentage", outputReserve: 4096, safetyMargin: 1024, pct: 0.7, absoluteBudget: 0 },
200000
);
assert.match(label, /percentage/);
// 200000 × 0.7 = 140000
assert.match(label, /140[.,\s ]?000|140000/);
});

View File

@@ -0,0 +1,150 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import {
DEFAULT_LADDER,
aggressivenessOf,
expectedReductionFactor,
} from "@omniroute/open-sse/services/compression/adaptiveCompression/ladder.ts";
test("default ladder is cheapest → most aggressive (stackPriority order)", () => {
assert.deepEqual(
DEFAULT_LADDER.map((s) => s.engine),
["session-dedup", "rtk", "headroom", "lite", "caveman", "aggressive", "ultra"]
);
});
test("aggressivenessOf increases monotonically along the ladder", () => {
const ranks = DEFAULT_LADDER.map((s) => aggressivenessOf(s.engine));
for (let i = 1; i < ranks.length; i++) {
assert.ok(ranks[i] > ranks[i - 1], `rank must increase at index ${i}`);
}
// a base "lite" plan ranks below caveman/aggressive/ultra (so floor escalates beyond it)
assert.ok(aggressivenessOf("lite") < aggressivenessOf("caveman"));
assert.ok(aggressivenessOf("standard") === aggressivenessOf("caveman")); // mode-name alias
});
test("expectedReductionFactor is in (0,1) and heavier engines reduce more", () => {
assert.ok(expectedReductionFactor("rtk") < 1 && expectedReductionFactor("rtk") > 0);
assert.ok(expectedReductionFactor("ultra") < expectedReductionFactor("rtk"));
});
import { resolveAdaptivePlan } from "@omniroute/open-sse/services/compression/adaptiveCompression/resolveAdaptivePlan.ts";
import { DEFAULT_CONTEXT_BUDGET } from "@omniroute/open-sse/services/compression/adaptiveCompression/types.ts";
const cfg = (over = {}) => ({ ...DEFAULT_CONTEXT_BUDGET, mode: "floor" as const, ...over });
const basePlan = { mode: "off", stackedPipeline: [] as Array<{ engine: string; intensity?: string }> };
test("already fits → base plan unchanged, fit=true, no stages", () => {
const { plan, telemetry } = resolveAdaptivePlan({
basePlan,
estimatedTokens: 1000, // well under target
modelContextLimit: 200000,
requestMaxTokens: 8000,
config: cfg(),
});
assert.deepEqual(plan, basePlan);
assert.ok(telemetry);
assert.equal(telemetry!.fit, true);
assert.deepEqual(telemetry!.stagesApplied, []);
assert.equal(telemetry!.target, 200000 - 8000 - 1024);
assert.ok(telemetry!.headroomBefore > 0);
assert.equal(telemetry!.headroomAfter, telemetry!.headroomBefore);
});
test("over target → escalates and stops at first fitting stage (no over-escalation)", () => {
// Injected estimator: each stage halves the prompt. target = 200000-8000-1024 = 190976.
// Start over target at 400000: stage1 → 200000 (still over), stage2 → 100000 (fits) → STOP.
const halve = (prior: number) => Math.round(prior / 2);
const { plan, telemetry } = resolveAdaptivePlan({
basePlan: { mode: "off", stackedPipeline: [] },
estimatedTokens: 400000,
modelContextLimit: 200000,
requestMaxTokens: 8000,
config: cfg(),
estimate: halve,
});
assert.equal(telemetry!.fit, true);
assert.equal(telemetry!.stagesApplied.length, 2); // stopped after the 2nd stage
assert.equal(plan.mode, "stacked");
assert.equal(plan.stackedPipeline.length, 2);
// first two ladder engines above "off": session-dedup then rtk
assert.deepEqual(telemetry!.stagesApplied, ["session-dedup", "rtk"]);
assert.ok(telemetry!.headroomAfter >= 0);
});
test("floor escalates beyond a light base plan (base lite → starts above lite)", () => {
const halve = (prior: number) => Math.round(prior / 2);
const { telemetry } = resolveAdaptivePlan({
basePlan: { mode: "lite", stackedPipeline: [] },
estimatedTokens: 400000,
modelContextLimit: 200000,
requestMaxTokens: 8000,
config: cfg(),
estimate: halve,
});
// base "lite" rank=4; ladder stages above rank 4 = caveman(5), aggressive(6), ultra(7).
assert.equal(telemetry!.stagesApplied[0], "caveman");
assert.ok(!telemetry!.stagesApplied.includes("session-dedup")); // did NOT restart below lite
assert.ok(!telemetry!.stagesApplied.includes("rtk"));
});
test("ladder exhausted, still over target → fit=false, all stages applied, plan still set", () => {
const noop = (prior: number) => prior; // estimator never reduces → never fits
const { plan, telemetry } = resolveAdaptivePlan({
basePlan: { mode: "off", stackedPipeline: [] },
estimatedTokens: 999999,
modelContextLimit: 200000,
requestMaxTokens: 8000,
config: cfg(),
estimate: noop,
});
assert.equal(telemetry!.fit, false); // budget-exceeded
assert.equal(telemetry!.stagesApplied.length, 7); // entire DEFAULT_LADDER above "off"
assert.equal(plan.mode, "stacked");
assert.ok(plan.stackedPipeline.length >= 7); // best-effort plan, content NOT dropped
assert.ok(telemetry!.headroomAfter < 0);
});
test("replace-autotrigger: fires on bare off base, defers to an explicit base plan", () => {
const halve = (prior: number) => Math.round(prior / 2);
// bare off base → it acts
const acts = resolveAdaptivePlan({
basePlan: { mode: "off", stackedPipeline: [] },
estimatedTokens: 400000, modelContextLimit: 200000, requestMaxTokens: 8000,
config: cfg({ mode: "replace-autotrigger" }), estimate: halve,
});
assert.ok(acts.telemetry!.stagesApplied.length > 0);
// explicit aggressive base → defer (choice wins, may overflow)
const defers = resolveAdaptivePlan({
basePlan: { mode: "aggressive", stackedPipeline: [] },
estimatedTokens: 400000, modelContextLimit: 200000, requestMaxTokens: 8000,
config: cfg({ mode: "replace-autotrigger" }), estimate: halve,
});
assert.deepEqual(defers.plan, { mode: "aggressive", stackedPipeline: [] });
assert.deepEqual(defers.telemetry!.stagesApplied, []);
assert.equal(defers.telemetry!.fit, false); // 400000 > target, recorded as not fitting
});
test("unknown model context limit → skip adaptive (null telemetry, base unchanged)", () => {
for (const lim of [null, 0, -1]) {
const { plan, telemetry } = resolveAdaptivePlan({
basePlan, estimatedTokens: 999999, modelContextLimit: lim,
requestMaxTokens: 8000, config: cfg(),
});
assert.equal(telemetry, null);
assert.deepEqual(plan, basePlan);
}
});
test("hard-off: floor still escalates an overflowing 'off' base plan (spec §9)", () => {
const halve = (prior: number) => Math.round(prior / 2);
const { telemetry } = resolveAdaptivePlan({
basePlan: { mode: "off", stackedPipeline: [] }, // explicit off (header off resolves to this)
estimatedTokens: 400000, modelContextLimit: 200000, requestMaxTokens: 8000,
config: cfg(), // mode: "floor"
estimate: halve,
});
assert.ok(telemetry!.stagesApplied.length > 0); // floor escalated despite off
assert.equal(telemetry!.fit, true);
});

View File

@@ -0,0 +1,82 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import {
selectCompressionPlan,
shouldAutoTrigger,
} from "@omniroute/open-sse/services/compression/strategySelector.ts";
import { getDefaultCompressionConfig } from "@omniroute/open-sse/services/compression/stats.ts";
function legacyCfg() {
return {
...getDefaultCompressionConfig(),
enabled: true,
enginesExplicit: false,
defaultMode: "lite" as const,
autoTriggerMode: "aggressive" as const,
autoTriggerTokens: 100000,
};
}
test("no contextBudget → auto-trigger path is byte-identical to legacy", () => {
const cfg = legacyCfg(); // no contextBudget field
// under threshold → derived default ("lite")
const small = selectCompressionPlan(cfg, null, 1000);
assert.equal(small.mode, "lite");
// over threshold → auto-trigger fires → "aggressive"
const big = selectCompressionPlan(cfg, null, 200000);
assert.equal(big.mode, "aggressive");
assert.equal(shouldAutoTrigger(cfg, 200000), true);
});
test("contextBudget.mode='off' → identical to no contextBudget", () => {
const cfg = { ...legacyCfg(), contextBudget: { mode: "off" as const } };
assert.equal(selectCompressionPlan(cfg as any, null, 200000).mode, "aggressive");
});
test("adaptive floor: bypasses auto-trigger, escalates a base plan to fit", () => {
const cfg = {
...legacyCfg(),
autoTriggerTokens: 100000,
autoTriggerMode: "lite" as const,
contextBudget: {
mode: "floor" as const,
policy: "reserve-output" as const,
outputReserve: 4096,
safetyMargin: 1024,
pct: 0.85,
absoluteBudget: 0,
},
};
const tel: {
value: import("@omniroute/open-sse/services/compression/adaptiveCompression/types.ts").AdaptiveTelemetry | null;
} = { value: null };
// estimatedTokens far over the 200000-window target → adaptive must escalate.
const plan = selectCompressionPlan(
cfg as any, null, 5_000_000, undefined, undefined, {}, null,
{ modelContextLimit: 200000, requestMaxTokens: 8000, onAdaptive: (t) => { tel.value = t; } }
);
assert.equal(plan.mode, "stacked");
assert.ok(plan.stackedPipeline.length > 0);
assert.ok(tel.value, "adaptive telemetry must be surfaced");
assert.equal(tel.value!.policy, "reserve-output");
assert.equal(tel.value!.target, 200000 - 8000 - 1024);
assert.ok(tel.value!.stagesApplied.length > 0);
});
test("adaptive escalation still respects caching downgrade (D-C / §6 cache-safety)", () => {
const cfg = {
...legacyCfg(),
contextBudget: { mode: "floor" as const, policy: "reserve-output" as const, outputReserve: 4096, safetyMargin: 1024, pct: 0.85, absoluteBudget: 0 },
};
// A caching provider context downgrades aggressive/ultra → standard; the adaptive plan's
// mode is "stacked", which getCacheAwareStrategy passes through unchanged, but the
// pipeline engines remain those that the existing apply path already cache-guards.
const body = { model: "openai/gpt-5", messages: [{ role: "user", content: "x" }] };
const plan = selectCompressionPlan(
cfg as any, null, 5_000_000, body, { provider: "openai", model: "openai/gpt-5" }, {}, null,
{ modelContextLimit: 200000, requestMaxTokens: 8000 }
);
// mode is still a valid CompressionMode string after the cache-aware pass
assert.ok(typeof plan.mode === "string");
assert.ok(plan.stackedPipeline.length > 0);
});