feat(dashboard): in-product guidance for prompt compression engines (#7530) (#7634)

Validated in local merge-train @ 8f27177d1 (full parity suite green: typecheck+file-size+complexity+cognitive+changelog+unit shards 1&2+vitest)
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-17 22:09:21 -03:00
committed by GitHub
parent c71eeae4ad
commit f5d705c277
8 changed files with 423 additions and 0 deletions

View File

@@ -0,0 +1 @@
- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530).

View File

@@ -1,3 +1,23 @@
// Cache impact is a qualitative estimate of how much an engine's per-request output
// variance disrupts upstream prompt-prefix caching (e.g. Anthropic/OpenAI prompt
// caching): "none"/"low" = deterministic, cache-friendly; "high" = output shape varies
// enough across requests (summarization, query-dependent pruning) that cached prefixes
// are less likely to be reused. Source: docs/compression/COMPRESSION_GUIDE.md,
// docs/compression/COMPRESSION_ENGINES.md (#7530).
export type CacheImpact = "none" | "low" | "moderate" | "high";
export interface EngineGuidance {
// Short, in-product explanation of the quality/latency tradeoff — adapted from
// docs/compression/COMPRESSION_GUIDE.md / COMPRESSION_ENGINES.md, not invented.
tradeoffs: string;
// true = the engine can drop/alter content a later turn might have needed (semantic
// condensation, summarization, pruning). false = structural/formatting-only, safe to
// leave on. "Safe default" status is DERIVED from this flag (see isSafeDefault) rather
// than duplicated as its own field.
lossy: boolean;
cacheImpact: CacheImpact;
}
export interface EngineMeta {
id: string;
label: string;
@@ -5,6 +25,7 @@ export interface EngineMeta {
levels?: string[]; // intensity options; undefined = no level selector
isSingleMode: boolean; // can be the effective mode when it is the only engine on
description: string;
guidance: EngineGuidance;
}
export const ENGINE_CATALOG: Record<string, EngineMeta> = {
@@ -14,6 +35,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 3,
isSingleMode: false,
description: "Cross-turn block deduplication.",
guidance: {
tradeoffs:
"Lossless — elides only text already sent earlier in the same session; nothing is summarized or dropped. Negligible latency overhead.",
lossy: false,
cacheImpact: "low",
},
},
ccr: {
id: "ccr",
@@ -21,6 +48,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 4,
isSingleMode: false,
description: "Content-addressed retrieval markers.",
guidance: {
tradeoffs:
"Lossless — replaces large repeated/contiguous blocks with content-addressed references instead of deleting them; the original content stays retrievable.",
lossy: false,
cacheImpact: "low",
},
},
lite: {
id: "lite",
@@ -28,6 +61,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 5,
isSingleMode: true,
description: "Whitespace/format cleanup.",
guidance: {
tradeoffs:
"Safest mode (~15% savings, <1ms latency): whitespace/dedup/formatting cleanup only, zero semantic change. Always safe to leave on.",
lossy: false,
cacheImpact: "none",
},
},
rtk: {
id: "rtk",
@@ -36,6 +75,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
levels: ["minimal", "standard", "aggressive"],
isSingleMode: true,
description: "Command-output filtering.",
guidance: {
tradeoffs:
"Strips ANSI noise, progress bars, and repeated lines from command/tool output while preserving failures, warnings, and summaries (60-90% upstream savings). The 'aggressive' level trims more tail context than 'minimal'/'standard'.",
lossy: true,
cacheImpact: "moderate",
},
},
headroom: {
id: "headroom",
@@ -43,6 +88,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 15,
isSingleMode: false,
description: "Tabular JSON compaction.",
guidance: {
tradeoffs:
"Lossless columnar compaction (SmartCrusher) of homogeneous JSON-array payloads into a compact '[N rows]' form — no data is discarded.",
lossy: false,
cacheImpact: "low",
},
},
relevance: {
id: "relevance",
@@ -50,6 +101,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 18,
isSingleMode: true,
description: "Extractive sentence scoring against the last user query.",
guidance: {
tradeoffs:
"Drops sentences scored as less relevant to the last user query — output depends on the query, so it can omit context a later turn needs.",
lossy: true,
cacheImpact: "moderate",
},
},
caveman: {
id: "caveman",
@@ -58,6 +115,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
levels: ["lite", "full", "ultra"],
isSingleMode: true,
description: "Rule-based prose compression.",
guidance: {
tradeoffs:
"Rule-based prose condensation (~30% savings at 'full'): strips filler and hedging while preserving meaning, but rewrites text so it is not byte-identical to the original.",
lossy: true,
cacheImpact: "moderate",
},
},
aggressive: {
id: "aggressive",
@@ -65,6 +128,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 30,
isSingleMode: true,
description: "Summarize + age old turns.",
guidance: {
tradeoffs:
"Summarizes and progressively ages older turns (~50% savings) — trades older-turn fidelity for context headroom in long sessions; summarized turns can't be perfectly reconstructed.",
lossy: true,
cacheImpact: "high",
},
},
llmlingua: {
id: "llmlingua",
@@ -72,6 +141,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 35,
isSingleMode: false,
description: "Semantic pruning (ONNX).",
guidance: {
tradeoffs:
"Semantic token pruning via a small ONNX classifier — removes individual tokens judged low-information. Fail-opens (returns the original text) on any error, so the worst case is no savings, never corruption.",
lossy: true,
cacheImpact: "high",
},
},
ultra: {
id: "ultra",
@@ -79,6 +154,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 40,
isSingleMode: true,
description: "Heuristic token pruning (+ optional SLM).",
guidance: {
tradeoffs:
"Maximum-compression mode (~75% savings): heuristic pruning, code-block thinning, and binary-search truncation. Highest risk of losing context a later turn depended on — best reserved for hitting context limits.",
lossy: true,
cacheImpact: "high",
},
},
omniglyph: {
id: "omniglyph",
@@ -86,6 +167,12 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
stackPriority: 90,
isSingleMode: true,
description: "Contexto-como-imagem (Claude Fable 5, rota direta).",
guidance: {
tradeoffs:
"Experimental context-as-image encoding routed directly to Claude Fable 5 only — the most aggressive and least broadly compatible option; not recommended as a general-purpose default.",
lossy: true,
cacheImpact: "high",
},
},
};
@@ -96,3 +183,11 @@ export const ENGINE_IDS: string[] = Object.values(ENGINE_CATALOG)
export function engineMeta(id: string): EngineMeta {
return ENGINE_CATALOG[id];
}
// "Safe default" = not lossy. Derived rather than a duplicated stored field (open
// question resolved in #7530: engineCatalog had no prior lossy-style attribute, so we
// added one and compute safe-default from it instead of two independently-maintained
// booleans).
export function isSafeDefault(id: string): boolean {
return !engineMeta(id).guidance.lossy;
}

