Files
renjue 321683f863
CI / docker (push) Successful in 3m38s
Split ingress keys into text/image protocols with Replicate model listing.
Add model input defaults (including prompt), workflow model editing, ingress API docs, and fix img2img image upload filenames for signed URLs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 23:49:06 +08:00

246 lines
11 KiB
Go

package model
import (
"time"
)
type ProviderType string
const (
ProviderOpenAI ProviderType = "openai"
ProviderAnthropic ProviderType = "anthropic"
ProviderCustom ProviderType = "custom"
ProviderAzureOpenAI ProviderType = "azure_openai"
ProviderOpenRouter ProviderType = "openrouter"
ProviderOllama ProviderType = "ollama"
ProviderComfyUI ProviderType = "comfyui"
)
type WorkflowType string
const (
WorkflowTxt2Img WorkflowType = "txt2img"
WorkflowImg2Img WorkflowType = "img2img"
)
type PredictionStatus string
const (
PredictionStarting PredictionStatus = "starting"
PredictionProcessing PredictionStatus = "processing"
PredictionSucceeded PredictionStatus = "succeeded"
PredictionFailed PredictionStatus = "failed"
PredictionCanceled PredictionStatus = "canceled"
)
type ProviderStatus string
const (
ProviderHealthy ProviderStatus = "healthy"
ProviderUnhealthy ProviderStatus = "unhealthy"
ProviderUnknown ProviderStatus = "unknown"
)
type Provider struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"uniqueIndex;not null" json:"name"`
Type ProviderType `gorm:"not null" json:"type"`
Category ProviderCategory `gorm:"not null;default:llm" json:"category"`
BaseURL string `json:"base_url"`
AllowedEndpointsJSON string `gorm:"default:'[\"list_models\",\"chat_completion\"]'" json:"allowed_endpoints_json"`
EndpointPathsJSON string `gorm:"default:'{}'" json:"endpoint_paths_json"`
Status ProviderStatus `gorm:"default:unknown" json:"status"`
Enabled bool `gorm:"default:true" json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Keys []ProviderKey `gorm:"foreignKey:ProviderID" json:"keys,omitempty"`
Models []ModelEntry `gorm:"foreignKey:ProviderID" json:"models,omitempty"`
}
type ProviderKey struct {
ID uint `gorm:"primaryKey" json:"id"`
ProviderID uint `gorm:"index;not null" json:"provider_id"`
Name string `gorm:"not null" json:"name"`
APIKeyEnc string `gorm:"not null" json:"-"`
Weight float64 `gorm:"default:1" json:"weight"`
ModelsJSON string `gorm:"default:'[\"*\"]'" json:"models_json"`
Enabled bool `gorm:"default:true" json:"enabled"`
MaxRequestsPerDay int `gorm:"default:0" json:"max_requests_per_day"`
MaxTokensPerDay int64 `gorm:"default:0" json:"max_tokens_per_day"`
RequestsToday int `gorm:"default:0" json:"requests_today"`
TokensToday int64 `gorm:"default:0" json:"tokens_today"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ModelEntry struct {
ID uint `gorm:"primaryKey" json:"id"`
ProviderID uint `gorm:"index;not null" json:"provider_id"`
ModelID string `gorm:"not null" json:"model_id"`
Alias string `gorm:"index" json:"alias"`
DisplayName string `json:"display_name"`
WorkflowType WorkflowType `gorm:"default:txt2img" json:"workflow_type"`
WorkflowJSON string `gorm:"type:text" json:"workflow_json"`
InputBindingJSON string `gorm:"type:text" json:"input_binding_json"`
InputDefaultsJSON string `gorm:"type:text;default:'{}'" json:"input_defaults_json"`
VersionHash string `gorm:"index" json:"version_hash"`
Enabled bool `gorm:"default:true" json:"enabled"`
CreatedAt time.Time `json:"created_at"`
}
type IngressKey struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null" json:"name"`
KeyHash string `gorm:"uniqueIndex;not null" json:"-"`
Prefix string `gorm:"not null" json:"prefix"`
Protocol IngressKeyProtocol `gorm:"not null;default:text" json:"protocol"`
Enabled bool `gorm:"default:true" json:"enabled"`
BudgetLimit float64 `gorm:"default:0" json:"budget_limit"`
BudgetUsed float64 `gorm:"default:0" json:"budget_used"`
RateLimitRPM int `gorm:"default:0" json:"rate_limit_rpm"`
RateLimitTPM int `gorm:"default:0" json:"rate_limit_tpm"`
AllowedProvidersJSON string `gorm:"default:'[\"*\"]'" json:"allowed_providers_json"`
AllowedModelsJSON string `gorm:"default:'[\"*\"]'" json:"allowed_models_json"`
RequestCount int64 `gorm:"default:0" json:"request_count"`
TokenCount int64 `gorm:"default:0" json:"token_count"`
ExpiresAt *time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type AdminUser struct {
ID uint `gorm:"primaryKey" json:"id"`
Username string `gorm:"uniqueIndex;not null" json:"username"`
PasswordHash string `gorm:"not null" json:"-"`
CreatedAt time.Time `json:"created_at"`
}
type AdminSession struct {
ID uint `gorm:"primaryKey" json:"id"`
TokenHash string `gorm:"uniqueIndex;not null" json:"-"`
ExpiresAt time.Time `gorm:"index" json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
}
type IPRuleType string
const (
IPRuleAllow IPRuleType = "allow"
IPRuleDeny IPRuleType = "deny"
)
type IPRuleScope string
const (
IPScopeAdmin IPRuleScope = "admin"
IPScopeProxy IPRuleScope = "proxy"
IPScopeAll IPRuleScope = "all"
)
type IPRule struct {
ID uint `gorm:"primaryKey" json:"id"`
CIDR string `gorm:"column:cidr;not null" json:"cidr"`
Type IPRuleType `gorm:"not null" json:"type"`
Scope IPRuleScope `gorm:"not null;default:proxy" json:"scope"`
Enabled bool `gorm:"default:true" json:"enabled"`
CreatedAt time.Time `json:"created_at"`
}
type UsageRecord struct {
ID uint `gorm:"primaryKey" json:"id"`
IngressKeyID uint `gorm:"index" json:"ingress_key_id"`
ProviderID uint `gorm:"index" json:"provider_id"`
ProviderKeyID uint `gorm:"index" json:"provider_key_id"`
ClientIP string `gorm:"index" json:"client_ip"`
Endpoint string `json:"endpoint"`
Model string `json:"model"`
TokensIn int `json:"tokens_in"`
TokensOut int `json:"tokens_out"`
Cost float64 `json:"cost"`
LatencyMs int64 `json:"latency_ms"`
Status string `json:"status"`
Stream bool `json:"stream"`
ErrorMsg string `json:"error_msg"`
RequestBody string `gorm:"type:text" json:"request_body,omitempty"`
ResponseBody string `gorm:"type:text" json:"response_body,omitempty"`
CreatedAt time.Time `gorm:"index" json:"created_at"`
}
const (
MaxUsageLogRecords = 500
EndpointAdminLogin = "admin_login"
EndpointPrediction = "prediction"
)
type Prediction struct {
ID string `gorm:"primaryKey" json:"id"`
IngressKeyID uint `gorm:"index;not null" json:"ingress_key_id"`
ProviderID uint `gorm:"index;not null" json:"provider_id"`
ProviderKeyID uint `gorm:"index" json:"provider_key_id"`
ModelEntryID uint `gorm:"index" json:"model_entry_id"`
Version string `json:"version"`
Model string `json:"model"`
InputJSON string `gorm:"type:text" json:"input_json"`
Status PredictionStatus `gorm:"index;not null;default:starting" json:"status"`
ComfyPromptID string `json:"comfy_prompt_id"`
ClientID string `json:"client_id"`
OutputJSON string `gorm:"type:text" json:"output_json"`
Error string `gorm:"type:text" json:"error"`
Logs string `gorm:"type:text" json:"logs"`
MetricsJSON string `gorm:"type:text" json:"metrics_json"`
CreatedAt time.Time `json:"created_at"`
StartedAt *time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at"`
}
type StoredImage struct {
ID string `gorm:"primaryKey" json:"id"`
PredictionID string `gorm:"index;not null" json:"prediction_id"`
Filename string `json:"filename"`
LocalPath string `json:"-"`
Mime string `json:"mime"`
Size int64 `json:"size"`
CreatedAt time.Time `json:"created_at"`
}
// RoutingRule Virtual Key 路由:按模型匹配绑定 Provider / ProviderKey
type RoutingRule struct {
ID uint `gorm:"primaryKey" json:"id"`
IngressKeyID uint `gorm:"index;not null" json:"ingress_key_id"`
ModelPattern string `gorm:"not null" json:"model_pattern"`
ProviderID uint `gorm:"not null" json:"provider_id"`
ProviderKeyID uint `gorm:"default:0" json:"provider_key_id"`
Priority int `gorm:"default:0" json:"priority"`
Enabled bool `gorm:"default:true" json:"enabled"`
CreatedAt time.Time `json:"created_at"`
}
// SystemSettings singleton (id=1) for runtime configuration managed via admin UI.
type SystemSettings struct {
ID uint `gorm:"primaryKey" json:"id"`
EncryptionKey string `gorm:"not null" json:"-"`
SessionTTLSeconds int64 `gorm:"not null;default:86400" json:"session_ttl_seconds"`
LoginMaxAttempts int `gorm:"not null;default:5" json:"login_max_attempts"`
LoginLockoutSeconds int64 `gorm:"not null;default:900" json:"login_lockout_seconds"`
TrustedProxiesJSON string `gorm:"default:'[]'" json:"trusted_proxies_json"`
UsageFlushSeconds int64 `gorm:"not null;default:5" json:"usage_flush_seconds"`
HealthCheckSeconds int64 `gorm:"not null;default:30" json:"health_check_seconds"`
GatewayMaxRetries int `gorm:"not null;default:3" json:"gateway_max_retries"`
GatewayRetryBackoffMs int `gorm:"not null;default:200" json:"gateway_retry_backoff_ms"`
ImageStoragePath string `gorm:"default:'images'" json:"image_storage_path"`
PublicBaseURL string `json:"public_base_url"`
SignedURLTTLSeconds int64 `gorm:"not null;default:3600" json:"signed_url_ttl_seconds"`
PredictionWaitSeconds int64 `gorm:"not null;default:60" json:"prediction_wait_seconds"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type HealthCheckRecord struct {
ID uint `gorm:"primaryKey" json:"id"`
ProviderID uint `gorm:"index" json:"provider_id"`
Status ProviderStatus `json:"status"`
LatencyMs int64 `json:"latency_ms"`
ErrorMsg string `json:"error_msg"`
CheckedAt time.Time `gorm:"index" json:"checked_at"`
}