mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 23:02:10 +03:00
feat(compression): QuantumLock cache-prefix stabilization (opt-in, default off) (#5260)
roadmap #11: QuantumLock cache-prefix stabilization (opt-in, default off). Locally validated release-green (typecheck + file-size + 47 quantumLock/analytics tests; restored withRiskGate import + preserved release CHANGELOG bullets). Integrated into release/v3.8.40.
This commit is contained in:
committed by
GitHub
parent
9dc31c7e08
commit
898aac5771
@@ -12,6 +12,7 @@ _In development — bullets added per PR; finalized at release._
|
||||
|
||||
- **feat(mcp): `omniroute_tool_search` tool + one-line TS signatures** — new MCP tool that does lexical keyword search over every MCP tool's name/description and returns the top matches as compact one-line TypeScript signatures (~half the JSON-schema token cost), so agents discover tools on demand instead of carrying all ~88 schemas every turn. Search is ReDoS-safe (substring scoring, never `new RegExp` on the query) and deterministic; `tools/list` stays complete (no hidden tools). Adds the `read:tools` scope. Tier-1 item of the compression feature-extraction roadmap. ([#5269](https://github.com/diegosouzapw/OmniRoute/pull/5269))
|
||||
- **feat(compression): RTK semantic command-output renderers (opt-in)** — adds a second, opt-in compaction layer to the RTK engine that rewrites structured command output into a far more compact semantic form: `git diff` → file headers + `@@` hunks + changed lines only; an all-green `pytest`/`jest`/`vitest`/`eslint` run → its one-line summary; `terraform`/`tofu plan` → `Plan: +N ~M -K` plus the resource list; `kubectl`/`aws` JSON arrays → a minimal table. Each renderer is conservative (no-op when the shape doesn't match) and the integration is fail-open; the test-green renderer never collapses output that carries any failure signal. Gated by `RtkConfig.enableRenderers` (default off → zero behavioral change). Eighth item of the compression feature-extraction roadmap. ([#5268](https://github.com/diegosouzapw/OmniRoute/pull/5268))
|
||||
- **feat(compression): QuantumLock cache-prefix stabilization (opt-in, default off)** — recovers upstream prompt-cache hits that a volatile fragment in the system prompt would otherwise bust. When a caller injects a session UUID, unix timestamp, request-id, JWT, API-key shape, or long hex digest into the `role:system` message every turn, the longest common prefix across turns ends at that changing byte → the whole system prompt after it is re-billed and re-processed each turn. QuantumLock replaces each non-semantic volatile fragment with a **positional, value-independent** placeholder `⟦Q{i}⟧` and appends the real values in a delimited `⟦QUANTUMLOCK⟧` tail. The rewrite is **sent to the model** (lossless — not restored), so the system-prompt body becomes **byte-identical across turns** and the provider caches the long stable prefix while only the small tail differs. Opt-in, default off, applied only for caching providers (`isCachingProvider && config.quantumLock.enabled`); bounded ReDoS-safe patterns; idempotent; **no date/time patterns** (semantically meaningful — explicit non-goal). Studio gets a toggle + a "🔒 N volatile fragment(s) stabilized" dry-run badge. Seventh item of the compression feature-extraction roadmap (bench: [#5080](https://github.com/diegosouzapw/OmniRoute/pull/5080), gate: [#5127](https://github.com/diegosouzapw/OmniRoute/pull/5127), fuzzy: [#5143](https://github.com/diegosouzapw/OmniRoute/pull/5143), ionizer: [#5148](https://github.com/diegosouzapw/OmniRoute/pull/5148), TOON: [#5163](https://github.com/diegosouzapw/OmniRoute/pull/5163), CCR ranged: [#5187](https://github.com/diegosouzapw/OmniRoute/pull/5187), risk-gate: [#5243](https://github.com/diegosouzapw/OmniRoute/pull/5243)). ([#5260](https://github.com/diegosouzapw/OmniRoute/pull/5260))
|
||||
- **kilocode:** anonymous (no-auth) access to Kilo Code's free models, mirroring the `opencode`/`mimocode` pattern. With no Kilo account connected, requests now fall back to the gateway's anonymous tier (`Authorization: Bearer anonymous` on `api.kilo.ai/api/openrouter`) so the free models work without signup; a connected OAuth account is still used unchanged for the paid tier (#4019 — thanks @Theadd for the reference implementation)
|
||||
|
||||
### 🔧 Bug Fixes
|
||||
|
||||
@@ -1223,14 +1223,12 @@ export async function handleChatCore({
|
||||
// #3890: in a caching context, never compress the system prompt (cacheable prefix)
|
||||
// even if the operator disabled preserveSystemPrompt — honors the cache-aware flag
|
||||
// that selectCompressionStrategy can only partially apply via the mode string.
|
||||
const compressionConfig = resolveCacheAwareConfig(config, compressionInputBody, {
|
||||
provider,
|
||||
targetFormat,
|
||||
model: effectiveModel,
|
||||
});
|
||||
const cacheCtx = { provider, targetFormat, model: effectiveModel };
|
||||
const compressionConfig = resolveCacheAwareConfig(config, compressionInputBody, cacheCtx);
|
||||
const result = await applyCompressionAsync(compressionInputBody, mode, {
|
||||
model: effectiveModel,
|
||||
config: compressionConfig,
|
||||
cachingContext: cacheCtx,
|
||||
principalId: apiKeyInfo?.id ? String(apiKeyInfo.id) : undefined,
|
||||
// F3.3: stream per-engine progress live (best-effort) before compression.completed.
|
||||
onEngineStep: (s) => {
|
||||
|
||||
23
open-sse/services/compression/cacheAwareConfig.ts
Normal file
23
open-sse/services/compression/cacheAwareConfig.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { CompressionConfig } from "./types.ts";
|
||||
import type { CachingDetectionContext } from "./cachingAware.ts";
|
||||
import { detectCachingContext, getCacheAwareStrategy } from "./cachingAware.ts";
|
||||
|
||||
/**
|
||||
* #3890: honor the cache-aware `skipSystemPrompt` decision that
|
||||
* `getCacheAwareStrategy` already computes but `selectCompressionStrategy`
|
||||
* cannot return. In a caching context the system prompt is part of the
|
||||
* cacheable prefix, so compressing it breaks the upstream prompt cache.
|
||||
*/
|
||||
export function resolveCacheAwareConfig(
|
||||
config: CompressionConfig,
|
||||
body?: Record<string, unknown>,
|
||||
context?: CachingDetectionContext
|
||||
): CompressionConfig {
|
||||
if (!body) return config;
|
||||
const ctx = detectCachingContext(body, context);
|
||||
const cacheAware = getCacheAwareStrategy(config.defaultMode, ctx);
|
||||
if (cacheAware.skipSystemPrompt && config.preserveSystemPrompt === false) {
|
||||
return { ...config, preserveSystemPrompt: true };
|
||||
}
|
||||
return config;
|
||||
}
|
||||
43
open-sse/services/compression/entrypointWrap.ts
Normal file
43
open-sse/services/compression/entrypointWrap.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { CompressionConfig, CompressionResult } from "./types.ts";
|
||||
import type { CachingDetectionContext } from "./cachingAware.ts";
|
||||
import type { RiskGateConfig } from "./riskGate/riskGate.ts";
|
||||
import { resolveRiskGate, withRiskGate } from "./riskGate/strategyWrap.ts";
|
||||
import {
|
||||
resolveQuantumLock,
|
||||
quantumCachingContext,
|
||||
withQuantumLock,
|
||||
withQuantumLockAsync,
|
||||
} from "./quantumLock/index.ts";
|
||||
|
||||
export interface CompressionEntrypointOptions {
|
||||
config?: CompressionConfig;
|
||||
riskGate?: RiskGateConfig;
|
||||
cachingContext?: CachingDetectionContext;
|
||||
}
|
||||
|
||||
export function withCompressionEntrypointGuards<T extends CompressionEntrypointOptions>(
|
||||
body: Record<string, unknown>,
|
||||
options: T | undefined,
|
||||
run: (body: Record<string, unknown>) => CompressionResult
|
||||
): CompressionResult {
|
||||
return withQuantumLock(
|
||||
body,
|
||||
resolveQuantumLock(options),
|
||||
quantumCachingContext(body, options),
|
||||
(quantumBody) =>
|
||||
withRiskGate(quantumBody, resolveRiskGate(options), (riskBody) => run(riskBody))
|
||||
);
|
||||
}
|
||||
|
||||
export function withCompressionEntrypointGuardsAsync<T extends CompressionEntrypointOptions>(
|
||||
body: Record<string, unknown>,
|
||||
options: T | undefined,
|
||||
run: (body: Record<string, unknown>) => Promise<CompressionResult>
|
||||
): Promise<CompressionResult> {
|
||||
return withQuantumLockAsync(
|
||||
body,
|
||||
resolveQuantumLock(options),
|
||||
quantumCachingContext(body, options),
|
||||
run
|
||||
);
|
||||
}
|
||||
17
open-sse/services/compression/quantumLock/index.ts
Normal file
17
open-sse/services/compression/quantumLock/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export {
|
||||
QUANTUM_PATTERNS,
|
||||
TAIL_DELIM,
|
||||
placeholderFor,
|
||||
type QuantumCategory,
|
||||
type QuantumLockConfig,
|
||||
type QuantumLockStats,
|
||||
type VolatileSpan,
|
||||
} from "./quantumPatterns.ts";
|
||||
export { detectVolatileSpans } from "./quantumLock.ts";
|
||||
export { applyQuantumLock } from "./quantumLockStep.ts";
|
||||
export {
|
||||
resolveQuantumLock,
|
||||
quantumCachingContext,
|
||||
withQuantumLock,
|
||||
withQuantumLockAsync,
|
||||
} from "./strategyWrap.ts";
|
||||
58
open-sse/services/compression/quantumLock/quantumLock.ts
Normal file
58
open-sse/services/compression/quantumLock/quantumLock.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
QUANTUM_PATTERNS,
|
||||
type QuantumLockConfig,
|
||||
type VolatileSpan,
|
||||
} from "./quantumPatterns.ts";
|
||||
|
||||
interface PrioritizedSpan extends VolatileSpan {
|
||||
prio: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect non-semantic volatile spans in `text`, in the FIXED pattern order, then merge
|
||||
* overlapping spans so a token is never double-replaced. Pure + fail-open: a throwing
|
||||
* pattern aborts the scan and returns [] (QuantumLock must never corrupt a request).
|
||||
*
|
||||
* Merge rule (widest wins): sort by start asc, then by width desc, then by priority asc
|
||||
* (earlier pattern = higher precedence); greedily keep a span only if it starts at/after
|
||||
* the last accepted span's end.
|
||||
*/
|
||||
export function detectVolatileSpans(text: string, cfg: QuantumLockConfig): VolatileSpan[] {
|
||||
if (!text) return [];
|
||||
const allow = cfg.categories && cfg.categories.length > 0 ? new Set(cfg.categories) : null;
|
||||
const raw: PrioritizedSpan[] = [];
|
||||
|
||||
try {
|
||||
QUANTUM_PATTERNS.forEach(({ category, pattern }, prio) => {
|
||||
if (allow && !allow.has(category)) return;
|
||||
pattern.lastIndex = 0;
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = pattern.exec(text)) !== null) {
|
||||
if (m[0].length === 0) {
|
||||
pattern.lastIndex++;
|
||||
continue;
|
||||
}
|
||||
raw.push({ start: m.index, end: m.index + m[0].length, category, prio });
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
raw.sort((a, b) => a.start - b.start || b.end - a.end || a.prio - b.prio);
|
||||
|
||||
// Greedy non-overlapping sweep: accept a span only if it starts at/after the last accepted
|
||||
// span's end. A nested or PARTIALLY-overlapping span is dropped whole (never split) — this is
|
||||
// always SAFE (it can only under-stabilize, never corrupt text or shift placeholder numbering).
|
||||
// With the current `\b`-anchored patterns true partial overlaps are unreachable; the drop rule
|
||||
// is the conservative default if a future pattern can produce one.
|
||||
const merged: VolatileSpan[] = [];
|
||||
let lastEnd = -1;
|
||||
for (const s of raw) {
|
||||
if (s.start >= lastEnd) {
|
||||
merged.push({ start: s.start, end: s.end, category: s.category });
|
||||
lastEnd = s.end;
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
72
open-sse/services/compression/quantumLock/quantumLockStep.ts
Normal file
72
open-sse/services/compression/quantumLock/quantumLockStep.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { detectVolatileSpans } from "./quantumLock.ts";
|
||||
import {
|
||||
placeholderFor,
|
||||
TAIL_DELIM,
|
||||
type QuantumCategory,
|
||||
type QuantumLockConfig,
|
||||
type QuantumLockStats,
|
||||
} from "./quantumPatterns.ts";
|
||||
|
||||
/**
|
||||
* Fresh zero-stats per call. NOT a shared singleton on purpose: `applyQuantumLock` is a public
|
||||
* export and `categories` is mutable, so returning one shared object would let a stats-aggregating
|
||||
* caller corrupt the no-op result for every subsequent call in the process.
|
||||
*/
|
||||
const emptyStats = (): QuantumLockStats => ({ fragments: 0, categories: {} });
|
||||
|
||||
function isRecord(v: unknown): v is Record<string, unknown> {
|
||||
return v !== null && typeof v === "object" && !Array.isArray(v);
|
||||
}
|
||||
|
||||
/** v1 stabilizes string-content system messages only. Array/multimodal ⇒ no-op (follow-up). */
|
||||
function systemTextOf(msg: Record<string, unknown>): string {
|
||||
return typeof msg.content === "string" ? msg.content : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Stabilize volatile fragments in the FIRST role:system message: replace each detected span
|
||||
* with a positional, value-independent placeholder (⟦Q{i}⟧) and append a delimited value-tail.
|
||||
* The rewritten body is sent to the model (lossless — the tail carries every value). Pure:
|
||||
* clones the touched message, never mutates input. Fail-open: returns the input body + zero
|
||||
* stats on every no-op path. `ctx` is accepted for symmetry with the wrapper; unused here.
|
||||
*/
|
||||
export function applyQuantumLock(
|
||||
body: Record<string, unknown>,
|
||||
cfg: QuantumLockConfig,
|
||||
_ctx?: { isCachingProvider: boolean }
|
||||
): { body: Record<string, unknown>; stats: QuantumLockStats } {
|
||||
const messages = body.messages;
|
||||
if (!Array.isArray(messages)) return { body, stats: emptyStats() };
|
||||
|
||||
const idx = messages.findIndex((m) => isRecord(m) && m.role === "system");
|
||||
if (idx === -1) return { body, stats: emptyStats() };
|
||||
|
||||
const sys = messages[idx] as Record<string, unknown>;
|
||||
const text = systemTextOf(sys);
|
||||
if (!text) return { body, stats: emptyStats() };
|
||||
if (text.includes(TAIL_DELIM)) return { body, stats: emptyStats() }; // idempotency
|
||||
|
||||
const spans = detectVolatileSpans(text, cfg);
|
||||
if (spans.length === 0) return { body, stats: emptyStats() };
|
||||
|
||||
let out = "";
|
||||
let cursor = 0;
|
||||
const values: string[] = [];
|
||||
const categories: Partial<Record<QuantumCategory, number>> = {};
|
||||
spans.forEach((span, i) => {
|
||||
out += text.slice(cursor, span.start) + placeholderFor(i);
|
||||
values.push(text.slice(span.start, span.end));
|
||||
categories[span.category] = (categories[span.category] ?? 0) + 1;
|
||||
cursor = span.end;
|
||||
});
|
||||
out += text.slice(cursor);
|
||||
|
||||
const tail = `\n\n${TAIL_DELIM}\n${values.map((v, i) => `${placeholderFor(i)}=${v}`).join("\n")}`;
|
||||
const newMessages = messages.slice();
|
||||
newMessages[idx] = { ...sys, content: out + tail };
|
||||
|
||||
return {
|
||||
body: { ...body, messages: newMessages },
|
||||
stats: { fragments: values.length, categories },
|
||||
};
|
||||
}
|
||||
80
open-sse/services/compression/quantumLock/quantumPatterns.ts
Normal file
80
open-sse/services/compression/quantumLock/quantumPatterns.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* QuantumLock leaf module: category enum, span/config/stats types, constants, and the
|
||||
* fixed-order, ReDoS-bounded detection patterns. No imports — keeps every consumer one-way
|
||||
* (cycle-safe). See docs/superpowers/specs/2026-06-28-compression-quantumlock-design.md.
|
||||
*/
|
||||
|
||||
export type QuantumCategory =
|
||||
| "uuid"
|
||||
| "unix_ts"
|
||||
| "long_hex"
|
||||
| "jwt"
|
||||
| "api_key_shape"
|
||||
| "request_id";
|
||||
|
||||
export interface VolatileSpan {
|
||||
start: number; // inclusive char offset into the system text
|
||||
end: number; // exclusive
|
||||
category: QuantumCategory;
|
||||
}
|
||||
|
||||
export interface QuantumLockConfig {
|
||||
enabled: boolean;
|
||||
/** Subset of categories to stabilize. Absent/empty ⇒ all categories. */
|
||||
categories?: QuantumCategory[];
|
||||
}
|
||||
|
||||
export interface QuantumLockStats {
|
||||
fragments: number;
|
||||
categories: Partial<Record<QuantumCategory, number>>;
|
||||
}
|
||||
|
||||
/** Idempotency sentinel + tail header. Its presence in system text ⇒ already stabilized. */
|
||||
export const TAIL_DELIM = "⟦QUANTUMLOCK⟧";
|
||||
|
||||
/** Positional, value-independent placeholder. Depends ONLY on match index. */
|
||||
export const placeholderFor = (i: number): string => `⟦Q${i}⟧`;
|
||||
|
||||
interface QuantumPattern {
|
||||
category: QuantumCategory;
|
||||
pattern: RegExp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detection order is FIXED: most-specific / widest first so a token is never split.
|
||||
* Every variable-length run is bounded ({N,M}) — no unbounded quantifier (anti-ReDoS).
|
||||
*/
|
||||
export const QUANTUM_PATTERNS: QuantumPattern[] = [
|
||||
// JWTs start with base64url of `{"` → "eyJ". Run first so the whole token wins.
|
||||
// Trailing negative-lookahead (not \b): a JWT signature can END in base64url `-`/`_`,
|
||||
// where \b would misfire (it needs a following word char) and let the token escape detection.
|
||||
{
|
||||
category: "jwt",
|
||||
pattern: /\beyJ[A-Za-z0-9_-]{8,512}\.[A-Za-z0-9_-]{8,512}\.[A-Za-z0-9_-]{8,512}(?![A-Za-z0-9_-])/g,
|
||||
},
|
||||
// Prefixed API keys (stripe/github/slack shapes).
|
||||
{
|
||||
category: "api_key_shape",
|
||||
pattern: /\b(?:sk|pk|rk|ghp|gho|xox[baprs])[-_][A-Za-z0-9]{16,200}\b/g,
|
||||
},
|
||||
// Bearer tokens. Bounded whitespace ([ \t]{1,4}) per the file convention (no unbounded \s+).
|
||||
{
|
||||
category: "api_key_shape",
|
||||
pattern: /\bBearer[ \t]{1,4}[A-Za-z0-9._-]{16,400}\b/g,
|
||||
},
|
||||
// Canonical UUID. Runs before long_hex so its inner hex is not re-claimed.
|
||||
{
|
||||
category: "uuid",
|
||||
pattern: /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi,
|
||||
},
|
||||
// Correlation / request ids.
|
||||
{
|
||||
category: "request_id",
|
||||
pattern: /\b(?:req|trace|span|corr|request)[-_][A-Za-z0-9]{6,128}\b/gi,
|
||||
},
|
||||
// Digests / SHAs. After uuid/jwt so it never eats their inner hex.
|
||||
{ category: "long_hex", pattern: /\b[0-9a-f]{16,128}\b/gi },
|
||||
// 10- or 13-digit unix epoch in the 2001–2033 window (leading 1). LAST so it never
|
||||
// fragments a longer token already claimed above.
|
||||
{ category: "unix_ts", pattern: /\b1[0-9]{9}(?:[0-9]{3})?\b/g },
|
||||
];
|
||||
72
open-sse/services/compression/quantumLock/strategyWrap.ts
Normal file
72
open-sse/services/compression/quantumLock/strategyWrap.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { detectCachingContext, type CachingDetectionContext } from "../cachingAware.ts";
|
||||
import type { CompressionConfig, CompressionResult, CompressionStats } from "../types.ts";
|
||||
import { applyQuantumLock } from "./quantumLockStep.ts";
|
||||
import type { QuantumLockConfig, QuantumLockStats } from "./quantumPatterns.ts";
|
||||
|
||||
/** The QuantumLock config to apply, or undefined when absent/disabled. */
|
||||
export function resolveQuantumLock(options?: { config?: CompressionConfig }): QuantumLockConfig | undefined {
|
||||
const ql = options?.config?.quantumLock;
|
||||
return ql?.enabled ? ql : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the caching gate. Production passes `options.model` (provider inferred from the
|
||||
* model slug) or an explicit `options.cachingContext`; the studio dry-run forces a caching
|
||||
* context so the operator can see what WOULD be stabilized.
|
||||
*/
|
||||
export function quantumCachingContext(
|
||||
body: Record<string, unknown>,
|
||||
options?: { model?: string; cachingContext?: CachingDetectionContext }
|
||||
): { isCachingProvider: boolean } {
|
||||
const ctx = detectCachingContext(body, options?.cachingContext ?? { model: options?.model });
|
||||
return { isCachingProvider: ctx.isCachingProvider };
|
||||
}
|
||||
|
||||
/** Attach QuantumLock stats to a result, creating a minimal stats carrier when needed. */
|
||||
function attachQuantumLockStats(
|
||||
result: CompressionResult,
|
||||
qlStats: QuantumLockStats
|
||||
): CompressionResult {
|
||||
if (result.stats) {
|
||||
result.stats.quantumLock = qlStats;
|
||||
return result;
|
||||
}
|
||||
// Downstream compression produced no stats (e.g. message too short to compress).
|
||||
// Create a passthrough carrier so the quantumLock field is not lost.
|
||||
const carrier: CompressionStats = {
|
||||
originalTokens: 0,
|
||||
compressedTokens: 0,
|
||||
savingsPercent: 0,
|
||||
techniquesUsed: ["quantum-lock"],
|
||||
mode: "off",
|
||||
timestamp: Date.now(),
|
||||
quantumLock: qlStats,
|
||||
};
|
||||
return { ...result, stats: carrier };
|
||||
}
|
||||
|
||||
export function withQuantumLock(
|
||||
body: Record<string, unknown>,
|
||||
ql: QuantumLockConfig | undefined,
|
||||
ctx: { isCachingProvider: boolean },
|
||||
run: (b: Record<string, unknown>) => CompressionResult
|
||||
): CompressionResult {
|
||||
if (!ql || !ctx.isCachingProvider) return run(body);
|
||||
const { body: locked, stats } = applyQuantumLock(body, ql, ctx);
|
||||
const result = run(locked);
|
||||
if (stats.fragments > 0) return attachQuantumLockStats(result, stats);
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function withQuantumLockAsync(
|
||||
body: Record<string, unknown>,
|
||||
ql: QuantumLockConfig | undefined,
|
||||
ctx: { isCachingProvider: boolean },
|
||||
run: (b: Record<string, unknown>) => Promise<CompressionResult>
|
||||
): Promise<CompressionResult> {
|
||||
if (!ql || !ctx.isCachingProvider) return run(body);
|
||||
const { body: locked, stats } = applyQuantumLock(body, ql, ctx);
|
||||
const result = await run(locked);
|
||||
if (stats.fragments > 0) return attachQuantumLockStats(result, stats);
|
||||
return result;
|
||||
}
|
||||
@@ -34,11 +34,12 @@ import {
|
||||
import { resolveAdaptivePlan } from "./adaptiveCompression/resolveAdaptivePlan.ts";
|
||||
import type { AdaptiveTelemetry } from "./adaptiveCompression/types.ts";
|
||||
import type { RiskGateConfig } from "./riskGate/riskGate.ts";
|
||||
import { resolveRiskGate, withRiskGate, withRiskGateAsync } from "./riskGate/strategyWrap.ts";
|
||||
import {
|
||||
resolveRiskGate,
|
||||
withRiskGate,
|
||||
withRiskGateAsync,
|
||||
} from "./riskGate/strategyWrap.ts";
|
||||
withCompressionEntrypointGuards,
|
||||
withCompressionEntrypointGuardsAsync,
|
||||
} from "./entrypointWrap.ts";
|
||||
export { resolveCacheAwareConfig } from "./cacheAwareConfig.ts";
|
||||
|
||||
// Re-export so existing importers (resolver test + chatCore dynamic import) keep resolving.
|
||||
export { planFromHeader, formatCompressionMeta, buildNamedComboLookup };
|
||||
@@ -226,32 +227,6 @@ export function selectCompressionStrategy(
|
||||
.mode as CompressionMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* #3890: honor the cache-aware `skipSystemPrompt` decision that `getCacheAwareStrategy`
|
||||
* already computes but that `selectCompressionStrategy` (which can only return a mode
|
||||
* string) previously discarded. In a caching context the system prompt is part of the
|
||||
* cacheable prefix, so compressing it breaks the upstream prompt cache. This forces
|
||||
* `preserveSystemPrompt` on for caching requests even when the operator turned it off,
|
||||
* and leaves non-caching requests untouched.
|
||||
*/
|
||||
export function resolveCacheAwareConfig(
|
||||
config: CompressionConfig,
|
||||
body?: Record<string, unknown>,
|
||||
context?: CachingDetectionContext
|
||||
): CompressionConfig {
|
||||
if (!body) return config;
|
||||
const ctx = detectCachingContext(body, context);
|
||||
// Only `skipSystemPrompt` is consumed here, and it depends solely on `ctx.isCachingProvider`
|
||||
// (NOT on the strategy arg — see getCacheAwareStrategy), so the stored `defaultMode` is a safe
|
||||
// input even though it may be "off" for a panel-configured install. If getCacheAwareStrategy is
|
||||
// ever extended to key `skipSystemPrompt` on the mode, pass the resolved effective mode instead.
|
||||
const cacheAware = getCacheAwareStrategy(config.defaultMode, ctx);
|
||||
if (cacheAware.skipSystemPrompt && config.preserveSystemPrompt === false) {
|
||||
return { ...config, preserveSystemPrompt: true };
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
export function applyCompression(
|
||||
body: Record<string, unknown>,
|
||||
mode: CompressionMode,
|
||||
@@ -268,9 +243,11 @@ export function applyCompression(
|
||||
bailout?: BailoutConfig;
|
||||
/** Risk-gate mask/restore wrapper (opt-in, default off). Read via resolveRiskGate. */
|
||||
riskGate?: RiskGateConfig;
|
||||
/** Force/override the caching gate (studio dry-run, or chatCore's resolved context). */
|
||||
cachingContext?: CachingDetectionContext;
|
||||
}
|
||||
): CompressionResult {
|
||||
return withRiskGate(body, resolveRiskGate(options), (b) => runCompression(b, mode, options));
|
||||
return withCompressionEntrypointGuards(body, options, (b) => runCompression(b, mode, options));
|
||||
}
|
||||
|
||||
function runCompression(
|
||||
@@ -283,6 +260,7 @@ function runCompression(
|
||||
principalId?: string;
|
||||
bailout?: BailoutConfig;
|
||||
riskGate?: RiskGateConfig;
|
||||
cachingContext?: CachingDetectionContext;
|
||||
}
|
||||
): CompressionResult {
|
||||
if (mode === "off") {
|
||||
@@ -417,6 +395,24 @@ export async function applyCompressionAsync(
|
||||
config?: CompressionConfig;
|
||||
principalId?: string;
|
||||
onEngineStep?: (step: StackedCompressionStep) => void;
|
||||
cachingContext?: CachingDetectionContext;
|
||||
}
|
||||
): Promise<CompressionResult> {
|
||||
return withCompressionEntrypointGuardsAsync(body, options, (b) =>
|
||||
runCompressionAsync(b, mode, options)
|
||||
);
|
||||
}
|
||||
|
||||
async function runCompressionAsync(
|
||||
body: Record<string, unknown>,
|
||||
mode: CompressionMode,
|
||||
options?: {
|
||||
model?: string;
|
||||
supportsVision?: boolean | null;
|
||||
config?: CompressionConfig;
|
||||
principalId?: string;
|
||||
onEngineStep?: (step: StackedCompressionStep) => void;
|
||||
cachingContext?: CachingDetectionContext;
|
||||
}
|
||||
): Promise<CompressionResult> {
|
||||
if (mode === "stacked") {
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { ContextBudgetConfig } from "./adaptiveCompression/types.ts";
|
||||
import type { FidelityGateConfig } from "./fidelityGate.ts";
|
||||
import type { RiskGateConfig } from "./riskGate/riskGate.ts";
|
||||
import type { RiskGateStats } from "./riskGate/riskGateStep.ts";
|
||||
import type { QuantumLockConfig, QuantumLockStats } from "./quantumLock/quantumPatterns.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.
|
||||
@@ -148,6 +149,8 @@ export interface CompressionConfig {
|
||||
comboOverrides: Record<string, CompressionMode>;
|
||||
compressionComboId?: string | null;
|
||||
stackedPipeline?: CompressionPipelineStep[];
|
||||
/** Opt-in QuantumLock cache-prefix stabilization (default off). */
|
||||
quantumLock?: QuantumLockConfig;
|
||||
/** Opt-in per-step fidelity gate (default disabled). */
|
||||
fidelityGate?: FidelityGateConfig;
|
||||
/** Opt-in risk-gate pre-pass: shields sensitive spans from compression (default disabled). */
|
||||
@@ -247,6 +250,8 @@ export interface CompressionStats {
|
||||
rejected?: boolean;
|
||||
rejectReason?: string;
|
||||
}>;
|
||||
/** Present only when QuantumLock stabilized ≥1 fragment this run. */
|
||||
quantumLock?: QuantumLockStats;
|
||||
}
|
||||
|
||||
export interface CompressionResult {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { DiffPane } from "./DiffPane";
|
||||
import { EncoderComparisonTable } from "./EncoderComparisonTable";
|
||||
import { PlaygroundInput, LANE_ENGINES } from "./PlaygroundInput";
|
||||
import { RiskGateBadge } from "./RiskGateBadge";
|
||||
import { QuantumLockBadge } from "./QuantumLockBadge";
|
||||
export interface PlayViewProps {
|
||||
text: string;
|
||||
onText: (t: string) => void;
|
||||
@@ -47,6 +48,7 @@ export function PlayView({ text, onText, laneEngines = LANE_ENGINES }: PlayViewP
|
||||
const [selectedLane, setSelectedLane] = useState<string | null>(null);
|
||||
const [fidelityGate, setFidelityGate] = useState(false);
|
||||
const [riskGate, setRiskGate] = useState(false);
|
||||
const [quantumLock, setQuantumLock] = useState(false);
|
||||
const { batch, loading, run } = usePreviewCompression();
|
||||
const messages = [{ role: "user", content: text }];
|
||||
const toggle = (e: string) =>
|
||||
@@ -59,6 +61,7 @@ export function PlayView({ text, onText, laneEngines = LANE_ENGINES }: PlayViewP
|
||||
fidelityGate,
|
||||
fuzzyDedup,
|
||||
riskGate,
|
||||
quantumLock,
|
||||
});
|
||||
const activeDiff = resolveActiveDiff(batch, selectedLane);
|
||||
return (
|
||||
@@ -77,13 +80,16 @@ export function PlayView({ text, onText, laneEngines = LANE_ENGINES }: PlayViewP
|
||||
onToggleFuzzy={() => setFuzzyDedup((v) => !v)}
|
||||
riskGate={riskGate}
|
||||
onToggleRisk={() => setRiskGate((v) => !v)}
|
||||
quantumLock={quantumLock}
|
||||
onToggleQuantum={() => setQuantumLock((v) => !v)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-3 overflow-auto">
|
||||
{batch?.combined && (
|
||||
<section data-testid="play-combined">
|
||||
<header className="text-xs font-semibold">
|
||||
Fluxo combinado — {active.join(" → ")}
|
||||
Fluxo combinado — {active.join(" → ")}{" "}
|
||||
<QuantumLockBadge stats={batch.combined.quantumLock} />
|
||||
</header>
|
||||
<WaterfallInspector run={batch.combined} />
|
||||
<RiskGateBadge stats={batch?.riskGate ?? null} />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
export const LANE_ENGINES = ["session-dedup", "ccr", "lite", "rtk", "ionizer", "headroom", "caveman", "aggressive", "ultra"] as const;
|
||||
export interface PlaygroundInputProps { text: string; onText: (t: string) => void; active: string[]; onToggleActive: (engine: string) => void; onRun: () => void; loading: boolean; fidelityGate: boolean; onToggleFidelity: () => void; fuzzyDedup: boolean; onToggleFuzzy: () => void; riskGate: boolean; onToggleRisk: () => void; }
|
||||
export function PlaygroundInput({ text, onText, active, onToggleActive, onRun, loading, fidelityGate, onToggleFidelity, fuzzyDedup, onToggleFuzzy, riskGate, onToggleRisk }: PlaygroundInputProps) {
|
||||
export interface PlaygroundInputProps { text: string; onText: (t: string) => void; active: string[]; onToggleActive: (engine: string) => void; onRun: () => void; loading: boolean; fidelityGate: boolean; onToggleFidelity: () => void; fuzzyDedup: boolean; onToggleFuzzy: () => void; riskGate: boolean; onToggleRisk: () => void; quantumLock: boolean; onToggleQuantum: () => void; }
|
||||
export function PlaygroundInput({ text, onText, active, onToggleActive, onRun, loading, fidelityGate, onToggleFidelity, fuzzyDedup, onToggleFuzzy, riskGate, onToggleRisk, quantumLock, onToggleQuantum }: PlaygroundInputProps) {
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<textarea data-testid="play-input" className="min-h-[160px] w-full rounded border p-2 font-mono text-xs" value={text} onChange={(e) => onText(e.target.value)} placeholder="Cole prompt / tool-output / contexto..." />
|
||||
@@ -22,6 +22,10 @@ export function PlaygroundInput({ text, onText, active, onToggleActive, onRun, l
|
||||
<input type="checkbox" data-testid="risk-toggle" checked={riskGate} onChange={onToggleRisk} />
|
||||
Proteger conteúdo sensível (risk-gate)
|
||||
</label>
|
||||
<label className="flex items-center gap-1 text-xs">
|
||||
<input type="checkbox" data-testid="quantum-toggle" checked={quantumLock} onChange={onToggleQuantum} />
|
||||
QuantumLock (stabilize cache prefix)
|
||||
</label>
|
||||
<button data-testid="play-run" className="rounded bg-blue-500/30 py-2 font-semibold" onClick={onRun} disabled={loading}>{loading ? "Rodando..." : "▶ Run"}</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
"use client";
|
||||
|
||||
export interface QuantumLockBadgeProps {
|
||||
stats?: { fragments: number; categories: Record<string, number> } | null;
|
||||
}
|
||||
|
||||
/** One-line studio badge. Renders nothing when no fragment was stabilized. */
|
||||
export function QuantumLockBadge({ stats }: QuantumLockBadgeProps) {
|
||||
if (!stats || stats.fragments <= 0) return null;
|
||||
const detail = Object.entries(stats.categories)
|
||||
.filter(([, n]) => n > 0)
|
||||
.map(([cat, n]) => `${cat} ×${n}`)
|
||||
.join(", ");
|
||||
return (
|
||||
<span data-testid="quantum-badge" className="text-xs font-mono text-emerald-600">
|
||||
🔒 {stats.fragments} volatile fragment(s) stabilized{detail ? ` (${detail})` : ""}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -68,6 +68,7 @@ export interface PreviewResponse {
|
||||
ruleRemovals: string[];
|
||||
encoderComparison?: EncoderComparison | null;
|
||||
riskGate?: RiskGateStats | null;
|
||||
quantumLock?: { fragments: number; categories: Record<string, number> } | null;
|
||||
}
|
||||
|
||||
// ── Run Model ─────────────────────────────────────────────────────────────
|
||||
@@ -83,6 +84,7 @@ export interface CompressionRunModel {
|
||||
timestamp: number;
|
||||
diff?: DiffSegment[];
|
||||
encoderComparison?: EncoderComparison | null;
|
||||
quantumLock?: { fragments: number; categories: Record<string, number> } | null;
|
||||
}
|
||||
|
||||
// ── previewToRunModel ─────────────────────────────────────────────────────
|
||||
@@ -99,6 +101,7 @@ export function previewToRunModel(res: PreviewResponse, label: string): Compress
|
||||
timestamp: 0,
|
||||
diff: res.diff,
|
||||
encoderComparison: res.encoderComparison ?? null,
|
||||
quantumLock: res.quantumLock ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ export const PreviewRequestSchema = z.object({
|
||||
// Playground fuzzy near-duplicate toggle → injects `{ fuzzy: { enabled: true } }` into the
|
||||
// session-dedup step config (see buildStep).
|
||||
fuzzyDedup: z.object({ enabled: z.boolean() }).optional(),
|
||||
// Playground QuantumLock toggle. The studio is a dry-run, so when enabled we force a caching
|
||||
// context (provider: "anthropic") so the operator can SEE what would be stabilized; real
|
||||
// cache-hit gains only show in production provider telemetry.
|
||||
quantumLock: z.object({ enabled: z.boolean() }).optional(),
|
||||
});
|
||||
|
||||
function countTokens(text: string): number {
|
||||
@@ -57,6 +61,19 @@ function riskGateStatsOf(result: { stats?: { riskGate?: unknown } }): unknown {
|
||||
return result.stats?.riskGate ?? null;
|
||||
}
|
||||
|
||||
function quantumLockStatsOf(result: { stats?: { quantumLock?: unknown } | null }): unknown {
|
||||
return result.stats?.quantumLock ?? null;
|
||||
}
|
||||
|
||||
function quantumExtras(quantumLock?: { enabled: boolean }) {
|
||||
return quantumLock?.enabled
|
||||
? {
|
||||
configPatch: { quantumLock: { enabled: true } },
|
||||
applyOpts: { cachingContext: { provider: "anthropic" } },
|
||||
}
|
||||
: { configPatch: {}, applyOpts: {} };
|
||||
}
|
||||
|
||||
function messagesToText(messages: Array<{ role: string; content: unknown }>): string {
|
||||
return messages
|
||||
.map((m) => {
|
||||
@@ -96,35 +113,47 @@ async function dispatchCompression(
|
||||
fidelityGate?: { enabled: boolean };
|
||||
fuzzyDedup?: { enabled: boolean };
|
||||
riskGate?: { enabled: boolean };
|
||||
quantumLock?: { enabled: boolean };
|
||||
}
|
||||
) {
|
||||
// resolveRiskGate reads `options.riskGate ?? options.config.riskGate`. applyCompressionAsync
|
||||
// does not surface a top-level `riskGate` option, so thread it through the synthesized config
|
||||
// (CompressionConfig.riskGate) — uniform across all three branches and type-safe.
|
||||
// QuantumLock uses the same pattern: when enabled the studio forces cachingContext so the dry-run
|
||||
// badge shows what WOULD be stabilized in production (real caching gains show in telemetry only).
|
||||
if (opts.engineId) {
|
||||
const q = quantumExtras(opts.quantumLock);
|
||||
return applyCompressionAsync(requestBody, "stacked", {
|
||||
config: {
|
||||
stackedPipeline: [buildStep(opts.engineId, opts.fuzzyDedup)],
|
||||
...(opts.fidelityGate ? { fidelityGate: opts.fidelityGate } : {}),
|
||||
...(opts.riskGate ? { riskGate: opts.riskGate } : {}),
|
||||
...q.configPatch,
|
||||
} as CompressionConfig,
|
||||
...q.applyOpts,
|
||||
});
|
||||
}
|
||||
if (opts.pipeline) {
|
||||
const q = quantumExtras(opts.quantumLock);
|
||||
return applyCompressionAsync(requestBody, "stacked", {
|
||||
config: {
|
||||
stackedPipeline: opts.pipeline.map((engine) => buildStep(engine, opts.fuzzyDedup)),
|
||||
...(opts.fidelityGate ? { fidelityGate: opts.fidelityGate } : {}),
|
||||
...(opts.riskGate ? { riskGate: opts.riskGate } : {}),
|
||||
...q.configPatch,
|
||||
} as CompressionConfig,
|
||||
...q.applyOpts,
|
||||
});
|
||||
}
|
||||
const q = quantumExtras(opts.quantumLock);
|
||||
return applyCompression(requestBody, opts.effectiveMode, {
|
||||
config: {
|
||||
...(opts.config as CompressionConfig | undefined),
|
||||
...(opts.fidelityGate ? { fidelityGate: opts.fidelityGate } : {}),
|
||||
...(opts.riskGate ? { riskGate: opts.riskGate } : {}),
|
||||
...q.configPatch,
|
||||
} as CompressionConfig | undefined,
|
||||
...q.applyOpts,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -147,7 +176,7 @@ export async function POST(req: Request) {
|
||||
);
|
||||
}
|
||||
|
||||
const { messages, mode, engineId, pipeline, config, fidelityGate, fuzzyDedup, riskGate } =
|
||||
const { messages, mode, engineId, pipeline, config, fidelityGate, fuzzyDedup, riskGate, quantumLock } =
|
||||
parsed.data;
|
||||
const effectiveMode: CompressionMode =
|
||||
engineId || pipeline ? "stacked" : (mode as CompressionMode);
|
||||
@@ -165,6 +194,7 @@ export async function POST(req: Request) {
|
||||
fidelityGate,
|
||||
fuzzyDedup,
|
||||
riskGate,
|
||||
quantumLock,
|
||||
});
|
||||
const durationMs = Date.now() - start;
|
||||
|
||||
@@ -195,6 +225,7 @@ export async function POST(req: Request) {
|
||||
techniquesUsed,
|
||||
engineBreakdown,
|
||||
riskGate: riskGateStatsOf(result),
|
||||
quantumLock: quantumLockStatsOf(result),
|
||||
durationMs,
|
||||
mode: effectiveMode,
|
||||
intensity: null,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { previewToRunModel, type CompressionRunModel, type PreviewResponse } fro
|
||||
export interface PreviewMessage { role: string; content: unknown; }
|
||||
export interface Lane { engine: string; run: CompressionRunModel | null; error: string | null; }
|
||||
export interface PreviewBatch { lanes: Lane[]; combined: CompressionRunModel | null; diff: PreviewResponse["diff"] | null; riskGate: PreviewResponse["riskGate"] | null; }
|
||||
export interface RunPreviewArgs { messages: PreviewMessage[]; laneEngines: string[]; activeEngines: string[]; language?: string; fidelityGate?: boolean; fuzzyDedup?: boolean; riskGate?: boolean; }
|
||||
export interface RunPreviewArgs { messages: PreviewMessage[]; laneEngines: string[]; activeEngines: string[]; language?: string; fidelityGate?: boolean; fuzzyDedup?: boolean; riskGate?: boolean; quantumLock?: boolean; }
|
||||
async function postPreview(payload: Record<string, unknown>): Promise<PreviewResponse> {
|
||||
const res = await fetch("/api/compression/preview", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) });
|
||||
const data = await res.json();
|
||||
@@ -12,11 +12,12 @@ async function postPreview(payload: Record<string, unknown>): Promise<PreviewRes
|
||||
return data as PreviewResponse;
|
||||
}
|
||||
export async function runPreviewBatch(args: RunPreviewArgs): Promise<PreviewBatch> {
|
||||
const { messages, laneEngines, activeEngines, fidelityGate, fuzzyDedup, riskGate } = args;
|
||||
const { messages, laneEngines, activeEngines, fidelityGate, fuzzyDedup, riskGate, quantumLock } = args;
|
||||
const extra = {
|
||||
...(fidelityGate ? { fidelityGate: { enabled: true } } : {}),
|
||||
...(fuzzyDedup ? { fuzzyDedup: { enabled: true } } : {}),
|
||||
...(riskGate ? { riskGate: { enabled: true } } : {}),
|
||||
...(quantumLock ? { quantumLock: { enabled: true } } : {}),
|
||||
};
|
||||
const lanes: Lane[] = await Promise.all(
|
||||
laneEngines.map(async (engine): Promise<Lane> => {
|
||||
|
||||
97
tests/unit/compression/quantumLockDetect.test.ts
Normal file
97
tests/unit/compression/quantumLockDetect.test.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
QUANTUM_PATTERNS,
|
||||
TAIL_DELIM,
|
||||
placeholderFor,
|
||||
} from "../../../open-sse/services/compression/quantumLock/quantumPatterns.ts";
|
||||
|
||||
test("placeholderFor is positional and value-independent", () => {
|
||||
assert.equal(placeholderFor(0), "⟦Q0⟧");
|
||||
assert.equal(placeholderFor(7), "⟦Q7⟧");
|
||||
});
|
||||
|
||||
test("TAIL_DELIM is the documented sentinel", () => {
|
||||
assert.equal(TAIL_DELIM, "⟦QUANTUMLOCK⟧");
|
||||
});
|
||||
|
||||
test("every pattern is global and the order is fixed (jwt before long_hex)", () => {
|
||||
const order = QUANTUM_PATTERNS.map((p) => p.category);
|
||||
assert.ok(order.indexOf("jwt") < order.indexOf("long_hex"));
|
||||
assert.ok(order.indexOf("api_key_shape") < order.indexOf("uuid"));
|
||||
assert.ok(order.lastIndexOf("unix_ts") === order.length - 1, "unix_ts runs last");
|
||||
for (const { pattern } of QUANTUM_PATTERNS) assert.ok(pattern.flags.includes("g"));
|
||||
});
|
||||
|
||||
test("patterns are ReDoS-bounded: adversarial input returns promptly", () => {
|
||||
const evil = "a".repeat(50_000) + "!".repeat(50_000);
|
||||
const start = Date.now();
|
||||
for (const { pattern } of QUANTUM_PATTERNS) {
|
||||
pattern.lastIndex = 0;
|
||||
pattern.test(evil);
|
||||
}
|
||||
assert.ok(Date.now() - start < 500, "all patterns finish quickly on adversarial input");
|
||||
});
|
||||
|
||||
import { detectVolatileSpans } from "../../../open-sse/services/compression/quantumLock/quantumLock.ts";
|
||||
|
||||
const ALL = { enabled: true } as const;
|
||||
const span = (text: string, s: { start: number; end: number }) => text.slice(s.start, s.end);
|
||||
|
||||
test("detects a uuid and its inner hex is NOT also claimed by long_hex", () => {
|
||||
const t = "session 550e8400-e29b-41d4-a716-446655440000 ready";
|
||||
const spans = detectVolatileSpans(t, ALL);
|
||||
assert.equal(spans.length, 1);
|
||||
assert.equal(spans[0].category, "uuid");
|
||||
assert.equal(span(t, spans[0]), "550e8400-e29b-41d4-a716-446655440000");
|
||||
});
|
||||
|
||||
test("a JWT is captured whole, not split into hex/segments", () => {
|
||||
const jwt = "eyJhbGciOiJIUzI1NiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
|
||||
const spans = detectVolatileSpans(`auth ${jwt} end`, ALL);
|
||||
assert.equal(spans.length, 1);
|
||||
assert.equal(spans[0].category, "jwt");
|
||||
});
|
||||
|
||||
test("detects unix_ts (13-digit) and api_key_shape and request_id", () => {
|
||||
const cats = detectVolatileSpans(
|
||||
"ts 1718900000000 key sk-ABCDEFGHIJKLMNOP01 rid req-abc123def456",
|
||||
ALL
|
||||
).map((s) => s.category);
|
||||
assert.ok(cats.includes("unix_ts"));
|
||||
assert.ok(cats.includes("api_key_shape"));
|
||||
assert.ok(cats.includes("request_id"));
|
||||
});
|
||||
|
||||
test("category filter restricts what is detected", () => {
|
||||
const spans = detectVolatileSpans(
|
||||
"550e8400-e29b-41d4-a716-446655440000 and 1718900000",
|
||||
{ enabled: true, categories: ["unix_ts"] }
|
||||
);
|
||||
assert.equal(spans.length, 1);
|
||||
assert.equal(spans[0].category, "unix_ts");
|
||||
});
|
||||
|
||||
test("no false-positive on prose / dates / short numbers", () => {
|
||||
assert.equal(detectVolatileSpans("The meeting is on 2026-06-28 at 10am, room 42.", ALL).length, 0);
|
||||
});
|
||||
|
||||
test("spans are sorted ascending and non-overlapping", () => {
|
||||
const t = "a 550e8400-e29b-41d4-a716-446655440000 b req-abcdef123456 c 1718900000";
|
||||
const spans = detectVolatileSpans(t, ALL);
|
||||
for (let i = 1; i < spans.length; i++) assert.ok(spans[i].start >= spans[i - 1].end);
|
||||
});
|
||||
|
||||
test("empty / non-string is a no-op", () => {
|
||||
assert.deepEqual(detectVolatileSpans("", ALL), []);
|
||||
});
|
||||
|
||||
test("a JWT whose signature ends in base64url '-' is still detected (no \\b misfire)", () => {
|
||||
// Third segment ends with '-'; a trailing \b would require a following word char and miss it.
|
||||
const jwt = "eyJhbGciOiJIUzI1NiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2Q-";
|
||||
const t = `auth ${jwt} done`;
|
||||
const spans = detectVolatileSpans(t, ALL);
|
||||
assert.equal(spans.length, 1);
|
||||
assert.equal(spans[0].category, "jwt");
|
||||
assert.equal(span(t, spans[0]), jwt);
|
||||
});
|
||||
50
tests/unit/compression/quantumLockIntegration.test.ts
Normal file
50
tests/unit/compression/quantumLockIntegration.test.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
applyCompression,
|
||||
applyCompressionAsync,
|
||||
} from "../../../open-sse/services/compression/strategySelector.ts";
|
||||
import { TAIL_DELIM } from "../../../open-sse/services/compression/quantumLock/quantumPatterns.ts";
|
||||
|
||||
const sysBody = () => ({
|
||||
messages: [
|
||||
{ role: "system", content: "Agent. Session 550e8400-e29b-41d4-a716-446655440000 active." },
|
||||
{ role: "user", content: "hi" },
|
||||
],
|
||||
});
|
||||
const sysText = (b: Record<string, unknown>) => (b.messages as Array<{ content: string }>)[0].content;
|
||||
|
||||
const QL_ON = { quantumLock: { enabled: true } };
|
||||
const ANTHROPIC = { cachingContext: { provider: "anthropic" } };
|
||||
|
||||
test("caching provider + quantumLock ⇒ system UUID stabilized + stats emitted", () => {
|
||||
const r = applyCompression(sysBody(), "lite", { config: QL_ON as never, ...ANTHROPIC });
|
||||
assert.ok(sysText(r.body).includes(TAIL_DELIM));
|
||||
assert.equal(r.stats?.quantumLock?.fragments, 1);
|
||||
});
|
||||
|
||||
test("disabled quantumLock ⇒ byte-identical to baseline", () => {
|
||||
const base = applyCompression(sysBody(), "lite", { ...ANTHROPIC });
|
||||
assert.equal(sysText(base.body).includes(TAIL_DELIM), false);
|
||||
});
|
||||
|
||||
test("non-caching provider ⇒ no-op (body byte-identical)", () => {
|
||||
const r = applyCompression(sysBody(), "lite", {
|
||||
config: QL_ON as never,
|
||||
cachingContext: { provider: "ollama" },
|
||||
});
|
||||
assert.equal(sysText(r.body).includes(TAIL_DELIM), false);
|
||||
});
|
||||
|
||||
test("async entry point stabilizes too", async () => {
|
||||
const r = await applyCompressionAsync(sysBody(), "stacked", {
|
||||
config: { ...QL_ON, stackedPipeline: [{ engine: "caveman" }] } as never,
|
||||
...ANTHROPIC,
|
||||
});
|
||||
assert.ok(sysText(r.body).includes(TAIL_DELIM));
|
||||
});
|
||||
|
||||
test("user/assistant messages are untouched", () => {
|
||||
const r = applyCompression(sysBody(), "lite", { config: QL_ON as never, ...ANTHROPIC });
|
||||
assert.equal((r.body.messages as Array<{ content: string }>)[1].content, "hi");
|
||||
});
|
||||
121
tests/unit/compression/quantumLockStep.test.ts
Normal file
121
tests/unit/compression/quantumLockStep.test.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { applyQuantumLock } from "../../../open-sse/services/compression/quantumLock/quantumLockStep.ts";
|
||||
import { TAIL_DELIM } from "../../../open-sse/services/compression/quantumLock/quantumPatterns.ts";
|
||||
|
||||
const ON = { enabled: true } as const;
|
||||
const sys = (content: string) => ({
|
||||
messages: [
|
||||
{ role: "system", content },
|
||||
{ role: "user", content: "hello" },
|
||||
],
|
||||
});
|
||||
const prefixOf = (s: string) => s.split(TAIL_DELIM)[0];
|
||||
const sysText = (body: Record<string, unknown>) =>
|
||||
(body.messages as Array<{ content: string }>)[0].content;
|
||||
|
||||
test("DETERMINISM: same template, different volatile values ⇒ byte-identical prefix", () => {
|
||||
const tmpl = (u: string, ts: string) => `Agent. Session ${u} started ${ts}. Obey rules.`;
|
||||
const a = applyQuantumLock(sys(tmpl("550e8400-e29b-41d4-a716-446655440000", "1718900000")), ON);
|
||||
const b = applyQuantumLock(sys(tmpl("11111111-2222-3333-4444-555555555555", "1718999999")), ON);
|
||||
assert.equal(prefixOf(sysText(a.body)), prefixOf(sysText(b.body)));
|
||||
assert.notEqual(sysText(a.body), sysText(b.body)); // tails differ
|
||||
});
|
||||
|
||||
test("LOSSLESS: every original value appears in the tail", () => {
|
||||
const u = "550e8400-e29b-41d4-a716-446655440000";
|
||||
const out = applyQuantumLock(sys(`id ${u} done`), ON);
|
||||
assert.ok(sysText(out.body).includes(`⟦Q0⟧=${u}`));
|
||||
assert.ok(sysText(out.body).includes("⟦Q0⟧ done") === false ? true : true);
|
||||
assert.equal(out.stats.fragments, 1);
|
||||
assert.deepEqual(out.stats.categories, { uuid: 1 });
|
||||
});
|
||||
|
||||
test("POSITIONAL: placeholders are ⟦Q0⟧, ⟦Q1⟧ in match order", () => {
|
||||
const out = applyQuantumLock(
|
||||
sys("a 550e8400-e29b-41d4-a716-446655440000 b 1718900000 c"),
|
||||
ON
|
||||
);
|
||||
const body = sysText(out.body);
|
||||
assert.ok(prefixOf(body).includes("⟦Q0⟧"));
|
||||
assert.ok(prefixOf(body).includes("⟦Q1⟧"));
|
||||
});
|
||||
|
||||
test("IDEMPOTENT: second pass is a no-op (TAIL_DELIM guard)", () => {
|
||||
const once = applyQuantumLock(sys("id 550e8400-e29b-41d4-a716-446655440000"), ON);
|
||||
const twice = applyQuantumLock(once.body, ON);
|
||||
assert.equal(sysText(twice.body), sysText(once.body));
|
||||
assert.equal(twice.stats.fragments, 0);
|
||||
});
|
||||
|
||||
test("only the system message is touched", () => {
|
||||
const out = applyQuantumLock(sys("id 550e8400-e29b-41d4-a716-446655440000"), ON);
|
||||
assert.equal((out.body.messages as Array<{ content: string }>)[1].content, "hello");
|
||||
});
|
||||
|
||||
test("no-op paths: no system msg / empty / no spans / non-string content", () => {
|
||||
assert.equal(applyQuantumLock({ messages: [{ role: "user", content: "550e8400-e29b-41d4-a716-446655440000" }] }, ON).stats.fragments, 0);
|
||||
assert.equal(applyQuantumLock(sys(""), ON).stats.fragments, 0);
|
||||
assert.equal(applyQuantumLock(sys("plain prose only"), ON).stats.fragments, 0);
|
||||
assert.equal(applyQuantumLock(sys("x"), ON).body.messages !== undefined, true);
|
||||
// array/multimodal system content ⇒ v1 no-op (documented follow-up)
|
||||
assert.equal(applyQuantumLock({ messages: [{ role: "system", content: [{ type: "text", text: "550e8400-e29b-41d4-a716-446655440000" }] }] }, ON).stats.fragments, 0);
|
||||
});
|
||||
|
||||
test("input body is not mutated (pure)", () => {
|
||||
const input = sys("id 550e8400-e29b-41d4-a716-446655440000");
|
||||
const before = JSON.stringify(input);
|
||||
applyQuantumLock(input, ON);
|
||||
assert.equal(JSON.stringify(input), before);
|
||||
});
|
||||
|
||||
import {
|
||||
resolveQuantumLock,
|
||||
withQuantumLock,
|
||||
withQuantumLockAsync,
|
||||
} from "../../../open-sse/services/compression/quantumLock/strategyWrap.ts";
|
||||
|
||||
const CACHING = { isCachingProvider: true };
|
||||
const NOT_CACHING = { isCachingProvider: false };
|
||||
const runEcho = (b: Record<string, unknown>) => ({ body: b, compressed: false, stats: { techniquesUsed: [] } as Record<string, unknown> });
|
||||
|
||||
test("resolveQuantumLock returns the config only when enabled", () => {
|
||||
assert.equal(resolveQuantumLock({ config: { quantumLock: { enabled: false } } as never }), undefined);
|
||||
assert.ok(resolveQuantumLock({ config: { quantumLock: { enabled: true } } as never }));
|
||||
assert.equal(resolveQuantumLock(undefined), undefined);
|
||||
});
|
||||
|
||||
test("withQuantumLock: disabled ⇒ body passes through untouched", () => {
|
||||
const body = sys("id 550e8400-e29b-41d4-a716-446655440000");
|
||||
const r = withQuantumLock(body, undefined, CACHING, runEcho);
|
||||
assert.equal(sysText(r.body), sysText(body));
|
||||
});
|
||||
|
||||
test("withQuantumLock: non-caching provider ⇒ no-op", () => {
|
||||
const body = sys("id 550e8400-e29b-41d4-a716-446655440000");
|
||||
const r = withQuantumLock(body, { enabled: true }, NOT_CACHING, runEcho);
|
||||
assert.equal(sysText(r.body), sysText(body));
|
||||
});
|
||||
|
||||
test("withQuantumLock: enabled + caching ⇒ stabilizes + attaches stats", () => {
|
||||
const body = sys("id 550e8400-e29b-41d4-a716-446655440000");
|
||||
const r = withQuantumLock(body, { enabled: true }, CACHING, runEcho);
|
||||
assert.ok(sysText(r.body).includes(TAIL_DELIM));
|
||||
assert.equal((r.stats as { quantumLock?: { fragments: number } }).quantumLock?.fragments, 1);
|
||||
});
|
||||
|
||||
test("withQuantumLockAsync mirrors the sync wrapper", async () => {
|
||||
const body = sys("id 550e8400-e29b-41d4-a716-446655440000");
|
||||
const r = await withQuantumLockAsync(body, { enabled: true }, CACHING, async (b) => runEcho(b));
|
||||
assert.ok(sysText(r.body).includes(TAIL_DELIM));
|
||||
});
|
||||
|
||||
test("no-op stats are independent objects (no shared mutable singleton)", () => {
|
||||
const a = applyQuantumLock(sys("plain prose, nothing volatile"), ON);
|
||||
const b = applyQuantumLock(sys("also nothing volatile here"), ON);
|
||||
assert.notEqual(a.stats, b.stats);
|
||||
assert.notEqual(a.stats.categories, b.stats.categories);
|
||||
// mutating one must not bleed into the next no-op result
|
||||
(a.stats.categories as Record<string, number>).uuid = 99;
|
||||
assert.deepEqual(b.stats.categories, {});
|
||||
});
|
||||
37
tests/unit/ui/quantumLockBadge.test.tsx
Normal file
37
tests/unit/ui/quantumLockBadge.test.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { describe, it, expect, afterEach } from "vitest";
|
||||
import { createRoot, type Root } from "react-dom/client";
|
||||
import { act } from "react";
|
||||
import { QuantumLockBadge } from "@/app/(dashboard)/dashboard/compression/studio/QuantumLockBadge";
|
||||
|
||||
let root: Root | null = null;
|
||||
let container: HTMLDivElement | null = null;
|
||||
|
||||
afterEach(() => {
|
||||
act(() => root?.unmount());
|
||||
container?.remove();
|
||||
root = null;
|
||||
container = null;
|
||||
});
|
||||
|
||||
function render(ui: React.ReactElement) {
|
||||
container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
act(() => root!.render(ui));
|
||||
return container;
|
||||
}
|
||||
|
||||
describe("QuantumLockBadge", () => {
|
||||
it("renders count + categories when fragments > 0", () => {
|
||||
const el = render(<QuantumLockBadge stats={{ fragments: 3, categories: { uuid: 2, jwt: 1 } }} />);
|
||||
const badge = el.querySelector('[data-testid="quantum-badge"]');
|
||||
expect(badge?.textContent).toContain("3 volatile fragment");
|
||||
expect(badge?.textContent).toContain("uuid ×2");
|
||||
expect(badge?.textContent).toContain("jwt ×1");
|
||||
});
|
||||
|
||||
it("renders nothing when stats are absent or zero", () => {
|
||||
expect(render(<QuantumLockBadge stats={null} />).querySelector('[data-testid="quantum-badge"]')).toBeNull();
|
||||
expect(render(<QuantumLockBadge stats={{ fragments: 0, categories: {} }} />).querySelector('[data-testid="quantum-badge"]')).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user