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"`
|
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
|
||||||
// 是否启用模型路由配置
|
// 是否启用模型路由配置
|
||||||
ModelRoutingEnabled bool `json:"model_routing_enabled,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.
|
// Edges holds the relations/edges for other nodes in the graph.
|
||||||
// The values are being populated by the GroupQuery when eager-loading is set.
|
// The values are being populated by the GroupQuery when eager-loading is set.
|
||||||
Edges GroupEdges `json:"edges"`
|
Edges GroupEdges `json:"edges"`
|
||||||
@@ -170,7 +172,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
|
|||||||
switch columns[i] {
|
switch columns[i] {
|
||||||
case group.FieldModelRouting:
|
case group.FieldModelRouting:
|
||||||
values[i] = new([]byte)
|
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)
|
values[i] = new(sql.NullBool)
|
||||||
case group.FieldRateMultiplier, group.FieldDailyLimitUsd, group.FieldWeeklyLimitUsd, group.FieldMonthlyLimitUsd, group.FieldImagePrice1k, group.FieldImagePrice2k, group.FieldImagePrice4k:
|
case group.FieldRateMultiplier, group.FieldDailyLimitUsd, group.FieldWeeklyLimitUsd, group.FieldMonthlyLimitUsd, group.FieldImagePrice1k, group.FieldImagePrice2k, group.FieldImagePrice4k:
|
||||||
values[i] = new(sql.NullFloat64)
|
values[i] = new(sql.NullFloat64)
|
||||||
@@ -345,6 +347,12 @@ func (_m *Group) assignValues(columns []string, values []any) error {
|
|||||||
} else if value.Valid {
|
} else if value.Valid {
|
||||||
_m.ModelRoutingEnabled = value.Bool
|
_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:
|
default:
|
||||||
_m.selectValues.Set(columns[i], values[i])
|
_m.selectValues.Set(columns[i], values[i])
|
||||||
}
|
}
|
||||||
@@ -506,6 +514,9 @@ func (_m *Group) String() string {
|
|||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
builder.WriteString("model_routing_enabled=")
|
builder.WriteString("model_routing_enabled=")
|
||||||
builder.WriteString(fmt.Sprintf("%v", _m.ModelRoutingEnabled))
|
builder.WriteString(fmt.Sprintf("%v", _m.ModelRoutingEnabled))
|
||||||
|
builder.WriteString(", ")
|
||||||
|
builder.WriteString("mcp_xml_inject=")
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", _m.McpXMLInject))
|
||||||
builder.WriteByte(')')
|
builder.WriteByte(')')
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ const (
|
|||||||
FieldModelRouting = "model_routing"
|
FieldModelRouting = "model_routing"
|
||||||
// FieldModelRoutingEnabled holds the string denoting the model_routing_enabled field in the database.
|
// FieldModelRoutingEnabled holds the string denoting the model_routing_enabled field in the database.
|
||||||
FieldModelRoutingEnabled = "model_routing_enabled"
|
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 holds the string denoting the api_keys edge name in mutations.
|
||||||
EdgeAPIKeys = "api_keys"
|
EdgeAPIKeys = "api_keys"
|
||||||
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
|
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
|
||||||
@@ -156,6 +158,7 @@ var Columns = []string{
|
|||||||
FieldFallbackGroupIDOnInvalidRequest,
|
FieldFallbackGroupIDOnInvalidRequest,
|
||||||
FieldModelRouting,
|
FieldModelRouting,
|
||||||
FieldModelRoutingEnabled,
|
FieldModelRoutingEnabled,
|
||||||
|
FieldMcpXMLInject,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -215,6 +218,8 @@ var (
|
|||||||
DefaultClaudeCodeOnly bool
|
DefaultClaudeCodeOnly bool
|
||||||
// DefaultModelRoutingEnabled holds the default value on creation for the "model_routing_enabled" field.
|
// DefaultModelRoutingEnabled holds the default value on creation for the "model_routing_enabled" field.
|
||||||
DefaultModelRoutingEnabled bool
|
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.
|
// 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()
|
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.
|
// ByAPIKeysCount orders the results by api_keys count.
|
||||||
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
|
func ByAPIKeysCount(opts ...sql.OrderTermOption) OrderOption {
|
||||||
return func(s *sql.Selector) {
|
return func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -160,6 +160,11 @@ func ModelRoutingEnabled(v bool) predicate.Group {
|
|||||||
return predicate.Group(sql.FieldEQ(FieldModelRoutingEnabled, v))
|
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.
|
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||||
func CreatedAtEQ(v time.Time) predicate.Group {
|
func CreatedAtEQ(v time.Time) predicate.Group {
|
||||||
return predicate.Group(sql.FieldEQ(FieldCreatedAt, v))
|
return predicate.Group(sql.FieldEQ(FieldCreatedAt, v))
|
||||||
@@ -1145,6 +1150,16 @@ func ModelRoutingEnabledNEQ(v bool) predicate.Group {
|
|||||||
return predicate.Group(sql.FieldNEQ(FieldModelRoutingEnabled, v))
|
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.
|
// HasAPIKeys applies the HasEdge predicate on the "api_keys" edge.
|
||||||
func HasAPIKeys() predicate.Group {
|
func HasAPIKeys() predicate.Group {
|
||||||
return predicate.Group(func(s *sql.Selector) {
|
return predicate.Group(func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -320,6 +320,20 @@ func (_c *GroupCreate) SetNillableModelRoutingEnabled(v *bool) *GroupCreate {
|
|||||||
return _c
|
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.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
|
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
|
||||||
_c.mutation.AddAPIKeyIDs(ids...)
|
_c.mutation.AddAPIKeyIDs(ids...)
|
||||||
@@ -493,6 +507,10 @@ func (_c *GroupCreate) defaults() error {
|
|||||||
v := group.DefaultModelRoutingEnabled
|
v := group.DefaultModelRoutingEnabled
|
||||||
_c.mutation.SetModelRoutingEnabled(v)
|
_c.mutation.SetModelRoutingEnabled(v)
|
||||||
}
|
}
|
||||||
|
if _, ok := _c.mutation.McpXMLInject(); !ok {
|
||||||
|
v := group.DefaultMcpXMLInject
|
||||||
|
_c.mutation.SetMcpXMLInject(v)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,6 +569,9 @@ func (_c *GroupCreate) check() error {
|
|||||||
if _, ok := _c.mutation.ModelRoutingEnabled(); !ok {
|
if _, ok := _c.mutation.ModelRoutingEnabled(); !ok {
|
||||||
return &ValidationError{Name: "model_routing_enabled", err: errors.New(`ent: missing required field "Group.model_routing_enabled"`)}
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,6 +687,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
||||||
_node.ModelRoutingEnabled = 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 {
|
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.O2M,
|
Rel: sqlgraph.O2M,
|
||||||
@@ -1200,6 +1225,18 @@ func (u *GroupUpsert) UpdateModelRoutingEnabled() *GroupUpsert {
|
|||||||
return u
|
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.
|
// UpdateNewValues updates the mutable fields using the new values that were set on create.
|
||||||
// Using this option is equivalent to using:
|
// 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.
|
// Exec executes the query.
|
||||||
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
|
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
|
||||||
if len(u.create.conflict) == 0 {
|
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.
|
// Exec executes the query.
|
||||||
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
|
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
|
||||||
if u.create.err != nil {
|
if u.create.err != nil {
|
||||||
|
|||||||
@@ -448,6 +448,20 @@ func (_u *GroupUpdate) SetNillableModelRoutingEnabled(v *bool) *GroupUpdate {
|
|||||||
return _u
|
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.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
|
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
|
||||||
_u.mutation.AddAPIKeyIDs(ids...)
|
_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 {
|
if value, ok := _u.mutation.ModelRoutingEnabled(); ok {
|
||||||
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
_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() {
|
if _u.mutation.APIKeysCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.O2M,
|
Rel: sqlgraph.O2M,
|
||||||
@@ -1602,6 +1619,20 @@ func (_u *GroupUpdateOne) SetNillableModelRoutingEnabled(v *bool) *GroupUpdateOn
|
|||||||
return _u
|
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.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
|
||||||
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
|
||||||
_u.mutation.AddAPIKeyIDs(ids...)
|
_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 {
|
if value, ok := _u.mutation.ModelRoutingEnabled(); ok {
|
||||||
_spec.SetField(group.FieldModelRoutingEnabled, field.TypeBool, value)
|
_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() {
|
if _u.mutation.APIKeysCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.O2M,
|
Rel: sqlgraph.O2M,
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ var (
|
|||||||
{Name: "fallback_group_id_on_invalid_request", 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", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}},
|
||||||
{Name: "model_routing_enabled", Type: field.TypeBool, Default: false},
|
{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 holds the schema information for the "groups" table.
|
||||||
GroupsTable = &schema.Table{
|
GroupsTable = &schema.Table{
|
||||||
|
|||||||
@@ -3868,6 +3868,7 @@ type GroupMutation struct {
|
|||||||
addfallback_group_id_on_invalid_request *int64
|
addfallback_group_id_on_invalid_request *int64
|
||||||
model_routing *map[string][]int64
|
model_routing *map[string][]int64
|
||||||
model_routing_enabled *bool
|
model_routing_enabled *bool
|
||||||
|
mcp_xml_inject *bool
|
||||||
clearedFields map[string]struct{}
|
clearedFields map[string]struct{}
|
||||||
api_keys map[int64]struct{}
|
api_keys map[int64]struct{}
|
||||||
removedapi_keys map[int64]struct{}
|
removedapi_keys map[int64]struct{}
|
||||||
@@ -5133,6 +5134,42 @@ func (m *GroupMutation) ResetModelRoutingEnabled() {
|
|||||||
m.model_routing_enabled = nil
|
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.
|
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by ids.
|
||||||
func (m *GroupMutation) AddAPIKeyIDs(ids ...int64) {
|
func (m *GroupMutation) AddAPIKeyIDs(ids ...int64) {
|
||||||
if m.api_keys == nil {
|
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
|
// order to get all numeric fields that were incremented/decremented, call
|
||||||
// AddedFields().
|
// AddedFields().
|
||||||
func (m *GroupMutation) Fields() []string {
|
func (m *GroupMutation) Fields() []string {
|
||||||
fields := make([]string, 0, 22)
|
fields := make([]string, 0, 23)
|
||||||
if m.created_at != nil {
|
if m.created_at != nil {
|
||||||
fields = append(fields, group.FieldCreatedAt)
|
fields = append(fields, group.FieldCreatedAt)
|
||||||
}
|
}
|
||||||
@@ -5558,6 +5595,9 @@ func (m *GroupMutation) Fields() []string {
|
|||||||
if m.model_routing_enabled != nil {
|
if m.model_routing_enabled != nil {
|
||||||
fields = append(fields, group.FieldModelRoutingEnabled)
|
fields = append(fields, group.FieldModelRoutingEnabled)
|
||||||
}
|
}
|
||||||
|
if m.mcp_xml_inject != nil {
|
||||||
|
fields = append(fields, group.FieldMcpXMLInject)
|
||||||
|
}
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5610,6 +5650,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
|
|||||||
return m.ModelRouting()
|
return m.ModelRouting()
|
||||||
case group.FieldModelRoutingEnabled:
|
case group.FieldModelRoutingEnabled:
|
||||||
return m.ModelRoutingEnabled()
|
return m.ModelRoutingEnabled()
|
||||||
|
case group.FieldMcpXMLInject:
|
||||||
|
return m.McpXMLInject()
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@@ -5663,6 +5705,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
|
|||||||
return m.OldModelRouting(ctx)
|
return m.OldModelRouting(ctx)
|
||||||
case group.FieldModelRoutingEnabled:
|
case group.FieldModelRoutingEnabled:
|
||||||
return m.OldModelRoutingEnabled(ctx)
|
return m.OldModelRoutingEnabled(ctx)
|
||||||
|
case group.FieldMcpXMLInject:
|
||||||
|
return m.OldMcpXMLInject(ctx)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unknown Group field %s", name)
|
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)
|
m.SetModelRoutingEnabled(v)
|
||||||
return nil
|
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)
|
return fmt.Errorf("unknown Group field %s", name)
|
||||||
}
|
}
|
||||||
@@ -6133,6 +6184,9 @@ func (m *GroupMutation) ResetField(name string) error {
|
|||||||
case group.FieldModelRoutingEnabled:
|
case group.FieldModelRoutingEnabled:
|
||||||
m.ResetModelRoutingEnabled()
|
m.ResetModelRoutingEnabled()
|
||||||
return nil
|
return nil
|
||||||
|
case group.FieldMcpXMLInject:
|
||||||
|
m.ResetMcpXMLInject()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unknown Group field %s", name)
|
return fmt.Errorf("unknown Group field %s", name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,6 +284,10 @@ func init() {
|
|||||||
groupDescModelRoutingEnabled := groupFields[18].Descriptor()
|
groupDescModelRoutingEnabled := groupFields[18].Descriptor()
|
||||||
// group.DefaultModelRoutingEnabled holds the default value on creation for the model_routing_enabled field.
|
// group.DefaultModelRoutingEnabled holds the default value on creation for the model_routing_enabled field.
|
||||||
group.DefaultModelRoutingEnabled = groupDescModelRoutingEnabled.Default.(bool)
|
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 := schema.PromoCode{}.Fields()
|
||||||
_ = promocodeFields
|
_ = promocodeFields
|
||||||
// promocodeDescCode is the schema descriptor for code field.
|
// promocodeDescCode is the schema descriptor for code field.
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ func (Group) Fields() []ent.Field {
|
|||||||
field.Bool("model_routing_enabled").
|
field.Bool("model_routing_enabled").
|
||||||
Default(false).
|
Default(false).
|
||||||
Comment("是否启用模型路由配置"),
|
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 平台使用)
|
// 模型路由配置(仅 anthropic 平台使用)
|
||||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||||
|
MCPXMLInject *bool `json:"mcp_xml_inject"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateGroupRequest represents update group request
|
// UpdateGroupRequest represents update group request
|
||||||
@@ -68,6 +69,7 @@ type UpdateGroupRequest struct {
|
|||||||
// 模型路由配置(仅 anthropic 平台使用)
|
// 模型路由配置(仅 anthropic 平台使用)
|
||||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||||
ModelRoutingEnabled *bool `json:"model_routing_enabled"`
|
ModelRoutingEnabled *bool `json:"model_routing_enabled"`
|
||||||
|
MCPXMLInject *bool `json:"mcp_xml_inject"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List handles listing all groups with pagination
|
// List handles listing all groups with pagination
|
||||||
@@ -174,6 +176,7 @@ func (h *GroupHandler) Create(c *gin.Context) {
|
|||||||
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
||||||
ModelRouting: req.ModelRouting,
|
ModelRouting: req.ModelRouting,
|
||||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||||
|
MCPXMLInject: req.MCPXMLInject,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
@@ -217,6 +220,7 @@ func (h *GroupHandler) Update(c *gin.Context) {
|
|||||||
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: req.FallbackGroupIDOnInvalidRequest,
|
||||||
ModelRouting: req.ModelRouting,
|
ModelRouting: req.ModelRouting,
|
||||||
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
ModelRoutingEnabled: req.ModelRoutingEnabled,
|
||||||
|
MCPXMLInject: req.MCPXMLInject,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorFrom(c, err)
|
response.ErrorFrom(c, err)
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ func GroupFromServiceShallow(g *service.Group) *Group {
|
|||||||
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
||||||
ModelRouting: g.ModelRouting,
|
ModelRouting: g.ModelRouting,
|
||||||
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
||||||
|
MCPXMLInject: g.MCPXMLInject,
|
||||||
CreatedAt: g.CreatedAt,
|
CreatedAt: g.CreatedAt,
|
||||||
UpdatedAt: g.UpdatedAt,
|
UpdatedAt: g.UpdatedAt,
|
||||||
AccountCount: g.AccountCount,
|
AccountCount: g.AccountCount,
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ type Group struct {
|
|||||||
ModelRouting map[string][]int64 `json:"model_routing"`
|
ModelRouting map[string][]int64 `json:"model_routing"`
|
||||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||||
|
|
||||||
|
// MCP XML 协议注入(仅 antigravity 平台使用)
|
||||||
|
MCPXMLInject bool `json:"mcp_xml_inject"`
|
||||||
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,13 @@ type TransformOptions struct {
|
|||||||
// IdentityPatch 可选:自定义注入到 systemInstruction 开头的身份防护提示词;
|
// IdentityPatch 可选:自定义注入到 systemInstruction 开头的身份防护提示词;
|
||||||
// 为空时使用默认模板(包含 [IDENTITY_PATCH] 及 SYSTEM_PROMPT_BEGIN 标记)。
|
// 为空时使用默认模板(包含 [IDENTITY_PATCH] 及 SYSTEM_PROMPT_BEGIN 标记)。
|
||||||
IdentityPatch string
|
IdentityPatch string
|
||||||
|
EnableMCPXML bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultTransformOptions() TransformOptions {
|
func DefaultTransformOptions() TransformOptions {
|
||||||
return TransformOptions{
|
return TransformOptions{
|
||||||
EnableIdentityPatch: true,
|
EnableIdentityPatch: true,
|
||||||
|
EnableMCPXML: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,8 +259,8 @@ func buildSystemInstruction(system json.RawMessage, modelName string, opts Trans
|
|||||||
// 添加用户的 system prompt
|
// 添加用户的 system prompt
|
||||||
parts = append(parts, userSystemParts...)
|
parts = append(parts, userSystemParts...)
|
||||||
|
|
||||||
// 检测是否有 MCP 工具,如有则注入 XML 调用协议
|
// 检测是否有 MCP 工具,如有且启用了 MCP XML 注入则注入 XML 调用协议
|
||||||
if hasMCPTools(tools) {
|
if opts.EnableMCPXML && hasMCPTools(tools) {
|
||||||
parts = append(parts, GeminiPart{Text: mcpXMLProtocol})
|
parts = append(parts, GeminiPart{Text: mcpXMLProtocol})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,7 +493,7 @@ func parseToolResultContent(content json.RawMessage, isError bool) string {
|
|||||||
|
|
||||||
// buildGenerationConfig 构建 generationConfig
|
// buildGenerationConfig 构建 generationConfig
|
||||||
const (
|
const (
|
||||||
defaultMaxOutputTokens = 64000
|
defaultMaxOutputTokens = 64000
|
||||||
maxOutputTokensUpperBound = 65000
|
maxOutputTokensUpperBound = 65000
|
||||||
maxOutputTokensClaude = 64000
|
maxOutputTokensClaude = 64000
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ func (r *apiKeyRepository) GetByKeyForAuth(ctx context.Context, key string) (*se
|
|||||||
group.FieldFallbackGroupIDOnInvalidRequest,
|
group.FieldFallbackGroupIDOnInvalidRequest,
|
||||||
group.FieldModelRoutingEnabled,
|
group.FieldModelRoutingEnabled,
|
||||||
group.FieldModelRouting,
|
group.FieldModelRouting,
|
||||||
|
group.FieldMcpXMLInject,
|
||||||
)
|
)
|
||||||
}).
|
}).
|
||||||
Only(ctx)
|
Only(ctx)
|
||||||
@@ -428,6 +429,7 @@ func groupEntityToService(g *dbent.Group) *service.Group {
|
|||||||
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: g.FallbackGroupIDOnInvalidRequest,
|
||||||
ModelRouting: g.ModelRouting,
|
ModelRouting: g.ModelRouting,
|
||||||
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
ModelRoutingEnabled: g.ModelRoutingEnabled,
|
||||||
|
MCPXMLInject: g.McpXMLInject,
|
||||||
CreatedAt: g.CreatedAt,
|
CreatedAt: g.CreatedAt,
|
||||||
UpdatedAt: g.UpdatedAt,
|
UpdatedAt: g.UpdatedAt,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ func (r *groupRepository) Create(ctx context.Context, groupIn *service.Group) er
|
|||||||
SetClaudeCodeOnly(groupIn.ClaudeCodeOnly).
|
SetClaudeCodeOnly(groupIn.ClaudeCodeOnly).
|
||||||
SetNillableFallbackGroupID(groupIn.FallbackGroupID).
|
SetNillableFallbackGroupID(groupIn.FallbackGroupID).
|
||||||
SetNillableFallbackGroupIDOnInvalidRequest(groupIn.FallbackGroupIDOnInvalidRequest).
|
SetNillableFallbackGroupIDOnInvalidRequest(groupIn.FallbackGroupIDOnInvalidRequest).
|
||||||
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled)
|
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled).
|
||||||
|
SetMcpXMLInject(groupIn.MCPXMLInject)
|
||||||
|
|
||||||
// 设置模型路由配置
|
// 设置模型路由配置
|
||||||
if groupIn.ModelRouting != nil {
|
if groupIn.ModelRouting != nil {
|
||||||
@@ -109,7 +110,8 @@ func (r *groupRepository) Update(ctx context.Context, groupIn *service.Group) er
|
|||||||
SetNillableImagePrice4k(groupIn.ImagePrice4K).
|
SetNillableImagePrice4k(groupIn.ImagePrice4K).
|
||||||
SetDefaultValidityDays(groupIn.DefaultValidityDays).
|
SetDefaultValidityDays(groupIn.DefaultValidityDays).
|
||||||
SetClaudeCodeOnly(groupIn.ClaudeCodeOnly).
|
SetClaudeCodeOnly(groupIn.ClaudeCodeOnly).
|
||||||
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled)
|
SetModelRoutingEnabled(groupIn.ModelRoutingEnabled).
|
||||||
|
SetMcpXMLInject(groupIn.MCPXMLInject)
|
||||||
|
|
||||||
// 处理 FallbackGroupID:nil 时清除,否则设置
|
// 处理 FallbackGroupID:nil 时清除,否则设置
|
||||||
if groupIn.FallbackGroupID != nil {
|
if groupIn.FallbackGroupID != nil {
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ type CreateGroupInput struct {
|
|||||||
// 模型路由配置(仅 anthropic 平台使用)
|
// 模型路由配置(仅 anthropic 平台使用)
|
||||||
ModelRouting map[string][]int64
|
ModelRouting map[string][]int64
|
||||||
ModelRoutingEnabled bool // 是否启用模型路由
|
ModelRoutingEnabled bool // 是否启用模型路由
|
||||||
|
MCPXMLInject *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateGroupInput struct {
|
type UpdateGroupInput struct {
|
||||||
@@ -137,6 +138,7 @@ type UpdateGroupInput struct {
|
|||||||
// 模型路由配置(仅 anthropic 平台使用)
|
// 模型路由配置(仅 anthropic 平台使用)
|
||||||
ModelRouting map[string][]int64
|
ModelRouting map[string][]int64
|
||||||
ModelRoutingEnabled *bool // 是否启用模型路由
|
ModelRoutingEnabled *bool // 是否启用模型路由
|
||||||
|
MCPXMLInject *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateAccountInput struct {
|
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{
|
group := &Group{
|
||||||
Name: input.Name,
|
Name: input.Name,
|
||||||
Description: input.Description,
|
Description: input.Description,
|
||||||
@@ -605,6 +613,7 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn
|
|||||||
FallbackGroupID: input.FallbackGroupID,
|
FallbackGroupID: input.FallbackGroupID,
|
||||||
FallbackGroupIDOnInvalidRequest: fallbackOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: fallbackOnInvalidRequest,
|
||||||
ModelRouting: input.ModelRouting,
|
ModelRouting: input.ModelRouting,
|
||||||
|
MCPXMLInject: mcpXMLInject,
|
||||||
}
|
}
|
||||||
if err := s.groupRepo.Create(ctx, group); err != nil {
|
if err := s.groupRepo.Create(ctx, group); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -785,6 +794,9 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd
|
|||||||
if input.ModelRoutingEnabled != nil {
|
if input.ModelRoutingEnabled != nil {
|
||||||
group.ModelRoutingEnabled = *input.ModelRoutingEnabled
|
group.ModelRoutingEnabled = *input.ModelRoutingEnabled
|
||||||
}
|
}
|
||||||
|
if input.MCPXMLInject != nil {
|
||||||
|
group.MCPXMLInject = *input.MCPXMLInject
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.groupRepo.Update(ctx, group); err != nil {
|
if err := s.groupRepo.Update(ctx, group); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
|
||||||
|
"github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
@@ -552,6 +553,10 @@ func (s *AntigravityGatewayService) getClaudeTransformOptions(ctx context.Contex
|
|||||||
}
|
}
|
||||||
opts.EnableIdentityPatch = s.settingService.IsIdentityPatchEnabled(ctx)
|
opts.EnableIdentityPatch = s.settingService.IsIdentityPatchEnabled(ctx)
|
||||||
opts.IdentityPatch = s.settingService.GetIdentityPatchPrompt(ctx)
|
opts.IdentityPatch = s.settingService.GetIdentityPatchPrompt(ctx)
|
||||||
|
|
||||||
|
if group, ok := ctx.Value(ctxkey.Group).(*Group); ok && group != nil {
|
||||||
|
opts.EnableMCPXML = group.MCPXMLInject
|
||||||
|
}
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ type APIKeyAuthGroupSnapshot struct {
|
|||||||
// Only anthropic groups use these fields; others may leave them empty.
|
// Only anthropic groups use these fields; others may leave them empty.
|
||||||
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
|
ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
|
||||||
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
ModelRoutingEnabled bool `json:"model_routing_enabled"`
|
||||||
|
MCPXMLInject bool `json:"mcp_xml_inject"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIKeyAuthCacheEntry 缓存条目,支持负缓存
|
// APIKeyAuthCacheEntry 缓存条目,支持负缓存
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ func (s *APIKeyService) snapshotFromAPIKey(apiKey *APIKey) *APIKeyAuthSnapshot {
|
|||||||
FallbackGroupIDOnInvalidRequest: apiKey.Group.FallbackGroupIDOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: apiKey.Group.FallbackGroupIDOnInvalidRequest,
|
||||||
ModelRouting: apiKey.Group.ModelRouting,
|
ModelRouting: apiKey.Group.ModelRouting,
|
||||||
ModelRoutingEnabled: apiKey.Group.ModelRoutingEnabled,
|
ModelRoutingEnabled: apiKey.Group.ModelRoutingEnabled,
|
||||||
|
MCPXMLInject: apiKey.Group.MCPXMLInject,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return snapshot
|
return snapshot
|
||||||
@@ -269,6 +270,7 @@ func (s *APIKeyService) snapshotToAPIKey(key string, snapshot *APIKeyAuthSnapsho
|
|||||||
FallbackGroupIDOnInvalidRequest: snapshot.Group.FallbackGroupIDOnInvalidRequest,
|
FallbackGroupIDOnInvalidRequest: snapshot.Group.FallbackGroupIDOnInvalidRequest,
|
||||||
ModelRouting: snapshot.Group.ModelRouting,
|
ModelRouting: snapshot.Group.ModelRouting,
|
||||||
ModelRoutingEnabled: snapshot.Group.ModelRoutingEnabled,
|
ModelRoutingEnabled: snapshot.Group.ModelRoutingEnabled,
|
||||||
|
MCPXMLInject: snapshot.Group.MCPXMLInject,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return apiKey
|
return apiKey
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ type Group struct {
|
|||||||
ModelRouting map[string][]int64
|
ModelRouting map[string][]int64
|
||||||
ModelRoutingEnabled bool
|
ModelRoutingEnabled bool
|
||||||
|
|
||||||
|
// MCP XML 协议注入开关(仅 antigravity 平台使用)
|
||||||
|
MCPXMLInject bool
|
||||||
|
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt 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',
|
noRulesHint: 'Add routing rules to route specific model requests to designated accounts',
|
||||||
searchAccountPlaceholder: 'Search accounts...',
|
searchAccountPlaceholder: 'Search accounts...',
|
||||||
accountsHint: 'Select accounts to prioritize for this model pattern'
|
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: '添加路由规则以将特定模型请求优先路由到指定账号',
|
noRulesHint: '添加路由规则以将特定模型请求优先路由到指定账号',
|
||||||
searchAccountPlaceholder: '搜索账号...',
|
searchAccountPlaceholder: '搜索账号...',
|
||||||
accountsHint: '选择此模型模式优先使用的账号'
|
accountsHint: '选择此模型模式优先使用的账号'
|
||||||
|
},
|
||||||
|
mcpXml: {
|
||||||
|
title: 'MCP XML 协议注入',
|
||||||
|
tooltip: '启用后,当请求包含 MCP 工具时,会在 system prompt 中注入 XML 格式调用协议提示词。关闭此选项可避免对某些客户端造成干扰。',
|
||||||
|
enabled: '已启用',
|
||||||
|
disabled: '已禁用'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ export interface Group {
|
|||||||
// 模型路由配置(仅 anthropic 平台使用)
|
// 模型路由配置(仅 anthropic 平台使用)
|
||||||
model_routing: Record<string, number[]> | null
|
model_routing: Record<string, number[]> | null
|
||||||
model_routing_enabled: boolean
|
model_routing_enabled: boolean
|
||||||
|
// MCP XML 协议注入(仅 antigravity 平台使用)
|
||||||
|
mcp_xml_inject: boolean
|
||||||
account_count?: number
|
account_count?: number
|
||||||
created_at: string
|
created_at: string
|
||||||
updated_at: string
|
updated_at: string
|
||||||
|
|||||||
@@ -404,6 +404,51 @@
|
|||||||
</div>
|
</div>
|
||||||
</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 平台) -->
|
<!-- Claude Code 客户端限制(仅 anthropic 平台) -->
|
||||||
<div v-if="createForm.platform === 'anthropic'" class="border-t pt-4">
|
<div v-if="createForm.platform === 'anthropic'" class="border-t pt-4">
|
||||||
<div class="mb-1.5 flex items-center gap-1">
|
<div class="mb-1.5 flex items-center gap-1">
|
||||||
@@ -862,6 +907,51 @@
|
|||||||
</div>
|
</div>
|
||||||
</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 平台) -->
|
<!-- Claude Code 客户端限制(仅 anthropic 平台) -->
|
||||||
<div v-if="editForm.platform === 'anthropic'" class="border-t pt-4">
|
<div v-if="editForm.platform === 'anthropic'" class="border-t pt-4">
|
||||||
<div class="mb-1.5 flex items-center gap-1">
|
<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: null as number | null,
|
||||||
fallback_group_id_on_invalid_request: 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: null as number | null,
|
||||||
fallback_group_id_on_invalid_request: 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.claude_code_only = false
|
||||||
createForm.fallback_group_id = null
|
createForm.fallback_group_id = null
|
||||||
createForm.fallback_group_id_on_invalid_request = null
|
createForm.fallback_group_id_on_invalid_request = null
|
||||||
|
createForm.mcp_xml_inject = true
|
||||||
createModelRoutingRules.value = []
|
createModelRoutingRules.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1617,6 +1710,7 @@ const handleEdit = async (group: Group) => {
|
|||||||
editForm.fallback_group_id = group.fallback_group_id
|
editForm.fallback_group_id = group.fallback_group_id
|
||||||
editForm.fallback_group_id_on_invalid_request = group.fallback_group_id_on_invalid_request
|
editForm.fallback_group_id_on_invalid_request = group.fallback_group_id_on_invalid_request
|
||||||
editForm.model_routing_enabled = group.model_routing_enabled || false
|
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)
|
editModelRoutingRules.value = await convertApiFormatToRoutingRules(group.model_routing)
|
||||||
showEditModal.value = true
|
showEditModal.value = true
|
||||||
|
|||||||
Reference in New Issue
Block a user