Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 1m40s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 42m16s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
112 lines
5.1 KiB
Go
112 lines
5.1 KiB
Go
package billingexpr
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/QuantumNous/new-api/common"
|
|
)
|
|
|
|
type RequestInput struct {
|
|
At *time.Time `json:"at,omitempty"`
|
|
Headers map[string]string
|
|
Body []byte
|
|
Usage map[string]any
|
|
// ImageCount is a validated billing quantity, separate from the frozen
|
|
// request's n. Settlement can replace it with the actual returned count.
|
|
ImageCount *int
|
|
}
|
|
|
|
// TokenParams holds all token dimensions passed into an Expr evaluation.
|
|
// Fields beyond P and C are optional — when absent they default to 0,
|
|
// which means cache-unaware expressions keep working unchanged.
|
|
type TokenParams struct {
|
|
P float64 // prompt tokens (text) — auto-excludes sub-categories priced separately
|
|
C float64 // completion tokens (text) — auto-excludes sub-categories priced separately
|
|
Len float64 // total input context length for tier conditions (non-Claude: raw prompt_tokens; Claude: text + cache read + cache creation)
|
|
CR float64 // cache read (hit) tokens
|
|
CC float64 // cache creation tokens (5-min TTL for Claude, generic for others)
|
|
CC1h float64 // cache creation tokens — 1-hour TTL (Claude only)
|
|
Img float64 // image input tokens
|
|
ImgCR float64 // image cache read tokens, separated only when explicitly priced
|
|
ImgO float64 // image output tokens
|
|
AI float64 // audio input tokens
|
|
AO float64 // audio output tokens
|
|
}
|
|
|
|
// RequestRuleTrace describes one request-dependent multiplier detected at compile time.
|
|
type RequestRuleTrace struct {
|
|
Cond string `json:"cond"`
|
|
Multiplier float64 `json:"multiplier"`
|
|
Matched bool `json:"matched"`
|
|
}
|
|
|
|
type BillingUnit string
|
|
|
|
const (
|
|
BillingUnitToken BillingUnit = "token"
|
|
BillingUnitRequest BillingUnit = "request"
|
|
)
|
|
|
|
// TraceResult holds side-channel info captured while an expression runs.
|
|
type TraceResult struct {
|
|
ImageCount *int `json:"image_count,omitempty"`
|
|
BillingUnit BillingUnit `json:"billing_unit"`
|
|
FixedPrice *float64 `json:"fixed_price,omitempty"`
|
|
MatchedTier string `json:"matched_tier"`
|
|
RequestRules []RequestRuleTrace `json:"request_rules,omitempty"`
|
|
Cost float64 `json:"cost"`
|
|
}
|
|
|
|
// BillingSnapshot captures billing state at pre-consume time. Expression and
|
|
// request fields stay frozen; group-dependent fields are refreshed before an
|
|
// auto-group retry and settlement. It is fully serializable and contains no
|
|
// compiled program pointers.
|
|
type BillingSnapshot struct {
|
|
EstimatedImageCount *int `json:"estimated_image_count,omitempty"`
|
|
BillingMode string `json:"billing_mode"`
|
|
ModelName string `json:"model_name"`
|
|
ExprString string `json:"expr_string"`
|
|
ExprHash string `json:"expr_hash"`
|
|
GroupRatio float64 `json:"group_ratio"`
|
|
EstimatedPromptTokens int `json:"estimated_prompt_tokens"`
|
|
EstimatedCompletionTokens int `json:"estimated_completion_tokens"`
|
|
EstimatedQuotaBeforeGroup float64 `json:"estimated_quota_before_group"`
|
|
EstimatedQuotaAfterGroup int `json:"estimated_quota_after_group"`
|
|
EstimatedTier string `json:"estimated_tier"`
|
|
EstimatedBillingUnit BillingUnit `json:"estimated_billing_unit,omitempty"`
|
|
EstimatedFixedPrice *float64 `json:"estimated_fixed_price,omitempty"`
|
|
QuotaPerUnit float64 `json:"quota_per_unit"`
|
|
ExprVersion int `json:"expr_version"`
|
|
TaskUsageBilling bool `json:"task_usage_billing,omitempty"`
|
|
UsageFacts map[string]any `json:"usage_facts,omitempty"`
|
|
}
|
|
|
|
// TieredResult holds everything needed after running tiered settlement.
|
|
type TieredResult struct {
|
|
// BillingTokens records the actual normalized inputs for successful token
|
|
// billing that explicitly references img_cr. Logs serialize these through
|
|
// the shared injection path, not as additional snapshot state.
|
|
BillingTokens *TokenParams `json:"-"`
|
|
ImageCount *int `json:"image_count,omitempty"`
|
|
BillingUnit BillingUnit `json:"billing_unit"`
|
|
FixedPrice *float64 `json:"fixed_price,omitempty"`
|
|
ActualQuotaBeforeGroup float64 `json:"actual_quota_before_group"`
|
|
ActualQuotaAfterGroup int `json:"actual_quota_after_group"`
|
|
MatchedTier string `json:"matched_tier"`
|
|
RequestRules []RequestRuleTrace `json:"request_rules,omitempty"`
|
|
CrossedTier bool `json:"crossed_tier"`
|
|
// Clamp records a single-request saturation event during quota conversion so the
|
|
// caller can surface it on the consume log for admin auditing. Nil when no
|
|
// clamping occurred. Not serialized: the marker is attached separately via
|
|
// the shared quota-saturation audit path.
|
|
Clamp *common.QuotaClamp `json:"-"`
|
|
}
|
|
|
|
// ExprHashString returns the SHA-256 hex digest of an expression string.
|
|
func ExprHashString(expr string) string {
|
|
h := sha256.Sum256([]byte(expr))
|
|
return fmt.Sprintf("%x", h)
|
|
}
|