/** * Per-model GPT rendering + vision-cost profiles. * * One place to retune when a new model ships with different image tokenization, * a different downscale threshold (max safe portrait-strip width), or a different * max image height. Unknown models preserve the conservative legacy fallback; * named profiles may deliberately select different fonts and geometry. * * Retune without a code change via the PXPIPE_GPT_PROFILES env var (JSON map of * model-id PREFIX -> partial profile; longest matching prefix wins, checked * BEFORE the built-in table). Partial fields fall back to the built-in match, so * you can override just one knob: * * PXPIPE_GPT_PROFILES='{"gpt-5.6-sol":{"vision":{"regime":"patch","multiplier":1,"patchCap":12000},"stripCols":120,"maxHeightPx":1900}}' * PXPIPE_GPT_PROFILES='{"gpt-5.6-sol":{"style":{"grid":true,"gridCols":4}}}' */ /** * GPT strip height, DECOUPLED from render.ts's MAX_HEIGHT_PX (which is Anthropic's * 1568-edge / ~1.15 MP clamp). Named profiles may override this where their image * sizing and font geometry differ. */ import { type RenderFont } from './render.js'; export declare const GPT_MAX_HEIGHT_PX = 1932; /** * Image-token cost model. Every provider family is DATA here — there is no * `if (isClaude)` branch anywhere in the pricing path; `visionTokens()` * (vision-cost.ts) is the single interpreter of these regimes. * * - `tile` OpenAI legacy: 2048/768 downscale, then base + perTile per 512-px tile. * - `patch` OpenAI 32-px patches × multiplier. An omitted patchCap bills original dims. * - `patch28` Anthropic 28-px patches after the tier downscale (see `visionTier`). * - `mpix` Pixel-priced families (Grok): megapixels × tokensPerMegapixel, min 1. * - `flat` One fixed charge per image (Gemini), with an optional measured * exact-canvas override for the production page size. */ export type GptVisionCost = { regime: 'tile'; base: number; perTile: number; } | { regime: 'patch'; multiplier: number; patchCap?: number; } | { regime: 'patch28'; } | { regime: 'mpix'; tokensPerMegapixel: number; } | { regime: 'flat'; tokens: number; exact?: { widthPx: number; heightPx: number; tokens: number; }; }; export interface GptRenderStyle { /** Rasterized font atlas. */ font: RenderFont; /** Extra px beside the 5px glyph (cell width = 5 + this). */ cellWBonus: number; /** Extra px above the 8px glyph (cell height = 8 + this). */ cellHBonus: number; /** Grayscale AA atlas. Default true for production dense pages. */ aa: boolean; /** Faint cell guides. */ grid: boolean; /** Vertical guide cadence when grid is enabled. */ gridCols: number; /** Per-glyph color cycle. */ colorCycle: boolean; /** Horizontal scale for the hard-newline marker. */ markerScale: number; /** Render hard-newline markers in red. */ markerRed: boolean; /** Pre-invert ink dilate radius (px). 0 = off. Thickens glyphs at fixed cell pitch. */ inkDilate: number; } export interface GptHistoryProfile { /** Total history-image budget after the static slab. */ maxImages: number; /** Recent ordinary conversation messages retained as native text. */ keepTail: number; /** Recent completed call/output pairs retained as native protocol state. */ keepRecentPairs: number; /** Local o200k floor before history profitability is evaluated. */ minCollapseTokens: number; /** Responses items eligible for history images. */ responsesMode: 'pairs' | 'mixed'; /** Native text bracketing each history image group. */ framing: 'full' | 'compact'; /** Fact-sheet placement for discontiguous Responses history groups. */ factSheetScope: 'per-segment' | 'combined'; } export interface GptModelProfile { /** How this model's provider bills the rendered images as input tokens. */ vision: GptVisionCost; /** Cached-input list price ÷ uncached-input list price for this family. * Savings reporting reads this instead of re-classifying the model id. */ cacheReadRate: number; /** Output list price ÷ uncached-input list price for this family. */ outputRate: number; /** Max portrait-strip width in columns. Combined with `style`, this must stay * at or below the provider's no-resize pixel width. */ stripCols: number; /** Max rendered image height in px. Threaded into the renderer so the gate's * cost estimate and the actual page split agree. */ maxHeightPx: number; /** Local o200k token floor before image profitability is evaluated. * Undefined preserves the legacy character floor for non-o200k models. */ minCompressTokens?: number; /** Anthropic image-resolution tier, consumed by `anthropicVisionProfile`. * Undefined = standard; only Claude profiles set it (Anthropic is the only * provider that tiers the pre-billing downscale by model). */ visionTier?: 'high-res' | 'standard'; /** Exact-token sheet wording beside rendered content. */ factSheetFormat: 'full' | 'compact'; /** Model-specific history coverage and native-text overhead. */ history: GptHistoryProfile; /** Complete model-specific font, cell spacing, color, and marker style. */ style: GptRenderStyle; /** Optional override of `stripCols` for COLLAPSED HISTORY only, leaving the * slab and tool-result pages on `stripCols`. Undefined = use `stripCols`, * i.e. behaviour is unchanged unless a profile opts in. * * Exists because reading accuracy and rendering cost are not the same axis. * Geometry is identical across a provider's models because the *billing* is, * but verbatim recall is not: on one 26-value battery at this profile's * 312-col dense geometry, Fable 5 read 25/26 exactly while Opus 5 read 3/26 * with 10 silent substitutions. A deployment that must re-read exact values * out of imaged history needs a lower density there — and only there, since * the static slab holds no such values. */ historyStripCols?: number; /** Optional override of `style` for collapsed history only. Same rationale as * `historyStripCols`; set both together, since a larger font at unchanged * columns overshoots the provider's no-resize width and is silently * downscaled, which removes the legibility it was meant to buy. */ historyStyle?: GptRenderStyle; /** Maximum serialized provider request produced by pxpipe. Undefined leaves * legacy behavior unchanged. Checked in the transform (which falls back to * the original body when imaging would overshoot) and enforced again on the * final wire body by the proxy, which answers 413. * * Set this ONLY for a limit the provider itself has shown us: published docs, * or a 413 that demonstrably came from the provider. A 413 is NOT evidence on * its own — an intermediate hop (local gateway daemon, corporate proxy, CDN) * can impose its own body cap and answer with a provider-shaped * `payload_too_large` naming ITS limit, for a request the provider never saw. * Such a cap is also usually deployment config, not a model property, so it * belongs in `PXPIPE_GPT_PROFILES`, not here. * * A guessed cap makes pxpipe refuse to compress requests the provider would * have accepted, which is the opposite of the point. No family currently * carries one. Largest body each provider has answered 200 for in local * telemetry, as a lower bound (cacheable prefix already on the wire, so the * real body was bigger): Claude 11.2 MB, GPT 10.1 MB, Gemini 6.2 MB, Grok * 2.7 MB. No provider-originated size rejection has been observed for any. */ maxSerializedRequestBytes?: number; /** Gate the static slab against the exact measured baseline (system text plus * the tool-description tokens actually stripped) instead of the rendered * text's own token count. Profiles that pin an exact static slab set this; * it is a property of the profile, not of one model id. */ exactStaticBaseline?: boolean; /** Hard provider cap on TOTAL images in one request (slab + history + * client-attached). When set, the history-collapse budget becomes dynamic: * min(configured history cap, this cap − images already in the request), so * client-attached images consume the same headroom pxpipe's own images do * and the final request can never overshoot the provider's limit. Set only * from a documented provider limit (Workers AI 3.8: 32). */ providerImageCap?: number; } /** Default downscale-safe strip width (768px). Exported as the global cols default. */ export declare const DEFAULT_GPT_STRIP_COLS = 152; /** * Conservative fallback for unrecognized models: tile 85/170 over-states cost, * which biases the gate toward pass-through (safe). Matches gpt-4o/4.1/4.5. */ export declare const DEFAULT_GPT_PROFILE: GptModelProfile; /** * True when an id NAMES a known provider family but does not match that * family's profile test — for example `gemini-3.6-pro`, when 3.6 Flash is the * only Gemini geometry pxpipe has measured. Such an id would fall through to * DEFAULT_GPT_PROFILE and be gated with OpenAI's tile math, i.e. priced with * the wrong provider's formula, so applicability refuses it instead of * compressing against numbers that do not apply to it. * * (DEFAULT_GPT_PROFILE is a legitimate *OpenAI* fallback — gpt-4o and friends * are deliberately gated with its conservative tile cost — so resolving to the * default is only a problem when the id is not an OpenAI id at all.) */ export declare function isMisresolvedModelId(model: string | null | undefined): boolean; export declare function resolveGptProfile(model: string | null | undefined): GptModelProfile; //# sourceMappingURL=gpt-model-profiles.d.ts.map