diff --git a/src/shared/components/compression/EngineConfigPage.tsx b/src/shared/components/compression/EngineConfigPage.tsx
index fcb316e8ea..ce6e71468e 100644
--- a/src/shared/components/compression/EngineConfigPage.tsx
+++ b/src/shared/components/compression/EngineConfigPage.tsx
@@ -31,10 +31,24 @@ interface Analytics {
days: number;
}
+interface PreviewDiffSegment {
+ type?: string;
+ value?: string;
+ text?: string;
+ content?: string;
+ original?: string;
+ compressed?: string;
+ before?: string;
+ after?: string;
+}
+
interface PreviewResult {
+ original?: string;
+ compressed?: string;
originalTokens: number;
compressedTokens: number;
savingsPct: number;
+ diff?: PreviewDiffSegment[];
}
// ── Default preview sample ────────────────────────────────────────────────
@@ -55,6 +69,27 @@ function StatCard({ label, value }: { label: string; value: string }) {
);
}
+function renderDiffSegment(segment: PreviewDiffSegment, index: number) {
+ const label = segment.type ?? "change";
+ const text =
+ segment.value ??
+ segment.text ??
+ segment.content ??
+ [segment.original ?? segment.before, segment.compressed ?? segment.after]
+ .filter(Boolean)
+ .join(" → ") ??
+ "";
+
+ return (
+
+
+ {label}
+
+ {text}
+
+ );
+}
+
// ── Main component ────────────────────────────────────────────────────────
export function EngineConfigPage({ engineId }: { engineId: string }) {
@@ -321,16 +356,46 @@ export function EngineConfigPage({ engineId }: { engineId: string }) {
{previewError && {previewError}
}
{preview && (
-
-
- Original tokens: {preview.originalTokens}
-
-
- Compressed tokens: {preview.compressedTokens}
-
-
- Savings: {preview.savingsPct.toFixed(1)}%
-
+
+
+
+ Original tokens: {preview.originalTokens}
+
+
+ Compressed tokens: {preview.compressedTokens}
+
+
+ Savings: {preview.savingsPct.toFixed(1)}%
+
+
+
+
+
+ Original
+
+
+ {preview.original ?? ""}
+
+
+
+
+ Compressed
+
+
+ {preview.compressed ?? ""}
+
+
+
+ {preview.diff && preview.diff.length > 0 && (
+
+
+ Diff
+
+
+ {preview.diff.map(renderDiffSegment)}
+
+
+ )}
)}
diff --git a/tests/unit/ui/engineConfigPage.test.tsx b/tests/unit/ui/engineConfigPage.test.tsx
index dd2ad9e3c1..c8a00a50ba 100644
--- a/tests/unit/ui/engineConfigPage.test.tsx
+++ b/tests/unit/ui/engineConfigPage.test.tsx
@@ -114,6 +114,19 @@ function setupFetchMock() {
headers: { "Content-Type": "application/json" },
});
}
+ if (url.includes("/api/compression/preview")) {
+ return new Response(
+ JSON.stringify({
+ original: "The original context contains duplicated details and verbose wording.",
+ compressed: "Original context, deduplicated.",
+ originalTokens: 11,
+ compressedTokens: 4,
+ savingsPct: 63.6,
+ diff: [{ type: "removed", text: "duplicated details and verbose wording" }],
+ }),
+ { status: 200, headers: { "Content-Type": "application/json" } }
+ );
+ }
return new Response(JSON.stringify({}), { status: 404 });
});
}
@@ -199,6 +212,37 @@ describe("EngineConfigPage", () => {
expect(container.textContent).toContain("Enable layer");
});
+ it("renders preview original, compressed text, and diff returned by the API", async () => {
+ setupFetchMock();
+ const { EngineConfigPage } =
+ await import("../../../src/shared/components/compression/EngineConfigPage");
+ let container!: HTMLElement;
+ await act(async () => {
+ container = mountInContainer();
+ });
+
+ await act(async () => {
+ await Promise.resolve();
+ });
+
+ const previewButton = Array.from(container.querySelectorAll("button")).find(
+ (button) => button.textContent === "Preview"
+ );
+ expect(previewButton).toBeTruthy();
+
+ await act(async () => {
+ previewButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
+ await Promise.resolve();
+ });
+
+ expect(container.textContent).toContain(
+ "The original context contains duplicated details and verbose wording."
+ );
+ expect(container.textContent).toContain("Original context, deduplicated.");
+ expect(container.textContent).toContain("Diff");
+ expect(container.textContent).toContain("duplicated details and verbose wording");
+ });
+
it("shows empty-state text when analytics returns runs=0", async () => {
setupFetchMock();
const { EngineConfigPage } =