Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ Engines run in pipeline order; each is independently toggleable and configurable
<tr><td align="center" nowrap>9</td><td align="left" nowrap><b>Aggressive</b></td><td align="left">Summarization + progressive aging of old turns</td></tr>
<tr><td align="center" nowrap>10</td><td align="left" nowrap><b>LLMLingua-2</b></td><td align="left">ML semantic pruning via MobileBERT ONNX — code-safe, async</td></tr>
<tr><td align="center" nowrap>11</td><td align="left" nowrap><b>Ultra</b></td><td align="left">Heuristic token pruning with an optional small-model (SLM) tier</td></tr>
<tr><td align="center" nowrap>12</td><td align="left" nowrap><b>OmniGlyph</b></td><td align="left">Experimental context-as-image encoding routed to Claude Fable 5 (most aggressive; opt-in)</td></tr>
<tr><td align="center" nowrap>12</td><td align="left" nowrap><b>OmniGlyph</b></td><td align="left">Experimental context-as-image encoding for measured Claude Fable 5 on the direct Anthropic wire; GPT 5.6 transformers remain fail-closed pending provider receipts. Four compression profiles (aggressive default, balanced, coding-safe, passthrough) (most aggressive; opt-in)</td></tr>
</table>

Code blocks, URLs and structured data are **always preserved** byte-perfect. **One-click presets** combine the engines:
Expand Down
28 changes: 28 additions & 0 deletions docs/compression/COMPRESSION_ENGINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,36 @@ OmniRoute compression is built around engine contracts. A mode can run one engin
| `aggressive` | Caveman + history/tool summarizers | Long chat sessions |
| `ultra` | Caveman + pruning helpers | Context-limit recovery |
| `rtk` | RTK | Terminal, shell, build, test, and git output |
| `omniglyph` | OmniGlyph | Context-as-image on the native provider wire |
| `stacked` | Pipeline, default `rtk -> caveman` | Mixed tool logs and prose, max savings |

### OmniGlyph compression profiles

The `omniglyph` engine (package `omniglyph`, 1.4.0+) accepts a named semantic profile, set
globally through `omniglyph.profile` in the compression settings or per step through the
stacked pipeline's step config:

| Profile | Boundary |
| -------------- | --------------------------------------------------------------------------- |
| `aggressive` | Default. The policy the published receipts measured — images system, tool docs and dense history |
| `balanced` | Keeps live state native, protects the last 8 turns, collapses older closed history |
| `coding-safe` | Keeps authority, tool schemas and live tool output native, protects the last 12 turns |
| `passthrough` | Routes without transforming; the engine is skipped |

The profile is a **ceiling, not a floor**: `mergeCompressionProfileOptions` in the package
refuses to let a caller override reopen a lossy lane the profile closed, so a per-step
`preserveSystemPrompt: false` cannot re-enable system compression under `coding-safe`.

Measured on this codebase: `coding-safe` and `balanced` raise `minCompressChars` to its
maximum and keep system, tool schemas and tool results native, so a session that has not
accumulated history yet stops at `below_min_chars` and the engine transforms nothing. That
is why the default is `aggressive` rather than the safest profile.

The package resolves its own model scope and profile from its environment configuration.
OmniRoute never delegates the decision: the adapter pins the model gate to the package's
most restrictive scope, so host environment settings can only narrow the allowlist, never
widen it past OmniRoute's measured receipts.

## Engine Registry

