Merge pull request #1633 from oyi77/feat/prompt-compression-phase1

feat(compression): Phase 1 — Modular Prompt Compression Pipeline (Lite mode, 61 tests)
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-04-30 16:56:45 -03:00
committed by GitHub
28 changed files with 1289 additions and 81 deletions

View File

@@ -132,7 +132,7 @@ All persistence uses SQLite through domain-specific modules:
`backup.ts`, `proxies.ts`, `prompts.ts`, `webhooks.ts`, `detailedLogs.ts`,
`domainState.ts`, `registeredKeys.ts`, `quotaSnapshots.ts`, `modelComboMappings.ts`,
`cliToolState.ts`, `encryption.ts`, `readCache.ts`, `secrets.ts`, `stateReset.ts`,
`contextHandoffs.ts`.
`contextHandoffs.ts`, `compression.ts`.
Schema migrations live in `db/migrations/` and run via `migrationRunner.ts`.
`src/lib/localDb.ts` is a **re-export layer only** — never add logic there.
@@ -142,7 +142,7 @@ Schema migrations live in `db/migrations/` and run via `migrationRunner.ts`.
journaling. `SCHEMA_SQL` defines 15 base tables. Helpers: `rowToCamel`, `encryptConnectionFields`.
- **`migrationRunner.ts`**: Applies versioned SQL files from `db/migrations/` inside transactions.
Tracks applied migrations in `_omniroute_migrations` table.
- **Migrations**: 21 files (`001_initial_schema.sql``021_combo_call_log_targets.sql`).
- **Migrations**: 22 files (`001_initial_schema.sql``022_compression_settings.sql`).
Each migration is idempotent and runs in a transaction.
- **Domain modules** import `getDbInstance()` from `core.ts` for all CRUD operations.
Each module owns a specific table/set of tables (e.g., `providers.ts``provider_connections`,
@@ -285,7 +285,24 @@ Includes request/response translators with helpers for image handling.
`autoCombo/`, `intentClassifier.ts`, `taskAwareRouter.ts`, `thinkingBudget.ts`,
`contextManager.ts`, `modelDeprecation.ts`, `modelFamilyFallback.ts`,
`emergencyFallback.ts`, `workflowFSM.ts`, `backgroundTaskDetector.ts`, `ipFilter.ts`,
`signatureCache.ts`, `volumeDetector.ts`, `contextHandoff.ts`, and more.
`signatureCache.ts`, `volumeDetector.ts`, `contextHandoff.ts`, `compression/` (prompt
compression pipeline), and more.
#### Prompt Compression Pipeline (`compression/`)
Modular prompt compression that runs proactively before the existing reactive context manager.
- **`strategySelector.ts`**: Selects compression mode based on config, combo overrides, auto-trigger
thresholds. Priority: combo override > auto-trigger > default mode > off.
- **`lite.ts`**: 5 lite-mode techniques: `collapseWhitespace`, `dedupSystemPrompt`,
`compressToolResults`, `removeRedundantContent`, `replaceImageUrls`. Target: 10-15% savings at
<1ms latency.
- **`stats.ts`**: Per-request compression stats tracking (original tokens, compressed tokens,
savings %, techniques used).
- **`types.ts`**: `CompressionMode` (off/lite/standard/aggressive/ultra), `CompressionConfig`,
`CompressionStats`, `CompressionResult`.
- DB settings in `src/lib/db/compression.ts`, API route at `src/app/api/settings/compression/`.
- Phase 1 implements lite mode only; standard/aggressive/ultra are placeholders for Phase 2.
#### Combo Routing Engine (`combo.ts`)

View File

@@ -53,7 +53,9 @@ function getRuntimePlatform(): string {
}
function getRuntimeArch(): string {
return typeof process !== "undefined" && typeof process.arch === "string" ? process.arch : "unknown";
return typeof process !== "undefined" && typeof process.arch === "string"
? process.arch
: "unknown";
}
function getRuntimeVersion(): string {

View File

@@ -1560,7 +1560,38 @@ export async function handleChatCore({
const allMessages =
body?.messages || body?.input || body?.contents || body?.request?.contents || [];
if (body && Array.isArray(allMessages) && allMessages.length > 0) {
const estimatedTokens = estimateTokens(JSON.stringify(allMessages));
let estimatedTokens = estimateTokens(JSON.stringify(allMessages));
// --- Modular Compression Pipeline (Phase 1: Lite mode) ---
// Runs BEFORE the existing reactive compressContext() to proactively reduce tokens.
try {
const { getCompressionSettings } = await import("../../src/lib/db/compression.ts");
const { selectCompressionStrategy, applyCompression } =
await import("../services/compression/strategySelector.ts");
const { trackCompressionStats } = await import("../services/compression/stats.ts");
const config = await getCompressionSettings();
const mode = selectCompressionStrategy(config, comboName ?? null, estimatedTokens);
if (mode !== "off") {
const result = applyCompression(body, mode, { model: effectiveModel });
if (result.compressed && result.stats) {
body = result.body as typeof body;
estimatedTokens = result.stats.compressedTokens;
trackCompressionStats(result.stats);
log?.info?.(
"COMPRESSION",
`Prompt compressed (${mode}): ${result.stats.originalTokens} -> ${result.stats.compressedTokens} tokens (${result.stats.savingsPercent}% saved, techniques: ${result.stats.techniquesUsed.join(",")})`
);
}
}
} catch (err) {
log?.warn?.(
"COMPRESSION",
"Compression pipeline error (non-fatal): " +
(err instanceof Error ? err.message : String(err))
);
}
// --- End Modular Compression Pipeline ---
let contextLimit = getTokenLimit(provider, effectiveModel);
if (isCombo && comboName) {

View File

@@ -48,6 +48,16 @@
- **`volumeDetector.ts`** — Detects request volume spikes; triggers rate-limit escalation or load-shedding.
- **`contextHandoff.ts`** — Serializes/restores session context for agent handoff (A2A protocol).
### Prompt Compression Pipeline
- **`compression/`** — Modular prompt compression running proactively before `contextManager.ts`.
- `strategySelector.ts` — Selects mode (off/lite/standard/aggressive/ultra) with combo overrides and auto-trigger.
- `lite.ts` — 5 lite techniques: whitespace collapse, system prompt dedup, tool result truncation, redundant removal, image URL placeholder.
- `stats.ts` — Per-request compression stats (original/compressed tokens, savings %, techniques).
- `types.ts` — Shared types (`CompressionMode`, `CompressionConfig`, `CompressionStats`, `CompressionResult`).
- `index.ts` — Barrel re-exports.
- Phase 1: lite mode only. Standard/aggressive/ultra = Phase 2.
### Auto-Routing & Adaptive
- **`autoCombo/`** — Auto-generates combo configs based on historical performance, cost, and latency.

View File

@@ -67,10 +67,7 @@ function evictExpired(now = Date.now()): void {
function evictUntilWithinLimits(maxBytes: number, incomingBytes: number): void {
// Drop oldest until both the entry-count and total-byte caps are satisfied.
// Map iteration is insertion-ordered so the first key is the oldest entry.
while (
(cache.size >= MAX_ENTRIES || cacheBytes + incomingBytes > maxBytes) &&
cache.size > 0
) {
while ((cache.size >= MAX_ENTRIES || cacheBytes + incomingBytes > maxBytes) && cache.size > 0) {
const firstKey = cache.keys().next().value;
if (!firstKey) break;
deleteEntry(firstKey);
@@ -122,9 +119,7 @@ export function getChatGptImageConversationContext(
* saved chatgpt.com conversation node and actually edit the image instead
* of generating an unrelated one from scratch.
*/
export function findChatGptImageBySha256(
hash: string
): { id: string; entry: CachedImage } | null {
export function findChatGptImageBySha256(hash: string): { id: string; entry: CachedImage } | null {
evictExpired();
const target = hash.toLowerCase();
for (const [id, entry] of cache.entries()) {

View File

@@ -0,0 +1,31 @@
/**
* Compression Pipeline — Phase 1 (Lite mode)
*
* Modular prompt compression that runs BEFORE the existing reactive context manager.
* Lite mode: 5 techniques, ~10-15% token savings, <1ms latency.
*/
// Types
export type {
CompressionMode,
CompressionConfig,
CompressionStats,
CompressionResult,
} from "./types";
export { DEFAULT_COMPRESSION_CONFIG } from "./types";
// Lite compression techniques
export {
applyLiteCompression,
collapseWhitespace,
dedupSystemPrompt,
compressToolResults,
removeRedundantContent,
replaceImageUrls,
} from "./lite";
// Strategy selector
export { selectCompressionStrategy, getEffectiveMode, applyCompression } from "./strategySelector";
// Stats tracking
export { estimateCompressionTokens, createCompressionStats, trackCompressionStats } from "./stats";

View File

@@ -0,0 +1,170 @@
import type { CompressionResult, CompressionMode } from "./types";
import { createCompressionStats } from "./stats";
interface Message {
role: string;
content: string | Array<Record<string, unknown>>;
[key: string]: unknown;
}
interface ChatBody {
messages?: Message[];
[key: string]: unknown;
}
export function collapseWhitespace(body: ChatBody): {
body: ChatBody;
applied: boolean;
} {
if (!body.messages) return { body, applied: false };
let applied = false;
const messages = body.messages.map((msg) => {
if (typeof msg.content !== "string") return msg;
const normalized = msg.content.replace(/\n{3,}/g, "\n\n").replace(/[ \t]+$/gm, "");
if (normalized !== msg.content) applied = true;
return { ...msg, content: normalized };
});
return { body: { ...body, messages }, applied };
}
export function dedupSystemPrompt(body: ChatBody): {
body: ChatBody;
applied: boolean;
} {
if (!body.messages) return { body, applied: false };
const seen = new Set<string>();
let applied = false;
const messages = body.messages.filter((msg) => {
if (msg.role !== "system" || typeof msg.content !== "string") return true;
const key = msg.content.trim().slice(0, 200);
if (seen.has(key)) {
applied = true;
return false;
}
seen.add(key);
return true;
});
return { body: { ...body, messages }, applied };
}
export function compressToolResults(body: ChatBody): {
body: ChatBody;
applied: boolean;
} {
if (!body.messages) return { body, applied: false };
const MAX_TOOL_LENGTH = 2000;
let applied = false;
const messages = body.messages.map((msg) => {
if (msg.role !== "tool" || typeof msg.content !== "string") return msg;
if (msg.content.length <= MAX_TOOL_LENGTH) return msg;
applied = true;
return {
...msg,
content: msg.content.slice(0, MAX_TOOL_LENGTH) + "\n...[truncated]",
};
});
return { body: { ...body, messages }, applied };
}
export function removeRedundantContent(body: ChatBody): {
body: ChatBody;
applied: boolean;
} {
if (!body.messages) return { body, applied: false };
let applied = false;
const messages: Message[] = [];
for (let i = 0; i < body.messages.length; i++) {
const msg = body.messages[i];
const contentStr = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
if (
i > 0 &&
body.messages[i - 1].role === msg.role &&
typeof body.messages[i - 1].content === "string" &&
body.messages[i - 1].content === contentStr
) {
applied = true;
continue;
}
messages.push(msg);
}
return { body: { ...body, messages }, applied };
}
export function replaceImageUrls(
body: ChatBody,
model?: string
): { body: ChatBody; applied: boolean } {
if (!body.messages) return { body, applied: false };
const isVisionModel = model && /\b(vision|gpt-4o|claude-3|gemini-1\.5|gemini-2)\b/i.test(model);
if (isVisionModel) return { body, applied: false };
let applied = false;
const messages = body.messages.map((msg) => {
if (!Array.isArray(msg.content)) return msg;
const newContent = msg.content.map((part) => {
if (
typeof part === "object" &&
part !== null &&
part.type === "image_url" &&
typeof (part as Record<string, unknown>).image_url === "object" &&
((part as Record<string, unknown>).image_url as Record<string, unknown>)?.url
) {
const url = String(
((part as Record<string, unknown>).image_url as Record<string, unknown>).url
);
if (url.startsWith("data:image/")) {
applied = true;
const format = url.slice(url.indexOf("/") + 1, url.indexOf(";")) || "unknown";
return { type: "text", text: `[image: ${format}]` };
}
}
return part;
});
return { ...msg, content: newContent };
});
return { body: { ...body, messages }, applied };
}
export function applyLiteCompression(
body: Record<string, unknown>,
options?: { model?: string }
): CompressionResult {
const originalBody = body;
let current = body as ChatBody;
const techniquesApplied: string[] = [];
const r1 = collapseWhitespace(current);
current = r1.body;
if (r1.applied) techniquesApplied.push("whitespace");
const r2 = dedupSystemPrompt(current);
current = r2.body;
if (r2.applied) techniquesApplied.push("system-dedup");
const r3 = compressToolResults(current);
current = r3.body;
if (r3.applied) techniquesApplied.push("tool-compress");
const r4 = removeRedundantContent(current);
current = r4.body;
if (r4.applied) techniquesApplied.push("redundant-remove");
const r5 = replaceImageUrls(current, options?.model);
current = r5.body;
if (r5.applied) techniquesApplied.push("image-placeholder");
const compressed = techniquesApplied.length > 0;
const stats = compressed
? createCompressionStats(
originalBody,
current as Record<string, unknown>,
"lite",
techniquesApplied
)
: null;
return {
body: current as Record<string, unknown>,
compressed,
stats,
};
}

View File

@@ -0,0 +1,38 @@
import type { CompressionStats, CompressionMode } from "./types";
const CHARS_PER_TOKEN = 4;
export function estimateCompressionTokens(text: string | object | null | undefined): number {
if (!text) return 0;
const str = typeof text === "string" ? text : JSON.stringify(text);
return Math.ceil(str.length / CHARS_PER_TOKEN);
}
export function createCompressionStats(
originalBody: Record<string, unknown>,
compressedBody: Record<string, unknown>,
mode: CompressionMode,
techniquesUsed: string[]
): CompressionStats {
const originalTokens = estimateCompressionTokens(originalBody);
const compressedTokens = estimateCompressionTokens(compressedBody);
const savingsPercent =
originalTokens > 0
? Math.round(((originalTokens - compressedTokens) / originalTokens) * 10000) / 100
: 0;
return {
originalTokens,
compressedTokens,
savingsPercent,
techniquesUsed,
mode,
timestamp: Date.now(),
};
}
export function trackCompressionStats(stats: CompressionStats): void {
if (stats.originalTokens <= 0) return;
console.log(
`[COMPRESSION] mode=${stats.mode} tokens=${stats.originalTokens}->${stats.compressedTokens} savings=${stats.savingsPercent}% techniques=${stats.techniquesUsed.join(",")}`
);
}

View File

@@ -0,0 +1,51 @@
import type { CompressionConfig, CompressionMode, CompressionResult } from "./types";
import { applyLiteCompression } from "./lite";
export function checkComboOverride(
config: CompressionConfig,
comboId: string | null
): CompressionMode | null {
if (!comboId || !config.comboOverrides) return null;
return config.comboOverrides[comboId] ?? null;
}
export function shouldAutoTrigger(config: CompressionConfig, estimatedTokens: number): boolean {
return config.autoTriggerTokens > 0 && estimatedTokens >= config.autoTriggerTokens;
}
export function getEffectiveMode(
config: CompressionConfig,
comboId: string | null,
estimatedTokens: number
): CompressionMode {
if (!config.enabled) return "off";
const comboMode = checkComboOverride(config, comboId);
if (comboMode) return comboMode;
if (shouldAutoTrigger(config, estimatedTokens)) return "lite";
return config.defaultMode;
}
export function selectCompressionStrategy(
config: CompressionConfig,
comboId: string | null,
estimatedTokens: number
): CompressionMode {
return getEffectiveMode(config, comboId, estimatedTokens);
}
export function applyCompression(
body: Record<string, unknown>,
mode: CompressionMode,
options?: { model?: string }
): CompressionResult {
if (mode === "off") {
return { body, compressed: false, stats: null };
}
if (mode === "lite") {
return applyLiteCompression(body, options);
}
return { body, compressed: false, stats: null };
}

View File

@@ -0,0 +1,45 @@
/**
* Compression Pipeline Types — Phase 1 (Lite mode)
*
* Modular prompt compression that runs BEFORE the existing reactive context manager.
*/
/** Compression mode levels (only 'off' and 'lite' are active in Phase 1) */
export type CompressionMode = "off" | "lite" | "standard" | "aggressive" | "ultra";
/** Compression configuration stored in DB */
export interface CompressionConfig {
enabled: boolean;
defaultMode: CompressionMode;
autoTriggerTokens: number;
cacheMinutes: number;
preserveSystemPrompt: boolean;
comboOverrides: Record<string, CompressionMode>;
}
/** Per-request compression statistics */
export interface CompressionStats {
originalTokens: number;
compressedTokens: number;
savingsPercent: number;
techniquesUsed: string[];
mode: CompressionMode;
timestamp: number;
}
/** Result of a compression operation */
export interface CompressionResult {
body: Record<string, unknown>;
compressed: boolean;
stats: CompressionStats | null;
}
/** Default compression config values */
export const DEFAULT_COMPRESSION_CONFIG: CompressionConfig = {
enabled: false,
defaultMode: "off",
autoTriggerTokens: 0,
cacheMinutes: 5,
preserveSystemPrompt: true,
comboOverrides: {},
};

View File

@@ -1230,7 +1230,11 @@ async function fetchAntigravityAvailableModelsCached(
const cacheKey = buildAntigravityUsageCacheKey(accessToken, projectId);
const cached = _antigravityAvailableModelsCache.get(cacheKey);
if (!options.forceRefresh && cached && Date.now() - cached.fetchedAt < ANTIGRAVITY_MODELS_CACHE_TTL_MS) {
if (
!options.forceRefresh &&
cached &&
Date.now() - cached.fetchedAt < ANTIGRAVITY_MODELS_CACHE_TTL_MS
) {
return cached.data;
}
@@ -1361,25 +1365,31 @@ async function probeAntigravityCreditBalance(
const cacheKey = buildAntigravityUsageCacheKey(accessToken, projectId || accountId);
const cached = _antigravityCreditProbeCache.get(cacheKey);
if (!options.forceRefresh && cached && Date.now() - cached.fetchedAt < ANTIGRAVITY_CREDIT_PROBE_TTL_MS) {
if (
!options.forceRefresh &&
cached &&
Date.now() - cached.fetchedAt < ANTIGRAVITY_CREDIT_PROBE_TTL_MS
) {
return cached.data;
}
const inflight = _antigravityCreditProbeInflight.get(cacheKey);
if (inflight) return inflight;
const promise = probeAntigravityCreditBalanceUncached(accessToken, accountId, projectId).then(
(data) => {
_antigravityCreditProbeCache.set(cacheKey, { data, fetchedAt: Date.now() });
return data;
},
(error) => {
_antigravityCreditProbeCache.set(cacheKey, { data: null, fetchedAt: Date.now() });
throw error;
}
).finally(() => {
_antigravityCreditProbeInflight.delete(cacheKey);
});
const promise = probeAntigravityCreditBalanceUncached(accessToken, accountId, projectId)
.then(
(data) => {
_antigravityCreditProbeCache.set(cacheKey, { data, fetchedAt: Date.now() });
return data;
},
(error) => {
_antigravityCreditProbeCache.set(cacheKey, { data: null, fetchedAt: Date.now() });
throw error;
}
)
.finally(() => {
_antigravityCreditProbeInflight.delete(cacheKey);
});
_antigravityCreditProbeInflight.set(cacheKey, promise);
return promise;
@@ -1501,7 +1511,12 @@ async function getAntigravityUsage(
// If no cached balance and credits mode is enabled, fire a minimal probe
const creditsMode = getCreditsMode();
if ((options.forceRefresh || creditBalance === null) && creditsMode !== "off") {
creditBalance = await probeAntigravityCreditBalance(accessToken, accountId, projectId, options);
creditBalance = await probeAntigravityCreditBalance(
accessToken,
accountId,
projectId,
options
);
}
const data = await fetchAntigravityAvailableModelsCached(accessToken, projectId, options);

View File

@@ -183,15 +183,12 @@ export default function ApiManagerPageClient() {
for (const key of apiKeys) {
// Match analytics entry by key name (reliable across both systems)
const analyticsMatch = byApiKey.find(
(entry: any) => entry.apiKeyName === key.name
);
const analyticsMatch = byApiKey.find((entry: any) => entry.apiKeyName === key.name);
// The call-logs endpoint returns entries sorted by timestamp DESC,
// so the first match is the most recent one.
const lastUsed = (logs || []).find(
(log: any) => log.apiKeyName === key.name
)?.timestamp || null;
const lastUsed =
(logs || []).find((log: any) => log.apiKeyName === key.name)?.timestamp || null;
stats[key.id] = {
totalRequests: analyticsMatch?.requests ?? 0,

View File

@@ -10,11 +10,7 @@ import {
} from "@/lib/auth/managementPassword";
import { loginSchema } from "@/shared/validation/schemas";
import { isValidationFailure, validateBody } from "@/shared/validation/helpers";
import {
checkLoginGuard,
clearLoginAttempts,
recordLoginFailure,
} from "@/server/auth/loginGuard";
import { checkLoginGuard, clearLoginAttempts, recordLoginFailure } from "@/server/auth/loginGuard";
// SECURITY: No hardcoded fallback — JWT_SECRET must be configured.
if (!process.env.JWT_SECRET) {

View File

@@ -65,7 +65,10 @@ import {
type JsonRecord = Record<string, unknown>;
const antigravityDiscoveryInflight = new Map<string, Promise<Array<{ id: string; name: string }>>>();
const antigravityDiscoveryInflight = new Map<
string,
Promise<Array<{ id: string; name: string }>>
>();
function asRecord(value: unknown): JsonRecord {
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {};
@@ -1636,7 +1639,11 @@ export async function GET(
});
}
const remoteModels = await fetchAntigravityDiscoveryModelsCached(accessToken, connectionId, proxy);
const remoteModels = await fetchAntigravityDiscoveryModelsCached(
accessToken,
connectionId,
proxy
);
if (remoteModels.length > 0) {
return buildApiDiscoveryResponse(remoteModels);
}

View File

@@ -0,0 +1,58 @@
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { isAuthenticated } from "@/shared/utils/apiAuth";
import { isValidationFailure, validateBody } from "@/shared/validation/helpers";
import { getCompressionSettings, updateCompressionSettings } from "@/lib/db/compression";
const compressionModeSchema = z.enum(["off", "lite", "standard", "aggressive", "ultra"]);
const compressionSettingsUpdateSchema = z
.object({
enabled: z.boolean().optional(),
defaultMode: compressionModeSchema.optional(),
autoTriggerTokens: z.number().int().min(0).optional(),
cacheMinutes: z.number().int().min(1).max(60).optional(),
preserveSystemPrompt: z.boolean().optional(),
comboOverrides: z.record(z.string(), compressionModeSchema).optional(),
})
.strict();
export async function GET(request: NextRequest) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const settings = await getCompressionSettings();
return NextResponse.json(settings);
} catch (error) {
return NextResponse.json({ error: String(error) }, { status: 500 });
}
}
export async function PUT(request: NextRequest) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
let rawBody: unknown;
try {
rawBody = await request.json();
} catch {
return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
}
const validation = validateBody(compressionSettingsUpdateSchema, rawBody);
if (isValidationFailure(validation)) {
return NextResponse.json({ error: validation.error }, { status: 400 });
}
const settings = await updateCompressionSettings(
validation.data as Parameters<typeof updateCompressionSettings>[0]
);
return NextResponse.json(settings);
} catch (error) {
return NextResponse.json({ error: String(error) }, { status: 500 });
}
}

View File

@@ -140,10 +140,15 @@ export async function GET(request: Request) {
// ── Enrich entries with missing apiKeyName ──────────────────────────
try {
// Only run enrichment if there are actually NULL entries
const hasNull = db.prepare("SELECT 1 FROM usage_history WHERE (api_key_name IS NULL OR api_key_name = '') AND connection_id IS NOT NULL LIMIT 1").get();
const hasNull = db
.prepare(
"SELECT 1 FROM usage_history WHERE (api_key_name IS NULL OR api_key_name = '') AND connection_id IS NOT NULL LIMIT 1"
)
.get();
if (hasNull) {
// Step 1: dominant key per connectionId from existing usage data
db.prepare(`
db.prepare(
`
UPDATE usage_history
SET
api_key_name = (
@@ -171,22 +176,29 @@ export async function GET(request: Request) {
WHERE uh3.connection_id = usage_history.connection_id
AND uh3.api_key_name IS NOT NULL AND uh3.api_key_name != ''
)
`).run();
`
).run();
// Step 2 & 3: For still unresolved connections, check apiKeys config
const stillNull = db.prepare("SELECT DISTINCT connection_id FROM usage_history WHERE (api_key_name IS NULL OR api_key_name = '') AND connection_id IS NOT NULL").all();
const stillNull = db
.prepare(
"SELECT DISTINCT connection_id FROM usage_history WHERE (api_key_name IS NULL OR api_key_name = '') AND connection_id IS NOT NULL"
)
.all();
if (stillNull.length > 0) {
const { getApiKeys } = await import("@/lib/localDb");
const apiKeys = (await getApiKeys()) as any[];
const updateStmt = db.prepare("UPDATE usage_history SET api_key_name = ?, api_key_id = ? WHERE connection_id = ? AND (api_key_name IS NULL OR api_key_name = '')");
const updateStmt = db.prepare(
"UPDATE usage_history SET api_key_name = ?, api_key_id = ? WHERE connection_id = ? AND (api_key_name IS NULL OR api_key_name = '')"
);
const updateMany = db.transaction((updates: any[]) => {
for (const u of updates) updateStmt.run(u.name, u.id, u.cid);
});
const updates = [];
const orphanIds = new Set(stillNull.map((r: any) => r.connection_id));
for (const ak of apiKeys) {
const allowed = Array.isArray(ak.allowedConnections) ? ak.allowedConnections : [];
const keyName = ak.name || ak.id;
@@ -198,17 +210,23 @@ export async function GET(request: Request) {
}
}
}
if (orphanIds.size > 0) {
const unrestrictedKeys = apiKeys.filter(
(ak: any) => !Array.isArray(ak.allowedConnections) || ak.allowedConnections.length === 0
(ak: any) =>
!Array.isArray(ak.allowedConnections) || ak.allowedConnections.length === 0
);
if (unrestrictedKeys.length > 0) {
let bestKey = unrestrictedKeys[0];
let bestCount = -1;
for (const uk of unrestrictedKeys) {
const countRow = db.prepare("SELECT COUNT(*) as c FROM usage_history WHERE api_key_name = ?").get(uk.name || uk.id) as any;
if (countRow.c > bestCount) { bestCount = countRow.c; bestKey = uk; }
const countRow = db
.prepare("SELECT COUNT(*) as c FROM usage_history WHERE api_key_name = ?")
.get(uk.name || uk.id) as any;
if (countRow.c > bestCount) {
bestCount = countRow.c;
bestKey = uk;
}
}
const fallbackName = bestKey.name || bestKey.id;
const fallbackId = bestKey.id || null;
@@ -217,11 +235,11 @@ export async function GET(request: Request) {
}
}
}
if (updates.length > 0) updateMany(updates);
}
}
} catch(e) {
} catch (e) {
console.error("Failed to backfill missing api_key_name:", e);
}
@@ -322,13 +340,15 @@ export async function GET(request: Request) {
heatmapStart.setTime(customStart.getTime());
}
}
// Heatmap needs its own whereClause if api keys are filtered
const heatmapConditions = ["timestamp >= @heatmapStart"];
if (apiKeyWhere) heatmapConditions.push(apiKeyWhere);
const heatmapParams: Record<string, string> = { heatmapStart: heatmapStart.toISOString() };
if (apiKeyIds.length > 0) {
apiKeyIds.forEach((key, i) => { heatmapParams[`apiKey${i}`] = key; });
apiKeyIds.forEach((key, i) => {
heatmapParams[`apiKey${i}`] = key;
});
}
const heatmapRows = db
@@ -535,7 +555,7 @@ export async function GET(request: Request) {
)
: 0,
avgLatencyMs: Math.round(Number(summaryRow?.avgLatencyMs || 0)),
totalCost: 0,
totalCost: 0,
firstRequest: summaryRow?.firstRequest || "",
lastRequest: summaryRow?.lastRequest || "",
fallbackCount: Number(fallbackRow?.fallbacks || 0),
@@ -772,10 +792,17 @@ export async function GET(request: Request) {
const presetSinceIso = getRangeStartIso(presetRange);
const presetConditions = [];
const presetParams: Record<string, string> = {};
if (presetSinceIso) { presetConditions.push("timestamp >= @presetSince"); presetParams.presetSince = presetSinceIso; }
if (apiKeyWhere) { presetConditions.push(apiKeyWhere); Object.assign(presetParams, params); }
if (presetSinceIso) {
presetConditions.push("timestamp >= @presetSince");
presetParams.presetSince = presetSinceIso;
}
if (apiKeyWhere) {
presetConditions.push(apiKeyWhere);
Object.assign(presetParams, params);
}
const presetWhere = presetConditions.length > 0 ? `WHERE ${presetConditions.join(" AND ")}` : "";
const presetWhere =
presetConditions.length > 0 ? `WHERE ${presetConditions.join(" AND ")}` : "";
const presetModelRows = db
.prepare(

50
src/lib/db/compression.ts Normal file
View File

@@ -0,0 +1,50 @@
import { getDbInstance } from "./core";
import { backupDbFile } from "./backup";
const DEFAULT_COMPRESSION_CONFIG = {
enabled: false,
defaultMode: "off" as const,
autoTriggerTokens: 0,
cacheMinutes: 5,
preserveSystemPrompt: true,
comboOverrides: {},
};
type CompressionConfig = typeof DEFAULT_COMPRESSION_CONFIG & {
comboOverrides: Record<string, "off" | "lite" | "standard" | "aggressive" | "ultra">;
};
export async function getCompressionSettings(): Promise<CompressionConfig> {
const db = getDbInstance();
const rows = db.prepare("SELECT key, value FROM key_value WHERE namespace = 'compression'").all();
const settings: Record<string, unknown> = { ...DEFAULT_COMPRESSION_CONFIG };
for (const row of rows) {
const record = row as Record<string, unknown>;
const key = typeof record.key === "string" ? record.key : null;
const rawValue = typeof record.value === "string" ? record.value : null;
if (!key || rawValue === null) continue;
try {
settings[key] = JSON.parse(rawValue);
} catch {
// skip malformed JSON
}
}
return settings as CompressionConfig;
}
export async function updateCompressionSettings(
updates: Partial<CompressionConfig>
): Promise<CompressionConfig> {
const db = getDbInstance();
const insert = db.prepare(
"INSERT OR REPLACE INTO key_value (namespace, key, value) VALUES ('compression', ?, ?)"
);
const tx = db.transaction(() => {
for (const [key, value] of Object.entries(updates)) {
insert.run(key, JSON.stringify(value));
}
});
tx();
backupDbFile("pre-write");
return getCompressionSettings();
}

View File

@@ -0,0 +1,10 @@
-- 034_compression_settings.sql
-- Insert default compression settings into key_value table (namespace='compression')
-- Uses INSERT OR IGNORE so existing user settings are never overwritten by migration replay.
INSERT OR IGNORE INTO key_value (namespace, key, value) VALUES ('compression', 'enabled', 'false');
INSERT OR IGNORE INTO key_value (namespace, key, value) VALUES ('compression', 'defaultMode', '"off"');
INSERT OR IGNORE INTO key_value (namespace, key, value) VALUES ('compression', 'autoTriggerTokens', '0');
INSERT OR IGNORE INTO key_value (namespace, key, value) VALUES ('compression', 'cacheMinutes', '5');
INSERT OR IGNORE INTO key_value (namespace, key, value) VALUES ('compression', 'preserveSystemPrompt', 'true');
INSERT OR IGNORE INTO key_value (namespace, key, value) VALUES ('compression', 'comboOverrides', '{}');

View File

@@ -0,0 +1,120 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
selectCompressionStrategy,
getEffectiveMode,
applyCompression,
} from "../../open-sse/services/compression/strategySelector.ts";
import { applyLiteCompression } from "../../open-sse/services/compression/lite.ts";
import {
createCompressionStats,
estimateCompressionTokens,
} from "../../open-sse/services/compression/stats.ts";
import type { CompressionConfig } from "../../open-sse/services/compression/types.ts";
const baseConfig: CompressionConfig = {
enabled: true,
defaultMode: "lite",
autoTriggerTokens: 0,
cacheMinutes: 5,
preserveSystemPrompt: true,
comboOverrides: {},
};
describe("Full Compression Pipeline", () => {
it("end-to-end: lite mode compresses whitespace and tracks stats", () => {
const body = {
messages: [
{ role: "system", content: "You are helpful." },
{ role: "system", content: "You are helpful." },
{ role: "user", content: "hello\n\n\n\nworld" },
],
};
// Step 1: Select strategy
const mode = selectCompressionStrategy(baseConfig, null, 100);
assert.equal(mode, "lite");
// Step 2: Apply compression
const result = applyCompression(body, mode);
assert.equal(result.compressed, true);
assert.ok(result.stats);
// Step 3: Verify stats
assert.ok(result.stats!.originalTokens > 0);
assert.ok(result.stats!.compressedTokens > 0);
assert.ok(result.stats!.compressedTokens <= result.stats!.originalTokens);
assert.ok(result.stats!.savingsPercent >= 0);
assert.equal(result.stats!.mode, "lite");
});
it("end-to-end: off mode returns unchanged body", () => {
const body = { messages: [{ role: "user", content: "test" }] };
const offConfig = { ...baseConfig, enabled: false };
const mode = selectCompressionStrategy(offConfig, null, 100);
assert.equal(mode, "off");
const result = applyCompression(body, mode);
assert.equal(result.compressed, false);
assert.equal(result.stats, null);
});
it("end-to-end: combo override selects lite for specific combo", () => {
const config: CompressionConfig = {
...baseConfig,
defaultMode: "off" as const,
comboOverrides: { "my-combo": "lite" as const },
};
const body = { messages: [{ role: "user", content: "test\n\n\n\nmessage" }] };
const mode = selectCompressionStrategy(config, "my-combo", 100);
assert.equal(mode, "lite");
const result = applyCompression(body, mode);
assert.equal(result.compressed, true);
});
it("end-to-end: auto-trigger activates compression", () => {
const config: CompressionConfig = {
...baseConfig,
defaultMode: "off" as const,
autoTriggerTokens: 50,
};
const body = { messages: [{ role: "user", content: "x".repeat(1000) }] };
// Below threshold → off
const mode1 = getEffectiveMode(config, null, 10);
assert.equal(mode1, "off");
// Above threshold → lite
const mode2 = getEffectiveMode(config, null, 100);
assert.equal(mode2, "lite");
});
it("lite compression + stats pipeline works together", () => {
const body = {
messages: [
{ role: "system", content: "Be helpful." },
{ role: "system", content: "Be helpful." },
{ role: "user", content: "hello\n\n\n\nworld" },
{ role: "user", content: "hello\n\n\n\nworld" },
],
};
const result = applyLiteCompression(body);
assert.equal(result.compressed, true);
assert.ok(result.stats);
assert.ok(result.stats.savingsPercent > 0);
assert.ok(result.stats.techniquesUsed.length >= 1);
});
it("token estimation is consistent", () => {
const text = "hello world this is a test";
const tokens = estimateCompressionTokens(text);
assert.equal(tokens, Math.ceil(text.length / 4));
const obj = { messages: [{ role: "user", content: text }] };
const objTokens = estimateCompressionTokens(obj);
assert.equal(objTokens, Math.ceil(JSON.stringify(obj).length / 4));
});
});

View File

@@ -8,12 +8,10 @@ const {
CLI_COMPAT_TOGGLE_IDS,
IMPLEMENTED_CLI_FINGERPRINT_PROVIDER_IDS,
normalizeCliCompatProviderId,
} =
await import("../../src/shared/constants/cliCompatProviders.ts");
} = await import("../../src/shared/constants/cliCompatProviders.ts");
const { CLI_TOOL_IDS } = await import("../../src/shared/services/cliRuntime.ts");
const { applyFingerprint, isCliCompatEnabled, setCliCompatProviders } = await import(
"../../open-sse/config/cliFingerprints.ts"
);
const { applyFingerprint, isCliCompatEnabled, setCliCompatProviders } =
await import("../../open-sse/config/cliFingerprints.ts");
test("Amp CLI is registered as a guide-based CLI tool with shorthand mapping guidance", () => {
const amp = CLI_TOOLS.amp;

View File

@@ -71,10 +71,10 @@ async function applyStreamReadiness(response: Response): Promise<Response> {
}
function errorResponse(status: number, message: string): Response {
return new Response(
JSON.stringify({ error: { message, type: "upstream_error" } }),
{ status, headers: { "Content-Type": "application/json" } }
);
return new Response(JSON.stringify({ error: { message, type: "upstream_error" } }), {
status,
headers: { "Content-Type": "application/json" },
});
}
test("combo falls back when first model returns HTTP 200 zombie SSE stream", async () => {
@@ -113,10 +113,7 @@ test("combo falls back when first model returns HTTP 200 zombie SSE stream", asy
assert.deepEqual(calls, ["glm/zombie-model", "openai/gpt-5.4-mini"]);
assert.ok(
log.entries.some(
(e) =>
e.level === "warn" &&
e.tag === "COMBO" &&
String(e.msg).includes("glm/zombie-model")
(e) => e.level === "warn" && e.tag === "COMBO" && String(e.msg).includes("glm/zombie-model")
),
"combo should log warning for the failed model"
);
@@ -190,11 +187,7 @@ test("combo retries 504 on same model before falling through (transient retry)",
assert.equal(result.ok, true, "combo should succeed via fallback after retries");
const zombieCalls = calls.filter((c) => c === "glm/zombie");
assert.equal(
zombieCalls.length,
2,
"combo should retry zombie once before falling through"
);
assert.equal(zombieCalls.length, 2, "combo should retry zombie once before falling through");
assert.ok(calls.includes("openai/gpt-5.4-mini"), "combo should reach fallback model");
});

View File

@@ -0,0 +1,113 @@
import { describe, it, beforeEach, afterEach, after } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-compression-db-"));
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../../src/lib/db/core.ts");
const { getCompressionSettings, updateCompressionSettings } =
await import("../../../src/lib/db/compression.ts");
beforeEach(() => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
});
afterEach(() => {
core.resetDbInstance();
});
after(() => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
if (ORIGINAL_DATA_DIR === undefined) {
delete process.env.DATA_DIR;
} else {
process.env.DATA_DIR = ORIGINAL_DATA_DIR;
}
});
describe("getCompressionSettings", () => {
it("returns default settings structure", async () => {
const settings = await getCompressionSettings();
assert.equal(typeof settings.enabled, "boolean");
assert.equal(typeof settings.defaultMode, "string");
assert.equal(typeof settings.autoTriggerTokens, "number");
assert.equal(typeof settings.cacheMinutes, "number");
assert.equal(typeof settings.preserveSystemPrompt, "boolean");
assert.equal(typeof settings.comboOverrides, "object");
});
it("has correct default values", async () => {
const settings = await getCompressionSettings();
assert.equal(settings.enabled, false);
assert.equal(settings.defaultMode, "off");
assert.equal(settings.autoTriggerTokens, 0);
assert.equal(settings.cacheMinutes, 5);
assert.equal(settings.preserveSystemPrompt, true);
assert.deepEqual(settings.comboOverrides, {});
});
});
describe("updateCompressionSettings", () => {
it("updates enabled flag", async () => {
await updateCompressionSettings({ enabled: true } as any);
const settings = await getCompressionSettings();
assert.equal(settings.enabled, true);
// Reset
await updateCompressionSettings({ enabled: false } as any);
});
it("updates defaultMode", async () => {
await updateCompressionSettings({ defaultMode: "lite" } as any);
const settings = await getCompressionSettings();
assert.equal(settings.defaultMode, "lite");
// Reset
await updateCompressionSettings({ defaultMode: "off" } as any);
});
it("updates autoTriggerTokens", async () => {
await updateCompressionSettings({ autoTriggerTokens: 5000 } as any);
const settings = await getCompressionSettings();
assert.equal(settings.autoTriggerTokens, 5000);
// Reset
await updateCompressionSettings({ autoTriggerTokens: 0 } as any);
});
it("updates multiple settings at once", async () => {
await updateCompressionSettings({
enabled: true,
defaultMode: "lite",
autoTriggerTokens: 1000,
cacheMinutes: 10,
} as any);
const settings = await getCompressionSettings();
assert.equal(settings.enabled, true);
assert.equal(settings.defaultMode, "lite");
assert.equal(settings.autoTriggerTokens, 1000);
assert.equal(settings.cacheMinutes, 10);
// Reset all
await updateCompressionSettings({
enabled: false,
defaultMode: "off",
autoTriggerTokens: 0,
cacheMinutes: 5,
} as any);
});
it("preserves unmodified settings", async () => {
const before = await getCompressionSettings();
await updateCompressionSettings({ enabled: true } as any);
const after = await getCompressionSettings();
assert.equal(after.enabled, true);
assert.equal(after.defaultMode, before.defaultMode);
assert.equal(after.cacheMinutes, before.cacheMinutes);
// Reset
await updateCompressionSettings({ enabled: false } as any);
});
});

View File

@@ -0,0 +1,209 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
applyLiteCompression,
collapseWhitespace,
dedupSystemPrompt,
compressToolResults,
removeRedundantContent,
replaceImageUrls,
} from "../../../open-sse/services/compression/lite.ts";
describe("collapseWhitespace", () => {
it("collapses 3+ newlines to 2", () => {
const body = { messages: [{ role: "user", content: "hello\n\n\n\nworld" }] };
const result = collapseWhitespace(body);
assert.equal(result.applied, true);
assert.equal(result.body.messages![0].content as string, "hello\n\nworld");
});
it("does not modify already-normal whitespace", () => {
const body = { messages: [{ role: "user", content: "hello\n\nworld" }] };
const result = collapseWhitespace(body);
assert.equal(result.applied, false);
});
it("trims trailing spaces", () => {
const body = { messages: [{ role: "user", content: "hello " }] };
const result = collapseWhitespace(body);
assert.equal(result.applied, true);
assert.equal(result.body.messages![0].content as string, "hello");
});
it("returns unchanged when no messages", () => {
const body = {};
const result = collapseWhitespace(body);
assert.equal(result.applied, false);
});
it("skips non-string content", () => {
const body = { messages: [{ role: "user", content: [{ type: "text", text: "hello" }] }] };
const result = collapseWhitespace(body);
assert.equal(result.applied, false);
});
});
describe("dedupSystemPrompt", () => {
it("removes duplicate system prompts", () => {
const body = {
messages: [
{ role: "system", content: "You are helpful." },
{ role: "system", content: "You are helpful." },
{ role: "user", content: "hi" },
],
};
const result = dedupSystemPrompt(body);
assert.equal(result.applied, true);
assert.equal(result.body.messages!.length, 2);
});
it("keeps different system prompts", () => {
const body = {
messages: [
{ role: "system", content: "You are helpful." },
{ role: "system", content: "Be concise." },
],
};
const result = dedupSystemPrompt(body);
assert.equal(result.applied, false);
assert.equal(result.body.messages!.length, 2);
});
it("returns unchanged when no messages", () => {
const result = dedupSystemPrompt({});
assert.equal(result.applied, false);
});
});
describe("compressToolResults", () => {
it("truncates long tool results", () => {
const longContent = "x".repeat(3000);
const body = { messages: [{ role: "tool", content: longContent }] };
const result = compressToolResults(body);
assert.equal(result.applied, true);
const content = result.body.messages![0].content as string;
assert.ok(content.length < 3000);
assert.ok(content.includes("[truncated]"));
});
it("keeps short tool results unchanged", () => {
const body = { messages: [{ role: "tool", content: "short result" }] };
const result = compressToolResults(body);
assert.equal(result.applied, false);
});
it("skips non-tool messages", () => {
const body = { messages: [{ role: "user", content: "x".repeat(3000) }] };
const result = compressToolResults(body);
assert.equal(result.applied, false);
});
});
describe("removeRedundantContent", () => {
it("removes consecutive duplicate messages", () => {
const body = {
messages: [
{ role: "user", content: "hello" },
{ role: "user", content: "hello" },
],
};
const result = removeRedundantContent(body);
assert.equal(result.applied, true);
assert.equal(result.body.messages!.length, 1);
});
it("keeps non-duplicate messages", () => {
const body = {
messages: [
{ role: "user", content: "hello" },
{ role: "user", content: "world" },
],
};
const result = removeRedundantContent(body);
assert.equal(result.applied, false);
assert.equal(result.body.messages!.length, 2);
});
it("only removes same-role consecutive duplicates", () => {
const body = {
messages: [
{ role: "system", content: "hello" },
{ role: "user", content: "hello" },
],
};
const result = removeRedundantContent(body);
assert.equal(result.applied, false);
});
});
describe("replaceImageUrls", () => {
it("replaces base64 images for non-vision models", () => {
const body = {
messages: [
{
role: "user",
content: [{ type: "image_url", image_url: { url: "data:image/png;base64,iVBOR" } }],
},
],
};
const result = replaceImageUrls(body, "gpt-3.5-turbo");
assert.equal(result.applied, true);
const content = result.body.messages![0].content as Array<Record<string, unknown>>;
assert.equal(content[0].type, "text");
assert.ok((content[0].text as string).includes("[image:"));
});
it("keeps images for vision models", () => {
const body = {
messages: [
{
role: "user",
content: [{ type: "image_url", image_url: { url: "data:image/png;base64,iVBOR" } }],
},
],
};
const result = replaceImageUrls(body, "gpt-4o");
assert.equal(result.applied, false);
});
it("skips non-image content", () => {
const body = {
messages: [{ role: "user", content: "just text" }],
};
const result = replaceImageUrls(body, "gpt-3.5-turbo");
assert.equal(result.applied, false);
});
});
describe("applyLiteCompression", () => {
it("applies all techniques that match", () => {
const body = {
messages: [
{ role: "system", content: "You are helpful." },
{ role: "system", content: "You are helpful." },
{ role: "user", content: "hello\n\n\n\nworld" },
{ role: "user", content: "hello\n\n\n\nworld" },
],
};
const result = applyLiteCompression(body);
assert.equal(result.compressed, true);
assert.ok(result.stats);
assert.ok(result.stats.techniquesUsed.length >= 2);
assert.ok(result.stats.savingsPercent > 0);
});
it("returns no compression for clean input", () => {
const body = {
messages: [{ role: "user", content: "clean message" }],
};
const result = applyLiteCompression(body);
assert.equal(result.compressed, false);
assert.equal(result.stats, null);
});
it("handles empty messages array", () => {
const body = { messages: [] };
const result = applyLiteCompression(body);
assert.equal(result.compressed, false);
});
});

View File

@@ -0,0 +1,92 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
estimateCompressionTokens,
createCompressionStats,
trackCompressionStats,
} from "../../../open-sse/services/compression/stats.ts";
describe("estimateCompressionTokens", () => {
it("returns 0 for null", () => {
assert.equal(estimateCompressionTokens(null), 0);
});
it("returns 0 for undefined", () => {
assert.equal(estimateCompressionTokens(undefined), 0);
});
it("returns 0 for empty string", () => {
assert.equal(estimateCompressionTokens(""), 0);
});
it("estimates tokens from text (chars/4)", () => {
assert.equal(estimateCompressionTokens("hello world"), 3);
});
it("estimates tokens from object", () => {
const tokens = estimateCompressionTokens({ messages: [{ role: "user", content: "test" }] });
assert.ok(tokens > 0);
});
it("handles long strings", () => {
const tokens = estimateCompressionTokens("x".repeat(400));
assert.equal(tokens, 100);
});
});
describe("createCompressionStats", () => {
it("calculates savings correctly", () => {
const original = { messages: [{ role: "user", content: "x".repeat(100) }] };
const compressed = { messages: [{ role: "user", content: "x".repeat(80) }] };
const origTokens = Math.ceil(JSON.stringify(original).length / 4);
const compTokens = Math.ceil(JSON.stringify(compressed).length / 4);
const expectedSavings = Math.round(((origTokens - compTokens) / origTokens) * 10000) / 100;
const stats = createCompressionStats(original, compressed, "lite", ["whitespace"]);
assert.equal(stats.originalTokens, origTokens);
assert.equal(stats.compressedTokens, compTokens);
assert.equal(stats.savingsPercent, expectedSavings);
assert.deepEqual(stats.techniquesUsed, ["whitespace"]);
assert.equal(stats.mode, "lite");
assert.ok(stats.timestamp > 0);
});
it("handles zero original tokens", () => {
const original = {};
const compressed = {};
const stats = createCompressionStats(original, compressed, "off", []);
assert.equal(stats.savingsPercent, 0);
});
it("rounds savings to 2 decimal places", () => {
const original = { messages: [{ role: "user", content: "x".repeat(97) }] };
const compressed = { messages: [{ role: "user", content: "x".repeat(80) }] };
const stats = createCompressionStats(original, compressed, "lite", ["test"]);
assert.ok(Number.isFinite(stats.savingsPercent));
});
});
describe("trackCompressionStats", () => {
it("does not throw for zero tokens", () => {
const stats = {
originalTokens: 0,
compressedTokens: 0,
savingsPercent: 0,
techniquesUsed: [],
mode: "off" as const,
timestamp: Date.now(),
};
assert.doesNotThrow(() => trackCompressionStats(stats));
});
it("logs compression stats", () => {
const stats = {
originalTokens: 100,
compressedTokens: 80,
savingsPercent: 20,
techniquesUsed: ["whitespace"],
mode: "lite" as const,
timestamp: Date.now(),
};
assert.doesNotThrow(() => trackCompressionStats(stats));
});
});

View File

@@ -0,0 +1,125 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
selectCompressionStrategy,
getEffectiveMode,
applyCompression,
checkComboOverride,
shouldAutoTrigger,
} from "../../../open-sse/services/compression/strategySelector.ts";
import type { CompressionConfig } from "../../../open-sse/services/compression/types.ts";
const baseConfig: CompressionConfig = {
enabled: true,
defaultMode: "lite",
autoTriggerTokens: 0,
cacheMinutes: 5,
preserveSystemPrompt: true,
comboOverrides: {},
};
describe("checkComboOverride", () => {
it("returns null when comboId is null", () => {
assert.equal(checkComboOverride(baseConfig, null), null);
});
it("returns null when comboOverrides is empty", () => {
assert.equal(checkComboOverride(baseConfig, "my-combo"), null);
});
it("returns mode when combo override exists", () => {
const config = { ...baseConfig, comboOverrides: { "my-combo": "off" as const } };
assert.equal(checkComboOverride(config, "my-combo"), "off");
});
it("returns null for non-existent combo", () => {
const config = { ...baseConfig, comboOverrides: { "other-combo": "lite" as const } };
assert.equal(checkComboOverride(config, "my-combo"), null);
});
});
describe("shouldAutoTrigger", () => {
it("returns false when autoTriggerTokens is 0", () => {
assert.equal(shouldAutoTrigger(baseConfig, 5000), false);
});
it("returns false when tokens below threshold", () => {
const config = { ...baseConfig, autoTriggerTokens: 1000 };
assert.equal(shouldAutoTrigger(config, 500), false);
});
it("returns true when tokens at threshold", () => {
const config = { ...baseConfig, autoTriggerTokens: 1000 };
assert.equal(shouldAutoTrigger(config, 1000), true);
});
it("returns true when tokens above threshold", () => {
const config = { ...baseConfig, autoTriggerTokens: 1000 };
assert.equal(shouldAutoTrigger(config, 1500), true);
});
});
describe("getEffectiveMode", () => {
it("returns off when not enabled", () => {
const config = { ...baseConfig, enabled: false };
assert.equal(getEffectiveMode(config, null, 100), "off");
});
it("returns default mode when no overrides", () => {
assert.equal(getEffectiveMode(baseConfig, null, 100), "lite");
});
it("returns combo override mode when present", () => {
const config = {
...baseConfig,
defaultMode: "off" as const,
comboOverrides: { "my-combo": "lite" as const },
};
assert.equal(getEffectiveMode(config, "my-combo", 100), "lite");
});
it("returns lite when auto-trigger threshold reached", () => {
const config = { ...baseConfig, defaultMode: "off" as const, autoTriggerTokens: 1000 };
assert.equal(getEffectiveMode(config, null, 1500), "lite");
});
it("combo override takes precedence over auto-trigger", () => {
const config = {
...baseConfig,
defaultMode: "off" as const,
autoTriggerTokens: 100,
comboOverrides: { "my-combo": "off" as const },
};
assert.equal(getEffectiveMode(config, "my-combo", 500), "off");
});
});
describe("selectCompressionStrategy", () => {
it("returns effective mode", () => {
assert.equal(selectCompressionStrategy(baseConfig, null, 100), "lite");
});
});
describe("applyCompression", () => {
it("returns unchanged body for off mode", () => {
const body = { messages: [{ role: "user", content: "test" }] };
const result = applyCompression(body, "off");
assert.equal(result.compressed, false);
assert.equal(result.stats, null);
assert.deepEqual(result.body, body);
});
it("applies lite compression for lite mode", () => {
const body = { messages: [{ role: "user", content: "test\n\n\n\nmessage" }] };
const result = applyCompression(body, "lite");
assert.equal(result.compressed, true);
assert.ok(result.stats);
assert.equal(result.stats.mode, "lite");
});
it("returns unchanged body for standard mode (Phase 2)", () => {
const body = { messages: [{ role: "user", content: "test" }] };
const result = applyCompression(body, "standard");
assert.equal(result.compressed, false);
});
});

View File

@@ -48,7 +48,10 @@ test("provider header profiles expose dedicated refresh, qwen, qoder, kiro and c
const qwenHeaders = getQwenOauthHeaders();
assert.equal(qwenHeaders["User-Agent"], getQwenCliUserAgent());
assert.equal(qwenHeaders["User-Agent"], `QwenCode/${QWEN_CLI_VERSION} (${process.platform}; ${process.arch})`);
assert.equal(
qwenHeaders["User-Agent"],
`QwenCode/${QWEN_CLI_VERSION} (${process.platform}; ${process.arch})`
);
assert.notEqual(qwenHeaders["User-Agent"], "QwenCode/0.15.3 (linux; x64)");
assert.equal(qwenHeaders["X-Dashscope-UserAgent"], getQwenCliUserAgent());
assert.equal(qwenHeaders["X-Stainless-Package-Version"], "5.11.0");

View File

@@ -100,7 +100,10 @@ test("ensureStreamReadiness preserves buffered chunks when stream starts", async
test("ensureStreamReadiness returns 504 when no useful content arrives before timeout", async () => {
const response = new Response(
streamFromChunks([": keepalive\n\n", `data: ${JSON.stringify({ type: "response.created" })}\n\n`], 20),
streamFromChunks(
[": keepalive\n\n", `data: ${JSON.stringify({ type: "response.created" })}\n\n`],
20
),
{ status: 200, headers: { "Content-Type": "text/event-stream" } }
);

View File

@@ -421,7 +421,9 @@ test("usage service manual Antigravity refresh bypasses usage TTL caches", async
globalThis.fetch = async (url) => {
const urlStr = String(url);
if (urlStr.includes("loadCodeAssist")) {
return new Response(JSON.stringify({ cloudaicompanionProject: "ag-project" }), { status: 200 });
return new Response(JSON.stringify({ cloudaicompanionProject: "ag-project" }), {
status: 200,
});
}
if (urlStr.includes("streamGenerateContent")) {