chore: gofmt 对齐(远端提交带入的未格式化文件)
This commit is contained in:
1 parent
dfe31b5b4f
commit
263bfb7845
8 files changed
+51
-51
No files matched your search
@@ -104,7 +104,7 @@ func (h *Handler) AdminChannelAddModel(c *gin.Context) {
|
||||
}
|
||||
var req struct {
|
||||
UpstreamModel string `json:"upstream_model" binding:"required"` // 渠道侧真实模型名
|
||||
CustomName string `json:"custom_name"` // 客户端调用名,空=用上游名
|
||||
CustomName string `json:"custom_name"` // 客户端调用名,空=用上游名
|
||||
Weight *int `json:"weight"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -56,9 +56,9 @@ func (h *Handler) channelRuntime(id uint64) (fails int, cooldownSeconds int64) {
|
||||
|
||||
type channelBody struct {
|
||||
Name string `json:"name" binding:"required,min=1,max=64"`
|
||||
Provider string `json:"provider"` // 可选:为空时按 formats 推断(兼容旧数据)
|
||||
Formats []string `json:"formats"` // 原生支持的协议 chat|responses|messages(主配置)
|
||||
BaseURL string `json:"base_url"` // 可选:留空按供应商默认;支持前缀或完整端点
|
||||
Provider string `json:"provider"` // 可选:为空时按 formats 推断(兼容旧数据)
|
||||
Formats []string `json:"formats"` // 原生支持的协议 chat|responses|messages(主配置)
|
||||
BaseURL string `json:"base_url"` // 可选:留空按供应商默认;支持前缀或完整端点
|
||||
BaseURLs map[string]string `json:"base_urls"` // 分协议 base_url 覆盖(chat/responses/messages)
|
||||
APIKey string `json:"api_key"`
|
||||
Weight *int `json:"weight"`
|
||||
@@ -194,7 +194,7 @@ func (h *Handler) AdminCreateChannel(c *gin.Context) {
|
||||
}
|
||||
ch := store.Channel{
|
||||
Name: req.Name, Provider: req.Provider, Formats: formats, BaseURL: baseURL,
|
||||
BaseURLs: normalizeBaseURLs(req.BaseURLs),
|
||||
BaseURLs: normalizeBaseURLs(req.BaseURLs),
|
||||
APIKeyEnc: enc, Weight: intOr(req.Weight, 1), Priority: intOr(req.Priority, 0),
|
||||
TimeoutMS: intOr(req.TimeoutMS, 300000), MaxConcurrency: intOr(req.MaxConcurrency, 16),
|
||||
HealthStatus: store.ChannelHealthHealthy, Enabled: boolOr(req.Enabled, true),
|
||||
|
||||
+13
-13
@@ -118,27 +118,27 @@ func (a *App) Seed() error {
|
||||
return err
|
||||
}
|
||||
ch := store.Channel{
|
||||
Name: a.Cfg.Proxy.DefaultChannelName,
|
||||
Provider: store.ChannelProviderOpenAI,
|
||||
Formats: []string{store.FormatChat, store.FormatResponses},
|
||||
BaseURL: a.Cfg.Proxy.UpstreamBaseURL,
|
||||
APIKeyEnc: enc,
|
||||
Weight: 1,
|
||||
Priority: 0,
|
||||
TimeoutMS: int(a.Cfg.Proxy.Timeout / time.Millisecond),
|
||||
Name: a.Cfg.Proxy.DefaultChannelName,
|
||||
Provider: store.ChannelProviderOpenAI,
|
||||
Formats: []string{store.FormatChat, store.FormatResponses},
|
||||
BaseURL: a.Cfg.Proxy.UpstreamBaseURL,
|
||||
APIKeyEnc: enc,
|
||||
Weight: 1,
|
||||
Priority: 0,
|
||||
TimeoutMS: int(a.Cfg.Proxy.Timeout / time.Millisecond),
|
||||
MaxConcurrency: 16,
|
||||
HealthStatus: store.ChannelHealthHealthy,
|
||||
Enabled: true,
|
||||
HealthStatus: store.ChannelHealthHealthy,
|
||||
Enabled: true,
|
||||
}
|
||||
if err := a.DB.Create(&ch).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 默认模型 + 绑定
|
||||
m := store.Model{
|
||||
Name: a.Cfg.Proxy.DefaultModel,
|
||||
InputPrice: 0.15, // 每百万 token,示例价
|
||||
Name: a.Cfg.Proxy.DefaultModel,
|
||||
InputPrice: 0.15, // 每百万 token,示例价
|
||||
OutputPrice: 0.60,
|
||||
Enabled: true,
|
||||
Enabled: true,
|
||||
}
|
||||
if err := a.DB.Create(&m).Error; err == nil {
|
||||
a.DB.Create(&store.ChannelModelBinding{ChannelID: ch.ID, ModelID: m.ID, UpstreamModel: m.Name})
|
||||
|
||||
@@ -175,4 +175,4 @@ func randomPassword(n int) (string, error) {
|
||||
buf[i] = pwAlphabet[k.Int64()]
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,4 @@ var rootCmd = &cobra.Command{
|
||||
RunE: func(c *cobra.Command, args []string) error {
|
||||
return serve()
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -61,10 +61,10 @@ type webUser struct {
|
||||
credentials []webauthn.Credential
|
||||
}
|
||||
|
||||
func (u *webUser) WebAuthnID() []byte { return []byte(strconv.FormatUint(u.id, 10)) }
|
||||
func (u *webUser) WebAuthnName() string { return u.name }
|
||||
func (u *webUser) WebAuthnDisplayName() string { return u.displayName }
|
||||
func (u *webUser) WebAuthnIcon() string { return "" }
|
||||
func (u *webUser) WebAuthnID() []byte { return []byte(strconv.FormatUint(u.id, 10)) }
|
||||
func (u *webUser) WebAuthnName() string { return u.name }
|
||||
func (u *webUser) WebAuthnDisplayName() string { return u.displayName }
|
||||
func (u *webUser) WebAuthnIcon() string { return "" }
|
||||
func (u *webUser) WebAuthnCredentials() []webauthn.Credential { return u.credentials }
|
||||
|
||||
func (s *Service) loadWebUser(u *store.User) (*webUser, error) {
|
||||
|
||||
@@ -56,7 +56,7 @@ type User struct {
|
||||
Role string `gorm:"size:16;not null;default:user" json:"role"`
|
||||
Balance float64 `gorm:"type:numeric(20,8);not null;default:0" json:"balance"`
|
||||
Status string `gorm:"size:16;not null;default:active" json:"status"`
|
||||
TokenVersion int `gorm:"not null;default:0" json:"-"` // 会话版本:改密/登出递增,低于当前版本的 token 全部失效
|
||||
TokenVersion int `gorm:"not null;default:0" json:"-"` // 会话版本:改密/登出递增,低于当前版本的 token 全部失效
|
||||
AllowedModels []string `gorm:"type:jsonb;serializer:json" json:"allowed_models,omitempty"` // 用户级模型白名单(空=不限制)
|
||||
DeniedModels []string `gorm:"type:jsonb;serializer:json" json:"denied_models,omitempty"` // 用户级模型黑名单
|
||||
InviteCode *string `json:"invite_code,omitempty"`
|
||||
@@ -183,30 +183,30 @@ type ChannelModelBinding struct {
|
||||
|
||||
// UsageLog 请求级用量明细(PLANNING §6.5)
|
||||
type UsageLog struct {
|
||||
ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
RequestID string `gorm:"size:128" json:"request_id"` // 上游 request id
|
||||
TraceID string `gorm:"size:64;index" json:"trace_id"`
|
||||
UserID uint64 `gorm:"index:idx_user_created,priority:1;not null" json:"user_id"`
|
||||
KeyID uint64 `gorm:"index" json:"key_id"`
|
||||
ChannelID uint64 `gorm:"index:idx_channel_created,priority:1" json:"channel_id"`
|
||||
ModelID uint64 `json:"model_id"`
|
||||
ModelName string `gorm:"size:128" json:"model_name"`
|
||||
Protocol string `gorm:"size:32" json:"protocol"` // responses|chat|messages
|
||||
InputTokens int64 `json:"input_tokens"`
|
||||
OutputTokens int64 `json:"output_tokens"`
|
||||
CacheReadTokens int64 `json:"cache_read_tokens"`
|
||||
CacheCreationTokens int64 `json:"cache_creation_tokens"`
|
||||
InputPrice float64 `gorm:"type:numeric(20,8)" json:"input_price"` // 快照
|
||||
OutputPrice float64 `gorm:"type:numeric(20,8)" json:"output_price"` // 快照
|
||||
CacheReadPrice float64 `gorm:"type:numeric(20,8)" json:"cache_read_price"` // 快照
|
||||
Cost float64 `gorm:"type:numeric(20,8)" json:"cost"`
|
||||
LatencyMS int `json:"latency_ms"`
|
||||
Status string `gorm:"size:16;not null" json:"status"`
|
||||
ErrorCode *string `json:"error_code,omitempty"`
|
||||
RawRequest string `gorm:"type:text" json:"raw_request"` // 客户端原始请求体(未转换)
|
||||
RawResponse string `gorm:"type:text" json:"raw_response"` // 上游原始响应(未转换;流式为全部 SSE 事件)
|
||||
ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
RequestID string `gorm:"size:128" json:"request_id"` // 上游 request id
|
||||
TraceID string `gorm:"size:64;index" json:"trace_id"`
|
||||
UserID uint64 `gorm:"index:idx_user_created,priority:1;not null" json:"user_id"`
|
||||
KeyID uint64 `gorm:"index" json:"key_id"`
|
||||
ChannelID uint64 `gorm:"index:idx_channel_created,priority:1" json:"channel_id"`
|
||||
ModelID uint64 `json:"model_id"`
|
||||
ModelName string `gorm:"size:128" json:"model_name"`
|
||||
Protocol string `gorm:"size:32" json:"protocol"` // responses|chat|messages
|
||||
InputTokens int64 `json:"input_tokens"`
|
||||
OutputTokens int64 `json:"output_tokens"`
|
||||
CacheReadTokens int64 `json:"cache_read_tokens"`
|
||||
CacheCreationTokens int64 `json:"cache_creation_tokens"`
|
||||
InputPrice float64 `gorm:"type:numeric(20,8)" json:"input_price"` // 快照
|
||||
OutputPrice float64 `gorm:"type:numeric(20,8)" json:"output_price"` // 快照
|
||||
CacheReadPrice float64 `gorm:"type:numeric(20,8)" json:"cache_read_price"` // 快照
|
||||
Cost float64 `gorm:"type:numeric(20,8)" json:"cost"`
|
||||
LatencyMS int `json:"latency_ms"`
|
||||
Status string `gorm:"size:16;not null" json:"status"`
|
||||
ErrorCode *string `json:"error_code,omitempty"`
|
||||
RawRequest string `gorm:"type:text" json:"raw_request"` // 客户端原始请求体(未转换)
|
||||
RawResponse string `gorm:"type:text" json:"raw_response"` // 上游原始响应(未转换;流式为全部 SSE 事件)
|
||||
// CreatedAt 同时参与 user/channel 两个复合索引(时间窗过滤),自身单列索引保留给全表时间扫
|
||||
CreatedAt time.Time `gorm:"index;index:idx_user_created,priority:2;index:idx_channel_created,priority:2" json:"created_at"`
|
||||
CreatedAt time.Time `gorm:"index;index:idx_user_created,priority:2;index:idx_channel_created,priority:2" json:"created_at"`
|
||||
}
|
||||
|
||||
// UsageDaily 日粒度预聚合(PLANNING §6.6)
|
||||
|
||||
@@ -37,9 +37,9 @@ func TestChannelUpstreamURL(t *testing.T) {
|
||||
}
|
||||
cases2 := []struct{ proto, path, want string }{
|
||||
{"chat", "/chat/completions", "https://open.bigmodel.cn/api/paas/v4/chat/completions"}, // 用主 base
|
||||
{"responses", "/responses", "https://resp.example.com/v4/responses"}, // 用覆盖 base
|
||||
{"messages", "/messages", "https://msg.example.com/v1/messages"}, // 用覆盖 base
|
||||
{"", "/models", "https://open.bigmodel.cn/api/paas/v4/models"}, // 空协议用主 base
|
||||
{"responses", "/responses", "https://resp.example.com/v4/responses"}, // 用覆盖 base
|
||||
{"messages", "/messages", "https://msg.example.com/v1/messages"}, // 用覆盖 base
|
||||
{"", "/models", "https://open.bigmodel.cn/api/paas/v4/models"}, // 空协议用主 base
|
||||
}
|
||||
for _, c := range cases2 {
|
||||
got := ch.UpstreamURL(c.proto, c.path)
|
||||
|
||||
Reference in new issue
Block a user