From d0c90f14a7d6b214eb1357e0d2e27ddb07a6421d Mon Sep 17 00:00:00 2001 From: Lisa Date: Wed, 25 Feb 2026 20:49:56 +0100 Subject: [PATCH 1/3] feat(demo): add browser-based demo app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single-page demo that lets users paste conversations in plain-text chat format, adjust compression settings, and see results with an inline diff view highlighting what changed. - esbuild bundles src/index.ts → demo/bundle.js (IIFE, global CCE) - Plain-text input format (role: message, blank line separates) - All CompressOptions exposed: recencyWindow, tokenBudget, preserve, dedup, fuzzyDedup, fuzzyThreshold, forceConverge - Line-level diff output: red/strikethrough for removed, green for added, tags for preserved/compressed/removed messages - 5 example conversations: coding assistant, technical prose, structured + credentials, short chat, deep conversation - npm scripts: demo:build, demo --- .gitignore | 3 + demo/build.mjs | 13 + demo/index.html | 1432 +++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 1 + package.json | 5 +- 5 files changed, 1453 insertions(+), 1 deletion(-) create mode 100644 demo/build.mjs create mode 100644 demo/index.html diff --git a/.gitignore b/.gitignore index a7e6b4d..965648d 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,9 @@ __pycache__/ .vscode/ *.swp +# demo +demo/bundle.js + # indexing / analysis artifacts .ckb/ *.scip diff --git a/demo/build.mjs b/demo/build.mjs new file mode 100644 index 0000000..536cb5e --- /dev/null +++ b/demo/build.mjs @@ -0,0 +1,13 @@ +import { build } from 'esbuild'; + +await build({ + entryPoints: ['src/index.ts'], + bundle: true, + format: 'iife', + globalName: 'CCE', + outfile: 'demo/bundle.js', + target: 'es2020', + platform: 'browser', +}); + +console.log('Built demo/bundle.js'); diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..d3a336b --- /dev/null +++ b/demo/index.html @@ -0,0 +1,1432 @@ + + + + + + Context Compression Engine — Demo + + + + + + +
+
+ +
+ deterministic + github ↗ +
+
+ +
+
+ + + 4 +
+ +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+ + +
+
+ +
+
+
+ Input + + + role: message — blank lines separate + +
+ +
+ +
+
+ Output + +
+
+
+
+
+
+ Write a conversation on the left,
then hit Compress +
+
+
+
+
+
+
+
+ + + + + diff --git a/package-lock.json b/package-lock.json index 5f5581f..9500d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@arethetypeswrong/cli": "^0.18.2", "@eslint/js": "^10.0.1", "@vitest/coverage-v8": "^4.0.18", + "esbuild": "^0.27.3", "eslint": "^10.0.2", "openai": "^6.25.0", "prettier": "^3.8.1", diff --git a/package.json b/package.json index 9b33f2f..08ef87a 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ "test:e2e:smoke": "cd e2e && npm install ../context-compression-engine-*.tgz && npm test", "test:e2e:cleanup": "rm -f context-compression-engine-*.tgz && rm -rf e2e/node_modules && rm -f e2e/package-lock.json", "test:e2e:published": "cd e2e && npm install context-compression-engine && npm test", - "prepublishOnly": "npm test && tsc" + "prepublishOnly": "npm test && tsc", + "demo:build": "node demo/build.mjs", + "demo": "npm run demo:build && npx serve demo" }, "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -61,6 +63,7 @@ "@arethetypeswrong/cli": "^0.18.2", "@eslint/js": "^10.0.1", "@vitest/coverage-v8": "^4.0.18", + "esbuild": "^0.27.3", "eslint": "^10.0.2", "openai": "^6.25.0", "prettier": "^3.8.1", From a159edd31e05f536ac1e1ec75eae76dbc1dffad4 Mon Sep 17 00:00:00 2001 From: Lisa Date: Wed, 25 Feb 2026 20:53:34 +0100 Subject: [PATCH 2/3] feat(demo): add help button with settings documentation --- demo/index.html | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) diff --git a/demo/index.html b/demo/index.html index d3a336b..27c0171 100644 --- a/demo/index.html +++ b/demo/index.html @@ -716,6 +716,97 @@ color: var(--text); } + /* ─── Help Panel ─── */ + + .help-btn { + width: 28px; + height: 28px; + border-radius: 50%; + border: 1px solid var(--border); + background: var(--surface-raised); + color: var(--text-dim); + font-family: var(--mono); + font-size: 13px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + } + + .help-btn:hover, + .help-btn.active { + border-color: var(--accent); + color: var(--accent); + background: var(--accent-glow); + } + + .help-panel { + max-height: 0; + overflow: hidden; + transition: + max-height 0.35s ease, + padding 0.35s ease, + border-color 0.35s ease; + background: var(--surface); + border-bottom: 1px solid transparent; + padding: 0 28px; + } + + .help-panel.open { + max-height: 500px; + padding: 16px 28px; + border-bottom-color: var(--border); + } + + .help-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 12px 24px; + } + + .help-item { + display: flex; + gap: 10px; + align-items: baseline; + } + + .help-item dt { + font-size: 11px; + font-weight: 600; + color: var(--text); + white-space: nowrap; + min-width: 90px; + flex-shrink: 0; + } + + .help-item dd { + font-size: 11px; + color: var(--text-dim); + line-height: 1.5; + } + + .help-item dd code { + color: var(--accent); + font-size: 10px; + } + + .help-section-title { + font-size: 9px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 1.5px; + color: var(--text-faint); + margin-bottom: 8px; + grid-column: 1 / -1; + } + + .help-section-title:not(:first-child) { + margin-top: 8px; + } + /* ─── Scrollbar ─── */ ::-webkit-scrollbar { @@ -836,6 +927,92 @@

Context Compression Engine / demo

+ + + + +
+
+
Compression
+ +
+
recency
+
+ Number of most recent messages to keep untouched. Only older messages are candidates + for compression. recencyWindow +
+
+
+
budget
+
+ Target token count. When enabled, binary-searches the recency window to fit the output + within this limit. tokenBudget +
+
+
+
preserve
+
+ Roles that are never compressed, comma-separated. Typically system. These + messages pass through verbatim regardless of position. +
+
+
+
converge
+
+ Hard-truncate non-recent messages when the binary search bottoms out and the budget is + still exceeded. Last resort. forceConverge +
+
+ +
Deduplication
+ +
+
dedup
+
+ Replace exact duplicate messages with a compact reference to the first occurrence. + Compares full content via hash + equality check. +
+
+
+
fuzzy
+
+ Detect near-duplicate messages using line-level Jaccard similarity. Catches messages + that are mostly the same but not identical. fuzzyDedup +
+
+
+
threshold
+
+ Similarity cutoff for fuzzy dedup, 0–1. Higher = stricter matching. Default + 0.85 means 85% of lines must overlap to count as a near-duplicate. +
+
+ +
Output
+ +
+
preserved
+
+ Message was kept verbatim — either in the recency window, a preserved role, or + classified as code/structured data (T0). +
+
+
+
compressed
+
+ Prose was summarized by the deterministic scorer. + Red strikethrough = removed text, + green = replacement summary. +
+
+
+
removed
+
+ Message was dropped entirely, typically by dedup replacing a duplicate with a + back-reference. +
+
+
@@ -1168,6 +1345,13 @@

Context Compression Engine / demo

const $forceConverge = document.getElementById('forceConverge'); const $exampleSelect = document.getElementById('exampleSelect'); + const $helpBtn = document.getElementById('helpBtn'); + const $helpPanel = document.getElementById('helpPanel'); + + $helpBtn.addEventListener('click', () => { + $helpPanel.classList.toggle('open'); + $helpBtn.classList.toggle('active'); + }); function loadExample(key) { $input.value = EXAMPLES[key] || ''; From e129bf21ed58cfb8a8bec65d1e64d3af37ad20c9 Mon Sep 17 00:00:00 2001 From: Lisa Date: Wed, 25 Feb 2026 20:55:43 +0100 Subject: [PATCH 3/3] fix(lint): exclude demo/ from ESLint --- eslint.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 73365b2..bd80311 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,7 +5,7 @@ export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended, { - ignores: ['dist/', 'coverage/', 'node_modules/'], + ignores: ['dist/', 'coverage/', 'node_modules/', 'demo/'], }, { rules: {