View File

@@ -28,6 +28,7 @@ import {
outputStyleMeta,
} from "../../../../../../open-sse/services/compression/outputStyles/catalog.ts";
import { deriveDefaultPlan } from "../../../../../../open-sse/services/compression/deriveDefaultPlan.ts";
import EngineGuidanceDetail from "./EngineGuidanceDetail";
import {
DEFAULT_CONTEXT_BUDGET,
type ContextBudgetConfig,
@@ -99,6 +100,9 @@ export default function CompressionPanel() {
const uiLang = (useLocale() || "en").split("-")[0];
const [config, setConfig] = useState<CompressionConfig>(DEFAULT_CONFIG);
const [mcpAccessibility, setMcpAccessibility] = useState(true);
// #7530 — per-engine expandable guidance (tradeoffs/lossy/cache-impact); collapsed by
// default so the grid stays scannable.
const [expandedGuidance, setExpandedGuidance] = useState<Record<string, boolean>>({});
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [status, setStatus] = useState<"" | "saved" | "error">("");
@@ -163,6 +167,10 @@ export default function CompressionPanel() {
save({ engines });
};
const toggleGuidance = (id: string) => {
setExpandedGuidance((prev) => ({ ...prev, [id]: !prev[id] }));
};
const setOutputStyle = (id: string, patch: { enabled?: boolean; level?: CavemanIntensity }) => {
const current = config.outputStyles ?? [];
const existing = current.find((s) => s.id === id);
@@ -225,6 +233,18 @@ export default function CompressionPanel() {
<div>
<h3 className="text-lg font-semibold">{t("compressionTitle")}</h3>
<p className="text-sm text-text-muted">{t("compressionDesc")}</p>
<a
href="https://github.com/diegosouzapw/OmniRoute/blob/main/docs/compression/COMPRESSION_GUIDE.md"
target="_blank"
rel="noopener noreferrer"
data-testid="compression-guide-link"
className="mt-0.5 inline-flex items-center gap-1 text-xs text-primary hover:underline"
>
{t("compressionGuidanceFullGuideLink")}
<span className="material-symbols-outlined text-[12px]" aria-hidden="true">
open_in_new
</span>
</a>
</div>
</div>
<div className="flex items-center gap-3">
@@ -290,6 +310,12 @@ export default function CompressionPanel() {
</Link>
</div>
<p className="mt-0.5 text-xs text-text-muted">{meta.description}</p>
<EngineGuidanceDetail
id={id}
guidance={meta.guidance}
expanded={Boolean(expandedGuidance[id])}
onToggle={() => toggleGuidance(id)}
/>
</div>
<div className="flex shrink-0 items-center gap-2">
{levels && (

View File

@@ -0,0 +1,74 @@
"use client";
// EngineGuidanceDetail — per-engine expandable guidance block for CompressionPanel
// (#7530). Surfaces the `guidance` metadata from engineCatalog.ts (tradeoffs, lossy
// flag → "safe default" badge, cache impact) so operators can see quality/latency
// tradeoffs without leaving Settings. Extracted into its own component to keep
// CompressionPanel's per-row JSX flat (cognitive-complexity ratchet).
//
// Like the rest of the engine row, the guidance copy itself is catalog-hardcoded
// English (not i18n) so it stays deterministic; only the surrounding chrome (toggle
// button, badge, "cache impact" label) is translated.
import { useTranslations } from "next-intl";
import type { CacheImpact, EngineGuidance } from "../../../../../../open-sse/services/compression/engineCatalog.ts";
const CACHE_IMPACT_LABEL: Record<CacheImpact, string> = {
none: "None",
low: "Low",
moderate: "Moderate",
high: "High",
};
interface EngineGuidanceDetailProps {
id: string;
guidance: EngineGuidance;
expanded: boolean;
onToggle: () => void;
}
export default function EngineGuidanceDetail({
id,
guidance,
expanded,
onToggle,
}: EngineGuidanceDetailProps) {
const t = useTranslations("settings");
return (
<div className="mt-1 flex flex-col gap-1">
<div className="flex items-center gap-2">
{!guidance.lossy && (
<span
data-testid={`engine-safe-default-${id}`}
className="rounded border border-emerald-500/30 bg-emerald-500/10 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-emerald-500"
>
{t("compressionGuidanceSafeDefault")}
</span>
)}
<button
type="button"
data-testid={`engine-guidance-toggle-${id}`}
onClick={onToggle}
aria-expanded={expanded}
className="text-[10px] uppercase tracking-wider text-primary hover:underline"
>
{expanded ? t("compressionGuidanceHide") : t("compressionGuidanceShow")}
</button>
</div>
{expanded && (
<div
data-testid={`engine-guidance-detail-${id}`}
className="rounded border border-border/50 bg-bg-subtle p-2 text-xs text-text-muted"
>
<p>{guidance.tradeoffs}</p>
<p className="mt-1">
<span className="font-medium text-text-main">
{t("compressionGuidanceCacheImpact")}:
</span>{" "}
{CACHE_IMPACT_LABEL[guidance.cacheImpact]}
</p>
</div>
)}
</div>
);
}

View File

@@ -5729,6 +5729,11 @@
"clearSyncedPricing": "Clear Synced Pricing",
"compressionTitle": "Prompt Compression",
"compressionDesc": "Reduce token usage by compressing prompts before sending to providers",
"compressionGuidanceFullGuideLink": "Full compression guide",
"compressionGuidanceShow": "Details",
"compressionGuidanceHide": "Hide details",
"compressionGuidanceSafeDefault": "Safe default",
"compressionGuidanceCacheImpact": "Cache impact",
"tokenSaverTitle": "Token Saver",
"tokenSaverSubtitle": "Spend fewer tokens on every request.",
"tokenSaverToolOutput": "Tool output",

View File

@@ -5691,6 +5691,11 @@
"clearSyncedPricing": "Limpar Sync",
"compressionTitle": "Prompt Compression",
"compressionDesc": "Reduce token usage by compressing prompts before sending to providers",
"compressionGuidanceFullGuideLink": "Guia completo de compressão",
"compressionGuidanceShow": "Detalhes",
"compressionGuidanceHide": "Ocultar detalhes",
"compressionGuidanceSafeDefault": "Padrão seguro",
"compressionGuidanceCacheImpact": "Impacto no cache",
"tokenSaverTitle": "__MISSING__:Token Saver",
"tokenSaverSubtitle": "__MISSING__:Spend fewer tokens on every request.",
"tokenSaverToolOutput": "__MISSING__:Tool output",

View File

@@ -0,0 +1,54 @@
// #7530 — in-product guidance for Prompt Compression engines.
//
// Regression guard for the richer `guidance` metadata on every engineCatalog.ts entry
// (tradeoffs, lossy flag, cache impact) and the derived "safe default" helper. This is
// the TDD-required test (Hard Rule #18): it FAILED before the `guidance` field existed
// (every `engineMeta(id).guidance` was `undefined`) and passes now that every catalog
// entry carries complete guidance.
import { test } from "node:test";
import assert from "node:assert/strict";
import {
ENGINE_IDS,
engineMeta,
isSafeDefault,
type CacheImpact,
} from "@omniroute/open-sse/services/compression/engineCatalog.ts";
const VALID_CACHE_IMPACTS: CacheImpact[] = ["none", "low", "moderate", "high"];
test("every engine in the catalog has a complete guidance entry", () => {
for (const id of ENGINE_IDS) {
const meta = engineMeta(id);
assert.ok(meta.guidance, `${id} is missing a guidance entry`);
assert.equal(typeof meta.guidance.tradeoffs, "string", `${id} guidance.tradeoffs must be a string`);
assert.ok(
meta.guidance.tradeoffs.length >= 20,
`${id} guidance.tradeoffs reads as a placeholder (too short): "${meta.guidance.tradeoffs}"`
);
assert.equal(typeof meta.guidance.lossy, "boolean", `${id} guidance.lossy must be a boolean`);
assert.ok(
VALID_CACHE_IMPACTS.includes(meta.guidance.cacheImpact),
`${id} guidance.cacheImpact "${meta.guidance.cacheImpact}" is not one of ${VALID_CACHE_IMPACTS.join(", ")}`
);
}
});
test("isSafeDefault is derived from guidance.lossy (no duplicated flag)", () => {
for (const id of ENGINE_IDS) {
assert.equal(isSafeDefault(id), !engineMeta(id).guidance.lossy, `${id} safe-default mismatch`);
}
});
test("lossless structural engines are flagged as safe defaults", () => {
for (const id of ["session-dedup", "ccr", "lite", "headroom"]) {
assert.equal(isSafeDefault(id), true, `${id} should be a safe default (lossless)`);
assert.equal(engineMeta(id).guidance.lossy, false, `${id} should be marked non-lossy`);
}
});
test("lossy semantic-condensation engines are NOT flagged as safe defaults", () => {
for (const id of ["rtk", "relevance", "caveman", "aggressive", "llmlingua", "ultra", "omniglyph"]) {
assert.equal(isSafeDefault(id), false, `${id} should NOT be a safe default (lossy)`);
assert.equal(engineMeta(id).guidance.lossy, true, `${id} should be marked lossy`);
}
});

View File

@@ -0,0 +1,163 @@
// @vitest-environment jsdom
//
// #7530 — in-product guidance for Prompt Compression engines.
// Asserts the Settings -> Prompt Compression panel surfaces each engine's guidance
// detail (expand/collapse), shows the "safe default" indicator only for lossless
// engines, and links out to the full compression guide.
import React, { act } from "react";
import { createRoot } from "react-dom/client";
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import {
ENGINE_IDS,
engineMeta,
isSafeDefault,
} from "../../../open-sse/services/compression/engineCatalog.ts";
vi.mock("next-intl", () => ({
useTranslations: () => (key: string) => key,
useLocale: () => "en",
}));
const containers: HTMLElement[] = [];
const roots: Array<{ unmount: () => void }> = [];
function mount(ui: React.ReactElement): HTMLElement {
const container = document.createElement("div");
document.body.appendChild(container);
containers.push(container);
const root = createRoot(container);
roots.push(root);
act(() => {
root.render(ui);
});
return container;
}
beforeEach(() => {
(
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
).IS_REACT_ACT_ENVIRONMENT = true;
});
afterEach(async () => {
vi.restoreAllMocks();
await act(async () => {
while (roots.length > 0) {
roots.pop()?.unmount();
}
});
for (let i = 0; i < 10; i++) {
await Promise.resolve();
}
while (containers.length > 0) {
containers.pop()?.remove();
}
document.body.innerHTML = "";
});
async function flush() {
await act(async () => {
for (let i = 0; i < 10; i++) await Promise.resolve();
});
}
function setupFetchMock() {
const json = (body: unknown, status = 200) =>
new Response(JSON.stringify(body), {
status,
headers: { "Content-Type": "application/json" },
});
const initialConfig = {
enabled: true,
autoTriggerTokens: 0,
preserveSystemPrompt: true,
engines: {},
activeComboId: null,
cavemanOutputMode: { enabled: false, intensity: "full", autoClarity: true },
};
vi.spyOn(globalThis, "fetch").mockImplementation(async (input: RequestInfo | URL) => {
const url = input.toString();
if (url.includes("/api/settings/compression/mcp-accessibility")) {
return json({ enabled: true, maxTextChars: 50000 });
}
if (url.includes("/api/settings/compression")) {
return json(initialConfig);
}
return json({}, 404);
});
}
describe("CompressionPanel — engine guidance (#7530)", () => {
it("links to the full compression guide", async () => {
setupFetchMock();
const { default: CompressionPanel } = await import(
"@/app/(dashboard)/dashboard/context/settings/CompressionPanel"
);
let container!: HTMLElement;
await act(async () => {
container = mount(<CompressionPanel />);
});
await flush();
const link = container.querySelector('[data-testid="compression-guide-link"]');
expect(link).toBeTruthy();
expect(link?.getAttribute("href")).toContain("docs/compression/COMPRESSION_GUIDE.md");
});
it("shows the safe-default badge only for lossless engines", async () => {
setupFetchMock();
const { default: CompressionPanel } = await import(
"@/app/(dashboard)/dashboard/context/settings/CompressionPanel"
);
let container!: HTMLElement;
await act(async () => {
container = mount(<CompressionPanel />);
});
await flush();
for (const id of ENGINE_IDS) {
const badge = container.querySelector(`[data-testid="engine-safe-default-${id}"]`);
if (isSafeDefault(id)) {
expect(badge, `${id} is lossless — expected the safe-default badge`).toBeTruthy();
} else {
expect(badge, `${id} is lossy — should NOT show the safe-default badge`).toBeFalsy();
}
}
});
it("expands an engine's guidance detail (tradeoffs + cache impact) on toggle", async () => {
setupFetchMock();
const { default: CompressionPanel } = await import(
"@/app/(dashboard)/dashboard/context/settings/CompressionPanel"
);
let container!: HTMLElement;
await act(async () => {
container = mount(<CompressionPanel />);
});
await flush();
const engineId = "caveman";
expect(
container.querySelector(`[data-testid="engine-guidance-detail-${engineId}"]`)
).toBeFalsy();
const toggle = container.querySelector(
`[data-testid="engine-guidance-toggle-${engineId}"]`
) as HTMLButtonElement | null;
expect(toggle, "guidance toggle button must exist").toBeTruthy();
await act(async () => {
toggle!.click();
});
await flush();
const detail = container.querySelector(`[data-testid="engine-guidance-detail-${engineId}"]`);
expect(detail).toBeTruthy();
expect(detail?.textContent).toContain(engineMeta(engineId).guidance.tradeoffs);
});
});