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
16131c3d
Commit
16131c3d
authored
Feb 09, 2026
by
yangjianbo
Browse files
Merge branch 'main' of
https://github.com/mt21625457/aicodex2api
parents
836ba14b
7d66f7ff
Changes
103
Show whitespace changes
Inline
Side-by-side
DEV_GUIDE.md
0 → 100644
View file @
16131c3d
# sub2api 项目开发指南
> 本文档记录项目环境配置、常见坑点和注意事项,供 Claude Code 和团队成员参考。
## 一、项目基本信息
| 项目 | 说明 |
|------|------|
|
**上游仓库**
| Wei-Shaw/sub2api |
|
**Fork 仓库**
| bayma888/sub2api-bmai |
|
**技术栈**
| Go 后端 (Ent ORM + Gin) + Vue3 前端 (pnpm) |
|
**数据库**
| PostgreSQL 16 + Redis |
|
**包管理**
| 后端: go modules, 前端:
**pnpm**
(不是 npm) |
## 二、本地环境配置
### PostgreSQL 16 (Windows 服务)
| 配置项 | 值 |
|--------|-----|
| 端口 | 5432 |
| psql 路径 |
`C:\Program Files\PostgreSQL\16\bin\psql.exe`
|
| pg_hba.conf |
`C:\Program Files\PostgreSQL\16\data\pg_hba.conf`
|
| 数据库凭据 | user=
`sub2api`
, password=
`sub2api`
, dbname=
`sub2api`
|
| 超级用户 | user=
`postgres`
, password=
`postgres`
|
### Redis
| 配置项 | 值 |
|--------|-----|
| 端口 | 6379 |
| 密码 | 无 |
### 开发工具
```
bash
# golangci-lint v2.7
go
install
github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.7
# pnpm (前端包管理)
npm
install
-g
pnpm
```
## 三、CI/CD 流水线
### GitHub Actions Workflows
| Workflow | 触发条件 | 检查内容 |
|----------|----------|----------|
|
**backend-ci.yml**
| push, pull_request | 单元测试 + 集成测试 + golangci-lint v2.7 |
|
**security-scan.yml**
| push, pull_request, 每周一 | govulncheck + gosec + pnpm audit |
|
**release.yml**
| tag
`v*`
| 构建发布(PR 不触发) |
### CI 要求
-
Go 版本必须是
**1.25.7**
-
前端使用
`pnpm install --frozen-lockfile`
,必须提交
`pnpm-lock.yaml`
### 本地测试命令
```
bash
# 后端单元测试
cd
backend
&&
go
test
-tags
=
unit ./...
# 后端集成测试
cd
backend
&&
go
test
-tags
=
integration ./...
# 代码质量检查
cd
backend
&&
golangci-lint run ./...
# 前端依赖安装(必须用 pnpm)
cd
frontend
&&
pnpm
install
```
## 四、常见坑点 & 解决方案
### 坑 1:pnpm-lock.yaml 必须同步提交
**问题**
:
`package.json`
新增依赖后,CI 的
`pnpm install --frozen-lockfile`
失败。
**原因**
:上游 CI 使用 pnpm,lock 文件不同步会报错。
**解决**
:
```
bash
cd
frontend
pnpm
install
# 更新 pnpm-lock.yaml
git add pnpm-lock.yaml
git commit
-m
"chore: update pnpm-lock.yaml"
```
---
### 坑 2:npm 和 pnpm 的 node_modules 冲突
**问题**
:之前用 npm 装过
`node_modules`
,pnpm install 报
`EPERM`
错误。
**解决**
:
```
bash
cd
frontend
rm
-rf
node_modules
# 或 PowerShell: Remove-Item -Recurse -Force node_modules
pnpm
install
```
---
### 坑 3:PowerShell 中 bcrypt hash 的 `$` 被转义
**问题**
:bcrypt hash 格式如
`$2a$10$xxx...`
,PowerShell 把
`$2a`
当变量解析,导致数据丢失。
**解决**
:将 SQL 写入文件,用
`psql -f`
执行:
```
bash
# 错误示范(PowerShell 会吃掉 $)
psql
-c
"INSERT INTO users ... VALUES ('
$2a$10$.
..')"
# 正确做法
echo
"INSERT INTO users ... VALUES ('
\$
2a
\$
10
\$
...')"
>
temp.sql
psql
-U
sub2api
-h
127.0.0.1
-d
sub2api
-f
temp.sql
```
---
### 坑 4:psql 不支持中文路径
**问题**
:
`psql -f "D:\中文路径\file.sql"`
报错找不到文件。
**解决**
:复制到纯英文路径再执行:
```
bash
cp
"D:
\中
文路径
\f
ile.sql"
"C:
\t
emp.sql"
psql
-f
"C:
\t
emp.sql"
```
---
### 坑 5:PostgreSQL 密码重置流程
**场景**
:忘记 PostgreSQL 密码。
**步骤**
:
1.
修改
`C:\Program Files\PostgreSQL\16\data\pg_hba.conf`
```
# 将 scram-sha-256 改为 trust
host all all 127.0.0.1/32 trust
```
2.
重启 PostgreSQL 服务
```
powershell
Restart-Service
postgresql-x64-16
```
3.
无密码登录并重置
```
bash
psql
-U
postgres
-h
127.0.0.1
ALTER USER sub2api WITH PASSWORD
'sub2api'
;
ALTER USER postgres WITH PASSWORD
'postgres'
;
```
4.
改回
`scram-sha-256`
并重启
---
### 坑 6:Go interface 新增方法后 test stub 必须补全
**问题**
:给 interface 新增方法后,编译报错
`does not implement interface (missing method XXX)`
。
**原因**
:所有测试文件中实现该 interface 的 stub/mock 都必须补上新方法。
**解决**
:
```
bash
# 搜索所有实现该 interface 的 struct
cd
backend
grep
-r
"type.*Stub.*struct"
internal/
grep
-r
"type.*Mock.*struct"
internal/
# 逐一补全新方法
```
---
### 坑 7:Windows 上 psql 连 localhost 的 IPv6 问题
**问题**
:psql 连
`localhost`
先尝试 IPv6 (::1),可能报错后再回退 IPv4。
**建议**
:直接用
`127.0.0.1`
代替
`localhost`
。
---
### 坑 8:Windows 没有 make 命令
**问题**
:CI 里用
`make test-unit`
,本地 Windows 没有 make。
**解决**
:直接用 Makefile 里的原始命令:
```
bash
# 代替 make test-unit
go
test
-tags
=
unit ./...
# 代替 make test-integration
go
test
-tags
=
integration ./...
```
---
### 坑 9:Ent Schema 修改后必须重新生成
**问题**
:修改
`ent/schema/*.go`
后,代码不生效。
**解决**
:
```
bash
cd
backend
go generate ./ent
# 重新生成 ent 代码
git add ent/
# 生成的文件也要提交
```
---
### 坑 10:PR 提交前检查清单
提交 PR 前务必本地验证:
-
[ ]
`go test -tags=unit ./...`
通过
-
[ ]
`go test -tags=integration ./...`
通过
-
[ ]
`golangci-lint run ./...`
无新增问题
-
[ ]
`pnpm-lock.yaml`
已同步(如果改了 package.json)
-
[ ] 所有 test stub 补全新接口方法(如果改了 interface)
-
[ ] Ent 生成的代码已提交(如果改了 schema)
## 五、常用命令速查
### 数据库操作
```
bash
# 连接数据库
psql
-U
sub2api
-h
127.0.0.1
-d
sub2api
# 查看所有用户
psql
-U
postgres
-h
127.0.0.1
-c
"
\d
u"
# 查看所有数据库
psql
-U
postgres
-h
127.0.0.1
-c
"
\l
"
# 执行 SQL 文件
psql
-U
sub2api
-h
127.0.0.1
-d
sub2api
-f
migration.sql
```
### Git 操作
```
bash
# 同步上游
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
# 创建功能分支
git checkout
-b
feature/xxx
# Rebase 到最新 main
git fetch upstream
git rebase upstream/main
```
### 前端操作
```
bash
# 安装依赖(必须用 pnpm)
cd
frontend
pnpm
install
# 开发服务器
pnpm dev
# 构建
pnpm build
```
### 后端操作
```
bash
# 运行服务器
cd
backend
go run ./cmd/server/
# 生成 Ent 代码
go generate ./ent
# 运行测试
go
test
-tags
=
unit ./...
go
test
-tags
=
integration ./...
# Lint 检查
golangci-lint run ./...
```
## 六、项目结构速览
```
sub2api-bmai/
├── backend/
│ ├── cmd/server/ # 主程序入口
│ ├── ent/ # Ent ORM 生成代码
│ │ └── schema/ # 数据库 Schema 定义
│ ├── internal/
│ │ ├── handler/ # HTTP 处理器
│ │ ├── service/ # 业务逻辑
│ │ ├── repository/ # 数据访问层
│ │ └── server/ # 服务器配置
│ ├── migrations/ # 数据库迁移脚本
│ └── config.yaml # 配置文件
├── frontend/
│ ├── src/
│ │ ├── api/ # API 调用
│ │ ├── components/ # Vue 组件
│ │ ├── views/ # 页面视图
│ │ ├── types/ # TypeScript 类型
│ │ └── i18n/ # 国际化
│ ├── package.json # 依赖配置
│ └── pnpm-lock.yaml # pnpm 锁文件(必须提交)
└── .claude/
└── CLAUDE.md # 本文档
```
## 七、参考资源
-
[
上游仓库
](
https://github.com/Wei-Shaw/sub2api
)
-
[
Ent 文档
](
https://entgo.io/docs/getting-started
)
-
[
Vue3 文档
](
https://vuejs.org/
)
-
[
pnpm 文档
](
https://pnpm.io/
)
backend/cmd/server/VERSION
View file @
16131c3d
0.1.7
0
.2
0.1.7
4
.2
backend/cmd/server/wire_gen.go
View file @
16131c3d
...
@@ -102,7 +102,9 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -102,7 +102,9 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
proxyExitInfoProber
:=
repository
.
NewProxyExitInfoProber
(
configConfig
)
proxyExitInfoProber
:=
repository
.
NewProxyExitInfoProber
(
configConfig
)
proxyLatencyCache
:=
repository
.
NewProxyLatencyCache
(
redisClient
)
proxyLatencyCache
:=
repository
.
NewProxyLatencyCache
(
redisClient
)
adminService
:=
service
.
NewAdminService
(
userRepository
,
groupRepository
,
accountRepository
,
proxyRepository
,
apiKeyRepository
,
redeemCodeRepository
,
userGroupRateRepository
,
billingCacheService
,
proxyExitInfoProber
,
proxyLatencyCache
,
apiKeyAuthCacheInvalidator
)
adminService
:=
service
.
NewAdminService
(
userRepository
,
groupRepository
,
accountRepository
,
proxyRepository
,
apiKeyRepository
,
redeemCodeRepository
,
userGroupRateRepository
,
billingCacheService
,
proxyExitInfoProber
,
proxyLatencyCache
,
apiKeyAuthCacheInvalidator
)
adminUserHandler
:=
admin
.
NewUserHandler
(
adminService
)
concurrencyCache
:=
repository
.
ProvideConcurrencyCache
(
redisClient
,
configConfig
)
concurrencyService
:=
service
.
ProvideConcurrencyService
(
concurrencyCache
,
accountRepository
,
configConfig
)
adminUserHandler
:=
admin
.
NewUserHandler
(
adminService
,
concurrencyService
)
groupHandler
:=
admin
.
NewGroupHandler
(
adminService
)
groupHandler
:=
admin
.
NewGroupHandler
(
adminService
)
claudeOAuthClient
:=
repository
.
NewClaudeOAuthClient
()
claudeOAuthClient
:=
repository
.
NewClaudeOAuthClient
()
oAuthService
:=
service
.
NewOAuthService
(
proxyRepository
,
claudeOAuthClient
)
oAuthService
:=
service
.
NewOAuthService
(
proxyRepository
,
claudeOAuthClient
)
...
@@ -126,13 +128,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -126,13 +128,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
accountUsageService
:=
service
.
NewAccountUsageService
(
accountRepository
,
usageLogRepository
,
claudeUsageFetcher
,
geminiQuotaService
,
antigravityQuotaFetcher
,
usageCache
,
identityCache
)
accountUsageService
:=
service
.
NewAccountUsageService
(
accountRepository
,
usageLogRepository
,
claudeUsageFetcher
,
geminiQuotaService
,
antigravityQuotaFetcher
,
usageCache
,
identityCache
)
geminiTokenProvider
:=
service
.
NewGeminiTokenProvider
(
accountRepository
,
geminiTokenCache
,
geminiOAuthService
)
geminiTokenProvider
:=
service
.
NewGeminiTokenProvider
(
accountRepository
,
geminiTokenCache
,
geminiOAuthService
)
gatewayCache
:=
repository
.
NewGatewayCache
(
redisClient
)
gatewayCache
:=
repository
.
NewGatewayCache
(
redisClient
)
antigravityTokenProvider
:=
service
.
NewAntigravityTokenProvider
(
accountRepository
,
geminiTokenCache
,
antigravityOAuthService
)
schedulerOutboxRepository
:=
repository
.
NewSchedulerOutboxRepository
(
db
)
schedulerOutboxRepository
:=
repository
.
NewSchedulerOutboxRepository
(
db
)
schedulerSnapshotService
:=
service
.
ProvideSchedulerSnapshotService
(
schedulerCache
,
schedulerOutboxRepository
,
accountRepository
,
groupRepository
,
configConfig
)
schedulerSnapshotService
:=
service
.
ProvideSchedulerSnapshotService
(
schedulerCache
,
schedulerOutboxRepository
,
accountRepository
,
groupRepository
,
configConfig
)
antigravityTokenProvider
:=
service
.
NewAntigravityTokenProvider
(
accountRepository
,
geminiTokenCache
,
antigravityOAuthService
)
antigravityGatewayService
:=
service
.
NewAntigravityGatewayService
(
accountRepository
,
gatewayCache
,
schedulerSnapshotService
,
antigravityTokenProvider
,
rateLimitService
,
httpUpstream
,
settingService
)
antigravityGatewayService
:=
service
.
NewAntigravityGatewayService
(
accountRepository
,
gatewayCache
,
schedulerSnapshotService
,
antigravityTokenProvider
,
rateLimitService
,
httpUpstream
,
settingService
)
accountTestService
:=
service
.
NewAccountTestService
(
accountRepository
,
geminiTokenProvider
,
antigravityGatewayService
,
httpUpstream
,
configConfig
)
accountTestService
:=
service
.
NewAccountTestService
(
accountRepository
,
geminiTokenProvider
,
antigravityGatewayService
,
httpUpstream
,
configConfig
)
concurrencyCache
:=
repository
.
ProvideConcurrencyCache
(
redisClient
,
configConfig
)
concurrencyService
:=
service
.
ProvideConcurrencyService
(
concurrencyCache
,
accountRepository
,
configConfig
)
crsSyncService
:=
service
.
NewCRSSyncService
(
accountRepository
,
proxyRepository
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
configConfig
)
crsSyncService
:=
service
.
NewCRSSyncService
(
accountRepository
,
proxyRepository
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
configConfig
)
sessionLimitCache
:=
repository
.
ProvideSessionLimitCache
(
redisClient
,
configConfig
)
sessionLimitCache
:=
repository
.
ProvideSessionLimitCache
(
redisClient
,
configConfig
)
accountHandler
:=
admin
.
NewAccountHandler
(
adminService
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
antigravityOAuthService
,
rateLimitService
,
accountUsageService
,
accountTestService
,
concurrencyService
,
crsSyncService
,
sessionLimitCache
,
compositeTokenCacheInvalidator
)
accountHandler
:=
admin
.
NewAccountHandler
(
adminService
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
antigravityOAuthService
,
rateLimitService
,
accountUsageService
,
accountTestService
,
concurrencyService
,
crsSyncService
,
sessionLimitCache
,
compositeTokenCacheInvalidator
)
...
@@ -154,7 +154,8 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -154,7 +154,8 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
identityService
:=
service
.
NewIdentityService
(
identityCache
)
identityService
:=
service
.
NewIdentityService
(
identityCache
)
deferredService
:=
service
.
ProvideDeferredService
(
accountRepository
,
timingWheelService
)
deferredService
:=
service
.
ProvideDeferredService
(
accountRepository
,
timingWheelService
)
claudeTokenProvider
:=
service
.
NewClaudeTokenProvider
(
accountRepository
,
geminiTokenCache
,
oAuthService
)
claudeTokenProvider
:=
service
.
NewClaudeTokenProvider
(
accountRepository
,
geminiTokenCache
,
oAuthService
)
gatewayService
:=
service
.
NewGatewayService
(
accountRepository
,
groupRepository
,
usageLogRepository
,
userRepository
,
userSubscriptionRepository
,
userGroupRateRepository
,
gatewayCache
,
configConfig
,
schedulerSnapshotService
,
concurrencyService
,
billingService
,
rateLimitService
,
billingCacheService
,
identityService
,
httpUpstream
,
deferredService
,
claudeTokenProvider
,
sessionLimitCache
)
digestSessionStore
:=
service
.
NewDigestSessionStore
()
gatewayService
:=
service
.
NewGatewayService
(
accountRepository
,
groupRepository
,
usageLogRepository
,
userRepository
,
userSubscriptionRepository
,
userGroupRateRepository
,
gatewayCache
,
configConfig
,
schedulerSnapshotService
,
concurrencyService
,
billingService
,
rateLimitService
,
billingCacheService
,
identityService
,
httpUpstream
,
deferredService
,
claudeTokenProvider
,
sessionLimitCache
,
digestSessionStore
)
openAITokenProvider
:=
service
.
NewOpenAITokenProvider
(
accountRepository
,
geminiTokenCache
,
openAIOAuthService
)
openAITokenProvider
:=
service
.
NewOpenAITokenProvider
(
accountRepository
,
geminiTokenCache
,
openAIOAuthService
)
openAIGatewayService
:=
service
.
NewOpenAIGatewayService
(
accountRepository
,
usageLogRepository
,
userRepository
,
userSubscriptionRepository
,
gatewayCache
,
configConfig
,
schedulerSnapshotService
,
concurrencyService
,
billingService
,
rateLimitService
,
billingCacheService
,
httpUpstream
,
deferredService
,
openAITokenProvider
)
openAIGatewayService
:=
service
.
NewOpenAIGatewayService
(
accountRepository
,
usageLogRepository
,
userRepository
,
userSubscriptionRepository
,
gatewayCache
,
configConfig
,
schedulerSnapshotService
,
concurrencyService
,
billingService
,
rateLimitService
,
billingCacheService
,
httpUpstream
,
deferredService
,
openAITokenProvider
)
geminiMessagesCompatService
:=
service
.
NewGeminiMessagesCompatService
(
accountRepository
,
groupRepository
,
gatewayCache
,
schedulerSnapshotService
,
geminiTokenProvider
,
rateLimitService
,
httpUpstream
,
antigravityGatewayService
,
configConfig
)
geminiMessagesCompatService
:=
service
.
NewGeminiMessagesCompatService
(
accountRepository
,
groupRepository
,
gatewayCache
,
schedulerSnapshotService
,
geminiTokenProvider
,
rateLimitService
,
httpUpstream
,
antigravityGatewayService
,
configConfig
)
...
...
backend/ent/group.go
View file @
16131c3d
...
@@ -66,6 +66,8 @@ type Group struct {
...
@@ -66,6 +66,8 @@ type Group struct {
McpXMLInject
bool
`json:"mcp_xml_inject,omitempty"`
McpXMLInject
bool
`json:"mcp_xml_inject,omitempty"`
// 支持的模型系列:claude, gemini_text, gemini_image
// 支持的模型系列:claude, gemini_text, gemini_image
SupportedModelScopes
[]
string
`json:"supported_model_scopes,omitempty"`
SupportedModelScopes
[]
string
`json:"supported_model_scopes,omitempty"`
// 分组显示排序,数值越小越靠前
SortOrder
int
`json:"sort_order,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"`
...
@@ -178,7 +180,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
...
@@ -178,7 +180,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
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
)
case
group
.
FieldID
,
group
.
FieldDefaultValidityDays
,
group
.
FieldFallbackGroupID
,
group
.
FieldFallbackGroupIDOnInvalidRequest
:
case
group
.
FieldID
,
group
.
FieldDefaultValidityDays
,
group
.
FieldFallbackGroupID
,
group
.
FieldFallbackGroupIDOnInvalidRequest
,
group
.
FieldSortOrder
:
values
[
i
]
=
new
(
sql
.
NullInt64
)
values
[
i
]
=
new
(
sql
.
NullInt64
)
case
group
.
FieldName
,
group
.
FieldDescription
,
group
.
FieldStatus
,
group
.
FieldPlatform
,
group
.
FieldSubscriptionType
:
case
group
.
FieldName
,
group
.
FieldDescription
,
group
.
FieldStatus
,
group
.
FieldPlatform
,
group
.
FieldSubscriptionType
:
values
[
i
]
=
new
(
sql
.
NullString
)
values
[
i
]
=
new
(
sql
.
NullString
)
...
@@ -363,6 +365,12 @@ func (_m *Group) assignValues(columns []string, values []any) error {
...
@@ -363,6 +365,12 @@ func (_m *Group) assignValues(columns []string, values []any) error {
return
fmt
.
Errorf
(
"unmarshal field supported_model_scopes: %w"
,
err
)
return
fmt
.
Errorf
(
"unmarshal field supported_model_scopes: %w"
,
err
)
}
}
}
}
case
group
.
FieldSortOrder
:
if
value
,
ok
:=
values
[
i
]
.
(
*
sql
.
NullInt64
);
!
ok
{
return
fmt
.
Errorf
(
"unexpected type %T for field sort_order"
,
values
[
i
])
}
else
if
value
.
Valid
{
_m
.
SortOrder
=
int
(
value
.
Int64
)
}
default
:
default
:
_m
.
selectValues
.
Set
(
columns
[
i
],
values
[
i
])
_m
.
selectValues
.
Set
(
columns
[
i
],
values
[
i
])
}
}
...
@@ -530,6 +538,9 @@ func (_m *Group) String() string {
...
@@ -530,6 +538,9 @@ func (_m *Group) String() string {
builder
.
WriteString
(
", "
)
builder
.
WriteString
(
", "
)
builder
.
WriteString
(
"supported_model_scopes="
)
builder
.
WriteString
(
"supported_model_scopes="
)
builder
.
WriteString
(
fmt
.
Sprintf
(
"%v"
,
_m
.
SupportedModelScopes
))
builder
.
WriteString
(
fmt
.
Sprintf
(
"%v"
,
_m
.
SupportedModelScopes
))
builder
.
WriteString
(
", "
)
builder
.
WriteString
(
"sort_order="
)
builder
.
WriteString
(
fmt
.
Sprintf
(
"%v"
,
_m
.
SortOrder
))
builder
.
WriteByte
(
')'
)
builder
.
WriteByte
(
')'
)
return
builder
.
String
()
return
builder
.
String
()
}
}
...
...
backend/ent/group/group.go
View file @
16131c3d
...
@@ -63,6 +63,8 @@ const (
...
@@ -63,6 +63,8 @@ const (
FieldMcpXMLInject
=
"mcp_xml_inject"
FieldMcpXMLInject
=
"mcp_xml_inject"
// FieldSupportedModelScopes holds the string denoting the supported_model_scopes field in the database.
// FieldSupportedModelScopes holds the string denoting the supported_model_scopes field in the database.
FieldSupportedModelScopes
=
"supported_model_scopes"
FieldSupportedModelScopes
=
"supported_model_scopes"
// FieldSortOrder holds the string denoting the sort_order field in the database.
FieldSortOrder
=
"sort_order"
// 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.
...
@@ -162,6 +164,7 @@ var Columns = []string{
...
@@ -162,6 +164,7 @@ var Columns = []string{
FieldModelRoutingEnabled
,
FieldModelRoutingEnabled
,
FieldMcpXMLInject
,
FieldMcpXMLInject
,
FieldSupportedModelScopes
,
FieldSupportedModelScopes
,
FieldSortOrder
,
}
}
var
(
var
(
...
@@ -225,6 +228,8 @@ var (
...
@@ -225,6 +228,8 @@ var (
DefaultMcpXMLInject
bool
DefaultMcpXMLInject
bool
// DefaultSupportedModelScopes holds the default value on creation for the "supported_model_scopes" field.
// DefaultSupportedModelScopes holds the default value on creation for the "supported_model_scopes" field.
DefaultSupportedModelScopes
[]
string
DefaultSupportedModelScopes
[]
string
// DefaultSortOrder holds the default value on creation for the "sort_order" field.
DefaultSortOrder
int
)
)
// OrderOption defines the ordering options for the Group queries.
// OrderOption defines the ordering options for the Group queries.
...
@@ -345,6 +350,11 @@ func ByMcpXMLInject(opts ...sql.OrderTermOption) OrderOption {
...
@@ -345,6 +350,11 @@ func ByMcpXMLInject(opts ...sql.OrderTermOption) OrderOption {
return
sql
.
OrderByField
(
FieldMcpXMLInject
,
opts
...
)
.
ToFunc
()
return
sql
.
OrderByField
(
FieldMcpXMLInject
,
opts
...
)
.
ToFunc
()
}
}
// BySortOrder orders the results by the sort_order field.
func
BySortOrder
(
opts
...
sql
.
OrderTermOption
)
OrderOption
{
return
sql
.
OrderByField
(
FieldSortOrder
,
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
)
{
...
...
backend/ent/group/where.go
View file @
16131c3d
...
@@ -165,6 +165,11 @@ func McpXMLInject(v bool) predicate.Group {
...
@@ -165,6 +165,11 @@ func McpXMLInject(v bool) predicate.Group {
return
predicate
.
Group
(
sql
.
FieldEQ
(
FieldMcpXMLInject
,
v
))
return
predicate
.
Group
(
sql
.
FieldEQ
(
FieldMcpXMLInject
,
v
))
}
}
// SortOrder applies equality check predicate on the "sort_order" field. It's identical to SortOrderEQ.
func
SortOrder
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldEQ
(
FieldSortOrder
,
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
))
...
@@ -1160,6 +1165,46 @@ func McpXMLInjectNEQ(v bool) predicate.Group {
...
@@ -1160,6 +1165,46 @@ func McpXMLInjectNEQ(v bool) predicate.Group {
return
predicate
.
Group
(
sql
.
FieldNEQ
(
FieldMcpXMLInject
,
v
))
return
predicate
.
Group
(
sql
.
FieldNEQ
(
FieldMcpXMLInject
,
v
))
}
}
// SortOrderEQ applies the EQ predicate on the "sort_order" field.
func
SortOrderEQ
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldEQ
(
FieldSortOrder
,
v
))
}
// SortOrderNEQ applies the NEQ predicate on the "sort_order" field.
func
SortOrderNEQ
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldNEQ
(
FieldSortOrder
,
v
))
}
// SortOrderIn applies the In predicate on the "sort_order" field.
func
SortOrderIn
(
vs
...
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldIn
(
FieldSortOrder
,
vs
...
))
}
// SortOrderNotIn applies the NotIn predicate on the "sort_order" field.
func
SortOrderNotIn
(
vs
...
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldNotIn
(
FieldSortOrder
,
vs
...
))
}
// SortOrderGT applies the GT predicate on the "sort_order" field.
func
SortOrderGT
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldGT
(
FieldSortOrder
,
v
))
}
// SortOrderGTE applies the GTE predicate on the "sort_order" field.
func
SortOrderGTE
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldGTE
(
FieldSortOrder
,
v
))
}
// SortOrderLT applies the LT predicate on the "sort_order" field.
func
SortOrderLT
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldLT
(
FieldSortOrder
,
v
))
}
// SortOrderLTE applies the LTE predicate on the "sort_order" field.
func
SortOrderLTE
(
v
int
)
predicate
.
Group
{
return
predicate
.
Group
(
sql
.
FieldLTE
(
FieldSortOrder
,
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
)
{
...
...
backend/ent/group_create.go
View file @
16131c3d
...
@@ -340,6 +340,20 @@ func (_c *GroupCreate) SetSupportedModelScopes(v []string) *GroupCreate {
...
@@ -340,6 +340,20 @@ func (_c *GroupCreate) SetSupportedModelScopes(v []string) *GroupCreate {
return
_c
return
_c
}
}
// SetSortOrder sets the "sort_order" field.
func
(
_c
*
GroupCreate
)
SetSortOrder
(
v
int
)
*
GroupCreate
{
_c
.
mutation
.
SetSortOrder
(
v
)
return
_c
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func
(
_c
*
GroupCreate
)
SetNillableSortOrder
(
v
*
int
)
*
GroupCreate
{
if
v
!=
nil
{
_c
.
SetSortOrder
(
*
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
...
)
...
@@ -521,6 +535,10 @@ func (_c *GroupCreate) defaults() error {
...
@@ -521,6 +535,10 @@ func (_c *GroupCreate) defaults() error {
v
:=
group
.
DefaultSupportedModelScopes
v
:=
group
.
DefaultSupportedModelScopes
_c
.
mutation
.
SetSupportedModelScopes
(
v
)
_c
.
mutation
.
SetSupportedModelScopes
(
v
)
}
}
if
_
,
ok
:=
_c
.
mutation
.
SortOrder
();
!
ok
{
v
:=
group
.
DefaultSortOrder
_c
.
mutation
.
SetSortOrder
(
v
)
}
return
nil
return
nil
}
}
...
@@ -585,6 +603,9 @@ func (_c *GroupCreate) check() error {
...
@@ -585,6 +603,9 @@ func (_c *GroupCreate) check() error {
if
_
,
ok
:=
_c
.
mutation
.
SupportedModelScopes
();
!
ok
{
if
_
,
ok
:=
_c
.
mutation
.
SupportedModelScopes
();
!
ok
{
return
&
ValidationError
{
Name
:
"supported_model_scopes"
,
err
:
errors
.
New
(
`ent: missing required field "Group.supported_model_scopes"`
)}
return
&
ValidationError
{
Name
:
"supported_model_scopes"
,
err
:
errors
.
New
(
`ent: missing required field "Group.supported_model_scopes"`
)}
}
}
if
_
,
ok
:=
_c
.
mutation
.
SortOrder
();
!
ok
{
return
&
ValidationError
{
Name
:
"sort_order"
,
err
:
errors
.
New
(
`ent: missing required field "Group.sort_order"`
)}
}
return
nil
return
nil
}
}
...
@@ -708,6 +729,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
...
@@ -708,6 +729,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
_spec
.
SetField
(
group
.
FieldSupportedModelScopes
,
field
.
TypeJSON
,
value
)
_spec
.
SetField
(
group
.
FieldSupportedModelScopes
,
field
.
TypeJSON
,
value
)
_node
.
SupportedModelScopes
=
value
_node
.
SupportedModelScopes
=
value
}
}
if
value
,
ok
:=
_c
.
mutation
.
SortOrder
();
ok
{
_spec
.
SetField
(
group
.
FieldSortOrder
,
field
.
TypeInt
,
value
)
_node
.
SortOrder
=
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
,
...
@@ -1266,6 +1291,24 @@ func (u *GroupUpsert) UpdateSupportedModelScopes() *GroupUpsert {
...
@@ -1266,6 +1291,24 @@ func (u *GroupUpsert) UpdateSupportedModelScopes() *GroupUpsert {
return
u
return
u
}
}
// SetSortOrder sets the "sort_order" field.
func
(
u
*
GroupUpsert
)
SetSortOrder
(
v
int
)
*
GroupUpsert
{
u
.
Set
(
group
.
FieldSortOrder
,
v
)
return
u
}
// UpdateSortOrder sets the "sort_order" field to the value that was provided on create.
func
(
u
*
GroupUpsert
)
UpdateSortOrder
()
*
GroupUpsert
{
u
.
SetExcluded
(
group
.
FieldSortOrder
)
return
u
}
// AddSortOrder adds v to the "sort_order" field.
func
(
u
*
GroupUpsert
)
AddSortOrder
(
v
int
)
*
GroupUpsert
{
u
.
Add
(
group
.
FieldSortOrder
,
v
)
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:
//
//
...
@@ -1780,6 +1823,27 @@ func (u *GroupUpsertOne) UpdateSupportedModelScopes() *GroupUpsertOne {
...
@@ -1780,6 +1823,27 @@ func (u *GroupUpsertOne) UpdateSupportedModelScopes() *GroupUpsertOne {
})
})
}
}
// SetSortOrder sets the "sort_order" field.
func
(
u
*
GroupUpsertOne
)
SetSortOrder
(
v
int
)
*
GroupUpsertOne
{
return
u
.
Update
(
func
(
s
*
GroupUpsert
)
{
s
.
SetSortOrder
(
v
)
})
}
// AddSortOrder adds v to the "sort_order" field.
func
(
u
*
GroupUpsertOne
)
AddSortOrder
(
v
int
)
*
GroupUpsertOne
{
return
u
.
Update
(
func
(
s
*
GroupUpsert
)
{
s
.
AddSortOrder
(
v
)
})
}
// UpdateSortOrder sets the "sort_order" field to the value that was provided on create.
func
(
u
*
GroupUpsertOne
)
UpdateSortOrder
()
*
GroupUpsertOne
{
return
u
.
Update
(
func
(
s
*
GroupUpsert
)
{
s
.
UpdateSortOrder
()
})
}
// 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
{
...
@@ -2460,6 +2524,27 @@ func (u *GroupUpsertBulk) UpdateSupportedModelScopes() *GroupUpsertBulk {
...
@@ -2460,6 +2524,27 @@ func (u *GroupUpsertBulk) UpdateSupportedModelScopes() *GroupUpsertBulk {
})
})
}
}
// SetSortOrder sets the "sort_order" field.
func
(
u
*
GroupUpsertBulk
)
SetSortOrder
(
v
int
)
*
GroupUpsertBulk
{
return
u
.
Update
(
func
(
s
*
GroupUpsert
)
{
s
.
SetSortOrder
(
v
)
})
}
// AddSortOrder adds v to the "sort_order" field.
func
(
u
*
GroupUpsertBulk
)
AddSortOrder
(
v
int
)
*
GroupUpsertBulk
{
return
u
.
Update
(
func
(
s
*
GroupUpsert
)
{
s
.
AddSortOrder
(
v
)
})
}
// UpdateSortOrder sets the "sort_order" field to the value that was provided on create.
func
(
u
*
GroupUpsertBulk
)
UpdateSortOrder
()
*
GroupUpsertBulk
{
return
u
.
Update
(
func
(
s
*
GroupUpsert
)
{
s
.
UpdateSortOrder
()
})
}
// 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 @
16131c3d
...
@@ -475,6 +475,27 @@ func (_u *GroupUpdate) AppendSupportedModelScopes(v []string) *GroupUpdate {
...
@@ -475,6 +475,27 @@ func (_u *GroupUpdate) AppendSupportedModelScopes(v []string) *GroupUpdate {
return
_u
return
_u
}
}
// SetSortOrder sets the "sort_order" field.
func
(
_u
*
GroupUpdate
)
SetSortOrder
(
v
int
)
*
GroupUpdate
{
_u
.
mutation
.
ResetSortOrder
()
_u
.
mutation
.
SetSortOrder
(
v
)
return
_u
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func
(
_u
*
GroupUpdate
)
SetNillableSortOrder
(
v
*
int
)
*
GroupUpdate
{
if
v
!=
nil
{
_u
.
SetSortOrder
(
*
v
)
}
return
_u
}
// AddSortOrder adds value to the "sort_order" field.
func
(
_u
*
GroupUpdate
)
AddSortOrder
(
v
int
)
*
GroupUpdate
{
_u
.
mutation
.
AddSortOrder
(
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
...
)
...
@@ -912,6 +933,12 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
...
@@ -912,6 +933,12 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
sqljson
.
Append
(
u
,
group
.
FieldSupportedModelScopes
,
value
)
sqljson
.
Append
(
u
,
group
.
FieldSupportedModelScopes
,
value
)
})
})
}
}
if
value
,
ok
:=
_u
.
mutation
.
SortOrder
();
ok
{
_spec
.
SetField
(
group
.
FieldSortOrder
,
field
.
TypeInt
,
value
)
}
if
value
,
ok
:=
_u
.
mutation
.
AddedSortOrder
();
ok
{
_spec
.
AddField
(
group
.
FieldSortOrder
,
field
.
TypeInt
,
value
)
}
if
_u
.
mutation
.
APIKeysCleared
()
{
if
_u
.
mutation
.
APIKeysCleared
()
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
edge
:=
&
sqlgraph
.
EdgeSpec
{
Rel
:
sqlgraph
.
O2M
,
Rel
:
sqlgraph
.
O2M
,
...
@@ -1666,6 +1693,27 @@ func (_u *GroupUpdateOne) AppendSupportedModelScopes(v []string) *GroupUpdateOne
...
@@ -1666,6 +1693,27 @@ func (_u *GroupUpdateOne) AppendSupportedModelScopes(v []string) *GroupUpdateOne
return
_u
return
_u
}
}
// SetSortOrder sets the "sort_order" field.
func
(
_u
*
GroupUpdateOne
)
SetSortOrder
(
v
int
)
*
GroupUpdateOne
{
_u
.
mutation
.
ResetSortOrder
()
_u
.
mutation
.
SetSortOrder
(
v
)
return
_u
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func
(
_u
*
GroupUpdateOne
)
SetNillableSortOrder
(
v
*
int
)
*
GroupUpdateOne
{
if
v
!=
nil
{
_u
.
SetSortOrder
(
*
v
)
}
return
_u
}
// AddSortOrder adds value to the "sort_order" field.
func
(
_u
*
GroupUpdateOne
)
AddSortOrder
(
v
int
)
*
GroupUpdateOne
{
_u
.
mutation
.
AddSortOrder
(
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
...
)
...
@@ -2133,6 +2181,12 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
...
@@ -2133,6 +2181,12 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
sqljson
.
Append
(
u
,
group
.
FieldSupportedModelScopes
,
value
)
sqljson
.
Append
(
u
,
group
.
FieldSupportedModelScopes
,
value
)
})
})
}
}
if
value
,
ok
:=
_u
.
mutation
.
SortOrder
();
ok
{
_spec
.
SetField
(
group
.
FieldSortOrder
,
field
.
TypeInt
,
value
)
}
if
value
,
ok
:=
_u
.
mutation
.
AddedSortOrder
();
ok
{
_spec
.
AddField
(
group
.
FieldSortOrder
,
field
.
TypeInt
,
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 @
16131c3d
...
@@ -372,6 +372,7 @@ var (
...
@@ -372,6 +372,7 @@ var (
{
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"
}},
{
Name
:
"supported_model_scopes"
,
Type
:
field
.
TypeJSON
,
SchemaType
:
map
[
string
]
string
{
"postgres"
:
"jsonb"
}},
{
Name
:
"sort_order"
,
Type
:
field
.
TypeInt
,
Default
:
0
},
}
}
// GroupsTable holds the schema information for the "groups" table.
// GroupsTable holds the schema information for the "groups" table.
GroupsTable
=
&
schema
.
Table
{
GroupsTable
=
&
schema
.
Table
{
...
@@ -404,6 +405,11 @@ var (
...
@@ -404,6 +405,11 @@ var (
Unique
:
false
,
Unique
:
false
,
Columns
:
[]
*
schema
.
Column
{
GroupsColumns
[
3
]},
Columns
:
[]
*
schema
.
Column
{
GroupsColumns
[
3
]},
},
},
{
Name
:
"group_sort_order"
,
Unique
:
false
,
Columns
:
[]
*
schema
.
Column
{
GroupsColumns
[
25
]},
},
},
},
}
}
// PromoCodesColumns holds the columns for the "promo_codes" table.
// PromoCodesColumns holds the columns for the "promo_codes" table.
...
...
backend/ent/mutation.go
View file @
16131c3d
...
@@ -7059,6 +7059,8 @@ type GroupMutation struct {
...
@@ -7059,6 +7059,8 @@ type GroupMutation struct {
mcp_xml_inject *bool
mcp_xml_inject *bool
supported_model_scopes *[]string
supported_model_scopes *[]string
appendsupported_model_scopes []string
appendsupported_model_scopes []string
sort_order *int
addsort_order *int
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{}
...
@@ -8411,6 +8413,62 @@ func (m *GroupMutation) ResetSupportedModelScopes() {
...
@@ -8411,6 +8413,62 @@ func (m *GroupMutation) ResetSupportedModelScopes() {
m.appendsupported_model_scopes = nil
m.appendsupported_model_scopes = nil
}
}
// SetSortOrder sets the "sort_order" field.
func (m *GroupMutation) SetSortOrder(i int) {
m.sort_order = &i
m.addsort_order = nil
}
// SortOrder returns the value of the "sort_order" field in the mutation.
func (m *GroupMutation) SortOrder() (r int, exists bool) {
v := m.sort_order
if v == nil {
return
}
return *v, true
}
// OldSortOrder returns the old "sort_order" 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) OldSortOrder(ctx context.Context) (v int, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldSortOrder is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldSortOrder requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldSortOrder: %w", err)
}
return oldValue.SortOrder, nil
}
// AddSortOrder adds i to the "sort_order" field.
func (m *GroupMutation) AddSortOrder(i int) {
if m.addsort_order != nil {
*m.addsort_order += i
} else {
m.addsort_order = &i
}
}
// AddedSortOrder returns the value that was added to the "sort_order" field in this mutation.
func (m *GroupMutation) AddedSortOrder() (r int, exists bool) {
v := m.addsort_order
if v == nil {
return
}
return *v, true
}
// ResetSortOrder resets all changes to the "sort_order" field.
func (m *GroupMutation) ResetSortOrder() {
m.sort_order = nil
m.addsort_order = 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 {
...
@@ -8769,7 +8827,7 @@ func (m *GroupMutation) Type() string {
...
@@ -8769,7 +8827,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
4
)
fields := make([]string, 0, 2
5
)
if m.created_at != nil {
if m.created_at != nil {
fields = append(fields, group.FieldCreatedAt)
fields = append(fields, group.FieldCreatedAt)
}
}
...
@@ -8842,6 +8900,9 @@ func (m *GroupMutation) Fields() []string {
...
@@ -8842,6 +8900,9 @@ func (m *GroupMutation) Fields() []string {
if m.supported_model_scopes != nil {
if m.supported_model_scopes != nil {
fields = append(fields, group.FieldSupportedModelScopes)
fields = append(fields, group.FieldSupportedModelScopes)
}
}
if m.sort_order != nil {
fields = append(fields, group.FieldSortOrder)
}
return fields
return fields
}
}
...
@@ -8898,6 +8959,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
...
@@ -8898,6 +8959,8 @@ func (m *GroupMutation) Field(name string) (ent.Value, bool) {
return m.McpXMLInject()
return m.McpXMLInject()
case group.FieldSupportedModelScopes:
case group.FieldSupportedModelScopes:
return m.SupportedModelScopes()
return m.SupportedModelScopes()
case group.FieldSortOrder:
return m.SortOrder()
}
}
return nil, false
return nil, false
}
}
...
@@ -8955,6 +9018,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
...
@@ -8955,6 +9018,8 @@ func (m *GroupMutation) OldField(ctx context.Context, name string) (ent.Value, e
return m.OldMcpXMLInject(ctx)
return m.OldMcpXMLInject(ctx)
case group.FieldSupportedModelScopes:
case group.FieldSupportedModelScopes:
return m.OldSupportedModelScopes(ctx)
return m.OldSupportedModelScopes(ctx)
case group.FieldSortOrder:
return m.OldSortOrder(ctx)
}
}
return nil, fmt.Errorf("unknown Group field %s", name)
return nil, fmt.Errorf("unknown Group field %s", name)
}
}
...
@@ -9132,6 +9197,13 @@ func (m *GroupMutation) SetField(name string, value ent.Value) error {
...
@@ -9132,6 +9197,13 @@ func (m *GroupMutation) SetField(name string, value ent.Value) error {
}
}
m.SetSupportedModelScopes(v)
m.SetSupportedModelScopes(v)
return nil
return nil
case group.FieldSortOrder:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetSortOrder(v)
return nil
}
}
return fmt.Errorf("unknown Group field %s", name)
return fmt.Errorf("unknown Group field %s", name)
}
}
...
@@ -9170,6 +9242,9 @@ func (m *GroupMutation) AddedFields() []string {
...
@@ -9170,6 +9242,9 @@ func (m *GroupMutation) AddedFields() []string {
if m.addfallback_group_id_on_invalid_request != nil {
if m.addfallback_group_id_on_invalid_request != nil {
fields = append(fields, group.FieldFallbackGroupIDOnInvalidRequest)
fields = append(fields, group.FieldFallbackGroupIDOnInvalidRequest)
}
}
if m.addsort_order != nil {
fields = append(fields, group.FieldSortOrder)
}
return fields
return fields
}
}
...
@@ -9198,6 +9273,8 @@ func (m *GroupMutation) AddedField(name string) (ent.Value, bool) {
...
@@ -9198,6 +9273,8 @@ func (m *GroupMutation) AddedField(name string) (ent.Value, bool) {
return m.AddedFallbackGroupID()
return m.AddedFallbackGroupID()
case group.FieldFallbackGroupIDOnInvalidRequest:
case group.FieldFallbackGroupIDOnInvalidRequest:
return m.AddedFallbackGroupIDOnInvalidRequest()
return m.AddedFallbackGroupIDOnInvalidRequest()
case group.FieldSortOrder:
return m.AddedSortOrder()
}
}
return nil, false
return nil, false
}
}
...
@@ -9277,6 +9354,13 @@ func (m *GroupMutation) AddField(name string, value ent.Value) error {
...
@@ -9277,6 +9354,13 @@ func (m *GroupMutation) AddField(name string, value ent.Value) error {
}
}
m.AddFallbackGroupIDOnInvalidRequest(v)
m.AddFallbackGroupIDOnInvalidRequest(v)
return nil
return nil
case group.FieldSortOrder:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddSortOrder(v)
return nil
}
}
return fmt.Errorf("unknown Group numeric field %s", name)
return fmt.Errorf("unknown Group numeric field %s", name)
}
}
...
@@ -9445,6 +9529,9 @@ func (m *GroupMutation) ResetField(name string) error {
...
@@ -9445,6 +9529,9 @@ func (m *GroupMutation) ResetField(name string) error {
case group.FieldSupportedModelScopes:
case group.FieldSupportedModelScopes:
m.ResetSupportedModelScopes()
m.ResetSupportedModelScopes()
return nil
return nil
case group.FieldSortOrder:
m.ResetSortOrder()
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 @
16131c3d
...
@@ -409,6 +409,10 @@ func init() {
...
@@ -409,6 +409,10 @@ func init() {
groupDescSupportedModelScopes
:=
groupFields
[
20
]
.
Descriptor
()
groupDescSupportedModelScopes
:=
groupFields
[
20
]
.
Descriptor
()
// group.DefaultSupportedModelScopes holds the default value on creation for the supported_model_scopes field.
// group.DefaultSupportedModelScopes holds the default value on creation for the supported_model_scopes field.
group
.
DefaultSupportedModelScopes
=
groupDescSupportedModelScopes
.
Default
.
([]
string
)
group
.
DefaultSupportedModelScopes
=
groupDescSupportedModelScopes
.
Default
.
([]
string
)
// groupDescSortOrder is the schema descriptor for sort_order field.
groupDescSortOrder
:=
groupFields
[
21
]
.
Descriptor
()
// group.DefaultSortOrder holds the default value on creation for the sort_order field.
group
.
DefaultSortOrder
=
groupDescSortOrder
.
Default
.
(
int
)
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 @
16131c3d
...
@@ -121,6 +121,11 @@ func (Group) Fields() []ent.Field {
...
@@ -121,6 +121,11 @@ func (Group) Fields() []ent.Field {
Default
([]
string
{
"claude"
,
"gemini_text"
,
"gemini_image"
})
.
Default
([]
string
{
"claude"
,
"gemini_text"
,
"gemini_image"
})
.
SchemaType
(
map
[
string
]
string
{
dialect
.
Postgres
:
"jsonb"
})
.
SchemaType
(
map
[
string
]
string
{
dialect
.
Postgres
:
"jsonb"
})
.
Comment
(
"支持的模型系列:claude, gemini_text, gemini_image"
),
Comment
(
"支持的模型系列:claude, gemini_text, gemini_image"
),
// 分组排序 (added by migration 052)
field
.
Int
(
"sort_order"
)
.
Default
(
0
)
.
Comment
(
"分组显示排序,数值越小越靠前"
),
}
}
}
}
...
@@ -149,5 +154,6 @@ func (Group) Indexes() []ent.Index {
...
@@ -149,5 +154,6 @@ func (Group) Indexes() []ent.Index {
index
.
Fields
(
"subscription_type"
),
index
.
Fields
(
"subscription_type"
),
index
.
Fields
(
"is_exclusive"
),
index
.
Fields
(
"is_exclusive"
),
index
.
Fields
(
"deleted_at"
),
index
.
Fields
(
"deleted_at"
),
index
.
Fields
(
"sort_order"
),
}
}
}
}
backend/go.mod
View file @
16131c3d
...
@@ -103,6 +103,7 @@ require (
...
@@ -103,6 +103,7 @@ require (
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/ncruces/go-strftime v1.0.0 // 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
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
...
...
backend/go.sum
View file @
16131c3d
...
@@ -135,6 +135,8 @@ github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
...
@@ -135,6 +135,8 @@ github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
github.com/imroc/req/v3 v3.57.0 h1:LMTUjNRUybUkTPn8oJDq8Kg3JRBOBTcnDhKu7mzupKI=
github.com/imroc/req/v3 v3.57.0 h1:LMTUjNRUybUkTPn8oJDq8Kg3JRBOBTcnDhKu7mzupKI=
github.com/imroc/req/v3 v3.57.0/go.mod h1:JL62ey1nvSLq81HORNcosvlf7SxZStONNqOprg0Pz00=
github.com/imroc/req/v3 v3.57.0/go.mod h1:JL62ey1nvSLq81HORNcosvlf7SxZStONNqOprg0Pz00=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
...
@@ -170,6 +172,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
...
@@ -170,6 +172,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
...
@@ -203,10 +207,14 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
...
@@ -203,10 +207,14 @@ 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 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
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/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=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
...
@@ -230,6 +238,8 @@ github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkr
...
@@ -230,6 +238,8 @@ github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkr
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 h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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/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=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
...
@@ -252,6 +262,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
...
@@ -252,6 +262,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
...
...
backend/internal/handler/admin/account_handler.go
View file @
16131c3d
...
@@ -429,6 +429,13 @@ type SyncFromCRSRequest struct {
...
@@ -429,6 +429,13 @@ type SyncFromCRSRequest struct {
Username
string
`json:"username" binding:"required"`
Username
string
`json:"username" binding:"required"`
Password
string
`json:"password" binding:"required"`
Password
string
`json:"password" binding:"required"`
SyncProxies
*
bool
`json:"sync_proxies"`
SyncProxies
*
bool
`json:"sync_proxies"`
SelectedAccountIDs
[]
string
`json:"selected_account_ids"`
}
type
PreviewFromCRSRequest
struct
{
BaseURL
string
`json:"base_url" binding:"required"`
Username
string
`json:"username" binding:"required"`
Password
string
`json:"password" binding:"required"`
}
}
// Test handles testing account connectivity with SSE streaming
// Test handles testing account connectivity with SSE streaming
...
@@ -471,6 +478,7 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
...
@@ -471,6 +478,7 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
Username
:
req
.
Username
,
Username
:
req
.
Username
,
Password
:
req
.
Password
,
Password
:
req
.
Password
,
SyncProxies
:
syncProxies
,
SyncProxies
:
syncProxies
,
SelectedAccountIDs
:
req
.
SelectedAccountIDs
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
// Provide detailed error message for CRS sync failures
// Provide detailed error message for CRS sync failures
...
@@ -481,6 +489,28 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
...
@@ -481,6 +489,28 @@ func (h *AccountHandler) SyncFromCRS(c *gin.Context) {
response
.
Success
(
c
,
result
)
response
.
Success
(
c
,
result
)
}
}
// PreviewFromCRS handles previewing accounts from CRS before sync
// POST /api/v1/admin/accounts/sync/crs/preview
func
(
h
*
AccountHandler
)
PreviewFromCRS
(
c
*
gin
.
Context
)
{
var
req
PreviewFromCRSRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid request: "
+
err
.
Error
())
return
}
result
,
err
:=
h
.
crsSyncService
.
PreviewFromCRS
(
c
.
Request
.
Context
(),
service
.
SyncFromCRSInput
{
BaseURL
:
req
.
BaseURL
,
Username
:
req
.
Username
,
Password
:
req
.
Password
,
})
if
err
!=
nil
{
response
.
InternalError
(
c
,
"CRS preview failed: "
+
err
.
Error
())
return
}
response
.
Success
(
c
,
result
)
}
// Refresh handles refreshing account credentials
// Refresh handles refreshing account credentials
// POST /api/v1/admin/accounts/:id/refresh
// POST /api/v1/admin/accounts/:id/refresh
func
(
h
*
AccountHandler
)
Refresh
(
c
*
gin
.
Context
)
{
func
(
h
*
AccountHandler
)
Refresh
(
c
*
gin
.
Context
)
{
...
...
backend/internal/handler/admin/admin_basic_handlers_test.go
View file @
16131c3d
...
@@ -16,7 +16,7 @@ func setupAdminRouter() (*gin.Engine, *stubAdminService) {
...
@@ -16,7 +16,7 @@ func setupAdminRouter() (*gin.Engine, *stubAdminService) {
router
:=
gin
.
New
()
router
:=
gin
.
New
()
adminSvc
:=
newStubAdminService
()
adminSvc
:=
newStubAdminService
()
userHandler
:=
NewUserHandler
(
adminSvc
)
userHandler
:=
NewUserHandler
(
adminSvc
,
nil
)
groupHandler
:=
NewGroupHandler
(
adminSvc
)
groupHandler
:=
NewGroupHandler
(
adminSvc
)
proxyHandler
:=
NewProxyHandler
(
adminSvc
)
proxyHandler
:=
NewProxyHandler
(
adminSvc
)
redeemHandler
:=
NewRedeemHandler
(
adminSvc
)
redeemHandler
:=
NewRedeemHandler
(
adminSvc
)
...
...
backend/internal/handler/admin/admin_service_stub_test.go
View file @
16131c3d
...
@@ -357,5 +357,9 @@ func (s *stubAdminService) GetUserBalanceHistory(ctx context.Context, userID int
...
@@ -357,5 +357,9 @@ func (s *stubAdminService) GetUserBalanceHistory(ctx context.Context, userID int
return
s
.
redeems
,
int64
(
len
(
s
.
redeems
)),
100.0
,
nil
return
s
.
redeems
,
int64
(
len
(
s
.
redeems
)),
100.0
,
nil
}
}
func
(
s
*
stubAdminService
)
UpdateGroupSortOrders
(
ctx
context
.
Context
,
updates
[]
service
.
GroupSortOrderUpdate
)
error
{
return
nil
}
// Ensure stub implements interface.
// Ensure stub implements interface.
var
_
service
.
AdminService
=
(
*
stubAdminService
)(
nil
)
var
_
service
.
AdminService
=
(
*
stubAdminService
)(
nil
)
backend/internal/handler/admin/group_handler.go
View file @
16131c3d
...
@@ -302,3 +302,36 @@ func (h *GroupHandler) GetGroupAPIKeys(c *gin.Context) {
...
@@ -302,3 +302,36 @@ func (h *GroupHandler) GetGroupAPIKeys(c *gin.Context) {
}
}
response
.
Paginated
(
c
,
outKeys
,
total
,
page
,
pageSize
)
response
.
Paginated
(
c
,
outKeys
,
total
,
page
,
pageSize
)
}
}
// UpdateSortOrderRequest represents the request to update group sort orders
type
UpdateSortOrderRequest
struct
{
Updates
[]
struct
{
ID
int64
`json:"id" binding:"required"`
SortOrder
int
`json:"sort_order"`
}
`json:"updates" binding:"required,min=1"`
}
// UpdateSortOrder handles updating group sort orders
// PUT /api/v1/admin/groups/sort-order
func
(
h
*
GroupHandler
)
UpdateSortOrder
(
c
*
gin
.
Context
)
{
var
req
UpdateSortOrderRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid request: "
+
err
.
Error
())
return
}
updates
:=
make
([]
service
.
GroupSortOrderUpdate
,
0
,
len
(
req
.
Updates
))
for
_
,
u
:=
range
req
.
Updates
{
updates
=
append
(
updates
,
service
.
GroupSortOrderUpdate
{
ID
:
u
.
ID
,
SortOrder
:
u
.
SortOrder
,
})
}
if
err
:=
h
.
adminService
.
UpdateGroupSortOrders
(
c
.
Request
.
Context
(),
updates
);
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
gin
.
H
{
"message"
:
"Sort order updated successfully"
})
}
backend/internal/handler/admin/user_handler.go
View file @
16131c3d
...
@@ -11,15 +11,23 @@ import (
...
@@ -11,15 +11,23 @@ import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
)
// UserWithConcurrency wraps AdminUser with current concurrency info
type
UserWithConcurrency
struct
{
dto
.
AdminUser
CurrentConcurrency
int
`json:"current_concurrency"`
}
// UserHandler handles admin user management
// UserHandler handles admin user management
type
UserHandler
struct
{
type
UserHandler
struct
{
adminService
service
.
AdminService
adminService
service
.
AdminService
concurrencyService
*
service
.
ConcurrencyService
}
}
// NewUserHandler creates a new admin user handler
// NewUserHandler creates a new admin user handler
func
NewUserHandler
(
adminService
service
.
AdminService
)
*
UserHandler
{
func
NewUserHandler
(
adminService
service
.
AdminService
,
concurrencyService
*
service
.
ConcurrencyService
)
*
UserHandler
{
return
&
UserHandler
{
return
&
UserHandler
{
adminService
:
adminService
,
adminService
:
adminService
,
concurrencyService
:
concurrencyService
,
}
}
}
}
...
@@ -87,10 +95,30 @@ func (h *UserHandler) List(c *gin.Context) {
...
@@ -87,10 +95,30 @@ func (h *UserHandler) List(c *gin.Context) {
return
return
}
}
out
:=
make
([]
dto
.
AdminUser
,
0
,
len
(
users
))
// Batch get current concurrency (nil map if unavailable)
var
loadInfo
map
[
int64
]
*
service
.
UserLoadInfo
if
len
(
users
)
>
0
&&
h
.
concurrencyService
!=
nil
{
usersConcurrency
:=
make
([]
service
.
UserWithConcurrency
,
len
(
users
))
for
i
:=
range
users
{
usersConcurrency
[
i
]
=
service
.
UserWithConcurrency
{
ID
:
users
[
i
]
.
ID
,
MaxConcurrency
:
users
[
i
]
.
Concurrency
,
}
}
loadInfo
,
_
=
h
.
concurrencyService
.
GetUsersLoadBatch
(
c
.
Request
.
Context
(),
usersConcurrency
)
}
// Build response with concurrency info
out
:=
make
([]
UserWithConcurrency
,
len
(
users
))
for
i
:=
range
users
{
for
i
:=
range
users
{
out
=
append
(
out
,
*
dto
.
UserFromServiceAdmin
(
&
users
[
i
]))
out
[
i
]
=
UserWithConcurrency
{
AdminUser
:
*
dto
.
UserFromServiceAdmin
(
&
users
[
i
]),
}
if
info
:=
loadInfo
[
users
[
i
]
.
ID
];
info
!=
nil
{
out
[
i
]
.
CurrentConcurrency
=
info
.
CurrentConcurrency
}
}
}
response
.
Paginated
(
c
,
out
,
total
,
page
,
pageSize
)
response
.
Paginated
(
c
,
out
,
total
,
page
,
pageSize
)
}
}
...
...
backend/internal/handler/dto/mappers.go
View file @
16131c3d
...
@@ -115,6 +115,7 @@ func GroupFromServiceAdmin(g *service.Group) *AdminGroup {
...
@@ -115,6 +115,7 @@ func GroupFromServiceAdmin(g *service.Group) *AdminGroup {
MCPXMLInject
:
g
.
MCPXMLInject
,
MCPXMLInject
:
g
.
MCPXMLInject
,
SupportedModelScopes
:
g
.
SupportedModelScopes
,
SupportedModelScopes
:
g
.
SupportedModelScopes
,
AccountCount
:
g
.
AccountCount
,
AccountCount
:
g
.
AccountCount
,
SortOrder
:
g
.
SortOrder
,
}
}
if
len
(
g
.
AccountGroups
)
>
0
{
if
len
(
g
.
AccountGroups
)
>
0
{
out
.
AccountGroups
=
make
([]
AccountGroup
,
0
,
len
(
g
.
AccountGroups
))
out
.
AccountGroups
=
make
([]
AccountGroup
,
0
,
len
(
g
.
AccountGroups
))
...
...
Prev
1
2
3
4
5
6
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