mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-03 06:52:13 +08:00
feat(group): 添加 MCP XML 注入开关
- Group 新增 mcp_xml_inject 字段,控制 Antigravity 平台的 MCP XML 协议注入 - 默认启用,可在分组设置中关闭 - 修复 GetByKeyForAuth 遗漏查询 mcp_xml_inject 字段导致认证缓存值始终为 false 的问题
This commit is contained in:
@@ -62,6 +62,8 @@ type Group struct {
|
||||
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"`
|
||||
// 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"`
|
||||
@@ -170,7 +172,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
|
||||
switch columns[i] {
|
||||
case group.FieldModelRouting:
|
||||
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)
|
||||
@@ -345,6 +347,12 @@ 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
|
||||
}
|
||||
default:
|
||||
_m.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
@@ -506,6 +514,9 @@ func (_m *Group) String() string {
|
||||
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.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ const (
|
||||
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"
|
||||
// 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.
|
||||
@@ -156,6 +158,7 @@ var Columns = []string{
|
||||
FieldFallbackGroupIDOnInvalidRequest,
|
||||
FieldModelRouting,
|
||||
FieldModelRoutingEnabled,
|
||||
FieldMcpXMLInject,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -215,6 +218,8 @@ 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
|
||||
)
|
||||
|
||||
// OrderOption defines the ordering options for the Group queries.
|
||||
@@ -330,6 +335,11 @@ 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) {
|
||||
|
||||
@@ -160,6 +160,11 @@ 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))
|
||||
@@ -1145,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) {
|
||||
|
||||
@@ -320,6 +320,20 @@ 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
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
|
||||
_c.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -493,6 +507,10 @@ 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)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -551,6 +569,9 @@ 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"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -666,6 +687,10 @@ 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 nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -1200,6 +1225,18 @@ 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
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
@@ -1686,6 +1723,20 @@ 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()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
@@ -2338,6 +2389,20 @@ 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()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
|
||||
@@ -448,6 +448,20 @@ 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
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
|
||||
_u.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -874,6 +888,9 @@ 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 _u.mutation.APIKeysCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
@@ -1602,6 +1619,20 @@ 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
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
||||
_u.mutation.AddAPIKeyIDs(ids...)
|
||||
@@ -2058,6 +2089,9 @@ 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 _u.mutation.APIKeysCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.O2M,
|
||||
|
||||
@@ -229,6 +229,7 @@ var (
|
||||
{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},
|
||||
}
|
||||
// GroupsTable holds the schema information for the "groups" table.
|
||||
GroupsTable = &schema.Table{
|
||||
|
||||
@@ -3868,6 +3868,7 @@ type GroupMutation struct {
|
||||
addfallback_group_id_on_invalid_request *int64
|
||||
model_routing *map[string][]int64
|
||||
model_routing_enabled *bool
|
||||
mcp_xml_inject *bool
|
||||
clearedFields map[string]struct{}
|
||||
api_keys map[int64]struct{}
|
||||
removedapi_keys map[int64]struct{}
|
||||
@@ -5133,6 +5134,42 @@ func (m *GroupMutation) ResetModelRoutingEnabled() {
|
||||
m.model_routing_enabled = nil
|
||||
}
|
||||
|
||||
// SetMcpXMLInject sets the "mcp_xml_inject" field.
|
||||
func (m *GroupMutation) SetMcpXMLInject(b bool) {
|
||||
m.mcp_xml_inject = &b
|
||||
}
|
||||
|
||||
// McpXMLInject returns the value of the "mcp_xml_inject" field in the mutation.
|
||||
func (m *GroupMutation) McpXMLInject() (r bool, exists bool) {
|
||||
v := m.mcp_xml_inject
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldMcpXMLInject returns the old "mcp_xml_inject" field's value of the Group entity.
|
||||
// If the Group object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *GroupMutation) OldMcpXMLInject(ctx context.Context) (v bool, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldMcpXMLInject is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldMcpXMLInject requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldMcpXMLInject: %w", err)
|
||||
}
|
||||
return oldValue.McpXMLInject, nil
|
||||
}
|
||||
|
||||
// ResetMcpXMLInject resets all changes to the "mcp_xml_inject" field.
|
||||
func (m *GroupMutation) ResetMcpXMLInject() {
|
||||
m.mcp_xml_inject = nil
|
||||
}
|
||||
|
||||
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by ids.
|
||||
func (m *GroupMutation) AddAPIKeyIDs(ids ...int64) {
|
||||
if m.api_keys == nil {
|
||||
@@ -5491,7 +5528,7 @@ func (m *GroupMutation) Type() string {
|
||||
// order to get all numeric fields that were incremented/decremented, call
|
||||
// AddedFields().
|
||||
func (m *GroupMutation) Fields() []string {
|
||||
fields := make([]string, 0, 22)
|
||||
fields := make([]string, 0, 23)
|
||||
if m.created_at != nil {
|
||||
fields = append(fields, group.FieldCreatedAt)
|
||||
}
|
||||
@@ -5558,6 +5595,9 @@ func (m *GroupMutation) Fields() []string {
|
||||
if m.model_routing_enabled != nil {
|
||||
fields = append(fields, group.FieldModelRoutingEnabled)
|
||||
}
|
||||
if m.mcp_xml_inject != nil {
|
||||
fields = append(fields, group.FieldMcpXMLInject)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
@@ -5610,6 +5650,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
|
||||
return m.ModelRouting()
|
||||
case group.FieldModelRoutingEnabled:
|
||||
return m.ModelRoutingEnabled()
|
||||
case group.FieldMcpXMLInject:
|
||||
return m.McpXMLInject()
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
@@ -5663,6 +5705,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
|
||||
return m.OldModelRouting(ctx)
|
||||
case group.FieldModelRoutingEnabled:
|
||||
return m.OldModelRoutingEnabled(ctx)
|
||||
case group.FieldMcpXMLInject:
|
||||
return m.OldMcpXMLInject(ctx)
|
||||
}
|
||||
return nil, fmt.Errorf("unknown Group field %s", name)
|
||||
}
|
||||
@@ -5826,6 +5870,13 @@ func (m *GroupMutation) SetField(name string, value ent.Value) error {
|
||||
}
|
||||
m.SetModelRoutingEnabled(v)
|
||||
return nil
|
||||
case group.FieldMcpXMLInject:
|
||||
v, ok := value.(bool)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetMcpXMLInject(v)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Group field %s", name)
|
||||
}
|
||||
@@ -6133,6 +6184,9 @@ func (m *GroupMutation) ResetField(name string) error {
|
||||
case group.FieldModelRoutingEnabled:
|
||||
m.ResetModelRoutingEnabled()
|
||||
return nil
|
||||
case group.FieldMcpXMLInject:
|
||||
m.ResetMcpXMLInject()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Group field %s", name)
|
||||
}
|
||||
|
||||
@@ -284,6 +284,10 @@ func init() {
|
||||
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)
|
||||
promocodeFields := schema.PromoCode{}.Fields()
|
||||
_ = promocodeFields
|
||||
// promocodeDescCode is the schema descriptor for code field.
|
||||
|
||||
@@ -110,6 +110,11 @@ 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 平台)"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ type CreateGroupRequest struct {
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||
MCPXMLInject *bool `json:"mcp_xml_inject"`
|
||||
}
|
||||
|
||||
// UpdateGroupRequest represents update group request
|
||||
@@ -68,6 +69,7 @@ type UpdateGroupRequest struct {
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||
ModelRoutingEnabled *bool `json:"model_routing_enabled"`
|
||||
MCPXMLInject *bool `json:"mcp_xml_inject"`
|
||||
}
|
||||
|
||||
// List handles listing all groups with pagination
|
||||
@@ -174,6 +176,7 @@ func (h *GroupHandler) Create(c *gin.Context) {
|
||||
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: req.ModelRouting,
|
||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||
MCPXMLInject: req.MCPXMLInject,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
@@ -217,6 +220,7 @@ func (h *GroupHandler) Update(c *gin.Context) {
|
||||
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: req.ModelRouting,
|
||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||
MCPXMLInject: req.MCPXMLInject,
|
||||
})
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
|
||||
@@ -92,6 +92,7 @@ func GroupFromServiceShallow(g *service.Group) *Group {
|
||||
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: g.ModelRouting,
|
||||
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
||||
MCPXMLInject: g.MCPXMLInject,
|
||||
CreatedAt: g.CreatedAt,
|
||||
UpdatedAt: g.UpdatedAt,
|
||||
AccountCount: g.AccountCount,
|
||||
|
||||
@@ -69,6 +69,9 @@ type Group struct {
|
||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||
|
||||
// MCP XML 协议注入(仅 antigravity 平台使用)
|
||||
MCPXMLInject bool `json:"mcp_xml_inject"`
|
||||
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
|
||||
@@ -44,11 +44,13 @@ type TransformOptions struct {
|
||||
// IdentityPatch 可选:自定义注入到 systemInstruction 开头的身份防护提示词;
|
||||
// 为空时使用默认模板(包含 [IDENTITY_PATCH] 及 SYSTEM_PROMPT_BEGIN 标记)。
|
||||
IdentityPatch string
|
||||
EnableMCPXML bool
|
||||
}
|
||||
|
||||
func DefaultTransformOptions() TransformOptions {
|
||||
return TransformOptions{
|
||||
EnableIdentityPatch: true,
|
||||
EnableMCPXML: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +259,8 @@ func buildSystemInstruction(system json.RawMessage, modelName string, opts Trans
|
||||
// 添加用户的 system prompt
|
||||
parts = append(parts, userSystemParts...)
|
||||
|
||||
// 检测是否有 MCP 工具,如有则注入 XML 调用协议
|
||||
if hasMCPTools(tools) {
|
||||
// 检测是否有 MCP 工具,如有且启用了 MCP XML 注入则注入 XML 调用协议
|
||||
if opts.EnableMCPXML && hasMCPTools(tools) {
|
||||
parts = append(parts, GeminiPart{Text: mcpXMLProtocol})
|
||||
}
|
||||
|
||||
@@ -491,7 +493,7 @@ func parseToolResultContent(content json.RawMessage, isError bool) string {
|
||||
|
||||
// buildGenerationConfig 构建 generationConfig
|
||||
const (
|
||||
defaultMaxOutputTokens = 64000
|
||||
defaultMaxOutputTokens = 64000
|
||||
maxOutputTokensUpperBound = 65000
|
||||
maxOutputTokensClaude = 64000
|
||||
)
|
||||
|
||||
@@ -139,6 +139,7 @@ func (r *apiKeyRepository) GetByKeyForAuth(ctx context.Context, key string) (*se
|
||||
group.FieldFallbackGroupIDOnInvalidRequest,
|
||||
group.FieldModelRoutingEnabled,
|
||||
group.FieldModelRouting,
|
||||
group.FieldMcpXMLInject,
|
||||
)
|
||||
}).
|
||||
Only(ctx)
|
||||
@@ -428,6 +429,7 @@ func groupEntityToService(g *dbent.Group) *service.Group {
|
||||
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: g.ModelRouting,
|
||||
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
||||
MCPXMLInject: g.McpXMLInject,
|
||||
CreatedAt: g.CreatedAt,
|
||||
UpdatedAt: g.UpdatedAt,
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ func (r *groupRepository) Create(ctx context.Context, groupIn *service.Group) er
|
||||
SetClaudeCodeOnly(groupIn.ClaudeCodeOnly).
|
||||
SetNillableFallbackGroupID(groupIn.FallbackGroupID).
|
||||
SetNillableFallbackGroupIDOnInvalidRequest(groupIn.FallbackGroupIDOnInvalidRequest).
|
||||
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled)
|
||||
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled).
|
||||
SetMcpXMLInject(groupIn.MCPXMLInject)
|
||||
|
||||
// 设置模型路由配置
|
||||
if groupIn.ModelRouting != nil {
|
||||
@@ -109,7 +110,8 @@ func (r *groupRepository) Update(ctx context.Context, groupIn *service.Group) er
|
||||
SetNillableImagePrice4k(groupIn.ImagePrice4K).
|
||||
SetDefaultValidityDays(groupIn.DefaultValidityDays).
|
||||
SetClaudeCodeOnly(groupIn.ClaudeCodeOnly).
|
||||
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled)
|
||||
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled).
|
||||
SetMcpXMLInject(groupIn.MCPXMLInject)
|
||||
|
||||
// 处理 FallbackGroupID:nil 时清除,否则设置
|
||||
if groupIn.FallbackGroupID != nil {
|
||||
|
||||
@@ -113,6 +113,7 @@ type CreateGroupInput struct {
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
ModelRouting map[string][]int64
|
||||
ModelRoutingEnabled bool // 是否启用模型路由
|
||||
MCPXMLInject *bool
|
||||
}
|
||||
|
||||
type UpdateGroupInput struct {
|
||||
@@ -137,6 +138,7 @@ type UpdateGroupInput struct {
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
ModelRouting map[string][]int64
|
||||
ModelRoutingEnabled *bool // 是否启用模型路由
|
||||
MCPXMLInject *bool
|
||||
}
|
||||
|
||||
type CreateAccountInput struct {
|
||||
@@ -587,6 +589,12 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn
|
||||
}
|
||||
}
|
||||
|
||||
// MCPXMLInject:默认为 true,仅当显式传入 false 时关闭
|
||||
mcpXMLInject := true
|
||||
if input.MCPXMLInject != nil {
|
||||
mcpXMLInject = *input.MCPXMLInject
|
||||
}
|
||||
|
||||
group := &Group{
|
||||
Name: input.Name,
|
||||
Description: input.Description,
|
||||
@@ -605,6 +613,7 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn
|
||||
FallbackGroupID: input.FallbackGroupID,
|
||||
FallbackGroupIDOnInvalidRequest: fallbackOnInvalidRequest,
|
||||
ModelRouting: input.ModelRouting,
|
||||
MCPXMLInject: mcpXMLInject,
|
||||
}
|
||||
if err := s.groupRepo.Create(ctx, group); err != nil {
|
||||
return nil, err
|
||||
@@ -785,6 +794,9 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd
|
||||
if input.ModelRoutingEnabled != nil {
|
||||
group.ModelRoutingEnabled = *input.ModelRoutingEnabled
|
||||
}
|
||||
if input.MCPXMLInject != nil {
|
||||
group.MCPXMLInject = *input.MCPXMLInject
|
||||
}
|
||||
|
||||
if err := s.groupRepo.Update(ctx, group); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@@ -552,6 +553,10 @@ func (s *AntigravityGatewayService) getClaudeTransformOptions(ctx context.Contex
|
||||
}
|
||||
opts.EnableIdentityPatch = s.settingService.IsIdentityPatchEnabled(ctx)
|
||||
opts.IdentityPatch = s.settingService.GetIdentityPatchPrompt(ctx)
|
||||
|
||||
if group, ok := ctx.Value(ctxkey.Group).(*Group); ok && group != nil {
|
||||
opts.EnableMCPXML = group.MCPXMLInject
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ type APIKeyAuthGroupSnapshot struct {
|
||||
// Only anthropic groups use these fields; others may leave them empty.
|
||||
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
|
||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||
MCPXMLInject bool `json:"mcp_xml_inject"`
|
||||
}
|
||||
|
||||
// APIKeyAuthCacheEntry 缓存条目,支持负缓存
|
||||
|
||||
@@ -224,6 +224,7 @@ func (s *APIKeyService) snapshotFromAPIKey(apiKey *APIKey) *APIKeyAuthSnapshot {
|
||||
FallbackGroupIDOnInvalidRequest: apiKey.Group.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: apiKey.Group.ModelRouting,
|
||||
ModelRoutingEnabled: apiKey.Group.ModelRoutingEnabled,
|
||||
MCPXMLInject: apiKey.Group.MCPXMLInject,
|
||||
}
|
||||
}
|
||||
return snapshot
|
||||
@@ -269,6 +270,7 @@ func (s *APIKeyService) snapshotToAPIKey(key string, snapshot *APIKeyAuthSnapsho
|
||||
FallbackGroupIDOnInvalidRequest: snapshot.Group.FallbackGroupIDOnInvalidRequest,
|
||||
ModelRouting: snapshot.Group.ModelRouting,
|
||||
ModelRoutingEnabled: snapshot.Group.ModelRoutingEnabled,
|
||||
MCPXMLInject: snapshot.Group.MCPXMLInject,
|
||||
}
|
||||
}
|
||||
return apiKey
|
||||
|
||||
@@ -38,6 +38,9 @@ type Group struct {
|
||||
ModelRouting map[string][]int64
|
||||
ModelRoutingEnabled bool
|
||||
|
||||
// MCP XML 协议注入开关(仅 antigravity 平台使用)
|
||||
MCPXMLInject bool
|
||||
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
|
||||
|
||||
2
backend/migrations/044_add_group_mcp_xml_inject.sql
Normal file
2
backend/migrations/044_add_group_mcp_xml_inject.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- Add mcp_xml_inject field to groups table (for antigravity platform)
|
||||
ALTER TABLE groups ADD COLUMN mcp_xml_inject BOOLEAN NOT NULL DEFAULT true;
|
||||
@@ -943,6 +943,12 @@ export default {
|
||||
noRulesHint: 'Add routing rules to route specific model requests to designated accounts',
|
||||
searchAccountPlaceholder: 'Search accounts...',
|
||||
accountsHint: 'Select accounts to prioritize for this model pattern'
|
||||
},
|
||||
mcpXml: {
|
||||
title: 'MCP XML Protocol Injection',
|
||||
tooltip: 'When enabled, if the request contains MCP tools, an XML format call protocol prompt will be injected into the system prompt. Disable this to avoid interference with certain clients.',
|
||||
enabled: 'Enabled',
|
||||
disabled: 'Disabled'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1019,6 +1019,12 @@ export default {
|
||||
noRulesHint: '添加路由规则以将特定模型请求优先路由到指定账号',
|
||||
searchAccountPlaceholder: '搜索账号...',
|
||||
accountsHint: '选择此模型模式优先使用的账号'
|
||||
},
|
||||
mcpXml: {
|
||||
title: 'MCP XML 协议注入',
|
||||
tooltip: '启用后,当请求包含 MCP 工具时,会在 system prompt 中注入 XML 格式调用协议提示词。关闭此选项可避免对某些客户端造成干扰。',
|
||||
enabled: '已启用',
|
||||
disabled: '已禁用'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -273,6 +273,8 @@ export interface Group {
|
||||
// 模型路由配置(仅 anthropic 平台使用)
|
||||
model_routing: Record<string, number[]> | null
|
||||
model_routing_enabled: boolean
|
||||
// MCP XML 协议注入(仅 antigravity 平台使用)
|
||||
mcp_xml_inject: boolean
|
||||
account_count?: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
|
||||
@@ -404,6 +404,51 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MCP XML 协议注入(仅 antigravity 平台) -->
|
||||
<div v-if="createForm.platform === 'antigravity'" class="border-t pt-4">
|
||||
<div class="mb-1.5 flex items-center gap-1">
|
||||
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('admin.groups.mcpXml.title') }}
|
||||
</label>
|
||||
<div class="group relative inline-flex">
|
||||
<Icon
|
||||
name="questionCircle"
|
||||
size="sm"
|
||||
:stroke-width="2"
|
||||
class="cursor-help text-gray-400 transition-colors hover:text-primary-500 dark:text-gray-500 dark:hover:text-primary-400"
|
||||
/>
|
||||
<div class="pointer-events-none absolute bottom-full left-0 z-50 mb-2 w-72 opacity-0 transition-all duration-200 group-hover:pointer-events-auto group-hover:opacity-100">
|
||||
<div class="rounded-lg bg-gray-900 p-3 text-white shadow-lg dark:bg-gray-800">
|
||||
<p class="text-xs leading-relaxed text-gray-300">
|
||||
{{ t('admin.groups.mcpXml.tooltip') }}
|
||||
</p>
|
||||
<div class="absolute -bottom-1.5 left-3 h-3 w-3 rotate-45 bg-gray-900 dark:bg-gray-800"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button
|
||||
type="button"
|
||||
@click="createForm.mcp_xml_inject = !createForm.mcp_xml_inject"
|
||||
:class="[
|
||||
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
|
||||
createForm.mcp_xml_inject ? 'bg-primary-500' : 'bg-gray-300 dark:bg-dark-600'
|
||||
]"
|
||||
>
|
||||
<span
|
||||
:class="[
|
||||
'inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform',
|
||||
createForm.mcp_xml_inject ? 'translate-x-6' : 'translate-x-1'
|
||||
]"
|
||||
/>
|
||||
</button>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400">
|
||||
{{ createForm.mcp_xml_inject ? t('admin.groups.mcpXml.enabled') : t('admin.groups.mcpXml.disabled') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Claude Code 客户端限制(仅 anthropic 平台) -->
|
||||
<div v-if="createForm.platform === 'anthropic'" class="border-t pt-4">
|
||||
<div class="mb-1.5 flex items-center gap-1">
|
||||
@@ -862,6 +907,51 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MCP XML 协议注入(仅 antigravity 平台) -->
|
||||
<div v-if="editForm.platform === 'antigravity'" class="border-t pt-4">
|
||||
<div class="mb-1.5 flex items-center gap-1">
|
||||
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('admin.groups.mcpXml.title') }}
|
||||
</label>
|
||||
<div class="group relative inline-flex">
|
||||
<Icon
|
||||
name="questionCircle"
|
||||
size="sm"
|
||||
:stroke-width="2"
|
||||
class="cursor-help text-gray-400 transition-colors hover:text-primary-500 dark:text-gray-500 dark:hover:text-primary-400"
|
||||
/>
|
||||
<div class="pointer-events-none absolute bottom-full left-0 z-50 mb-2 w-72 opacity-0 transition-all duration-200 group-hover:pointer-events-auto group-hover:opacity-100">
|
||||
<div class="rounded-lg bg-gray-900 p-3 text-white shadow-lg dark:bg-gray-800">
|
||||
<p class="text-xs leading-relaxed text-gray-300">
|
||||
{{ t('admin.groups.mcpXml.tooltip') }}
|
||||
</p>
|
||||
<div class="absolute -bottom-1.5 left-3 h-3 w-3 rotate-45 bg-gray-900 dark:bg-gray-800"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button
|
||||
type="button"
|
||||
@click="editForm.mcp_xml_inject = !editForm.mcp_xml_inject"
|
||||
:class="[
|
||||
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
|
||||
editForm.mcp_xml_inject ? 'bg-primary-500' : 'bg-gray-300 dark:bg-dark-600'
|
||||
]"
|
||||
>
|
||||
<span
|
||||
:class="[
|
||||
'inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform',
|
||||
editForm.mcp_xml_inject ? 'translate-x-6' : 'translate-x-1'
|
||||
]"
|
||||
/>
|
||||
</button>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400">
|
||||
{{ editForm.mcp_xml_inject ? t('admin.groups.mcpXml.enabled') : t('admin.groups.mcpXml.disabled') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Claude Code 客户端限制(仅 anthropic 平台) -->
|
||||
<div v-if="editForm.platform === 'anthropic'" class="border-t pt-4">
|
||||
<div class="mb-1.5 flex items-center gap-1">
|
||||
@@ -1311,7 +1401,8 @@ const createForm = reactive({
|
||||
fallback_group_id: null as number | null,
|
||||
fallback_group_id_on_invalid_request: null as number | null,
|
||||
// 模型路由开关
|
||||
model_routing_enabled: false
|
||||
model_routing_enabled: false,
|
||||
mcp_xml_inject: true
|
||||
})
|
||||
|
||||
// 简单账号类型(用于模型路由选择)
|
||||
@@ -1483,7 +1574,8 @@ const editForm = reactive({
|
||||
fallback_group_id: null as number | null,
|
||||
fallback_group_id_on_invalid_request: null as number | null,
|
||||
// 模型路由开关
|
||||
model_routing_enabled: false
|
||||
model_routing_enabled: false,
|
||||
mcp_xml_inject: true
|
||||
})
|
||||
|
||||
// 根据分组类型返回不同的删除确认消息
|
||||
@@ -1566,6 +1658,7 @@ const closeCreateModal = () => {
|
||||
createForm.claude_code_only = false
|
||||
createForm.fallback_group_id = null
|
||||
createForm.fallback_group_id_on_invalid_request = null
|
||||
createForm.mcp_xml_inject = true
|
||||
createModelRoutingRules.value = []
|
||||
}
|
||||
|
||||
@@ -1617,6 +1710,7 @@ const handleEdit = async (group: Group) => {
|
||||
editForm.fallback_group_id = group.fallback_group_id
|
||||
editForm.fallback_group_id_on_invalid_request = group.fallback_group_id_on_invalid_request
|
||||
editForm.model_routing_enabled = group.model_routing_enabled || false
|
||||
editForm.mcp_xml_inject = group.mcp_xml_inject ?? true
|
||||
// 加载模型路由规则(异步加载账号名称)
|
||||
editModelRoutingRules.value = await convertApiFormatToRoutingRules(group.model_routing)
|
||||
showEditModal.value = true
|
||||
|
||||
Reference in New Issue
Block a user