Unverified Commit dd96ada3 authored by 程序猿MT's avatar 程序猿MT Committed by GitHub
Browse files

Merge branch 'Wei-Shaw:main' into main

parents 31fe0178 8f397548
FROM golang:1.25.5-alpine
FROM golang:1.25.6-alpine
WORKDIR /app
......@@ -15,7 +15,7 @@ RUN go mod download
COPY . .
# 构建应用
RUN go build -o main cmd/server/main.go
RUN go build -o main ./cmd/server/
# 暴露端口
EXPOSE 8080
......
......@@ -173,8 +173,8 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
userAttributeService := service.NewUserAttributeService(userAttributeDefinitionRepository, userAttributeValueRepository)
userAttributeHandler := admin.NewUserAttributeHandler(userAttributeService)
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, adminAnnouncementHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, promoHandler, settingHandler, opsHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler)
gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService, usageService, configConfig)
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, configConfig)
gatewayHandler := handler.NewGatewayHandler(gatewayService, geminiMessagesCompatService, antigravityGatewayService, userService, concurrencyService, billingCacheService, usageService, apiKeyService, configConfig)
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, apiKeyService, configConfig)
handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo)
totpHandler := handler.NewTotpHandler(totpService)
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, announcementHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler, totpHandler)
......
......@@ -40,6 +40,12 @@ type APIKey struct {
IPWhitelist []string `json:"ip_whitelist,omitempty"`
// Blocked IPs/CIDRs
IPBlacklist []string `json:"ip_blacklist,omitempty"`
// Quota limit in USD for this API key (0 = unlimited)
Quota float64 `json:"quota,omitempty"`
// Used quota amount in USD
QuotaUsed float64 `json:"quota_used,omitempty"`
// Expiration time for this API key (null = never expires)
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the APIKeyQuery when eager-loading is set.
Edges APIKeyEdges `json:"edges"`
......@@ -97,11 +103,13 @@ func (*APIKey) scanValues(columns []string) ([]any, error) {
switch columns[i] {
case apikey.FieldIPWhitelist, apikey.FieldIPBlacklist:
values[i] = new([]byte)
case apikey.FieldQuota, apikey.FieldQuotaUsed:
values[i] = new(sql.NullFloat64)
case apikey.FieldID, apikey.FieldUserID, apikey.FieldGroupID:
values[i] = new(sql.NullInt64)
case apikey.FieldKey, apikey.FieldName, apikey.FieldStatus:
values[i] = new(sql.NullString)
case apikey.FieldCreatedAt, apikey.FieldUpdatedAt, apikey.FieldDeletedAt:
case apikey.FieldCreatedAt, apikey.FieldUpdatedAt, apikey.FieldDeletedAt, apikey.FieldExpiresAt:
values[i] = new(sql.NullTime)
default:
values[i] = new(sql.UnknownType)
......@@ -190,6 +198,25 @@ func (_m *APIKey) assignValues(columns []string, values []any) error {
return fmt.Errorf("unmarshal field ip_blacklist: %w", err)
}
}
case apikey.FieldQuota:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field quota", values[i])
} else if value.Valid {
_m.Quota = value.Float64
}
case apikey.FieldQuotaUsed:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field quota_used", values[i])
} else if value.Valid {
_m.QuotaUsed = value.Float64
}
case apikey.FieldExpiresAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field expires_at", values[i])
} else if value.Valid {
_m.ExpiresAt = new(time.Time)
*_m.ExpiresAt = value.Time
}
default:
_m.selectValues.Set(columns[i], values[i])
}
......@@ -274,6 +301,17 @@ func (_m *APIKey) String() string {
builder.WriteString(", ")
builder.WriteString("ip_blacklist=")
builder.WriteString(fmt.Sprintf("%v", _m.IPBlacklist))
builder.WriteString(", ")
builder.WriteString("quota=")
builder.WriteString(fmt.Sprintf("%v", _m.Quota))
builder.WriteString(", ")
builder.WriteString("quota_used=")
builder.WriteString(fmt.Sprintf("%v", _m.QuotaUsed))
builder.WriteString(", ")
if v := _m.ExpiresAt; v != nil {
builder.WriteString("expires_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteByte(')')
return builder.String()
}
......
......@@ -35,6 +35,12 @@ const (
FieldIPWhitelist = "ip_whitelist"
// FieldIPBlacklist holds the string denoting the ip_blacklist field in the database.
FieldIPBlacklist = "ip_blacklist"
// FieldQuota holds the string denoting the quota field in the database.
FieldQuota = "quota"
// FieldQuotaUsed holds the string denoting the quota_used field in the database.
FieldQuotaUsed = "quota_used"
// FieldExpiresAt holds the string denoting the expires_at field in the database.
FieldExpiresAt = "expires_at"
// EdgeUser holds the string denoting the user edge name in mutations.
EdgeUser = "user"
// EdgeGroup holds the string denoting the group edge name in mutations.
......@@ -79,6 +85,9 @@ var Columns = []string{
FieldStatus,
FieldIPWhitelist,
FieldIPBlacklist,
FieldQuota,
FieldQuotaUsed,
FieldExpiresAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
......@@ -113,6 +122,10 @@ var (
DefaultStatus string
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
StatusValidator func(string) error
// DefaultQuota holds the default value on creation for the "quota" field.
DefaultQuota float64
// DefaultQuotaUsed holds the default value on creation for the "quota_used" field.
DefaultQuotaUsed float64
)
// OrderOption defines the ordering options for the APIKey queries.
......@@ -163,6 +176,21 @@ func ByStatus(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldStatus, opts...).ToFunc()
}
// ByQuota orders the results by the quota field.
func ByQuota(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldQuota, opts...).ToFunc()
}
// ByQuotaUsed orders the results by the quota_used field.
func ByQuotaUsed(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldQuotaUsed, opts...).ToFunc()
}
// ByExpiresAt orders the results by the expires_at field.
func ByExpiresAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldExpiresAt, opts...).ToFunc()
}
// ByUserField orders the results by user field.
func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
......
......@@ -95,6 +95,21 @@ func Status(v string) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldStatus, v))
}
// Quota applies equality check predicate on the "quota" field. It's identical to QuotaEQ.
func Quota(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldQuota, v))
}
// QuotaUsed applies equality check predicate on the "quota_used" field. It's identical to QuotaUsedEQ.
func QuotaUsed(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldQuotaUsed, v))
}
// ExpiresAt applies equality check predicate on the "expires_at" field. It's identical to ExpiresAtEQ.
func ExpiresAt(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldExpiresAt, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldCreatedAt, v))
......@@ -490,6 +505,136 @@ func IPBlacklistNotNil() predicate.APIKey {
return predicate.APIKey(sql.FieldNotNull(FieldIPBlacklist))
}
// QuotaEQ applies the EQ predicate on the "quota" field.
func QuotaEQ(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldQuota, v))
}
// QuotaNEQ applies the NEQ predicate on the "quota" field.
func QuotaNEQ(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldQuota, v))
}
// QuotaIn applies the In predicate on the "quota" field.
func QuotaIn(vs ...float64) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldQuota, vs...))
}
// QuotaNotIn applies the NotIn predicate on the "quota" field.
func QuotaNotIn(vs ...float64) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldQuota, vs...))
}
// QuotaGT applies the GT predicate on the "quota" field.
func QuotaGT(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldQuota, v))
}
// QuotaGTE applies the GTE predicate on the "quota" field.
func QuotaGTE(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldQuota, v))
}
// QuotaLT applies the LT predicate on the "quota" field.
func QuotaLT(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldQuota, v))
}
// QuotaLTE applies the LTE predicate on the "quota" field.
func QuotaLTE(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldQuota, v))
}
// QuotaUsedEQ applies the EQ predicate on the "quota_used" field.
func QuotaUsedEQ(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldQuotaUsed, v))
}
// QuotaUsedNEQ applies the NEQ predicate on the "quota_used" field.
func QuotaUsedNEQ(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldQuotaUsed, v))
}
// QuotaUsedIn applies the In predicate on the "quota_used" field.
func QuotaUsedIn(vs ...float64) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldQuotaUsed, vs...))
}
// QuotaUsedNotIn applies the NotIn predicate on the "quota_used" field.
func QuotaUsedNotIn(vs ...float64) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldQuotaUsed, vs...))
}
// QuotaUsedGT applies the GT predicate on the "quota_used" field.
func QuotaUsedGT(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldQuotaUsed, v))
}
// QuotaUsedGTE applies the GTE predicate on the "quota_used" field.
func QuotaUsedGTE(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldQuotaUsed, v))
}
// QuotaUsedLT applies the LT predicate on the "quota_used" field.
func QuotaUsedLT(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldQuotaUsed, v))
}
// QuotaUsedLTE applies the LTE predicate on the "quota_used" field.
func QuotaUsedLTE(v float64) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldQuotaUsed, v))
}
// ExpiresAtEQ applies the EQ predicate on the "expires_at" field.
func ExpiresAtEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldEQ(FieldExpiresAt, v))
}
// ExpiresAtNEQ applies the NEQ predicate on the "expires_at" field.
func ExpiresAtNEQ(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNEQ(FieldExpiresAt, v))
}
// ExpiresAtIn applies the In predicate on the "expires_at" field.
func ExpiresAtIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldIn(FieldExpiresAt, vs...))
}
// ExpiresAtNotIn applies the NotIn predicate on the "expires_at" field.
func ExpiresAtNotIn(vs ...time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldNotIn(FieldExpiresAt, vs...))
}
// ExpiresAtGT applies the GT predicate on the "expires_at" field.
func ExpiresAtGT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGT(FieldExpiresAt, v))
}
// ExpiresAtGTE applies the GTE predicate on the "expires_at" field.
func ExpiresAtGTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldGTE(FieldExpiresAt, v))
}
// ExpiresAtLT applies the LT predicate on the "expires_at" field.
func ExpiresAtLT(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLT(FieldExpiresAt, v))
}
// ExpiresAtLTE applies the LTE predicate on the "expires_at" field.
func ExpiresAtLTE(v time.Time) predicate.APIKey {
return predicate.APIKey(sql.FieldLTE(FieldExpiresAt, v))
}
// ExpiresAtIsNil applies the IsNil predicate on the "expires_at" field.
func ExpiresAtIsNil() predicate.APIKey {
return predicate.APIKey(sql.FieldIsNull(FieldExpiresAt))
}
// ExpiresAtNotNil applies the NotNil predicate on the "expires_at" field.
func ExpiresAtNotNil() predicate.APIKey {
return predicate.APIKey(sql.FieldNotNull(FieldExpiresAt))
}
// HasUser applies the HasEdge predicate on the "user" edge.
func HasUser() predicate.APIKey {
return predicate.APIKey(func(s *sql.Selector) {
......
......@@ -125,6 +125,48 @@ func (_c *APIKeyCreate) SetIPBlacklist(v []string) *APIKeyCreate {
return _c
}
// SetQuota sets the "quota" field.
func (_c *APIKeyCreate) SetQuota(v float64) *APIKeyCreate {
_c.mutation.SetQuota(v)
return _c
}
// SetNillableQuota sets the "quota" field if the given value is not nil.
func (_c *APIKeyCreate) SetNillableQuota(v *float64) *APIKeyCreate {
if v != nil {
_c.SetQuota(*v)
}
return _c
}
// SetQuotaUsed sets the "quota_used" field.
func (_c *APIKeyCreate) SetQuotaUsed(v float64) *APIKeyCreate {
_c.mutation.SetQuotaUsed(v)
return _c
}
// SetNillableQuotaUsed sets the "quota_used" field if the given value is not nil.
func (_c *APIKeyCreate) SetNillableQuotaUsed(v *float64) *APIKeyCreate {
if v != nil {
_c.SetQuotaUsed(*v)
}
return _c
}
// SetExpiresAt sets the "expires_at" field.
func (_c *APIKeyCreate) SetExpiresAt(v time.Time) *APIKeyCreate {
_c.mutation.SetExpiresAt(v)
return _c
}
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
func (_c *APIKeyCreate) SetNillableExpiresAt(v *time.Time) *APIKeyCreate {
if v != nil {
_c.SetExpiresAt(*v)
}
return _c
}
// SetUser sets the "user" edge to the User entity.
func (_c *APIKeyCreate) SetUser(v *User) *APIKeyCreate {
return _c.SetUserID(v.ID)
......@@ -205,6 +247,14 @@ func (_c *APIKeyCreate) defaults() error {
v := apikey.DefaultStatus
_c.mutation.SetStatus(v)
}
if _, ok := _c.mutation.Quota(); !ok {
v := apikey.DefaultQuota
_c.mutation.SetQuota(v)
}
if _, ok := _c.mutation.QuotaUsed(); !ok {
v := apikey.DefaultQuotaUsed
_c.mutation.SetQuotaUsed(v)
}
return nil
}
......@@ -243,6 +293,12 @@ func (_c *APIKeyCreate) check() error {
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "APIKey.status": %w`, err)}
}
}
if _, ok := _c.mutation.Quota(); !ok {
return &ValidationError{Name: "quota", err: errors.New(`ent: missing required field "APIKey.quota"`)}
}
if _, ok := _c.mutation.QuotaUsed(); !ok {
return &ValidationError{Name: "quota_used", err: errors.New(`ent: missing required field "APIKey.quota_used"`)}
}
if len(_c.mutation.UserIDs()) == 0 {
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "APIKey.user"`)}
}
......@@ -305,6 +361,18 @@ func (_c *APIKeyCreate) createSpec() (*APIKey, *sqlgraph.CreateSpec) {
_spec.SetField(apikey.FieldIPBlacklist, field.TypeJSON, value)
_node.IPBlacklist = value
}
if value, ok := _c.mutation.Quota(); ok {
_spec.SetField(apikey.FieldQuota, field.TypeFloat64, value)
_node.Quota = value
}
if value, ok := _c.mutation.QuotaUsed(); ok {
_spec.SetField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
_node.QuotaUsed = value
}
if value, ok := _c.mutation.ExpiresAt(); ok {
_spec.SetField(apikey.FieldExpiresAt, field.TypeTime, value)
_node.ExpiresAt = &value
}
if nodes := _c.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
......@@ -539,6 +607,60 @@ func (u *APIKeyUpsert) ClearIPBlacklist() *APIKeyUpsert {
return u
}
// SetQuota sets the "quota" field.
func (u *APIKeyUpsert) SetQuota(v float64) *APIKeyUpsert {
u.Set(apikey.FieldQuota, v)
return u
}
// UpdateQuota sets the "quota" field to the value that was provided on create.
func (u *APIKeyUpsert) UpdateQuota() *APIKeyUpsert {
u.SetExcluded(apikey.FieldQuota)
return u
}
// AddQuota adds v to the "quota" field.
func (u *APIKeyUpsert) AddQuota(v float64) *APIKeyUpsert {
u.Add(apikey.FieldQuota, v)
return u
}
// SetQuotaUsed sets the "quota_used" field.
func (u *APIKeyUpsert) SetQuotaUsed(v float64) *APIKeyUpsert {
u.Set(apikey.FieldQuotaUsed, v)
return u
}
// UpdateQuotaUsed sets the "quota_used" field to the value that was provided on create.
func (u *APIKeyUpsert) UpdateQuotaUsed() *APIKeyUpsert {
u.SetExcluded(apikey.FieldQuotaUsed)
return u
}
// AddQuotaUsed adds v to the "quota_used" field.
func (u *APIKeyUpsert) AddQuotaUsed(v float64) *APIKeyUpsert {
u.Add(apikey.FieldQuotaUsed, v)
return u
}
// SetExpiresAt sets the "expires_at" field.
func (u *APIKeyUpsert) SetExpiresAt(v time.Time) *APIKeyUpsert {
u.Set(apikey.FieldExpiresAt, v)
return u
}
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
func (u *APIKeyUpsert) UpdateExpiresAt() *APIKeyUpsert {
u.SetExcluded(apikey.FieldExpiresAt)
return u
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (u *APIKeyUpsert) ClearExpiresAt() *APIKeyUpsert {
u.SetNull(apikey.FieldExpiresAt)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
......@@ -738,6 +860,69 @@ func (u *APIKeyUpsertOne) ClearIPBlacklist() *APIKeyUpsertOne {
})
}
// SetQuota sets the "quota" field.
func (u *APIKeyUpsertOne) SetQuota(v float64) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetQuota(v)
})
}
// AddQuota adds v to the "quota" field.
func (u *APIKeyUpsertOne) AddQuota(v float64) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.AddQuota(v)
})
}
// UpdateQuota sets the "quota" field to the value that was provided on create.
func (u *APIKeyUpsertOne) UpdateQuota() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateQuota()
})
}
// SetQuotaUsed sets the "quota_used" field.
func (u *APIKeyUpsertOne) SetQuotaUsed(v float64) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetQuotaUsed(v)
})
}
// AddQuotaUsed adds v to the "quota_used" field.
func (u *APIKeyUpsertOne) AddQuotaUsed(v float64) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.AddQuotaUsed(v)
})
}
// UpdateQuotaUsed sets the "quota_used" field to the value that was provided on create.
func (u *APIKeyUpsertOne) UpdateQuotaUsed() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateQuotaUsed()
})
}
// SetExpiresAt sets the "expires_at" field.
func (u *APIKeyUpsertOne) SetExpiresAt(v time.Time) *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.SetExpiresAt(v)
})
}
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
func (u *APIKeyUpsertOne) UpdateExpiresAt() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateExpiresAt()
})
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (u *APIKeyUpsertOne) ClearExpiresAt() *APIKeyUpsertOne {
return u.Update(func(s *APIKeyUpsert) {
s.ClearExpiresAt()
})
}
// Exec executes the query.
func (u *APIKeyUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
......@@ -1103,6 +1288,69 @@ func (u *APIKeyUpsertBulk) ClearIPBlacklist() *APIKeyUpsertBulk {
})
}
// SetQuota sets the "quota" field.
func (u *APIKeyUpsertBulk) SetQuota(v float64) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetQuota(v)
})
}
// AddQuota adds v to the "quota" field.
func (u *APIKeyUpsertBulk) AddQuota(v float64) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.AddQuota(v)
})
}
// UpdateQuota sets the "quota" field to the value that was provided on create.
func (u *APIKeyUpsertBulk) UpdateQuota() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateQuota()
})
}
// SetQuotaUsed sets the "quota_used" field.
func (u *APIKeyUpsertBulk) SetQuotaUsed(v float64) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetQuotaUsed(v)
})
}
// AddQuotaUsed adds v to the "quota_used" field.
func (u *APIKeyUpsertBulk) AddQuotaUsed(v float64) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.AddQuotaUsed(v)
})
}
// UpdateQuotaUsed sets the "quota_used" field to the value that was provided on create.
func (u *APIKeyUpsertBulk) UpdateQuotaUsed() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateQuotaUsed()
})
}
// SetExpiresAt sets the "expires_at" field.
func (u *APIKeyUpsertBulk) SetExpiresAt(v time.Time) *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.SetExpiresAt(v)
})
}
// UpdateExpiresAt sets the "expires_at" field to the value that was provided on create.
func (u *APIKeyUpsertBulk) UpdateExpiresAt() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.UpdateExpiresAt()
})
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (u *APIKeyUpsertBulk) ClearExpiresAt() *APIKeyUpsertBulk {
return u.Update(func(s *APIKeyUpsert) {
s.ClearExpiresAt()
})
}
// Exec executes the query.
func (u *APIKeyUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil {
......
......@@ -170,6 +170,68 @@ func (_u *APIKeyUpdate) ClearIPBlacklist() *APIKeyUpdate {
return _u
}
// SetQuota sets the "quota" field.
func (_u *APIKeyUpdate) SetQuota(v float64) *APIKeyUpdate {
_u.mutation.ResetQuota()
_u.mutation.SetQuota(v)
return _u
}
// SetNillableQuota sets the "quota" field if the given value is not nil.
func (_u *APIKeyUpdate) SetNillableQuota(v *float64) *APIKeyUpdate {
if v != nil {
_u.SetQuota(*v)
}
return _u
}
// AddQuota adds value to the "quota" field.
func (_u *APIKeyUpdate) AddQuota(v float64) *APIKeyUpdate {
_u.mutation.AddQuota(v)
return _u
}
// SetQuotaUsed sets the "quota_used" field.
func (_u *APIKeyUpdate) SetQuotaUsed(v float64) *APIKeyUpdate {
_u.mutation.ResetQuotaUsed()
_u.mutation.SetQuotaUsed(v)
return _u
}
// SetNillableQuotaUsed sets the "quota_used" field if the given value is not nil.
func (_u *APIKeyUpdate) SetNillableQuotaUsed(v *float64) *APIKeyUpdate {
if v != nil {
_u.SetQuotaUsed(*v)
}
return _u
}
// AddQuotaUsed adds value to the "quota_used" field.
func (_u *APIKeyUpdate) AddQuotaUsed(v float64) *APIKeyUpdate {
_u.mutation.AddQuotaUsed(v)
return _u
}
// SetExpiresAt sets the "expires_at" field.
func (_u *APIKeyUpdate) SetExpiresAt(v time.Time) *APIKeyUpdate {
_u.mutation.SetExpiresAt(v)
return _u
}
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
func (_u *APIKeyUpdate) SetNillableExpiresAt(v *time.Time) *APIKeyUpdate {
if v != nil {
_u.SetExpiresAt(*v)
}
return _u
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (_u *APIKeyUpdate) ClearExpiresAt() *APIKeyUpdate {
_u.mutation.ClearExpiresAt()
return _u
}
// SetUser sets the "user" edge to the User entity.
func (_u *APIKeyUpdate) SetUser(v *User) *APIKeyUpdate {
return _u.SetUserID(v.ID)
......@@ -350,6 +412,24 @@ func (_u *APIKeyUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if _u.mutation.IPBlacklistCleared() {
_spec.ClearField(apikey.FieldIPBlacklist, field.TypeJSON)
}
if value, ok := _u.mutation.Quota(); ok {
_spec.SetField(apikey.FieldQuota, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedQuota(); ok {
_spec.AddField(apikey.FieldQuota, field.TypeFloat64, value)
}
if value, ok := _u.mutation.QuotaUsed(); ok {
_spec.SetField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedQuotaUsed(); ok {
_spec.AddField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
}
if value, ok := _u.mutation.ExpiresAt(); ok {
_spec.SetField(apikey.FieldExpiresAt, field.TypeTime, value)
}
if _u.mutation.ExpiresAtCleared() {
_spec.ClearField(apikey.FieldExpiresAt, field.TypeTime)
}
if _u.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
......@@ -611,6 +691,68 @@ func (_u *APIKeyUpdateOne) ClearIPBlacklist() *APIKeyUpdateOne {
return _u
}
// SetQuota sets the "quota" field.
func (_u *APIKeyUpdateOne) SetQuota(v float64) *APIKeyUpdateOne {
_u.mutation.ResetQuota()
_u.mutation.SetQuota(v)
return _u
}
// SetNillableQuota sets the "quota" field if the given value is not nil.
func (_u *APIKeyUpdateOne) SetNillableQuota(v *float64) *APIKeyUpdateOne {
if v != nil {
_u.SetQuota(*v)
}
return _u
}
// AddQuota adds value to the "quota" field.
func (_u *APIKeyUpdateOne) AddQuota(v float64) *APIKeyUpdateOne {
_u.mutation.AddQuota(v)
return _u
}
// SetQuotaUsed sets the "quota_used" field.
func (_u *APIKeyUpdateOne) SetQuotaUsed(v float64) *APIKeyUpdateOne {
_u.mutation.ResetQuotaUsed()
_u.mutation.SetQuotaUsed(v)
return _u
}
// SetNillableQuotaUsed sets the "quota_used" field if the given value is not nil.
func (_u *APIKeyUpdateOne) SetNillableQuotaUsed(v *float64) *APIKeyUpdateOne {
if v != nil {
_u.SetQuotaUsed(*v)
}
return _u
}
// AddQuotaUsed adds value to the "quota_used" field.
func (_u *APIKeyUpdateOne) AddQuotaUsed(v float64) *APIKeyUpdateOne {
_u.mutation.AddQuotaUsed(v)
return _u
}
// SetExpiresAt sets the "expires_at" field.
func (_u *APIKeyUpdateOne) SetExpiresAt(v time.Time) *APIKeyUpdateOne {
_u.mutation.SetExpiresAt(v)
return _u
}
// SetNillableExpiresAt sets the "expires_at" field if the given value is not nil.
func (_u *APIKeyUpdateOne) SetNillableExpiresAt(v *time.Time) *APIKeyUpdateOne {
if v != nil {
_u.SetExpiresAt(*v)
}
return _u
}
// ClearExpiresAt clears the value of the "expires_at" field.
func (_u *APIKeyUpdateOne) ClearExpiresAt() *APIKeyUpdateOne {
_u.mutation.ClearExpiresAt()
return _u
}
// SetUser sets the "user" edge to the User entity.
func (_u *APIKeyUpdateOne) SetUser(v *User) *APIKeyUpdateOne {
return _u.SetUserID(v.ID)
......@@ -821,6 +963,24 @@ func (_u *APIKeyUpdateOne) sqlSave(ctx context.Context) (_node *APIKey, err erro
if _u.mutation.IPBlacklistCleared() {
_spec.ClearField(apikey.FieldIPBlacklist, field.TypeJSON)
}
if value, ok := _u.mutation.Quota(); ok {
_spec.SetField(apikey.FieldQuota, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedQuota(); ok {
_spec.AddField(apikey.FieldQuota, field.TypeFloat64, value)
}
if value, ok := _u.mutation.QuotaUsed(); ok {
_spec.SetField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedQuotaUsed(); ok {
_spec.AddField(apikey.FieldQuotaUsed, field.TypeFloat64, value)
}
if value, ok := _u.mutation.ExpiresAt(); ok {
_spec.SetField(apikey.FieldExpiresAt, field.TypeTime, value)
}
if _u.mutation.ExpiresAtCleared() {
_spec.ClearField(apikey.FieldExpiresAt, field.TypeTime)
}
if _u.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
......
......@@ -56,10 +56,16 @@ type Group struct {
ClaudeCodeOnly bool `json:"claude_code_only,omitempty"`
// 非 Claude Code 请求降级使用的分组 ID
FallbackGroupID *int64 `json:"fallback_group_id,omitempty"`
// 无效请求兜底使用的分组 ID
FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request,omitempty"`
// 模型路由配置:模型模式 -> 优先账号ID列表
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
// 是否启用模型路由配置
ModelRoutingEnabled bool `json:"model_routing_enabled,omitempty"`
// 是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)
McpXMLInject bool `json:"mcp_xml_inject,omitempty"`
// 支持的模型系列:claude, gemini_text, gemini_image
SupportedModelScopes []string `json:"supported_model_scopes,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the GroupQuery when eager-loading is set.
Edges GroupEdges `json:"edges"`
......@@ -166,13 +172,13 @@ func (*Group) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case group.FieldModelRouting:
case group.FieldModelRouting, group.FieldSupportedModelScopes:
values[i] = new([]byte)
case group.FieldIsExclusive, group.FieldClaudeCodeOnly, group.FieldModelRoutingEnabled:
case group.FieldIsExclusive, group.FieldClaudeCodeOnly, group.FieldModelRoutingEnabled, group.FieldMcpXMLInject:
values[i] = new(sql.NullBool)
case group.FieldRateMultiplier, group.FieldDailyLimitUsd, group.FieldWeeklyLimitUsd, group.FieldMonthlyLimitUsd, group.FieldImagePrice1k, group.FieldImagePrice2k, group.FieldImagePrice4k:
values[i] = new(sql.NullFloat64)
case group.FieldID, group.FieldDefaultValidityDays, group.FieldFallbackGroupID:
case group.FieldID, group.FieldDefaultValidityDays, group.FieldFallbackGroupID, group.FieldFallbackGroupIDOnInvalidRequest:
values[i] = new(sql.NullInt64)
case group.FieldName, group.FieldDescription, group.FieldStatus, group.FieldPlatform, group.FieldSubscriptionType:
values[i] = new(sql.NullString)
......@@ -322,6 +328,13 @@ func (_m *Group) assignValues(columns []string, values []any) error {
_m.FallbackGroupID = new(int64)
*_m.FallbackGroupID = value.Int64
}
case group.FieldFallbackGroupIDOnInvalidRequest:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field fallback_group_id_on_invalid_request", values[i])
} else if value.Valid {
_m.FallbackGroupIDOnInvalidRequest = new(int64)
*_m.FallbackGroupIDOnInvalidRequest = value.Int64
}
case group.FieldModelRouting:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field model_routing", values[i])
......@@ -336,6 +349,20 @@ func (_m *Group) assignValues(columns []string, values []any) error {
} else if value.Valid {
_m.ModelRoutingEnabled = value.Bool
}
case group.FieldMcpXMLInject:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field mcp_xml_inject", values[i])
} else if value.Valid {
_m.McpXMLInject = value.Bool
}
case group.FieldSupportedModelScopes:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field supported_model_scopes", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &_m.SupportedModelScopes); err != nil {
return fmt.Errorf("unmarshal field supported_model_scopes: %w", err)
}
}
default:
_m.selectValues.Set(columns[i], values[i])
}
......@@ -487,11 +514,22 @@ func (_m *Group) String() string {
builder.WriteString(fmt.Sprintf("%v", *v))
}
builder.WriteString(", ")
if v := _m.FallbackGroupIDOnInvalidRequest; v != nil {
builder.WriteString("fallback_group_id_on_invalid_request=")
builder.WriteString(fmt.Sprintf("%v", *v))
}
builder.WriteString(", ")
builder.WriteString("model_routing=")
builder.WriteString(fmt.Sprintf("%v", _m.ModelRouting))
builder.WriteString(", ")
builder.WriteString("model_routing_enabled=")
builder.WriteString(fmt.Sprintf("%v", _m.ModelRoutingEnabled))
builder.WriteString(", ")
builder.WriteString("mcp_xml_inject=")
builder.WriteString(fmt.Sprintf("%v", _m.McpXMLInject))
builder.WriteString(", ")
builder.WriteString("supported_model_scopes=")
builder.WriteString(fmt.Sprintf("%v", _m.SupportedModelScopes))
builder.WriteByte(')')
return builder.String()
}
......
......@@ -53,10 +53,16 @@ const (
FieldClaudeCodeOnly = "claude_code_only"
// FieldFallbackGroupID holds the string denoting the fallback_group_id field in the database.
FieldFallbackGroupID = "fallback_group_id"
// FieldFallbackGroupIDOnInvalidRequest holds the string denoting the fallback_group_id_on_invalid_request field in the database.
FieldFallbackGroupIDOnInvalidRequest = "fallback_group_id_on_invalid_request"
// FieldModelRouting holds the string denoting the model_routing field in the database.
FieldModelRouting = "model_routing"
// FieldModelRoutingEnabled holds the string denoting the model_routing_enabled field in the database.
FieldModelRoutingEnabled = "model_routing_enabled"
// FieldMcpXMLInject holds the string denoting the mcp_xml_inject field in the database.
FieldMcpXMLInject = "mcp_xml_inject"
// FieldSupportedModelScopes holds the string denoting the supported_model_scopes field in the database.
FieldSupportedModelScopes = "supported_model_scopes"
// EdgeAPIKeys holds the string denoting the api_keys edge name in mutations.
EdgeAPIKeys = "api_keys"
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
......@@ -151,8 +157,11 @@ var Columns = []string{
FieldImagePrice4k,
FieldClaudeCodeOnly,
FieldFallbackGroupID,
FieldFallbackGroupIDOnInvalidRequest,
FieldModelRouting,
FieldModelRoutingEnabled,
FieldMcpXMLInject,
FieldSupportedModelScopes,
}
var (
......@@ -212,6 +221,10 @@ var (
DefaultClaudeCodeOnly bool
// DefaultModelRoutingEnabled holds the default value on creation for the "model_routing_enabled" field.
DefaultModelRoutingEnabled bool
// DefaultMcpXMLInject holds the default value on creation for the "mcp_xml_inject" field.
DefaultMcpXMLInject bool
// DefaultSupportedModelScopes holds the default value on creation for the "supported_model_scopes" field.
DefaultSupportedModelScopes []string
)
// OrderOption defines the ordering options for the Group queries.
......@@ -317,11 +330,21 @@ func ByFallbackGroupID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldFallbackGroupID, opts...).ToFunc()
}
// ByFallbackGroupIDOnInvalidRequest orders the results by the fallback_group_id_on_invalid_request field.
func ByFallbackGroupIDOnInvalidRequest(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldFallbackGroupIDOnInvalidRequest, opts...).ToFunc()
}
// ByModelRoutingEnabled orders the results by the model_routing_enabled field.
func ByModelRoutingEnabled(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldModelRoutingEnabled, opts...).ToFunc()
}
// ByMcpXMLInject orders the results by the mcp_xml_inject field.
func ByMcpXMLInject(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldMcpXMLInject, opts...).ToFunc()
}
// ByAPIKeysCount orders the results by api_keys count.
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
......
......@@ -150,11 +150,21 @@ func FallbackGroupID(v int64) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldFallbackGroupID, v))
}
// FallbackGroupIDOnInvalidRequest applies equality check predicate on the "fallback_group_id_on_invalid_request" field. It's identical to FallbackGroupIDOnInvalidRequestEQ.
func FallbackGroupIDOnInvalidRequest(v int64) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldFallbackGroupIDOnInvalidRequest, v))
}
// ModelRoutingEnabled applies equality check predicate on the "model_routing_enabled" field. It's identical to ModelRoutingEnabledEQ.
func ModelRoutingEnabled(v bool) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldModelRoutingEnabled, v))
}
// McpXMLInject applies equality check predicate on the "mcp_xml_inject" field. It's identical to McpXMLInjectEQ.
func McpXMLInject(v bool) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldMcpXMLInject, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldCreatedAt, v))
......@@ -1070,6 +1080,56 @@ func FallbackGroupIDNotNil() predicate.Group {
return predicate.Group(sql.FieldNotNull(FieldFallbackGroupID))
}
// FallbackGroupIDOnInvalidRequestEQ applies the EQ predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestEQ(v int64) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldFallbackGroupIDOnInvalidRequest, v))
}
// FallbackGroupIDOnInvalidRequestNEQ applies the NEQ predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestNEQ(v int64) predicate.Group {
return predicate.Group(sql.FieldNEQ(FieldFallbackGroupIDOnInvalidRequest, v))
}
// FallbackGroupIDOnInvalidRequestIn applies the In predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestIn(vs ...int64) predicate.Group {
return predicate.Group(sql.FieldIn(FieldFallbackGroupIDOnInvalidRequest, vs...))
}
// FallbackGroupIDOnInvalidRequestNotIn applies the NotIn predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestNotIn(vs ...int64) predicate.Group {
return predicate.Group(sql.FieldNotIn(FieldFallbackGroupIDOnInvalidRequest, vs...))
}
// FallbackGroupIDOnInvalidRequestGT applies the GT predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestGT(v int64) predicate.Group {
return predicate.Group(sql.FieldGT(FieldFallbackGroupIDOnInvalidRequest, v))
}
// FallbackGroupIDOnInvalidRequestGTE applies the GTE predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestGTE(v int64) predicate.Group {
return predicate.Group(sql.FieldGTE(FieldFallbackGroupIDOnInvalidRequest, v))
}
// FallbackGroupIDOnInvalidRequestLT applies the LT predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestLT(v int64) predicate.Group {
return predicate.Group(sql.FieldLT(FieldFallbackGroupIDOnInvalidRequest, v))
}
// FallbackGroupIDOnInvalidRequestLTE applies the LTE predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestLTE(v int64) predicate.Group {
return predicate.Group(sql.FieldLTE(FieldFallbackGroupIDOnInvalidRequest, v))
}
// FallbackGroupIDOnInvalidRequestIsNil applies the IsNil predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestIsNil() predicate.Group {
return predicate.Group(sql.FieldIsNull(FieldFallbackGroupIDOnInvalidRequest))
}
// FallbackGroupIDOnInvalidRequestNotNil applies the NotNil predicate on the "fallback_group_id_on_invalid_request" field.
func FallbackGroupIDOnInvalidRequestNotNil() predicate.Group {
return predicate.Group(sql.FieldNotNull(FieldFallbackGroupIDOnInvalidRequest))
}
// ModelRoutingIsNil applies the IsNil predicate on the "model_routing" field.
func ModelRoutingIsNil() predicate.Group {
return predicate.Group(sql.FieldIsNull(FieldModelRouting))
......@@ -1090,6 +1150,16 @@ func ModelRoutingEnabledNEQ(v bool) predicate.Group {
return predicate.Group(sql.FieldNEQ(FieldModelRoutingEnabled, v))
}
// McpXMLInjectEQ applies the EQ predicate on the "mcp_xml_inject" field.
func McpXMLInjectEQ(v bool) predicate.Group {
return predicate.Group(sql.FieldEQ(FieldMcpXMLInject, v))
}
// McpXMLInjectNEQ applies the NEQ predicate on the "mcp_xml_inject" field.
func McpXMLInjectNEQ(v bool) predicate.Group {
return predicate.Group(sql.FieldNEQ(FieldMcpXMLInject, v))
}
// HasAPIKeys applies the HasEdge predicate on the "api_keys" edge.
func HasAPIKeys() predicate.Group {
return predicate.Group(func(s *sql.Selector) {
......
......@@ -286,6 +286,20 @@ func (_c *GroupCreate) SetNillableFallbackGroupID(v *int64) *GroupCreate {
return _c
}
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
func (_c *GroupCreate) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupCreate {
_c.mutation.SetFallbackGroupIDOnInvalidRequest(v)
return _c
}
// SetNillableFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field if the given value is not nil.
func (_c *GroupCreate) SetNillableFallbackGroupIDOnInvalidRequest(v *int64) *GroupCreate {
if v != nil {
_c.SetFallbackGroupIDOnInvalidRequest(*v)
}
return _c
}
// SetModelRouting sets the "model_routing" field.
func (_c *GroupCreate) SetModelRouting(v map[string][]int64) *GroupCreate {
_c.mutation.SetModelRouting(v)
......@@ -306,6 +320,26 @@ func (_c *GroupCreate) SetNillableModelRoutingEnabled(v *bool) *GroupCreate {
return _c
}
// SetMcpXMLInject sets the "mcp_xml_inject" field.
func (_c *GroupCreate) SetMcpXMLInject(v bool) *GroupCreate {
_c.mutation.SetMcpXMLInject(v)
return _c
}
// SetNillableMcpXMLInject sets the "mcp_xml_inject" field if the given value is not nil.
func (_c *GroupCreate) SetNillableMcpXMLInject(v *bool) *GroupCreate {
if v != nil {
_c.SetMcpXMLInject(*v)
}
return _c
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (_c *GroupCreate) SetSupportedModelScopes(v []string) *GroupCreate {
_c.mutation.SetSupportedModelScopes(v)
return _c
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
_c.mutation.AddAPIKeyIDs(ids...)
......@@ -479,6 +513,14 @@ func (_c *GroupCreate) defaults() error {
v := group.DefaultModelRoutingEnabled
_c.mutation.SetModelRoutingEnabled(v)
}
if _, ok := _c.mutation.McpXMLInject(); !ok {
v := group.DefaultMcpXMLInject
_c.mutation.SetMcpXMLInject(v)
}
if _, ok := _c.mutation.SupportedModelScopes(); !ok {
v := group.DefaultSupportedModelScopes
_c.mutation.SetSupportedModelScopes(v)
}
return nil
}
......@@ -537,6 +579,12 @@ func (_c *GroupCreate) check() error {
if _, ok := _c.mutation.ModelRoutingEnabled(); !ok {
return &ValidationError{Name: "model_routing_enabled", err: errors.New(`ent: missing required field "Group.model_routing_enabled"`)}
}
if _, ok := _c.mutation.McpXMLInject(); !ok {
return &ValidationError{Name: "mcp_xml_inject", err: errors.New(`ent: missing required field "Group.mcp_xml_inject"`)}
}
if _, ok := _c.mutation.SupportedModelScopes(); !ok {
return &ValidationError{Name: "supported_model_scopes", err: errors.New(`ent: missing required field "Group.supported_model_scopes"`)}
}
return nil
}
......@@ -640,6 +688,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
_spec.SetField(group.FieldFallbackGroupID, field.TypeInt64, value)
_node.FallbackGroupID = &value
}
if value, ok := _c.mutation.FallbackGroupIDOnInvalidRequest(); ok {
_spec.SetField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
_node.FallbackGroupIDOnInvalidRequest = &value
}
if value, ok := _c.mutation.ModelRouting(); ok {
_spec.SetField(group.FieldModelRouting, field.TypeJSON, value)
_node.ModelRouting = value
......@@ -648,6 +700,14 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
_node.ModelRoutingEnabled = value
}
if value, ok := _c.mutation.McpXMLInject(); ok {
_spec.SetField(group.FieldMcpXMLInject, field.TypeBool, value)
_node.McpXMLInject = value
}
if value, ok := _c.mutation.SupportedModelScopes(); ok {
_spec.SetField(group.FieldSupportedModelScopes, field.TypeJSON, value)
_node.SupportedModelScopes = value
}
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
......@@ -1128,6 +1188,30 @@ func (u *GroupUpsert) ClearFallbackGroupID() *GroupUpsert {
return u
}
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsert) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsert {
u.Set(group.FieldFallbackGroupIDOnInvalidRequest, v)
return u
}
// UpdateFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field to the value that was provided on create.
func (u *GroupUpsert) UpdateFallbackGroupIDOnInvalidRequest() *GroupUpsert {
u.SetExcluded(group.FieldFallbackGroupIDOnInvalidRequest)
return u
}
// AddFallbackGroupIDOnInvalidRequest adds v to the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsert) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsert {
u.Add(group.FieldFallbackGroupIDOnInvalidRequest, v)
return u
}
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsert) ClearFallbackGroupIDOnInvalidRequest() *GroupUpsert {
u.SetNull(group.FieldFallbackGroupIDOnInvalidRequest)
return u
}
// SetModelRouting sets the "model_routing" field.
func (u *GroupUpsert) SetModelRouting(v map[string][]int64) *GroupUpsert {
u.Set(group.FieldModelRouting, v)
......@@ -1158,6 +1242,30 @@ func (u *GroupUpsert) UpdateModelRoutingEnabled() *GroupUpsert {
return u
}
// SetMcpXMLInject sets the "mcp_xml_inject" field.
func (u *GroupUpsert) SetMcpXMLInject(v bool) *GroupUpsert {
u.Set(group.FieldMcpXMLInject, v)
return u
}
// UpdateMcpXMLInject sets the "mcp_xml_inject" field to the value that was provided on create.
func (u *GroupUpsert) UpdateMcpXMLInject() *GroupUpsert {
u.SetExcluded(group.FieldMcpXMLInject)
return u
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (u *GroupUpsert) SetSupportedModelScopes(v []string) *GroupUpsert {
u.Set(group.FieldSupportedModelScopes, v)
return u
}
// UpdateSupportedModelScopes sets the "supported_model_scopes" field to the value that was provided on create.
func (u *GroupUpsert) UpdateSupportedModelScopes() *GroupUpsert {
u.SetExcluded(group.FieldSupportedModelScopes)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
......@@ -1581,6 +1689,34 @@ func (u *GroupUpsertOne) ClearFallbackGroupID() *GroupUpsertOne {
})
}
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsertOne) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.SetFallbackGroupIDOnInvalidRequest(v)
})
}
// AddFallbackGroupIDOnInvalidRequest adds v to the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsertOne) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.AddFallbackGroupIDOnInvalidRequest(v)
})
}
// UpdateFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field to the value that was provided on create.
func (u *GroupUpsertOne) UpdateFallbackGroupIDOnInvalidRequest() *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.UpdateFallbackGroupIDOnInvalidRequest()
})
}
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsertOne) ClearFallbackGroupIDOnInvalidRequest() *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.ClearFallbackGroupIDOnInvalidRequest()
})
}
// SetModelRouting sets the "model_routing" field.
func (u *GroupUpsertOne) SetModelRouting(v map[string][]int64) *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
......@@ -1616,6 +1752,34 @@ func (u *GroupUpsertOne) UpdateModelRoutingEnabled() *GroupUpsertOne {
})
}
// SetMcpXMLInject sets the "mcp_xml_inject" field.
func (u *GroupUpsertOne) SetMcpXMLInject(v bool) *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.SetMcpXMLInject(v)
})
}
// UpdateMcpXMLInject sets the "mcp_xml_inject" field to the value that was provided on create.
func (u *GroupUpsertOne) UpdateMcpXMLInject() *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.UpdateMcpXMLInject()
})
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (u *GroupUpsertOne) SetSupportedModelScopes(v []string) *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.SetSupportedModelScopes(v)
})
}
// UpdateSupportedModelScopes sets the "supported_model_scopes" field to the value that was provided on create.
func (u *GroupUpsertOne) UpdateSupportedModelScopes() *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.UpdateSupportedModelScopes()
})
}
// Exec executes the query.
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
......@@ -2205,6 +2369,34 @@ func (u *GroupUpsertBulk) ClearFallbackGroupID() *GroupUpsertBulk {
})
}
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsertBulk) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.SetFallbackGroupIDOnInvalidRequest(v)
})
}
// AddFallbackGroupIDOnInvalidRequest adds v to the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsertBulk) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.AddFallbackGroupIDOnInvalidRequest(v)
})
}
// UpdateFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field to the value that was provided on create.
func (u *GroupUpsertBulk) UpdateFallbackGroupIDOnInvalidRequest() *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.UpdateFallbackGroupIDOnInvalidRequest()
})
}
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
func (u *GroupUpsertBulk) ClearFallbackGroupIDOnInvalidRequest() *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.ClearFallbackGroupIDOnInvalidRequest()
})
}
// SetModelRouting sets the "model_routing" field.
func (u *GroupUpsertBulk) SetModelRouting(v map[string][]int64) *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
......@@ -2240,6 +2432,34 @@ func (u *GroupUpsertBulk) UpdateModelRoutingEnabled() *GroupUpsertBulk {
})
}
// SetMcpXMLInject sets the "mcp_xml_inject" field.
func (u *GroupUpsertBulk) SetMcpXMLInject(v bool) *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.SetMcpXMLInject(v)
})
}
// UpdateMcpXMLInject sets the "mcp_xml_inject" field to the value that was provided on create.
func (u *GroupUpsertBulk) UpdateMcpXMLInject() *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.UpdateMcpXMLInject()
})
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (u *GroupUpsertBulk) SetSupportedModelScopes(v []string) *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.SetSupportedModelScopes(v)
})
}
// UpdateSupportedModelScopes sets the "supported_model_scopes" field to the value that was provided on create.
func (u *GroupUpsertBulk) UpdateSupportedModelScopes() *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.UpdateSupportedModelScopes()
})
}
// Exec executes the query.
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil {
......
......@@ -10,6 +10,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/dialect/sql/sqljson"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/account"
"github.com/Wei-Shaw/sub2api/ent/apikey"
......@@ -395,6 +396,33 @@ func (_u *GroupUpdate) ClearFallbackGroupID() *GroupUpdate {
return _u
}
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
func (_u *GroupUpdate) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdate {
_u.mutation.ResetFallbackGroupIDOnInvalidRequest()
_u.mutation.SetFallbackGroupIDOnInvalidRequest(v)
return _u
}
// SetNillableFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field if the given value is not nil.
func (_u *GroupUpdate) SetNillableFallbackGroupIDOnInvalidRequest(v *int64) *GroupUpdate {
if v != nil {
_u.SetFallbackGroupIDOnInvalidRequest(*v)
}
return _u
}
// AddFallbackGroupIDOnInvalidRequest adds value to the "fallback_group_id_on_invalid_request" field.
func (_u *GroupUpdate) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdate {
_u.mutation.AddFallbackGroupIDOnInvalidRequest(v)
return _u
}
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
func (_u *GroupUpdate) ClearFallbackGroupIDOnInvalidRequest() *GroupUpdate {
_u.mutation.ClearFallbackGroupIDOnInvalidRequest()
return _u
}
// SetModelRouting sets the "model_routing" field.
func (_u *GroupUpdate) SetModelRouting(v map[string][]int64) *GroupUpdate {
_u.mutation.SetModelRouting(v)
......@@ -421,6 +449,32 @@ func (_u *GroupUpdate) SetNillableModelRoutingEnabled(v *bool) *GroupUpdate {
return _u
}
// SetMcpXMLInject sets the "mcp_xml_inject" field.
func (_u *GroupUpdate) SetMcpXMLInject(v bool) *GroupUpdate {
_u.mutation.SetMcpXMLInject(v)
return _u
}
// SetNillableMcpXMLInject sets the "mcp_xml_inject" field if the given value is not nil.
func (_u *GroupUpdate) SetNillableMcpXMLInject(v *bool) *GroupUpdate {
if v != nil {
_u.SetMcpXMLInject(*v)
}
return _u
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (_u *GroupUpdate) SetSupportedModelScopes(v []string) *GroupUpdate {
_u.mutation.SetSupportedModelScopes(v)
return _u
}
// AppendSupportedModelScopes appends value to the "supported_model_scopes" field.
func (_u *GroupUpdate) AppendSupportedModelScopes(v []string) *GroupUpdate {
_u.mutation.AppendSupportedModelScopes(v)
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
_u.mutation.AddAPIKeyIDs(ids...)
......@@ -829,6 +883,15 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if _u.mutation.FallbackGroupIDCleared() {
_spec.ClearField(group.FieldFallbackGroupID, field.TypeInt64)
}
if value, ok := _u.mutation.FallbackGroupIDOnInvalidRequest(); ok {
_spec.SetField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
}
if value, ok := _u.mutation.AddedFallbackGroupIDOnInvalidRequest(); ok {
_spec.AddField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
}
if _u.mutation.FallbackGroupIDOnInvalidRequestCleared() {
_spec.ClearField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64)
}
if value, ok := _u.mutation.ModelRouting(); ok {
_spec.SetField(group.FieldModelRouting, field.TypeJSON, value)
}
......@@ -838,6 +901,17 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if value, ok := _u.mutation.ModelRoutingEnabled(); ok {
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
}
if value, ok := _u.mutation.McpXMLInject(); ok {
_spec.SetField(group.FieldMcpXMLInject, field.TypeBool, value)
}
if value, ok := _u.mutation.SupportedModelScopes(); ok {
_spec.SetField(group.FieldSupportedModelScopes, field.TypeJSON, value)
}
if value, ok := _u.mutation.AppendedSupportedModelScopes(); ok {
_spec.AddModifier(func(u *sql.UpdateBuilder) {
sqljson.Append(u, group.FieldSupportedModelScopes, value)
})
}
if _u.mutation.APIKeysCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
......@@ -1513,6 +1587,33 @@ func (_u *GroupUpdateOne) ClearFallbackGroupID() *GroupUpdateOne {
return _u
}
// SetFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field.
func (_u *GroupUpdateOne) SetFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdateOne {
_u.mutation.ResetFallbackGroupIDOnInvalidRequest()
_u.mutation.SetFallbackGroupIDOnInvalidRequest(v)
return _u
}
// SetNillableFallbackGroupIDOnInvalidRequest sets the "fallback_group_id_on_invalid_request" field if the given value is not nil.
func (_u *GroupUpdateOne) SetNillableFallbackGroupIDOnInvalidRequest(v *int64) *GroupUpdateOne {
if v != nil {
_u.SetFallbackGroupIDOnInvalidRequest(*v)
}
return _u
}
// AddFallbackGroupIDOnInvalidRequest adds value to the "fallback_group_id_on_invalid_request" field.
func (_u *GroupUpdateOne) AddFallbackGroupIDOnInvalidRequest(v int64) *GroupUpdateOne {
_u.mutation.AddFallbackGroupIDOnInvalidRequest(v)
return _u
}
// ClearFallbackGroupIDOnInvalidRequest clears the value of the "fallback_group_id_on_invalid_request" field.
func (_u *GroupUpdateOne) ClearFallbackGroupIDOnInvalidRequest() *GroupUpdateOne {
_u.mutation.ClearFallbackGroupIDOnInvalidRequest()
return _u
}
// SetModelRouting sets the "model_routing" field.
func (_u *GroupUpdateOne) SetModelRouting(v map[string][]int64) *GroupUpdateOne {
_u.mutation.SetModelRouting(v)
......@@ -1539,6 +1640,32 @@ func (_u *GroupUpdateOne) SetNillableModelRoutingEnabled(v *bool) *GroupUpdateOn
return _u
}
// SetMcpXMLInject sets the "mcp_xml_inject" field.
func (_u *GroupUpdateOne) SetMcpXMLInject(v bool) *GroupUpdateOne {
_u.mutation.SetMcpXMLInject(v)
return _u
}
// SetNillableMcpXMLInject sets the "mcp_xml_inject" field if the given value is not nil.
func (_u *GroupUpdateOne) SetNillableMcpXMLInject(v *bool) *GroupUpdateOne {
if v != nil {
_u.SetMcpXMLInject(*v)
}
return _u
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (_u *GroupUpdateOne) SetSupportedModelScopes(v []string) *GroupUpdateOne {
_u.mutation.SetSupportedModelScopes(v)
return _u
}
// AppendSupportedModelScopes appends value to the "supported_model_scopes" field.
func (_u *GroupUpdateOne) AppendSupportedModelScopes(v []string) *GroupUpdateOne {
_u.mutation.AppendSupportedModelScopes(v)
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
_u.mutation.AddAPIKeyIDs(ids...)
......@@ -1977,6 +2104,15 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
if _u.mutation.FallbackGroupIDCleared() {
_spec.ClearField(group.FieldFallbackGroupID, field.TypeInt64)
}
if value, ok := _u.mutation.FallbackGroupIDOnInvalidRequest(); ok {
_spec.SetField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
}
if value, ok := _u.mutation.AddedFallbackGroupIDOnInvalidRequest(); ok {
_spec.AddField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64, value)
}
if _u.mutation.FallbackGroupIDOnInvalidRequestCleared() {
_spec.ClearField(group.FieldFallbackGroupIDOnInvalidRequest, field.TypeInt64)
}
if value, ok := _u.mutation.ModelRouting(); ok {
_spec.SetField(group.FieldModelRouting, field.TypeJSON, value)
}
......@@ -1986,6 +2122,17 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
if value, ok := _u.mutation.ModelRoutingEnabled(); ok {
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
}
if value, ok := _u.mutation.McpXMLInject(); ok {
_spec.SetField(group.FieldMcpXMLInject, field.TypeBool, value)
}
if value, ok := _u.mutation.SupportedModelScopes(); ok {
_spec.SetField(group.FieldSupportedModelScopes, field.TypeJSON, value)
}
if value, ok := _u.mutation.AppendedSupportedModelScopes(); ok {
_spec.AddModifier(func(u *sql.UpdateBuilder) {
sqljson.Append(u, group.FieldSupportedModelScopes, value)
})
}
if _u.mutation.APIKeysCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
......
......@@ -20,6 +20,9 @@ var (
{Name: "status", Type: field.TypeString, Size: 20, Default: "active"},
{Name: "ip_whitelist", Type: field.TypeJSON, Nullable: true},
{Name: "ip_blacklist", Type: field.TypeJSON, Nullable: true},
{Name: "quota", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
{Name: "quota_used", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
{Name: "expires_at", Type: field.TypeTime, Nullable: true},
{Name: "group_id", Type: field.TypeInt64, Nullable: true},
{Name: "user_id", Type: field.TypeInt64},
}
......@@ -31,13 +34,13 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "api_keys_groups_api_keys",
Columns: []*schema.Column{APIKeysColumns[9]},
Columns: []*schema.Column{APIKeysColumns[12]},
RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "api_keys_users_api_keys",
Columns: []*schema.Column{APIKeysColumns[10]},
Columns: []*schema.Column{APIKeysColumns[13]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
......@@ -46,12 +49,12 @@ var (
{
Name: "apikey_user_id",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[10]},
Columns: []*schema.Column{APIKeysColumns[13]},
},
{
Name: "apikey_group_id",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[9]},
Columns: []*schema.Column{APIKeysColumns[12]},
},
{
Name: "apikey_status",
......@@ -63,6 +66,16 @@ var (
Unique: false,
Columns: []*schema.Column{APIKeysColumns[3]},
},
{
Name: "apikey_quota_quota_used",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[9], APIKeysColumns[10]},
},
{
Name: "apikey_expires_at",
Unique: false,
Columns: []*schema.Column{APIKeysColumns[11]},
},
},
}
// AccountsColumns holds the columns for the "accounts" table.
......@@ -318,8 +331,11 @@ var (
{Name: "image_price_4k", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,8)"}},
{Name: "claude_code_only", Type: field.TypeBool, Default: false},
{Name: "fallback_group_id", Type: field.TypeInt64, Nullable: true},
{Name: "fallback_group_id_on_invalid_request", Type: field.TypeInt64, Nullable: true},
{Name: "model_routing", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
{Name: "model_routing_enabled", Type: field.TypeBool, Default: false},
{Name: "mcp_xml_inject", Type: field.TypeBool, Default: true},
{Name: "supported_model_scopes", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
}
// GroupsTable holds the schema information for the "groups" table.
GroupsTable = &schema.Table{
......
This diff is collapsed.
......@@ -91,6 +91,14 @@ func init() {
apikey.DefaultStatus = apikeyDescStatus.Default.(string)
// apikey.StatusValidator is a validator for the "status" field. It is called by the builders before save.
apikey.StatusValidator = apikeyDescStatus.Validators[0].(func(string) error)
// apikeyDescQuota is the schema descriptor for quota field.
apikeyDescQuota := apikeyFields[7].Descriptor()
// apikey.DefaultQuota holds the default value on creation for the quota field.
apikey.DefaultQuota = apikeyDescQuota.Default.(float64)
// apikeyDescQuotaUsed is the schema descriptor for quota_used field.
apikeyDescQuotaUsed := apikeyFields[8].Descriptor()
// apikey.DefaultQuotaUsed holds the default value on creation for the quota_used field.
apikey.DefaultQuotaUsed = apikeyDescQuotaUsed.Default.(float64)
accountMixin := schema.Account{}.Mixin()
accountMixinHooks1 := accountMixin[1].Hooks()
account.Hooks[0] = accountMixinHooks1[0]
......@@ -334,9 +342,17 @@ func init() {
// group.DefaultClaudeCodeOnly holds the default value on creation for the claude_code_only field.
group.DefaultClaudeCodeOnly = groupDescClaudeCodeOnly.Default.(bool)
// groupDescModelRoutingEnabled is the schema descriptor for model_routing_enabled field.
groupDescModelRoutingEnabled := groupFields[17].Descriptor()
groupDescModelRoutingEnabled := groupFields[18].Descriptor()
// group.DefaultModelRoutingEnabled holds the default value on creation for the model_routing_enabled field.
group.DefaultModelRoutingEnabled = groupDescModelRoutingEnabled.Default.(bool)
// groupDescMcpXMLInject is the schema descriptor for mcp_xml_inject field.
groupDescMcpXMLInject := groupFields[19].Descriptor()
// group.DefaultMcpXMLInject holds the default value on creation for the mcp_xml_inject field.
group.DefaultMcpXMLInject = groupDescMcpXMLInject.Default.(bool)
// groupDescSupportedModelScopes is the schema descriptor for supported_model_scopes field.
groupDescSupportedModelScopes := groupFields[20].Descriptor()
// group.DefaultSupportedModelScopes holds the default value on creation for the supported_model_scopes field.
group.DefaultSupportedModelScopes = groupDescSupportedModelScopes.Default.([]string)
promocodeFields := schema.PromoCode{}.Fields()
_ = promocodeFields
// promocodeDescCode is the schema descriptor for code field.
......
......@@ -5,6 +5,7 @@ import (
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
......@@ -52,6 +53,23 @@ func (APIKey) Fields() []ent.Field {
field.JSON("ip_blacklist", []string{}).
Optional().
Comment("Blocked IPs/CIDRs"),
// ========== Quota fields ==========
// Quota limit in USD (0 = unlimited)
field.Float("quota").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
Default(0).
Comment("Quota limit in USD for this API key (0 = unlimited)"),
// Used quota amount
field.Float("quota_used").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
Default(0).
Comment("Used quota amount in USD"),
// Expiration time (nil = never expires)
field.Time("expires_at").
Optional().
Nillable().
Comment("Expiration time for this API key (null = never expires)"),
}
}
......@@ -77,5 +95,8 @@ func (APIKey) Indexes() []ent.Index {
index.Fields("group_id"),
index.Fields("status"),
index.Fields("deleted_at"),
// Index for quota queries
index.Fields("quota", "quota_used"),
index.Fields("expires_at"),
}
}
......@@ -95,6 +95,10 @@ func (Group) Fields() []ent.Field {
Optional().
Nillable().
Comment("非 Claude Code 请求降级使用的分组 ID"),
field.Int64("fallback_group_id_on_invalid_request").
Optional().
Nillable().
Comment("无效请求兜底使用的分组 ID"),
// 模型路由配置 (added by migration 040)
field.JSON("model_routing", map[string][]int64{}).
......@@ -106,6 +110,17 @@ func (Group) Fields() []ent.Field {
field.Bool("model_routing_enabled").
Default(false).
Comment("是否启用模型路由配置"),
// MCP XML 协议注入开关 (added by migration 042)
field.Bool("mcp_xml_inject").
Default(true).
Comment("是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)"),
// 支持的模型系列 (added by migration 046)
field.JSON("supported_model_scopes", []string{}).
Default([]string{"claude", "gemini_text", "gemini_image"}).
SchemaType(map[string]string{dialect.Postgres: "jsonb"}).
Comment("支持的模型系列:claude, gemini_text, gemini_image"),
}
}
......
......@@ -4,6 +4,8 @@ go 1.25.6
require (
entgo.io/ent v0.14.5
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/dgraph-io/ristretto v0.2.0
github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/google/uuid v1.6.0
......@@ -11,7 +13,10 @@ require (
github.com/gorilla/websocket v1.5.3
github.com/imroc/req/v3 v3.57.0
github.com/lib/pq v1.10.9
github.com/pquerna/otp v1.5.0
github.com/redis/go-redis/v9 v9.17.2
github.com/refraction-networking/utls v1.8.1
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.25.6
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.11.1
......@@ -25,13 +30,13 @@ require (
golang.org/x/sync v0.19.0
golang.org/x/term v0.38.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.44.3
)
require (
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect
dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
......@@ -48,7 +53,6 @@ require (
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgraph-io/ristretto v0.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v28.5.1+incompatible // indirect
......@@ -107,13 +111,10 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/otp v1.5.0 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.57.1 // indirect
github.com/refraction-networking/utls v1.8.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
......@@ -149,12 +150,10 @@ require (
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/tools v0.39.0 // indirect
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
google.golang.org/grpc v1.75.1 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
modernc.org/libc v1.67.6 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.44.1 // indirect
)
......@@ -55,6 +55,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
......@@ -113,6 +115,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
......@@ -123,6 +127,9 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo=
......@@ -345,8 +352,6 @@ golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
......@@ -374,9 +379,8 @@ golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY=
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
......@@ -399,12 +403,32 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/sqlite v1.44.1 h1:qybx/rNpfQipX/t47OxbHmkkJuv2JWifCMH8SVUiDas=
modernc.org/sqlite v1.44.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.44.3 h1:+39JvV/HWMcYslAwRxHb8067w+2zowvFOUrOWIy9PjY=
modernc.org/sqlite v1.44.3/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
......@@ -29,6 +29,7 @@ const (
AccountTypeOAuth = "oauth" // OAuth类型账号(full scope: profile + inference)
AccountTypeSetupToken = "setup-token" // Setup Token类型账号(inference only scope)
AccountTypeAPIKey = "apikey" // API Key类型账号
AccountTypeUpstream = "upstream" // 上游透传类型账号(通过 Base URL + API Key 连接上游)
)
// Redeem type constants
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment