Files
2026-07-13 13:39:12 +08:00

244 lines
8.4 KiB
TypeScript

import { applyRulesToText } from "../services/compression/caveman.ts";
import { getRulesForContext } from "../services/compression/cavemanRules.ts";
import {
extractPreservedBlocks,
restorePreservedBlocks,
} from "../services/compression/preservation.ts";
export interface DescriptionCompressionResult {
compressed: string;
before: number;
after: number;
changed: boolean;
}
export interface DescriptionCompressionOptions {
enabled?: boolean;
}
export interface McpDescriptionCompressionStats {
descriptionsCompressed: number;
charsBefore: number;
charsAfter: number;
charsSaved: number;
estimatedTokensSaved: number;
}
const descriptionCompressionStats: McpDescriptionCompressionStats = {
descriptionsCompressed: 0,
charsBefore: 0,
charsAfter: 0,
charsSaved: 0,
estimatedTokensSaved: 0,
};
const persistedDescriptionCompressionStats: McpDescriptionCompressionStats = {
descriptionsCompressed: 0,
charsBefore: 0,
charsAfter: 0,
charsSaved: 0,
estimatedTokensSaved: 0,
};
const MCP_LIST_CONTAINER_KEYS = new Set(["tools", "prompts", "resources", "resourceTemplates"]);
const MCP_METADATA_DESCRIPTION_FIELDS = ["description"];
function isDisabledEnvValue(value: string | undefined): boolean {
return !!value && ["0", "false", "off", "no"].includes(value.trim().toLowerCase());
}
export function isMcpDescriptionCompressionEnabled(
options: DescriptionCompressionOptions = {}
): boolean {
if (isDisabledEnvValue(process.env.OMNIROUTE_MCP_COMPRESS_DESCRIPTIONS)) return false;
if (isDisabledEnvValue(process.env.OMNIROUTE_MCP_DESCRIPTION_COMPRESSION)) return false;
return options.enabled !== false;
}
export function compressMcpDescription(description: string): DescriptionCompressionResult {
if (!description) {
return { compressed: description, before: 0, after: 0, changed: false };
}
const { text, blocks } = extractPreservedBlocks(description);
const rules = getRulesForContext("all", "full");
const applied = applyRulesToText(text, rules).text;
const normalized = applied
.replace(/[ \t]{2,}/g, " ")
.replace(/[ \t]([,.;:!?])/g, "$1")
.replace(/\n{3,}/g, "\n\n")
.replace(/(^|[.!?][ \t]|\n[ \t]*)([a-z])/g, (_match, prefix: string, char: string) => {
return `${prefix}${char.toUpperCase()}`;
})
.trim();
const compressed = restorePreservedBlocks(normalized, blocks);
return {
compressed,
before: description.length,
after: compressed.length,
changed: compressed !== description,
};
}
export function maybeCompressMcpDescription(
description: string,
options: DescriptionCompressionOptions = {}
): string {
if (!isMcpDescriptionCompressionEnabled(options)) return description;
const result = compressMcpDescription(description);
if (result.changed && result.after < result.before) {
descriptionCompressionStats.descriptionsCompressed += 1;
descriptionCompressionStats.charsBefore += result.before;
descriptionCompressionStats.charsAfter += result.after;
descriptionCompressionStats.charsSaved += result.before - result.after;
descriptionCompressionStats.estimatedTokensSaved += Math.ceil(
(result.before - result.after) / 4
);
return result.compressed;
}
return description;
}
export function compressDescriptionsInPlace(
value: unknown,
fieldNames: string[] = ["description"],
options: DescriptionCompressionOptions = {}
): void {
if (!value || typeof value !== "object") return;
const fields = new Set(fieldNames);
if (Array.isArray(value)) {
for (const item of value) compressDescriptionsInPlace(item, fieldNames, options);
return;
}
for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {
if (fields.has(key) && typeof nested === "string") {
(value as Record<string, unknown>)[key] = maybeCompressMcpDescription(nested, options);
} else if (nested && typeof nested === "object") {
compressDescriptionsInPlace(nested, fieldNames, options);
}
}
}
function clonePlainMetadata<T>(value: T): T {
if (!value || typeof value !== "object") return value;
return JSON.parse(JSON.stringify(value)) as T;
}
function compressMcpListContainersInPlace(
value: unknown,
options: DescriptionCompressionOptions = {}
): void {
if (!value || typeof value !== "object") return;
if (Array.isArray(value)) {
for (const item of value) compressMcpListContainersInPlace(item, options);
return;
}
for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {
if (MCP_LIST_CONTAINER_KEYS.has(key) && Array.isArray(nested)) {
compressDescriptionsInPlace(nested, MCP_METADATA_DESCRIPTION_FIELDS, options);
} else if (nested && typeof nested === "object") {
compressMcpListContainersInPlace(nested, options);
}
}
}
export function compressMcpListMetadata<T>(
value: T,
options: DescriptionCompressionOptions = {}
): T {
if (!isMcpDescriptionCompressionEnabled(options)) return value;
const clone = clonePlainMetadata(value);
compressMcpListContainersInPlace(clone, options);
return clone;
}
export function compressMcpRegistryMetadata<T extends Record<string, unknown>>(
metadata: T,
options: DescriptionCompressionOptions = {}
): T {
if (!isMcpDescriptionCompressionEnabled(options)) return metadata;
const clone: Record<string, unknown> = { ...metadata };
if (typeof clone.description === "string") {
clone.description = maybeCompressMcpDescription(clone.description, options);
}
return clone as T;
}
export function getMcpDescriptionCompressionStats(): McpDescriptionCompressionStats {
return { ...descriptionCompressionStats };
}
function getUnpersistedMcpDescriptionCompressionStats(): McpDescriptionCompressionStats {
return {
descriptionsCompressed:
descriptionCompressionStats.descriptionsCompressed -
persistedDescriptionCompressionStats.descriptionsCompressed,
charsBefore:
descriptionCompressionStats.charsBefore - persistedDescriptionCompressionStats.charsBefore,
charsAfter:
descriptionCompressionStats.charsAfter - persistedDescriptionCompressionStats.charsAfter,
charsSaved:
descriptionCompressionStats.charsSaved - persistedDescriptionCompressionStats.charsSaved,
estimatedTokensSaved:
descriptionCompressionStats.estimatedTokensSaved -
persistedDescriptionCompressionStats.estimatedTokensSaved,
};
}
export async function snapshotMcpDescriptionCompressionStats(): Promise<McpDescriptionCompressionStats> {
const delta = getUnpersistedMcpDescriptionCompressionStats();
if (
delta.descriptionsCompressed <= 0 ||
delta.charsSaved <= 0 ||
delta.estimatedTokensSaved <= 0
) {
return {
descriptionsCompressed: 0,
charsBefore: 0,
charsAfter: 0,
charsSaved: 0,
estimatedTokensSaved: 0,
};
}
const originalTokens = Math.max(delta.estimatedTokensSaved, Math.ceil(delta.charsBefore / 4));
const compressedTokens = Math.max(0, originalTokens - delta.estimatedTokensSaved);
const { insertCompressionAnalyticsRow } =
await import("../../src/lib/db/compressionAnalytics.ts");
insertCompressionAnalyticsRow({
timestamp: new Date().toISOString(),
mode: "mcp-description",
engine: "mcp-description",
original_tokens: originalTokens,
compressed_tokens: compressedTokens,
tokens_saved: delta.estimatedTokensSaved,
mcp_description_tokens_saved: delta.estimatedTokensSaved,
});
persistedDescriptionCompressionStats.descriptionsCompressed =
descriptionCompressionStats.descriptionsCompressed;
persistedDescriptionCompressionStats.charsBefore = descriptionCompressionStats.charsBefore;
persistedDescriptionCompressionStats.charsAfter = descriptionCompressionStats.charsAfter;
persistedDescriptionCompressionStats.charsSaved = descriptionCompressionStats.charsSaved;
persistedDescriptionCompressionStats.estimatedTokensSaved =
descriptionCompressionStats.estimatedTokensSaved;
return delta;
}
export function resetMcpDescriptionCompressionStats(): void {
descriptionCompressionStats.descriptionsCompressed = 0;
descriptionCompressionStats.charsBefore = 0;
descriptionCompressionStats.charsAfter = 0;
descriptionCompressionStats.charsSaved = 0;
descriptionCompressionStats.estimatedTokensSaved = 0;
persistedDescriptionCompressionStats.descriptionsCompressed = 0;
persistedDescriptionCompressionStats.charsBefore = 0;
persistedDescriptionCompressionStats.charsAfter = 0;
persistedDescriptionCompressionStats.charsSaved = 0;
persistedDescriptionCompressionStats.estimatedTokensSaved = 0;
}