Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
3ecadf4a
Commit
3ecadf4a
authored
Feb 02, 2026
by
song
Browse files
chore: apply stashed changes
parent
0170d19f
Changes
33
Hide whitespace changes
Inline
Side-by-side
backend/ent/group.go
View file @
3ecadf4a
...
@@ -64,6 +64,8 @@ type Group struct {
...
@@ -64,6 +64,8 @@ type Group struct {
ModelRoutingEnabled
bool
`json:"model_routing_enabled,omitempty"`
ModelRoutingEnabled
bool
`json:"model_routing_enabled,omitempty"`
// 是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)
// 是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)
McpXMLInject
bool
`json:"mcp_xml_inject,omitempty"`
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.
// 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) {
...
@@ -170,7 +172,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
values
:=
make
([]
any
,
len
(
columns
))
values
:=
make
([]
any
,
len
(
columns
))
for
i
:=
range
columns
{
for
i
:=
range
columns
{
switch
columns
[
i
]
{
switch
columns
[
i
]
{
case
group
.
FieldModelRouting
:
case
group
.
FieldModelRouting
,
group
.
FieldSupportedModelScopes
:
values
[
i
]
=
new
([]
byte
)
values
[
i
]
=
new
([]
byte
)
case
group
.
FieldIsExclusive
,
group
.
FieldClaudeCodeOnly
,
group
.
FieldModelRoutingEnabled
,
group
.
FieldMcpXMLInject
:
case
group
.
FieldIsExclusive
,
group
.
FieldClaudeCodeOnly
,
group
.
FieldModelRoutingEnabled
,
group
.
FieldMcpXMLInject
:
values
[
i
]
=
new
(
sql
.
NullBool
)
values
[
i
]
=
new
(
sql
.
NullBool
)
...
@@ -353,6 +355,14 @@ func (_m *Group) assignValues(columns []string, values []any) error {
...
@@ -353,6 +355,14 @@ func (_m *Group) assignValues(columns []string, values []any) error {
}
else
if
value
.
Valid
{
}
else
if
value
.
Valid
{
_m
.
McpXMLInject
=
value
.
Bool
_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
:
default
:
_m
.
selectValues
.
Set
(
columns
[
i
],
values
[
i
])
_m
.
selectValues
.
Set
(
columns
[
i
],
values
[
i
])
}
}
...
@@ -517,6 +527,9 @@ func (_m *Group) String() string {
...
@@ -517,6 +527,9 @@ func (_m *Group) String() string {
builder
.
WriteString
(
", "
)
builder
.
WriteString
(
", "
)
builder
.
WriteString
(
"mcp_xml_inject="
)
builder
.
WriteString
(
"mcp_xml_inject="
)
builder
.
WriteString
(
fmt
.
Sprintf
(
"%v"
,
_m
.
McpXMLInject
))
builder
.
WriteString
(
fmt
.
Sprintf
(
"%v"
,
_m
.
McpXMLInject
))
builder
.
WriteString
(
", "
)
builder
.
WriteString
(
"supported_model_scopes="
)
builder
.
WriteString
(
fmt
.
Sprintf
(
"%v"
,
_m
.
SupportedModelScopes
))
builder
.
WriteByte
(
')'
)
builder
.
WriteByte
(
')'
)
return
builder
.
String
()
return
builder
.
String
()
}
}
...
...
backend/ent/group/group.go
View file @
3ecadf4a
...
@@ -61,6 +61,8 @@ const (
...
@@ -61,6 +61,8 @@ const (
FieldModelRoutingEnabled
=
"model_routing_enabled"
FieldModelRoutingEnabled
=
"model_routing_enabled"
// FieldMcpXMLInject holds the string denoting the mcp_xml_inject field in the database.
// FieldMcpXMLInject holds the string denoting the mcp_xml_inject field in the database.
FieldMcpXMLInject
=
"mcp_xml_inject"
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 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.
...
@@ -159,6 +161,7 @@ var Columns = []string{
...
@@ -159,6 +161,7 @@ var Columns = []string{
FieldModelRouting
,
FieldModelRouting
,
FieldModelRoutingEnabled
,
FieldModelRoutingEnabled
,
FieldMcpXMLInject
,
FieldMcpXMLInject
,
FieldSupportedModelScopes
,
}
}
var
(
var
(
...
@@ -220,6 +223,8 @@ var (
...
@@ -220,6 +223,8 @@ var (
DefaultModelRoutingEnabled
bool
DefaultModelRoutingEnabled
bool
// DefaultMcpXMLInject holds the default value on creation for the "mcp_xml_inject" field.
// DefaultMcpXMLInject holds the default value on creation for the "mcp_xml_inject" field.
DefaultMcpXMLInject
bool
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.
// OrderOption defines the ordering options for the Group queries.
...
...
backend/ent/group_create.go
View file @
3ecadf4a
...
@@ -334,6 +334,12 @@ func (_c *GroupCreate) SetNillableMcpXMLInject(v *bool) *GroupCreate {
...
@@ -334,6 +334,12 @@ func (_c *GroupCreate) SetNillableMcpXMLInject(v *bool) *GroupCreate {
return
_c
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.
// 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
...
)
...
@@ -511,6 +517,10 @@ func (_c *GroupCreate) defaults() error {
...
@@ -511,6 +517,10 @@ func (_c *GroupCreate) defaults() error {
v
:=
group
.
DefaultMcpXMLInject
v
:=
group
.
DefaultMcpXMLInject
_c
.
mutation
.
SetMcpXMLInject
(
v
)
_c
.
mutation
.
SetMcpXMLInject
(
v
)
}
}
if
_
,
ok
:=
_c
.
mutation
.
SupportedModelScopes
();
!
ok
{
v
:=
group
.
DefaultSupportedModelScopes
_c
.
mutation
.
SetSupportedModelScopes
(
v
)
}
return
nil
return
nil
}
}
...
@@ -572,6 +582,9 @@ func (_c *GroupCreate) check() error {
...
@@ -572,6 +582,9 @@ func (_c *GroupCreate) check() error {
if
_
,
ok
:=
_c
.
mutation
.
McpXMLInject
();
!
ok
{
if
_
,
ok
:=
_c
.
mutation
.
McpXMLInject
();
!
ok
{
return
&
ValidationError
{
Name
:
"mcp_xml_inject"
,
err
:
errors
.
New
(
`ent: missing required field "Group.mcp_xml_inject"`
)}
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
return
nil
}
}
...
@@ -691,6 +704,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
...
@@ -691,6 +704,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
_spec
.
SetField
(
group
.
FieldMcpXMLInject
,
field
.
TypeBool
,
value
)
_spec
.
SetField
(
group
.
FieldMcpXMLInject
,
field
.
TypeBool
,
value
)
_node
.
McpXMLInject
=
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
{
if
nodes
:=
_c
.
mutation
.
APIKeysIDs
();
len
(
nodes
)
>
0
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
Rel
:
sqlgraph
.
O2M
,
Rel
:
sqlgraph
.
O2M
,
...
@@ -1237,6 +1254,18 @@ func (u *GroupUpsert) UpdateMcpXMLInject() *GroupUpsert {
...
@@ -1237,6 +1254,18 @@ func (u *GroupUpsert) UpdateMcpXMLInject() *GroupUpsert {
return
u
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.
// 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:
//
//
...
@@ -1737,6 +1766,20 @@ func (u *GroupUpsertOne) UpdateMcpXMLInject() *GroupUpsertOne {
...
@@ -1737,6 +1766,20 @@ func (u *GroupUpsertOne) UpdateMcpXMLInject() *GroupUpsertOne {
})
})
}
}
// 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.
// 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
{
...
@@ -2403,6 +2446,20 @@ func (u *GroupUpsertBulk) UpdateMcpXMLInject() *GroupUpsertBulk {
...
@@ -2403,6 +2446,20 @@ func (u *GroupUpsertBulk) UpdateMcpXMLInject() *GroupUpsertBulk {
})
})
}
}
// 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.
// 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
{
...
...
backend/ent/group_update.go
View file @
3ecadf4a
...
@@ -10,6 +10,7 @@ import (
...
@@ -10,6 +10,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/dialect/sql/sqljson"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/account"
"github.com/Wei-Shaw/sub2api/ent/account"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/apikey"
...
@@ -462,6 +463,18 @@ func (_u *GroupUpdate) SetNillableMcpXMLInject(v *bool) *GroupUpdate {
...
@@ -462,6 +463,18 @@ func (_u *GroupUpdate) SetNillableMcpXMLInject(v *bool) *GroupUpdate {
return
_u
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.
// 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
...
)
...
@@ -891,6 +904,14 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
...
@@ -891,6 +904,14 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if
value
,
ok
:=
_u
.
mutation
.
McpXMLInject
();
ok
{
if
value
,
ok
:=
_u
.
mutation
.
McpXMLInject
();
ok
{
_spec
.
SetField
(
group
.
FieldMcpXMLInject
,
field
.
TypeBool
,
value
)
_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
()
{
if
_u
.
mutation
.
APIKeysCleared
()
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
Rel
:
sqlgraph
.
O2M
,
Rel
:
sqlgraph
.
O2M
,
...
@@ -1633,6 +1654,18 @@ func (_u *GroupUpdateOne) SetNillableMcpXMLInject(v *bool) *GroupUpdateOne {
...
@@ -1633,6 +1654,18 @@ func (_u *GroupUpdateOne) SetNillableMcpXMLInject(v *bool) *GroupUpdateOne {
return
_u
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.
// 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
...
)
...
@@ -2092,6 +2125,14 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
...
@@ -2092,6 +2125,14 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
if
value
,
ok
:=
_u
.
mutation
.
McpXMLInject
();
ok
{
if
value
,
ok
:=
_u
.
mutation
.
McpXMLInject
();
ok
{
_spec
.
SetField
(
group
.
FieldMcpXMLInject
,
field
.
TypeBool
,
value
)
_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
()
{
if
_u
.
mutation
.
APIKeysCleared
()
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
Rel
:
sqlgraph
.
O2M
,
Rel
:
sqlgraph
.
O2M
,
...
...
backend/ent/migrate/schema.go
View file @
3ecadf4a
...
@@ -322,6 +322,7 @@ var (
...
@@ -322,6 +322,7 @@ var (
{
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
},
{
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 holds the schema information for the "groups" table.
GroupsTable
=
&
schema
.
Table
{
GroupsTable
=
&
schema
.
Table
{
...
...
backend/ent/mutation.go
View file @
3ecadf4a
...
@@ -5542,6 +5542,8 @@ type GroupMutation struct {
...
@@ -5542,6 +5542,8 @@ type GroupMutation struct {
model_routing *map[string][]int64
model_routing *map[string][]int64
model_routing_enabled *bool
model_routing_enabled *bool
mcp_xml_inject *bool
mcp_xml_inject *bool
supported_model_scopes *[]string
appendsupported_model_scopes []string
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{}
...
@@ -6843,6 +6845,57 @@ func (m *GroupMutation) ResetMcpXMLInject() {
...
@@ -6843,6 +6845,57 @@ func (m *GroupMutation) ResetMcpXMLInject() {
m.mcp_xml_inject = nil
m.mcp_xml_inject = nil
}
}
// SetSupportedModelScopes sets the "supported_model_scopes" field.
func (m *GroupMutation) SetSupportedModelScopes(s []string) {
m.supported_model_scopes = &s
m.appendsupported_model_scopes = nil
}
// SupportedModelScopes returns the value of the "supported_model_scopes" field in the mutation.
func (m *GroupMutation) SupportedModelScopes() (r []string, exists bool) {
v := m.supported_model_scopes
if v == nil {
return
}
return *v, true
}
// OldSupportedModelScopes returns the old "supported_model_scopes" 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) OldSupportedModelScopes(ctx context.Context) (v []string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldSupportedModelScopes is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldSupportedModelScopes requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldSupportedModelScopes: %w", err)
}
return oldValue.SupportedModelScopes, nil
}
// AppendSupportedModelScopes adds s to the "supported_model_scopes" field.
func (m *GroupMutation) AppendSupportedModelScopes(s []string) {
m.appendsupported_model_scopes = append(m.appendsupported_model_scopes, s...)
}
// AppendedSupportedModelScopes returns the list of values that were appended to the "supported_model_scopes" field in this mutation.
func (m *GroupMutation) AppendedSupportedModelScopes() ([]string, bool) {
if len(m.appendsupported_model_scopes) == 0 {
return nil, false
}
return m.appendsupported_model_scopes, true
}
// ResetSupportedModelScopes resets all changes to the "supported_model_scopes" field.
func (m *GroupMutation) ResetSupportedModelScopes() {
m.supported_model_scopes = nil
m.appendsupported_model_scopes = 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 {
...
@@ -7201,7 +7254,7 @@ func (m *GroupMutation) Type() string {
...
@@ -7201,7 +7254,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, 2
3
)
fields := make([]string, 0, 2
4
)
if m.created_at != nil {
if m.created_at != nil {
fields = append(fields, group.FieldCreatedAt)
fields = append(fields, group.FieldCreatedAt)
}
}
...
@@ -7271,6 +7324,9 @@ func (m *GroupMutation) Fields() []string {
...
@@ -7271,6 +7324,9 @@ func (m *GroupMutation) Fields() []string {
if m.mcp_xml_inject != nil {
if m.mcp_xml_inject != nil {
fields = append(fields, group.FieldMcpXMLInject)
fields = append(fields, group.FieldMcpXMLInject)
}
}
if m.supported_model_scopes != nil {
fields = append(fields, group.FieldSupportedModelScopes)
}
return fields
return fields
}
}
...
@@ -7325,6 +7381,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
...
@@ -7325,6 +7381,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
return m.ModelRoutingEnabled()
return m.ModelRoutingEnabled()
case group.FieldMcpXMLInject:
case group.FieldMcpXMLInject:
return m.McpXMLInject()
return m.McpXMLInject()
case group.FieldSupportedModelScopes:
return m.SupportedModelScopes()
}
}
return nil, false
return nil, false
}
}
...
@@ -7380,6 +7438,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
...
@@ -7380,6 +7438,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
return m.OldModelRoutingEnabled(ctx)
return m.OldModelRoutingEnabled(ctx)
case group.FieldMcpXMLInject:
case group.FieldMcpXMLInject:
return m.OldMcpXMLInject(ctx)
return m.OldMcpXMLInject(ctx)
case group.FieldSupportedModelScopes:
return m.OldSupportedModelScopes(ctx)
}
}
return nil, fmt.Errorf("unknown Group field %s", name)
return nil, fmt.Errorf("unknown Group field %s", name)
}
}
...
@@ -7550,6 +7610,13 @@ func (m *GroupMutation) SetField(name string, value ent.Value) error {
...
@@ -7550,6 +7610,13 @@ func (m *GroupMutation) SetField(name string, value ent.Value) error {
}
}
m.SetMcpXMLInject(v)
m.SetMcpXMLInject(v)
return nil
return nil
case group.FieldSupportedModelScopes:
v, ok := value.([]string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetSupportedModelScopes(v)
return nil
}
}
return fmt.Errorf("unknown Group field %s", name)
return fmt.Errorf("unknown Group field %s", name)
}
}
...
@@ -7860,6 +7927,9 @@ func (m *GroupMutation) ResetField(name string) error {
...
@@ -7860,6 +7927,9 @@ func (m *GroupMutation) ResetField(name string) error {
case group.FieldMcpXMLInject:
case group.FieldMcpXMLInject:
m.ResetMcpXMLInject()
m.ResetMcpXMLInject()
return nil
return nil
case group.FieldSupportedModelScopes:
m.ResetSupportedModelScopes()
return nil
}
}
return fmt.Errorf("unknown Group field %s", name)
return fmt.Errorf("unknown Group field %s", name)
}
}
...
...
backend/ent/runtime/runtime.go
View file @
3ecadf4a
...
@@ -341,6 +341,10 @@ func init() {
...
@@ -341,6 +341,10 @@ func init() {
groupDescMcpXMLInject
:=
groupFields
[
19
]
.
Descriptor
()
groupDescMcpXMLInject
:=
groupFields
[
19
]
.
Descriptor
()
// group.DefaultMcpXMLInject holds the default value on creation for the mcp_xml_inject field.
// group.DefaultMcpXMLInject holds the default value on creation for the mcp_xml_inject field.
group
.
DefaultMcpXMLInject
=
groupDescMcpXMLInject
.
Default
.
(
bool
)
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
:=
schema
.
PromoCode
{}
.
Fields
()
_
=
promocodeFields
_
=
promocodeFields
// promocodeDescCode is the schema descriptor for code field.
// promocodeDescCode is the schema descriptor for code field.
...
...
backend/ent/schema/group.go
View file @
3ecadf4a
...
@@ -115,6 +115,12 @@ func (Group) Fields() []ent.Field {
...
@@ -115,6 +115,12 @@ func (Group) Fields() []ent.Field {
field
.
Bool
(
"mcp_xml_inject"
)
.
field
.
Bool
(
"mcp_xml_inject"
)
.
Default
(
true
)
.
Default
(
true
)
.
Comment
(
"是否注入 MCP XML 调用协议提示词(仅 antigravity 平台)"
),
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"
),
}
}
}
}
...
...
backend/go.mod
View file @
3ecadf4a
...
@@ -4,6 +4,8 @@ go 1.25.6
...
@@ -4,6 +4,8 @@ go 1.25.6
require (
require (
entgo.io/ent v0.14.5
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/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/google/uuid v1.6.0
github.com/google/uuid v1.6.0
...
@@ -11,7 +13,10 @@ require (
...
@@ -11,7 +13,10 @@ require (
github.com/gorilla/websocket v1.5.3
github.com/gorilla/websocket v1.5.3
github.com/imroc/req/v3 v3.57.0
github.com/imroc/req/v3 v3.57.0
github.com/lib/pq v1.10.9
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/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/shirou/gopsutil/v4 v4.25.6
github.com/spf13/viper v1.18.2
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.11.1
github.com/stretchr/testify v1.11.1
...
@@ -25,6 +30,7 @@ require (
...
@@ -25,6 +30,7 @@ require (
golang.org/x/sync v0.19.0
golang.org/x/sync v0.19.0
golang.org/x/term v0.38.0
golang.org/x/term v0.38.0
gopkg.in/yaml.v3 v3.0.1
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.44.3
)
)
require (
require (
...
@@ -36,6 +42,7 @@ require (
...
@@ -36,6 +42,7 @@ require (
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
...
@@ -46,7 +53,6 @@ require (
...
@@ -46,7 +53,6 @@ require (
github.com/containerd/platforms v0.2.1 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v28.5.1+incompatible // indirect
github.com/docker/docker v28.5.1+incompatible // indirect
...
@@ -97,6 +103,7 @@ require (
...
@@ -97,6 +103,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
...
@@ -106,9 +113,8 @@ require (
...
@@ -106,9 +113,8 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.57.1 // indirect
github.com/quic-go/quic-go v0.57.1 // indirect
github.com/re
fraction-networking/utls v1.8.1
// indirect
github.com/re
myoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec
// indirect
github.com/rivo/uniseg v0.2.0 // 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/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
...
@@ -139,13 +145,15 @@ require (
...
@@ -139,13 +145,15 @@ require (
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/exp v0.0.0-202
30905200255-921286631fa9
// indirect
golang.org/x/exp v0.0.0-202
51023183803-a4bb9ffd2546
// indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/tools v0.39.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/grpc v1.75.1 // indirect
google.golang.org/protobuf v1.36.10 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/ini.v1 v1.67.0 // 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
)
)
backend/go.sum
View file @
3ecadf4a
...
@@ -20,6 +20,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
...
@@ -20,6 +20,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
...
@@ -53,6 +55,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
...
@@ -53,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/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 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
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 h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
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=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
...
@@ -111,6 +115,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
...
@@ -111,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 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
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/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 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
...
@@ -121,6 +127,9 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
...
@@ -121,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/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 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
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 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
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=
github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo=
...
@@ -141,6 +150,7 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
...
@@ -141,6 +150,7 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
...
@@ -199,6 +209,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
...
@@ -199,6 +209,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
...
@@ -214,6 +226,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
...
@@ -214,6 +226,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
...
@@ -224,6 +238,8 @@ github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4Vi
...
@@ -224,6 +238,8 @@ github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4Vi
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
github.com/refraction-networking/utls v1.8.1/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/refraction-networking/utls v1.8.1/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
...
@@ -336,8 +352,8 @@ golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
...
@@ -336,8 +352,8 @@ 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/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 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-202
30905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g
=
golang.org/x/exp v0.0.0-202
51023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY
=
golang.org/x/exp v0.0.0-202
30905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k
=
golang.org/x/exp v0.0.0-202
51023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70
=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
...
@@ -363,8 +379,8 @@ golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
...
@@ -363,8 +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/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
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 v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/tools/go/expect v0.1.
0
-deprecated h1:j
Y2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY
=
golang.org/x/tools/go/expect v0.1.
1
-deprecated h1:j
pBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM
=
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/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 h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
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=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
...
@@ -387,4 +403,32 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
...
@@ -387,4 +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=
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 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
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/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=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
backend/internal/domain/constants.go
View file @
3ecadf4a
...
@@ -29,6 +29,7 @@ const (
...
@@ -29,6 +29,7 @@ const (
AccountTypeOAuth
=
"oauth"
// OAuth类型账号(full scope: profile + inference)
AccountTypeOAuth
=
"oauth"
// OAuth类型账号(full scope: profile + inference)
AccountTypeSetupToken
=
"setup-token"
// Setup Token类型账号(inference only scope)
AccountTypeSetupToken
=
"setup-token"
// Setup Token类型账号(inference only scope)
AccountTypeAPIKey
=
"apikey"
// API Key类型账号
AccountTypeAPIKey
=
"apikey"
// API Key类型账号
AccountTypeUpstream
=
"upstream"
// 上游透传类型账号(通过 Base URL + API Key 连接上游)
)
)
// Redeem type constants
// Redeem type constants
...
...
backend/internal/handler/admin/account_handler.go
View file @
3ecadf4a
...
@@ -84,7 +84,7 @@ type CreateAccountRequest struct {
...
@@ -84,7 +84,7 @@ type CreateAccountRequest struct {
Name
string
`json:"name" binding:"required"`
Name
string
`json:"name" binding:"required"`
Notes
*
string
`json:"notes"`
Notes
*
string
`json:"notes"`
Platform
string
`json:"platform" binding:"required"`
Platform
string
`json:"platform" binding:"required"`
Type
string
`json:"type" binding:"required,oneof=oauth setup-token apikey"`
Type
string
`json:"type" binding:"required,oneof=oauth setup-token apikey
upstream
"`
Credentials
map
[
string
]
any
`json:"credentials" binding:"required"`
Credentials
map
[
string
]
any
`json:"credentials" binding:"required"`
Extra
map
[
string
]
any
`json:"extra"`
Extra
map
[
string
]
any
`json:"extra"`
ProxyID
*
int64
`json:"proxy_id"`
ProxyID
*
int64
`json:"proxy_id"`
...
@@ -102,7 +102,7 @@ type CreateAccountRequest struct {
...
@@ -102,7 +102,7 @@ type CreateAccountRequest struct {
type
UpdateAccountRequest
struct
{
type
UpdateAccountRequest
struct
{
Name
string
`json:"name"`
Name
string
`json:"name"`
Notes
*
string
`json:"notes"`
Notes
*
string
`json:"notes"`
Type
string
`json:"type" binding:"omitempty,oneof=oauth setup-token apikey"`
Type
string
`json:"type" binding:"omitempty,oneof=oauth setup-token apikey
upstream
"`
Credentials
map
[
string
]
any
`json:"credentials"`
Credentials
map
[
string
]
any
`json:"credentials"`
Extra
map
[
string
]
any
`json:"extra"`
Extra
map
[
string
]
any
`json:"extra"`
ProxyID
*
int64
`json:"proxy_id"`
ProxyID
*
int64
`json:"proxy_id"`
...
...
backend/internal/handler/admin/group_handler.go
View file @
3ecadf4a
...
@@ -45,6 +45,8 @@ type CreateGroupRequest struct {
...
@@ -45,6 +45,8 @@ type CreateGroupRequest 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"`
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
[]
string
`json:"supported_model_scopes"`
}
}
// UpdateGroupRequest represents update group request
// UpdateGroupRequest represents update group request
...
@@ -70,6 +72,8 @@ type UpdateGroupRequest struct {
...
@@ -70,6 +72,8 @@ type UpdateGroupRequest 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"`
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
*
[]
string
`json:"supported_model_scopes"`
}
}
// List handles listing all groups with pagination
// List handles listing all groups with pagination
...
@@ -177,6 +181,7 @@ func (h *GroupHandler) Create(c *gin.Context) {
...
@@ -177,6 +181,7 @@ func (h *GroupHandler) Create(c *gin.Context) {
ModelRouting
:
req
.
ModelRouting
,
ModelRouting
:
req
.
ModelRouting
,
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
MCPXMLInject
:
req
.
MCPXMLInject
,
MCPXMLInject
:
req
.
MCPXMLInject
,
SupportedModelScopes
:
req
.
SupportedModelScopes
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
response
.
ErrorFrom
(
c
,
err
)
...
@@ -221,6 +226,7 @@ func (h *GroupHandler) Update(c *gin.Context) {
...
@@ -221,6 +226,7 @@ func (h *GroupHandler) Update(c *gin.Context) {
ModelRouting
:
req
.
ModelRouting
,
ModelRouting
:
req
.
ModelRouting
,
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
MCPXMLInject
:
req
.
MCPXMLInject
,
MCPXMLInject
:
req
.
MCPXMLInject
,
SupportedModelScopes
:
req
.
SupportedModelScopes
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
response
.
ErrorFrom
(
c
,
err
)
...
...
backend/internal/handler/dto/types.go
View file @
3ecadf4a
...
@@ -88,6 +88,8 @@ type AdminGroup struct {
...
@@ -88,6 +88,8 @@ type AdminGroup struct {
// MCP XML 协议注入(仅 antigravity 平台使用)
// MCP XML 协议注入(仅 antigravity 平台使用)
MCPXMLInject
bool
`json:"mcp_xml_inject"`
MCPXMLInject
bool
`json:"mcp_xml_inject"`
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
[]
string
`json:"supported_model_scopes"`
AccountGroups
[]
AccountGroup
`json:"account_groups,omitempty"`
AccountGroups
[]
AccountGroup
`json:"account_groups,omitempty"`
AccountCount
int64
`json:"account_count,omitempty"`
AccountCount
int64
`json:"account_count,omitempty"`
}
}
...
...
backend/internal/repository/api_key_repo.go
View file @
3ecadf4a
...
@@ -140,6 +140,7 @@ func (r *apiKeyRepository) GetByKeyForAuth(ctx context.Context, key string) (*se
...
@@ -140,6 +140,7 @@ func (r *apiKeyRepository) GetByKeyForAuth(ctx context.Context, key string) (*se
group
.
FieldModelRoutingEnabled
,
group
.
FieldModelRoutingEnabled
,
group
.
FieldModelRouting
,
group
.
FieldModelRouting
,
group
.
FieldMcpXMLInject
,
group
.
FieldMcpXMLInject
,
group
.
FieldSupportedModelScopes
,
)
)
})
.
})
.
Only
(
ctx
)
Only
(
ctx
)
...
@@ -433,6 +434,7 @@ func groupEntityToService(g *dbent.Group) *service.Group {
...
@@ -433,6 +434,7 @@ func groupEntityToService(g *dbent.Group) *service.Group {
ModelRouting
:
g
.
ModelRouting
,
ModelRouting
:
g
.
ModelRouting
,
ModelRoutingEnabled
:
g
.
ModelRoutingEnabled
,
ModelRoutingEnabled
:
g
.
ModelRoutingEnabled
,
MCPXMLInject
:
g
.
McpXMLInject
,
MCPXMLInject
:
g
.
McpXMLInject
,
SupportedModelScopes
:
g
.
SupportedModelScopes
,
CreatedAt
:
g
.
CreatedAt
,
CreatedAt
:
g
.
CreatedAt
,
UpdatedAt
:
g
.
UpdatedAt
,
UpdatedAt
:
g
.
UpdatedAt
,
}
}
...
...
backend/internal/repository/group_repo.go
View file @
3ecadf4a
...
@@ -59,6 +59,9 @@ func (r *groupRepository) Create(ctx context.Context, groupIn *service.Group) er
...
@@ -59,6 +59,9 @@ func (r *groupRepository) Create(ctx context.Context, groupIn *service.Group) er
builder
=
builder
.
SetModelRouting
(
groupIn
.
ModelRouting
)
builder
=
builder
.
SetModelRouting
(
groupIn
.
ModelRouting
)
}
}
// 设置支持的模型系列(始终设置,空数组表示不限制)
builder
=
builder
.
SetSupportedModelScopes
(
groupIn
.
SupportedModelScopes
)
created
,
err
:=
builder
.
Save
(
ctx
)
created
,
err
:=
builder
.
Save
(
ctx
)
if
err
==
nil
{
if
err
==
nil
{
groupIn
.
ID
=
created
.
ID
groupIn
.
ID
=
created
.
ID
...
@@ -89,7 +92,6 @@ func (r *groupRepository) GetByIDLite(ctx context.Context, id int64) (*service.G
...
@@ -89,7 +92,6 @@ func (r *groupRepository) GetByIDLite(ctx context.Context, id int64) (*service.G
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
translatePersistenceError
(
err
,
service
.
ErrGroupNotFound
,
nil
)
return
nil
,
translatePersistenceError
(
err
,
service
.
ErrGroupNotFound
,
nil
)
}
}
return
groupEntityToService
(
m
),
nil
return
groupEntityToService
(
m
),
nil
}
}
...
@@ -133,6 +135,9 @@ func (r *groupRepository) Update(ctx context.Context, groupIn *service.Group) er
...
@@ -133,6 +135,9 @@ func (r *groupRepository) Update(ctx context.Context, groupIn *service.Group) er
builder
=
builder
.
ClearModelRouting
()
builder
=
builder
.
ClearModelRouting
()
}
}
// 处理 SupportedModelScopes(始终设置,空数组表示不限制)
builder
=
builder
.
SetSupportedModelScopes
(
groupIn
.
SupportedModelScopes
)
updated
,
err
:=
builder
.
Save
(
ctx
)
updated
,
err
:=
builder
.
Save
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
translatePersistenceError
(
err
,
service
.
ErrGroupNotFound
,
service
.
ErrGroupExists
)
return
translatePersistenceError
(
err
,
service
.
ErrGroupNotFound
,
service
.
ErrGroupExists
)
...
...
backend/internal/service/admin_service.go
View file @
3ecadf4a
...
@@ -113,6 +113,8 @@ type CreateGroupInput struct {
...
@@ -113,6 +113,8 @@ type CreateGroupInput struct {
ModelRouting
map
[
string
][]
int64
ModelRouting
map
[
string
][]
int64
ModelRoutingEnabled
bool
// 是否启用模型路由
ModelRoutingEnabled
bool
// 是否启用模型路由
MCPXMLInject
*
bool
MCPXMLInject
*
bool
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
[]
string
}
}
type
UpdateGroupInput
struct
{
type
UpdateGroupInput
struct
{
...
@@ -138,6 +140,8 @@ type UpdateGroupInput struct {
...
@@ -138,6 +140,8 @@ type UpdateGroupInput struct {
ModelRouting
map
[
string
][]
int64
ModelRouting
map
[
string
][]
int64
ModelRoutingEnabled
*
bool
// 是否启用模型路由
ModelRoutingEnabled
*
bool
// 是否启用模型路由
MCPXMLInject
*
bool
MCPXMLInject
*
bool
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
*
[]
string
}
}
type
CreateAccountInput
struct
{
type
CreateAccountInput
struct
{
...
@@ -613,6 +617,7 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn
...
@@ -613,6 +617,7 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn
FallbackGroupIDOnInvalidRequest
:
fallbackOnInvalidRequest
,
FallbackGroupIDOnInvalidRequest
:
fallbackOnInvalidRequest
,
ModelRouting
:
input
.
ModelRouting
,
ModelRouting
:
input
.
ModelRouting
,
MCPXMLInject
:
mcpXMLInject
,
MCPXMLInject
:
mcpXMLInject
,
SupportedModelScopes
:
input
.
SupportedModelScopes
,
}
}
if
err
:=
s
.
groupRepo
.
Create
(
ctx
,
group
);
err
!=
nil
{
if
err
:=
s
.
groupRepo
.
Create
(
ctx
,
group
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -797,6 +802,11 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd
...
@@ -797,6 +802,11 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd
group
.
MCPXMLInject
=
*
input
.
MCPXMLInject
group
.
MCPXMLInject
=
*
input
.
MCPXMLInject
}
}
// 支持的模型系列(仅 antigravity 平台使用)
if
input
.
SupportedModelScopes
!=
nil
{
group
.
SupportedModelScopes
=
*
input
.
SupportedModelScopes
}
if
err
:=
s
.
groupRepo
.
Update
(
ctx
,
group
);
err
!=
nil
{
if
err
:=
s
.
groupRepo
.
Update
(
ctx
,
group
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
backend/internal/service/antigravity_gateway_service.go
View file @
3ecadf4a
...
@@ -412,6 +412,11 @@ type TestConnectionResult struct {
...
@@ -412,6 +412,11 @@ type TestConnectionResult struct {
// TestConnection 测试 Antigravity 账号连接(非流式,无重试、无计费)
// TestConnection 测试 Antigravity 账号连接(非流式,无重试、无计费)
// 支持 Claude 和 Gemini 两种协议,根据 modelID 前缀自动选择
// 支持 Claude 和 Gemini 两种协议,根据 modelID 前缀自动选择
func
(
s
*
AntigravityGatewayService
)
TestConnection
(
ctx
context
.
Context
,
account
*
Account
,
modelID
string
)
(
*
TestConnectionResult
,
error
)
{
func
(
s
*
AntigravityGatewayService
)
TestConnection
(
ctx
context
.
Context
,
account
*
Account
,
modelID
string
)
(
*
TestConnectionResult
,
error
)
{
// 上游透传账号使用专用测试方法
if
account
.
Type
==
AccountTypeUpstream
{
return
s
.
testUpstreamConnection
(
ctx
,
account
,
modelID
)
}
// 获取 token
// 获取 token
if
s
.
tokenProvider
==
nil
{
if
s
.
tokenProvider
==
nil
{
return
nil
,
errors
.
New
(
"antigravity token provider not configured"
)
return
nil
,
errors
.
New
(
"antigravity token provider not configured"
)
...
@@ -506,6 +511,87 @@ func (s *AntigravityGatewayService) TestConnection(ctx context.Context, account
...
@@ -506,6 +511,87 @@ func (s *AntigravityGatewayService) TestConnection(ctx context.Context, account
return
nil
,
lastErr
return
nil
,
lastErr
}
}
// testUpstreamConnection 测试上游透传账号连接
func
(
s
*
AntigravityGatewayService
)
testUpstreamConnection
(
ctx
context
.
Context
,
account
*
Account
,
modelID
string
)
(
*
TestConnectionResult
,
error
)
{
baseURL
:=
strings
.
TrimSpace
(
account
.
GetCredential
(
"base_url"
))
apiKey
:=
strings
.
TrimSpace
(
account
.
GetCredential
(
"api_key"
))
if
baseURL
==
""
||
apiKey
==
""
{
return
nil
,
errors
.
New
(
"upstream account missing base_url or api_key"
)
}
baseURL
=
strings
.
TrimSuffix
(
baseURL
,
"/"
)
// 使用 Claude 模型进行测试
if
modelID
==
""
{
modelID
=
"claude-sonnet-4-20250514"
}
// 构建最小测试请求
testReq
:=
map
[
string
]
any
{
"model"
:
modelID
,
"max_tokens"
:
1
,
"messages"
:
[]
map
[
string
]
any
{
{
"role"
:
"user"
,
"content"
:
"."
},
},
}
requestBody
,
err
:=
json
.
Marshal
(
testReq
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"构建请求失败: %w"
,
err
)
}
// 构建 HTTP 请求
upstreamURL
:=
baseURL
+
"/v1/messages"
req
,
err
:=
http
.
NewRequestWithContext
(
ctx
,
http
.
MethodPost
,
upstreamURL
,
bytes
.
NewReader
(
requestBody
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"创建请求失败: %w"
,
err
)
}
req
.
Header
.
Set
(
"Content-Type"
,
"application/json"
)
req
.
Header
.
Set
(
"Authorization"
,
"Bearer "
+
apiKey
)
req
.
Header
.
Set
(
"x-api-key"
,
apiKey
)
req
.
Header
.
Set
(
"anthropic-version"
,
"2023-06-01"
)
// 代理 URL
proxyURL
:=
""
if
account
.
ProxyID
!=
nil
&&
account
.
Proxy
!=
nil
{
proxyURL
=
account
.
Proxy
.
URL
()
}
log
.
Printf
(
"[antigravity-Test-Upstream] account=%s url=%s"
,
account
.
Name
,
upstreamURL
)
// 发送请求
resp
,
err
:=
s
.
httpUpstream
.
Do
(
req
,
proxyURL
,
account
.
ID
,
account
.
Concurrency
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"请求失败: %w"
,
err
)
}
defer
func
()
{
_
=
resp
.
Body
.
Close
()
}()
respBody
,
err
:=
io
.
ReadAll
(
io
.
LimitReader
(
resp
.
Body
,
2
<<
20
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"读取响应失败: %w"
,
err
)
}
if
resp
.
StatusCode
>=
400
{
return
nil
,
fmt
.
Errorf
(
"API 返回 %d: %s"
,
resp
.
StatusCode
,
string
(
respBody
))
}
// 提取响应文本
var
respData
map
[
string
]
any
text
:=
""
if
json
.
Unmarshal
(
respBody
,
&
respData
)
==
nil
{
if
content
,
ok
:=
respData
[
"content"
]
.
([]
any
);
ok
&&
len
(
content
)
>
0
{
if
block
,
ok
:=
content
[
0
]
.
(
map
[
string
]
any
);
ok
{
if
t
,
ok
:=
block
[
"text"
]
.
(
string
);
ok
{
text
=
t
}
}
}
}
return
&
TestConnectionResult
{
Text
:
text
,
MappedModel
:
modelID
,
},
nil
}
// buildGeminiTestRequest 构建 Gemini 格式测试请求
// buildGeminiTestRequest 构建 Gemini 格式测试请求
// 使用最小 token 消耗:输入 "." + maxOutputTokens: 1
// 使用最小 token 消耗:输入 "." + maxOutputTokens: 1
func
(
s
*
AntigravityGatewayService
)
buildGeminiTestRequest
(
projectID
,
model
string
)
([]
byte
,
error
)
{
func
(
s
*
AntigravityGatewayService
)
buildGeminiTestRequest
(
projectID
,
model
string
)
([]
byte
,
error
)
{
...
@@ -728,6 +814,11 @@ func isModelNotFoundError(statusCode int, body []byte) bool {
...
@@ -728,6 +814,11 @@ func isModelNotFoundError(statusCode int, body []byte) bool {
// Forward 转发 Claude 协议请求(Claude → Gemini 转换)
// Forward 转发 Claude 协议请求(Claude → Gemini 转换)
func
(
s
*
AntigravityGatewayService
)
Forward
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
Account
,
body
[]
byte
)
(
*
ForwardResult
,
error
)
{
func
(
s
*
AntigravityGatewayService
)
Forward
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
Account
,
body
[]
byte
)
(
*
ForwardResult
,
error
)
{
// 上游透传账号直接转发,不走 OAuth token 刷新
if
account
.
Type
==
AccountTypeUpstream
{
return
s
.
ForwardUpstream
(
ctx
,
c
,
account
,
body
)
}
startTime
:=
time
.
Now
()
startTime
:=
time
.
Now
()
sessionID
:=
getSessionID
(
c
)
sessionID
:=
getSessionID
(
c
)
prefix
:=
logPrefix
(
sessionID
,
account
.
Name
)
prefix
:=
logPrefix
(
sessionID
,
account
.
Name
)
...
@@ -1349,6 +1440,208 @@ func stripSignatureSensitiveBlocksFromClaudeRequest(req *antigravity.ClaudeReque
...
@@ -1349,6 +1440,208 @@ func stripSignatureSensitiveBlocksFromClaudeRequest(req *antigravity.ClaudeReque
return
changed
,
nil
return
changed
,
nil
}
}
// ForwardUpstream 透传请求到上游 Antigravity 服务
// 用于 upstream 类型账号,直接使用 base_url + api_key 转发,不走 OAuth token
func
(
s
*
AntigravityGatewayService
)
ForwardUpstream
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
Account
,
body
[]
byte
)
(
*
ForwardResult
,
error
)
{
startTime
:=
time
.
Now
()
sessionID
:=
getSessionID
(
c
)
prefix
:=
logPrefix
(
sessionID
,
account
.
Name
)
// 获取上游配置
baseURL
:=
strings
.
TrimSpace
(
account
.
GetCredential
(
"base_url"
))
apiKey
:=
strings
.
TrimSpace
(
account
.
GetCredential
(
"api_key"
))
if
baseURL
==
""
||
apiKey
==
""
{
return
nil
,
fmt
.
Errorf
(
"upstream account missing base_url or api_key"
)
}
baseURL
=
strings
.
TrimSuffix
(
baseURL
,
"/"
)
// 解析请求获取模型信息
var
claudeReq
antigravity
.
ClaudeRequest
if
err
:=
json
.
Unmarshal
(
body
,
&
claudeReq
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"parse claude request: %w"
,
err
)
}
if
strings
.
TrimSpace
(
claudeReq
.
Model
)
==
""
{
return
nil
,
fmt
.
Errorf
(
"missing model"
)
}
originalModel
:=
claudeReq
.
Model
billingModel
:=
originalModel
// 构建上游请求 URL
upstreamURL
:=
baseURL
+
"/v1/messages"
// 创建请求
req
,
err
:=
http
.
NewRequestWithContext
(
ctx
,
http
.
MethodPost
,
upstreamURL
,
bytes
.
NewReader
(
body
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"create upstream request: %w"
,
err
)
}
// 设置请求头
req
.
Header
.
Set
(
"Content-Type"
,
"application/json"
)
req
.
Header
.
Set
(
"Authorization"
,
"Bearer "
+
apiKey
)
req
.
Header
.
Set
(
"x-api-key"
,
apiKey
)
// Claude API 兼容
// 透传 Claude 相关 headers
if
v
:=
c
.
GetHeader
(
"anthropic-version"
);
v
!=
""
{
req
.
Header
.
Set
(
"anthropic-version"
,
v
)
}
if
v
:=
c
.
GetHeader
(
"anthropic-beta"
);
v
!=
""
{
req
.
Header
.
Set
(
"anthropic-beta"
,
v
)
}
// 代理 URL
proxyURL
:=
""
if
account
.
ProxyID
!=
nil
&&
account
.
Proxy
!=
nil
{
proxyURL
=
account
.
Proxy
.
URL
()
}
// 发送请求
resp
,
err
:=
s
.
httpUpstream
.
Do
(
req
,
proxyURL
,
account
.
ID
,
account
.
Concurrency
)
if
err
!=
nil
{
log
.
Printf
(
"%s upstream request failed: %v"
,
prefix
,
err
)
return
nil
,
fmt
.
Errorf
(
"upstream request failed: %w"
,
err
)
}
defer
func
()
{
_
=
resp
.
Body
.
Close
()
}()
// 处理错误响应
if
resp
.
StatusCode
>=
400
{
respBody
,
_
:=
io
.
ReadAll
(
io
.
LimitReader
(
resp
.
Body
,
2
<<
20
))
// 429 错误时标记账号限流
if
resp
.
StatusCode
==
http
.
StatusTooManyRequests
{
s
.
handleUpstreamError
(
ctx
,
prefix
,
account
,
resp
.
StatusCode
,
resp
.
Header
,
respBody
,
AntigravityQuotaScopeClaude
)
}
// 透传上游错误
c
.
Header
(
"Content-Type"
,
resp
.
Header
.
Get
(
"Content-Type"
))
c
.
Status
(
resp
.
StatusCode
)
_
,
_
=
c
.
Writer
.
Write
(
respBody
)
return
&
ForwardResult
{
Model
:
billingModel
,
},
nil
}
// 处理成功响应(流式/非流式)
var
usage
*
ClaudeUsage
var
firstTokenMs
*
int
if
claudeReq
.
Stream
{
// 流式响应:透传
c
.
Header
(
"Content-Type"
,
"text/event-stream"
)
c
.
Header
(
"Cache-Control"
,
"no-cache"
)
c
.
Header
(
"Connection"
,
"keep-alive"
)
c
.
Header
(
"X-Accel-Buffering"
,
"no"
)
c
.
Status
(
http
.
StatusOK
)
usage
,
firstTokenMs
=
s
.
streamUpstreamResponse
(
c
,
resp
,
startTime
)
}
else
{
// 非流式响应:直接透传
respBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"read upstream response: %w"
,
err
)
}
// 提取 usage
usage
=
s
.
extractClaudeUsage
(
respBody
)
c
.
Header
(
"Content-Type"
,
resp
.
Header
.
Get
(
"Content-Type"
))
c
.
Status
(
http
.
StatusOK
)
_
,
_
=
c
.
Writer
.
Write
(
respBody
)
}
// 构建计费结果
duration
:=
time
.
Since
(
startTime
)
log
.
Printf
(
"%s status=success duration_ms=%d"
,
prefix
,
duration
.
Milliseconds
())
return
&
ForwardResult
{
Model
:
billingModel
,
Stream
:
claudeReq
.
Stream
,
Duration
:
duration
,
FirstTokenMs
:
firstTokenMs
,
Usage
:
ClaudeUsage
{
InputTokens
:
usage
.
InputTokens
,
OutputTokens
:
usage
.
OutputTokens
,
CacheReadInputTokens
:
usage
.
CacheReadInputTokens
,
CacheCreationInputTokens
:
usage
.
CacheCreationInputTokens
,
},
},
nil
}
// streamUpstreamResponse 透传上游流式响应并提取 usage
func
(
s
*
AntigravityGatewayService
)
streamUpstreamResponse
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
startTime
time
.
Time
)
(
*
ClaudeUsage
,
*
int
)
{
usage
:=
&
ClaudeUsage
{}
var
firstTokenMs
*
int
var
firstTokenRecorded
bool
scanner
:=
bufio
.
NewScanner
(
resp
.
Body
)
buf
:=
make
([]
byte
,
0
,
64
*
1024
)
scanner
.
Buffer
(
buf
,
1024
*
1024
)
for
scanner
.
Scan
()
{
line
:=
scanner
.
Bytes
()
// 记录首 token 时间
if
!
firstTokenRecorded
&&
len
(
line
)
>
0
{
ms
:=
int
(
time
.
Since
(
startTime
)
.
Milliseconds
())
firstTokenMs
=
&
ms
firstTokenRecorded
=
true
}
// 尝试从 message_delta 或 message_stop 事件提取 usage
if
bytes
.
HasPrefix
(
line
,
[]
byte
(
"data: "
))
{
dataStr
:=
bytes
.
TrimPrefix
(
line
,
[]
byte
(
"data: "
))
var
event
map
[
string
]
any
if
json
.
Unmarshal
(
dataStr
,
&
event
)
==
nil
{
if
u
,
ok
:=
event
[
"usage"
]
.
(
map
[
string
]
any
);
ok
{
if
v
,
ok
:=
u
[
"input_tokens"
]
.
(
float64
);
ok
&&
int
(
v
)
>
0
{
usage
.
InputTokens
=
int
(
v
)
}
if
v
,
ok
:=
u
[
"output_tokens"
]
.
(
float64
);
ok
&&
int
(
v
)
>
0
{
usage
.
OutputTokens
=
int
(
v
)
}
if
v
,
ok
:=
u
[
"cache_read_input_tokens"
]
.
(
float64
);
ok
&&
int
(
v
)
>
0
{
usage
.
CacheReadInputTokens
=
int
(
v
)
}
if
v
,
ok
:=
u
[
"cache_creation_input_tokens"
]
.
(
float64
);
ok
&&
int
(
v
)
>
0
{
usage
.
CacheCreationInputTokens
=
int
(
v
)
}
}
}
}
// 透传行
_
,
_
=
c
.
Writer
.
Write
(
line
)
_
,
_
=
c
.
Writer
.
Write
([]
byte
(
"
\n
"
))
c
.
Writer
.
Flush
()
}
return
usage
,
firstTokenMs
}
// extractClaudeUsage 从非流式 Claude 响应提取 usage
func
(
s
*
AntigravityGatewayService
)
extractClaudeUsage
(
body
[]
byte
)
*
ClaudeUsage
{
usage
:=
&
ClaudeUsage
{}
var
resp
map
[
string
]
any
if
json
.
Unmarshal
(
body
,
&
resp
)
!=
nil
{
return
usage
}
if
u
,
ok
:=
resp
[
"usage"
]
.
(
map
[
string
]
any
);
ok
{
if
v
,
ok
:=
u
[
"input_tokens"
]
.
(
float64
);
ok
{
usage
.
InputTokens
=
int
(
v
)
}
if
v
,
ok
:=
u
[
"output_tokens"
]
.
(
float64
);
ok
{
usage
.
OutputTokens
=
int
(
v
)
}
if
v
,
ok
:=
u
[
"cache_read_input_tokens"
]
.
(
float64
);
ok
{
usage
.
CacheReadInputTokens
=
int
(
v
)
}
if
v
,
ok
:=
u
[
"cache_creation_input_tokens"
]
.
(
float64
);
ok
{
usage
.
CacheCreationInputTokens
=
int
(
v
)
}
}
return
usage
}
// ForwardGemini 转发 Gemini 协议请求
// ForwardGemini 转发 Gemini 协议请求
func
(
s
*
AntigravityGatewayService
)
ForwardGemini
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
Account
,
originalModel
string
,
action
string
,
stream
bool
,
body
[]
byte
)
(
*
ForwardResult
,
error
)
{
func
(
s
*
AntigravityGatewayService
)
ForwardGemini
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
Account
,
originalModel
string
,
action
string
,
stream
bool
,
body
[]
byte
)
(
*
ForwardResult
,
error
)
{
startTime
:=
time
.
Now
()
startTime
:=
time
.
Now
()
...
...
backend/internal/service/antigravity_quota_scope.go
View file @
3ecadf4a
package
service
package
service
import
(
import
(
"slices"
"strings"
"strings"
"time"
"time"
)
)
...
@@ -16,6 +17,21 @@ const (
...
@@ -16,6 +17,21 @@ const (
AntigravityQuotaScopeGeminiImage
AntigravityQuotaScope
=
"gemini_image"
AntigravityQuotaScopeGeminiImage
AntigravityQuotaScope
=
"gemini_image"
)
)
// IsScopeSupported 检查给定的 scope 是否在分组支持的 scope 列表中
func
IsScopeSupported
(
supportedScopes
[]
string
,
scope
AntigravityQuotaScope
)
bool
{
if
len
(
supportedScopes
)
==
0
{
// 未配置时默认全部支持
return
true
}
supported
:=
slices
.
Contains
(
supportedScopes
,
string
(
scope
))
return
supported
}
// ResolveAntigravityQuotaScope 根据模型名称解析配额域(导出版本)
func
ResolveAntigravityQuotaScope
(
requestedModel
string
)
(
AntigravityQuotaScope
,
bool
)
{
return
resolveAntigravityQuotaScope
(
requestedModel
)
}
// resolveAntigravityQuotaScope 根据模型名称解析配额域
// resolveAntigravityQuotaScope 根据模型名称解析配额域
func
resolveAntigravityQuotaScope
(
requestedModel
string
)
(
AntigravityQuotaScope
,
bool
)
{
func
resolveAntigravityQuotaScope
(
requestedModel
string
)
(
AntigravityQuotaScope
,
bool
)
{
model
:=
normalizeAntigravityModelName
(
requestedModel
)
model
:=
normalizeAntigravityModelName
(
requestedModel
)
...
...
backend/internal/service/api_key_auth_cache.go
View file @
3ecadf4a
...
@@ -44,6 +44,9 @@ type APIKeyAuthGroupSnapshot struct {
...
@@ -44,6 +44,9 @@ type APIKeyAuthGroupSnapshot struct {
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"`
MCPXMLInject
bool
`json:"mcp_xml_inject"`
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
[]
string
`json:"supported_model_scopes,omitempty"`
}
}
// APIKeyAuthCacheEntry 缓存条目,支持负缓存
// APIKeyAuthCacheEntry 缓存条目,支持负缓存
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment