/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
import { BILLING_CACHE_VAR_MAP } from './billing-expr'
export const CACHE_MODE_TIMED = 'timed'
export const CACHE_MODE_GENERIC = 'generic'
export type CacheMode = typeof CACHE_MODE_TIMED | typeof CACHE_MODE_GENERIC
export type TierConditionInput = {
var: 'p' | 'c' | 'len'
op: '<' | '<=' | '>' | '>='
value: number | string
}
export type VisualTier = {
label: string
conditions: TierConditionInput[]
input_unit_cost: number
output_unit_cost: number
cache_mode: CacheMode
cache_read_unit_cost?: number
cache_create_unit_cost?: number
cache_create_1h_unit_cost?: number
image_unit_cost?: number
image_output_unit_cost?: number
audio_input_unit_cost?: number
audio_output_unit_cost?: number
[field: string]: unknown
}
export type VisualConfig = {
tiers: VisualTier[]
}
export function getTierCacheMode(
tier: Partial | null | undefined
): CacheMode {
if (tier?.cache_mode === CACHE_MODE_TIMED) return CACHE_MODE_TIMED
if (tier?.cache_mode === CACHE_MODE_GENERIC) return CACHE_MODE_GENERIC
return Number(tier?.cache_create_1h_unit_cost) > 0
? CACHE_MODE_TIMED
: CACHE_MODE_GENERIC
}
export function normalizeVisualTier(
tier: Partial = {}
): VisualTier {
return {
label: tier.label ?? '',
input_unit_cost: Number(tier.input_unit_cost) || 0,
output_unit_cost: Number(tier.output_unit_cost) || 0,
cache_mode: getTierCacheMode(tier),
conditions: Array.isArray(tier.conditions) ? tier.conditions : [],
...tier,
cache_read_unit_cost: Number(tier.cache_read_unit_cost) || 0,
cache_create_unit_cost: Number(tier.cache_create_unit_cost) || 0,
cache_create_1h_unit_cost: Number(tier.cache_create_1h_unit_cost) || 0,
image_unit_cost: Number(tier.image_unit_cost) || 0,
image_output_unit_cost: Number(tier.image_output_unit_cost) || 0,
audio_input_unit_cost: Number(tier.audio_input_unit_cost) || 0,
audio_output_unit_cost: Number(tier.audio_output_unit_cost) || 0,
}
}
export function createDefaultVisualConfig(): VisualConfig {
return {
tiers: [
normalizeVisualTier({
conditions: [],
input_unit_cost: 0,
output_unit_cost: 0,
label: 'base',
cache_mode: CACHE_MODE_GENERIC,
}),
],
}
}
export function normalizeVisualConfig(
config: VisualConfig | null | undefined
): VisualConfig {
if (!config || !Array.isArray(config.tiers) || config.tiers.length === 0) {
return createDefaultVisualConfig()
}
return {
...config,
tiers: config.tiers.map((tier) => normalizeVisualTier(tier)),
}
}
function buildConditionStr(conditions: TierConditionInput[]): string {
if (!conditions || conditions.length === 0) return ''
return conditions
.filter((c) => c.var && c.op && c.value != null && c.value !== '')
.map((c) => `${c.var} ${c.op} ${c.value}`)
.join(' && ')
}
function buildTierBodyExpr(tier: VisualTier): string {
const parts: string[] = []
const ic = Number(tier.input_unit_cost) || 0
const oc = Number(tier.output_unit_cost) || 0
parts.push(`p * ${ic}`)
parts.push(`c * ${oc}`)
for (const cv of BILLING_CACHE_VAR_MAP) {
const v = Number((tier as Record)[cv.field]) || 0
if (v !== 0) parts.push(`${cv.exprVar} * ${v}`)
}
return parts.join(' + ')
}
export function generateExprFromVisualConfig(
config: VisualConfig | null | undefined
): string {
if (!config || !config.tiers || config.tiers.length === 0) {
return 'p * 0 + c * 0'
}
const tiers = config.tiers
if (tiers.length === 1) {
const tier = tiers[0]
const label = tier.label || 'default'
const body = `tier("${label}", ${buildTierBodyExpr(tier)})`
const cond = buildConditionStr(tier.conditions)
if (cond) {
return `${cond} ? ${body} : p * 0 + c * 0`
}
return body
}
const parts: string[] = []
for (let i = 0; i < tiers.length; i++) {
const tier = tiers[i]
const label = tier.label || `tier_${i + 1}`
const body = `tier("${label}", ${buildTierBodyExpr(tier)})`
const cond = buildConditionStr(tier.conditions)
if (i < tiers.length - 1 && cond) {
parts.push(`${cond} ? ${body}`)
} else {
parts.push(body)
}
}
return parts.join(' : ')
}
export function tryParseVisualConfig(
exprStr: string | null | undefined
): VisualConfig | null {
if (!exprStr) return null
try {
let body = exprStr
const versionMatch = body.match(/^v\d+:([\s\S]*)$/)
if (versionMatch) body = versionMatch[1]
const cacheVarNames = BILLING_CACHE_VAR_MAP.map((cv) => cv.exprVar)
const optCacheStr = cacheVarNames
.map((v) => `(?:\\s*\\+\\s*${v}\\s*\\*\\s*([\\d.eE+-]+))?`)
.join('')
const bodyPat = `p\\s*\\*\\s*([\\d.eE+-]+)\\s*\\+\\s*c\\s*\\*\\s*([\\d.eE+-]+)${optCacheStr}`
const singleRe = new RegExp(`^tier\\("([^"]*)",\\s*${bodyPat}\\)$`)
const simple = body.match(singleRe)
if (simple) {
const tier: Record = {
conditions: [],
input_unit_cost: Number(simple[2]),
output_unit_cost: Number(simple[3]),
label: simple[1],
}
BILLING_CACHE_VAR_MAP.forEach((cv, i) => {
const val = simple[4 + i]
if (val != null) tier[cv.field] = Number(val)
})
return normalizeVisualConfig({
tiers: [normalizeVisualTier(tier as Partial)],
})
}
const condGroup =
`((?:(?:p|c|len)\\s*(?:<|<=|>|>=)\\s*[\\d.eE+]+)` +
`(?:\\s*&&\\s*(?:p|c|len)\\s*(?:<|<=|>|>=)\\s*[\\d.eE+]+)*)`
const tierRe = new RegExp(
`(?:${condGroup}\\s*\\?\\s*)?tier\\("([^"]*)",\\s*${bodyPat}\\)`,
'g'
)
const tiers: VisualTier[] = []
let match: RegExpExecArray | null
while ((match = tierRe.exec(body)) !== null) {
const condStr = match[1] || ''
const conditions: TierConditionInput[] = []
if (condStr) {
for (const cp of condStr.split(/\s*&&\s*/)) {
const cm = cp.trim().match(/^(p|c|len)\s*(<|<=|>|>=)\s*([\d.eE+]+)$/)
if (cm) {
conditions.push({
var: cm[1] as TierConditionInput['var'],
op: cm[2] as TierConditionInput['op'],
value: Number(cm[3]),
})
}
}
}
const tier: Record = {
conditions,
input_unit_cost: Number(match[3]),
output_unit_cost: Number(match[4]),
label: match[2],
}
const m = match
BILLING_CACHE_VAR_MAP.forEach((cv, i) => {
const val = m[5 + i]
if (val != null) tier[cv.field] = Number(val)
})
tiers.push(normalizeVisualTier(tier as Partial))
}
if (tiers.length === 0) return null
const cfg = normalizeVisualConfig({ tiers })
const regenerated = generateExprFromVisualConfig(cfg)
if (regenerated.replace(/\s+/g, '') !== body.replace(/\s+/g, '')) {
return null
}
return cfg
} catch {
return null
}
}
// ---------------------------------------------------------------------------
// Local cost evaluator (for the estimator preview)
// ---------------------------------------------------------------------------
const ESTIMATOR_VARS = [
{ var: 'cr', stateKey: 'cacheReadTokens' },
{ var: 'cc', stateKey: 'cacheCreateTokens' },
{ var: 'cc1h', stateKey: 'cacheCreate1hTokens' },
{ var: 'img', stateKey: 'imageTokens' },
{ var: 'img_o', stateKey: 'imageOutputTokens' },
{ var: 'ai', stateKey: 'audioInputTokens' },
{ var: 'ao', stateKey: 'audioOutputTokens' },
] as const
export type ExtraTokenValues = Record<
(typeof ESTIMATOR_VARS)[number]['stateKey'],
number
>
export type EvalResult = {
cost: number
matchedTier: string
error: string | null
}
export function evalExprLocally(
exprStr: string,
promptTokens: number,
completionTokens: number,
extraTokenValues: ExtraTokenValues
): EvalResult {
try {
if (!exprStr || !exprStr.trim()) {
return { cost: 0, matchedTier: '', error: null }
}
let matchedTier = ''
const tierFn = (name: string, value: number) => {
matchedTier = name
return value
}
const cacheReadTokens = extraTokenValues.cacheReadTokens || 0
const cacheCreateTokens = extraTokenValues.cacheCreateTokens || 0
const cacheCreate1hTokens = extraTokenValues.cacheCreate1hTokens || 0
const len =
promptTokens + cacheReadTokens + cacheCreateTokens + cacheCreate1hTokens
const env: Record = {
p: promptTokens,
c: completionTokens,
len,
tier: tierFn,
max: Math.max,
min: Math.min,
abs: Math.abs,
ceil: Math.ceil,
floor: Math.floor,
}
for (const field of ESTIMATOR_VARS) {
env[field.var] = extraTokenValues[field.stateKey] || 0
}
const fn = new Function(
...Object.keys(env),
`"use strict"; return (${exprStr});`
)
const cost = Number(fn(...Object.values(env))) || 0
return { cost, matchedTier, error: null }
} catch (e) {
const message = e instanceof Error ? e.message : String(e)
return { cost: 0, matchedTier: '', error: message }
}
}
export function exprUsesExtraVars(exprStr: string): boolean {
if (!exprStr) return false
const varNames = ESTIMATOR_VARS.map((f) => f.var).join('|')
return new RegExp(`\\b(${varNames})\\b`).test(exprStr)
}
export const ESTIMATOR_EXTRA_FIELDS = ESTIMATOR_VARS