The registry lives in `open-sse/services/compression/engines/registry.ts`. Engines expose a shared
Expand Down
18 changes: 8 additions & 10 deletions open-sse/handlers/chatCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import { checkResourcePressureGuard } from "../utils/resourcePressure.ts";
import { normalizeHeaders } from "../utils/headers.ts";
import { resolveChatCoreRequestFormat } from "./chatCore/requestFormat.ts";
import { resolveChatCoreTargetFormat } from "./chatCore/targetFormat.ts";
import { resolveOmniGlyphTransport } from "../services/compression/imageTransportPolicy.ts";
import { stripStore, usesClaudeBridge } from "./chatCore/agentRouterProtocol.ts";
import { defaultClaudeToolType } from "./chatCore/claudeToolDefaults.ts";
import { injectSystemPrompt, injectCustomSystemPrompt } from "../services/systemPrompt.ts";
Expand Down Expand Up @@ -1611,16 +1612,13 @@ export async function handleChatCore({
// models, which is intentionally NOT `false` so the gate still preserves images.
supportsVision: getResolvedModelCapabilities({ provider, model: effectiveModel })
.supportsVision,
// Rotas diretas oficiais ('anthropic' API key e 'claude' OAuth) vs agregadores:
// o engine omniglyph exige 'direct' — agregadores redimensionam imagens
// (medido 2026-07-06). OAuth 'claude' é rota direta oficial (#7863).
providerTransport:
provider === "anthropic" ||
provider === "claude" ||
provider === "openai" ||
provider === "xai"
? ("direct" as const)
: ("aggregator" as const),
// OmniGlyph uses a measured provider/image-fidelity allowlist. Direct HTTP
// alone is not proof that a route preserves PNG bytes and dimensions.
...resolveOmniGlyphTransport(provider),
// Sem o provider, a contabilidade do OmniGlyph cai para `unknown` e
// recusa deduzir a semântica de cache (Anthropic usa buckets disjuntos,
// OpenAI reporta cached como subconjunto do input).
provider,
sourceFormat,
targetFormat,
compressionStage: "pre-translation" as const,
Expand Down
197 changes: 156 additions & 41 deletions open-sse/services/compression/engines/omniglyphAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* - modelo fora da allowlist medida → skip:model_not_approved
* - providerTransport !== 'direct' → skip:transport_not_direct
* (agregadores redimensionam imagens e destroem a legibilidade — medido)
* - imageTransportFidelity !== 'byte-preserving' → skip:transport_fidelity_unknown/resizes
* - wire não é Claude/OpenAI suportado → skip:target_format_not_supported
* - gate de rentabilidade interno do omniglyph decide o resto (patches 28px
* exatos; texto esparso/pequeno passa direto) → skip:not_profitable
Expand All @@ -20,14 +21,65 @@ import type { CompressionEngine, CompressionEngineApplyOptions } from "./types.t
import type { CompressionResult } from "../types.ts";
import { createCompressionStats } from "../stats.ts";
import {
isOmniGlyphSupportedGptModel,
isOmniGlyphSupportedModel,
buildOmniGlyphAccounting,
type OmniGlyphAccounting,
} from "../omniglyphTelemetry.ts";
import {
isOmniGlyphSupportedModelForScope,
mergeCompressionProfileOptions,
resolveCompressionProfile,
transformAnthropicMessages,
transformOpenAIChatCompletions,
transformOpenAIResponses,
type CompressionProfile,
type OmniGlyphSafetyScope,
} from "omniglyph";
import { isModelImageable } from "omniglyph/applicability";

/**
* Teto de modelos do OmniRoute — sempre o escopo mais restrito do pacote.
*
* `isOmniGlyphSupportedModel()` resolve o escopo lendo `OMNIGLYPH_PROFILE` do
* processo, e a lista base sai de `OMNIGLYPH_MODELS`. Duas variáveis do HOST
* decidiriam, em silêncio, o gate de todo request do OmniRoute: `passthrough`
* desligaria a engine inteira e `OMNIGLYPH_MODELS` ADMITIRIA modelos sem
* recibo medido — enquanto a UI continua prometendo "Claude Fable 5 na rota
* direta medida". Fixar o escopo mais restrito faz o gate só poder ESTREITAR
* pela env, nunca alargar, e mantém a decisão na configuração do OmniRoute.
*/
const MEASURED_MODEL_SCOPE: OmniGlyphSafetyScope = "coding-safe";

/**
* Perfil padrão do OmniRoute.
*
* `aggressive` é a política que os recibos publicados mediram. `coding-safe` e
* `balanced` fixam `minCompressChars` no máximo e só colapsam histórico antigo:
* medido nesta base, uma sessão sem histórico acumulado fica em
* `below_min_chars` e a engine não faz nada — o operador veria "ligado, 0% de
* ganho". Ficam disponíveis como escolha explícita, não como default.
*/
const DEFAULT_PROFILE: OmniGlyphSafetyScope = "aggressive";

/** Perfil do passo (mais específico) > perfil global > default do OmniRoute. */
function resolveProfileName(options?: CompressionEngineApplyOptions): string {
const step = options?.stepConfig?.profile;
if (typeof step === "string" && step.trim()) return step;
const global = (options?.config as { omniglyph?: { profile?: unknown } } | undefined)?.omniglyph
?.profile;
if (typeof global === "string" && global.trim()) return global;
return DEFAULT_PROFILE;
}

/**
* O modelo precisa passar no teto medido E no escopo em vigor. Os dois wires
* (Anthropic e GPT) compartilham a mesma allowlist no pacote desde 1.4.0, então
* uma única checagem cobre os dois.
*/
function isModelWithinScope(model: string, scope: OmniGlyphSafetyScope): boolean {
if (!isOmniGlyphSupportedModelForScope(model, MEASURED_MODEL_SCOPE)) return false;
return isOmniGlyphSupportedModelForScope(model, scope);
}

function skip(body: Record<string, unknown>, reason: string): CompressionResult {
try {
return {
Expand Down Expand Up @@ -80,9 +132,36 @@ async function applyOmniglyph(
const model = options?.model ?? (body as { model?: string }).model ?? "";
if (options?.supportsVision !== true) return skip(body, "no_vision");
if (options?.providerTransport !== "direct") return skip(body, "transport_not_direct");
// Keep the old direct-call contract usable for standalone callers, but let
// production callers override it explicitly. The chat pipeline supplies
// `unknown` for every provider without a byte-preservation receipt.
if (
options?.imageTransportFidelity !== undefined &&
options.imageTransportFidelity !== "byte-preserving"
) {
return skip(
body,
options.imageTransportFidelity === "resizes"
? "transport_resizes_images"
: "transport_fidelity_unknown"
);
}

const stage = options?.compressionStage ?? "pre-translation";
const wireFormat = resolveWireFormat(body, options);
// A source/target format mismatch means the body is still on the wrong wire,
// even when the source itself is native Claude. Defer the engine until the
// translated provider body so Claude→OpenAI cannot be imaged once before
// translation and then considered again on the target wire.
const sourceWireFormat = options?.sourceFormat ?? wireFormat;
if (
stage === "pre-translation" &&
options?.targetFormat &&
sourceWireFormat &&
options.targetFormat !== sourceWireFormat
) {
return skip(body, "requires_post_translation");
}
// The pre-translation lane is retained for the existing native Claude
// passthrough. OpenAI requests must wait until translation has produced the
// exact provider wire, otherwise Responses input[] would be flattened by the
Expand All @@ -104,62 +183,98 @@ async function applyOmniglyph(
) {
return skip(body, "source_format_not_openai_responses");
}
const supportedModel =
wireFormat === "claude"
? isOmniGlyphSupportedModel(model)
: isOmniGlyphSupportedGptModel(model);
if (!supportedModel) return skip(body, "model_not_approved");
let profile: CompressionProfile;
try {
profile = resolveCompressionProfile(resolveProfileName(options));
} catch {
// `resolveCompressionProfile` lança em nome desconhecido. Um perfil que o
// pacote não entende não pode virar "roda com a política padrão".
return skip(body, "invalid_profile");
}
if (profile.name === "passthrough") return skip(body, "profile_passthrough");
if (!isModelWithinScope(model, profile.name)) {
return skip(body, "model_not_approved");
}
const preserveSystemPrompt =
(typeof options?.stepConfig?.preserveSystemPrompt === "boolean"
? options.stepConfig.preserveSystemPrompt
: options?.config?.preserveSystemPrompt) === true;
// `compressSystem` só existe no transform Anthropic. Os wires OpenAI honram
// apenas compressTools/gptHistory/minCompressChars/reflow e sempre trocam a
// instrução por um ponteiro para a imagem. Imagear o system quando o OmniRoute
// decidiu preservá-lo queimaria o prefixo quente que a política cache-aware
// está protegendo — e nada no corpo devolvido denunciaria isso. Sem como
// honrar a política nesse wire, a engine pula.
if (preserveSystemPrompt && wireFormat !== "claude") {
return skip(body, "system_preservation_unsupported_on_wire");
}
// OmniGlyph 1.3.x deliberately keeps unverified families (currently Grok)
// text-only until the operator acknowledges them via its own env gate.
if (!isModelImageable(model)) return skip(body, "model_not_imageable");

const started = Date.now();
let outBody: Record<string, unknown>;
let accounting: OmniGlyphAccounting | undefined;
try {
const encoded = new TextEncoder().encode(JSON.stringify(body));
// Branch explicitly so TS narrows each transformer's return type:
// the Anthropic wrapper reports `applied`, the OpenAI ones `info.compressed`.
let applied: boolean;
let transformed: { body: Uint8Array; info: { compressed: boolean; reason?: string } };
if (wireFormat === "claude") {
const result = await transformAnthropicMessages({ body: encoded, model });
transformed = result;
applied = result.applied;
} else {
const result =
wireFormat === "openai"
? await transformOpenAIChatCompletions(encoded)
: await transformOpenAIResponses(encoded);
transformed = result;
applied = result.info.compressed;
}
if (!applied) return skip(body, transformed.info?.reason ?? "not_profitable");
outBody = JSON.parse(new TextDecoder().decode(transformed.body)) as Record<string, unknown>;
// The upstream OpenAI transformer resolves its billing/render profile from
// body.model. Keep the provider body byte-compatible on output, but use the
// already-resolved engine model for that internal gate when a translator
// omitted the model or left an alias in place.
const transformBody =
wireFormat !== "claude" && model && body.model !== model ? { ...body, model } : body;
const encoded = new TextEncoder().encode(JSON.stringify(transformBody));
const overrides = preserveSystemPrompt ? { compressSystem: false } : {};
// Só `transformAnthropicMessages` resolve o perfil por conta própria; os
// transformadores OpenAI recebem TransformOptions cru e ignorariam o campo.
const openAIOptions = mergeCompressionProfileOptions(profile, overrides);
const result =
wireFormat === "claude"
? await transformAnthropicMessages({
body: encoded,
model,
options: { ...overrides, profile: profile.name },
})
: wireFormat === "openai"
? await transformOpenAIChatCompletions(encoded, openAIOptions)
: await transformOpenAIResponses(encoded, openAIOptions);
const applied = "applied" in result ? result.applied : result.info.compressed;
if (!applied) return skip(body, result.info?.reason ?? "not_profitable");
outBody = JSON.parse(new TextDecoder().decode(result.body)) as Record<string, unknown>;
if (transformBody !== body && body.model !== undefined) outBody.model = body.model;
accounting = buildOmniGlyphAccounting({
provider: options?.provider,
model,
originalBytes: encoded.byteLength,
transformedBytes: result.body.byteLength,
info: result.info,
durationMs: Date.now() - started,
});
} catch {
// Fail-open: qualquer erro no encode/transform/decode (ex.: corpo não serializável,
// render PNG estourando, JSON decodificado malformado) vira skip, nunca propaga.
return skip(body, "transform_error");
}

return {
body: outBody,
compressed: true,
stats: createCompressionStats(
body,
outBody,
"stacked",
["omniglyph:context-as-image"],
undefined,
Date.now() - started
),
};
const stats = createCompressionStats(
body,
outBody,
"stacked",
["omniglyph:context-as-image"],
undefined,
Date.now() - started
);
// A contabilidade só acompanha uma conversão que realmente aconteceu: um skip
// não tem economia para reportar, e inventar zeros ali viraria "0% de ganho"
// indistinguível de "a engine nem rodou".
if (accounting) stats.omniglyph = accounting;

return { body: outBody, compressed: true, stats };
}

export const omniglyphEngine: CompressionEngine = {
id: "omniglyph",
name: "OmniGlyph",
description:
"Contexto-como-imagem (Anthropic Fable 5, rota direta): system prompt, tool docs e histórico viram páginas PNG densas — ~10× menos tokens no bloco convertido.",
"Contexto-como-imagem para Claude Fable 5 na rota direta medida; wires GPT nativos ficam disponíveis apenas após recibo de fidelidade do provedor.",
icon: "image",
targets: ["messages", "tool_results"],
stackable: true,
Expand All @@ -169,7 +284,7 @@ export const omniglyphEngine: CompressionEngine = {
id: "omniglyph",
name: "OmniGlyph",
description:
"Contexto-como-imagem para Claude Fable 5 e GPT 5.6 via wires nativos Anthropic/OpenAI em rota direta.",
"Contexto-como-imagem para Claude Fable 5 na rota direta medida; transformadores GPT nativos permanecem fail-closed até validação do provedor.",
inputScope: "mixed",
targetLatencyMs: 250, // render+encode PNG de páginas grandes
supportsPreview: true,
Expand Down
12 changes: 11 additions & 1 deletion open-sse/services/compression/engines/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export type CompressionWireFormat = "claude" | "openai" | "openai-responses" | s

export type CompressionStage = "pre-translation" | "post-translation";

/** Whether an upstream route preserves OmniGlyph PNG bytes and dimensions. */
export type ImageTransportFidelity = "byte-preserving" | "resizes" | "unknown";

export interface EngineConfigField {
key: string;
type: "boolean" | "number" | "string" | "select" | "multiselect";
Expand Down Expand Up @@ -42,8 +45,11 @@ export interface CompressionEngineApplyOptions {
/** Como o request chega ao provider: rota direta oficial ('direct') vs
* agregador que pode reprocessar imagens ('aggregator'). O engine omniglyph
* exige 'direct' — medição 2026-07-06: agregadores redimensionam as páginas
* e destroem a legibilidade. undefined = desconhecido = skip (fail-closed). */
* e destroem a legibilidade. A política de produção também informa
* imageTransportFidelity; chamadas legadas sem esse campo mantêm o gate direct. */
providerTransport?: "direct" | "aggregator";
/** Independent image-fidelity gate; direct HTTP does not imply byte preservation. */
imageTransportFidelity?: ImageTransportFidelity;
/** Protocol shape before the current compression stage. */
sourceFormat?: CompressionWireFormat;
/** Protocol shape expected by the upstream provider. */
Expand All @@ -55,6 +61,10 @@ export interface CompressionEngineApplyOptions {
stepConfig?: Record<string, unknown>;
/** Authenticated principal (API key id) making the request. Used by CCR to scope its store. */
principalId?: string;
/** Provider resolvido do alvo. A contabilidade do omniglyph depende dele:
* Anthropic reporta input/cache em buckets disjuntos, OpenAI/xAI reportam
* cached como subconjunto do input. Ausente => `unknown` (falha fechado). */
provider?: string;
}

export interface CompressionEngine {
Expand Down
Loading
Loading