diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index b6c9c3c7b..c491cc9ff 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -296,11 +296,11 @@ func (b *BaseApi) DeleteHermesChatSession(c *gin.Context) { } // @Tags AI -// @Summary Get Providers +// @Summary Get model account providers // @Success 200 {array} dto.ProviderInfo // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/providers [get] +// @Router /ai/accounts/providers [get] func (b *BaseApi) GetAgentProviders(c *gin.Context) { list, err := agentService.GetProviders() if err != nil { @@ -311,13 +311,13 @@ func (b *BaseApi) GetAgentProviders(c *gin.Context) { } // @Tags AI -// @Summary Create Agent account +// @Summary Create model account // @Accept json // @Param request body dto.AgentAccountCreateReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts [post] +// @Router /ai/accounts [post] func (b *BaseApi) CreateAgentAccount(c *gin.Context) { var req dto.AgentAccountCreateReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -331,13 +331,13 @@ func (b *BaseApi) CreateAgentAccount(c *gin.Context) { } // @Tags AI -// @Summary Update Agent account +// @Summary Update model account // @Accept json // @Param request body dto.AgentAccountUpdateReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/update [post] +// @Router /ai/accounts/update [post] func (b *BaseApi) UpdateAgentAccount(c *gin.Context) { var req dto.AgentAccountUpdateReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -351,13 +351,13 @@ func (b *BaseApi) UpdateAgentAccount(c *gin.Context) { } // @Tags AI -// @Summary Page Agent accounts +// @Summary Page model accounts // @Accept json // @Param request body dto.AgentAccountSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/search [post] +// @Router /ai/accounts/search [post] func (b *BaseApi) PageAgentAccounts(c *gin.Context) { var req dto.AgentAccountSearch if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -375,13 +375,34 @@ func (b *BaseApi) PageAgentAccounts(c *gin.Context) { } // @Tags AI -// @Summary List Agent account models +// @Summary Count model accounts by provider +// @Accept json +// @Param request body dto.AgentAccountProviderCountReq true "request" +// @Success 200 {object} map[string]int64 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/accounts/counts [post] +func (b *BaseApi) CountAgentAccountsByProviders(c *gin.Context) { + var req dto.AgentAccountProviderCountReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + counts, err := agentService.CountAccountsByProviders(req) + if err != nil { + helper.BadRequest(c, err) + return + } + helper.SuccessWithData(c, counts) +} + +// @Tags AI +// @Summary List model account models // @Accept json // @Param request body dto.AgentAccountModelReq true "request" // @Success 200 {array} dto.AgentAccountModel // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/models [post] +// @Router /ai/accounts/models [post] func (b *BaseApi) GetAgentAccountModels(c *gin.Context) { var req dto.AgentAccountModelReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -396,13 +417,13 @@ func (b *BaseApi) GetAgentAccountModels(c *gin.Context) { } // @Tags AI -// @Summary Create Agent account model +// @Summary Create model account model // @Accept json // @Param request body dto.AgentAccountModelCreateReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/models/create [post] +// @Router /ai/accounts/models/create [post] func (b *BaseApi) CreateAgentAccountModel(c *gin.Context) { var req dto.AgentAccountModelCreateReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -416,13 +437,13 @@ func (b *BaseApi) CreateAgentAccountModel(c *gin.Context) { } // @Tags AI -// @Summary Update Agent account model +// @Summary Update model account model // @Accept json // @Param request body dto.AgentAccountModelUpdateReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/models/update [post] +// @Router /ai/accounts/models/update [post] func (b *BaseApi) UpdateAgentAccountModel(c *gin.Context) { var req dto.AgentAccountModelUpdateReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -436,13 +457,13 @@ func (b *BaseApi) UpdateAgentAccountModel(c *gin.Context) { } // @Tags AI -// @Summary Delete Agent account model +// @Summary Delete model account model // @Accept json // @Param request body dto.AgentAccountModelDeleteReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/models/delete [post] +// @Router /ai/accounts/models/delete [post] func (b *BaseApi) DeleteAgentAccountModel(c *gin.Context) { var req dto.AgentAccountModelDeleteReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -456,13 +477,13 @@ func (b *BaseApi) DeleteAgentAccountModel(c *gin.Context) { } // @Tags AI -// @Summary Verify Agent account +// @Summary Verify model account // @Accept json // @Param request body dto.AgentAccountVerifyReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/verify [post] +// @Router /ai/accounts/verify [post] func (b *BaseApi) VerifyAgentAccount(c *gin.Context) { var req dto.AgentAccountVerifyReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -476,13 +497,13 @@ func (b *BaseApi) VerifyAgentAccount(c *gin.Context) { } // @Tags AI -// @Summary Delete Agent account +// @Summary Delete model account // @Accept json // @Param request body dto.AgentAccountDeleteReq true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /ai/agents/accounts/delete [post] +// @Router /ai/accounts/delete [post] func (b *BaseApi) DeleteAgentAccount(c *gin.Context) { var req dto.AgentAccountDeleteReq if err := helper.CheckBindAndValidate(&req, c); err != nil { diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go index d73d9a1d7..54fd18224 100644 --- a/agent/app/dto/agents.go +++ b/agent/app/dto/agents.go @@ -274,6 +274,10 @@ type AgentAccountSearch struct { Name string `json:"name"` } +type AgentAccountProviderCountReq struct { + Providers []string `json:"providers"` +} + type AgentAccountInfo struct { ID uint `json:"id"` Provider string `json:"provider"` diff --git a/agent/app/repo/agent_account.go b/agent/app/repo/agent_account.go index eab88e566..609a3947b 100644 --- a/agent/app/repo/agent_account.go +++ b/agent/app/repo/agent_account.go @@ -1,6 +1,10 @@ package repo -import "github.com/1Panel-dev/1Panel/agent/app/model" +import ( + "strings" + + "github.com/1Panel-dev/1Panel/agent/app/model" +) type AgentAccountRepo struct{} @@ -11,6 +15,7 @@ type IAgentAccountRepo interface { Save(account *model.AgentAccount) error DeleteByID(id uint) error List(opts ...DBOption) ([]model.AgentAccount, error) + CountByProviders(providers []string) (map[string]int64, error) } func NewIAgentAccountRepo() IAgentAccountRepo { @@ -53,3 +58,49 @@ func (a AgentAccountRepo) List(opts ...DBOption) ([]model.AgentAccount, error) { } return accounts, nil } + +func (a AgentAccountRepo) CountByProviders(providers []string) (map[string]int64, error) { + normalizedProviders := normalizeProviders(providers) + counts := make(map[string]int64, len(normalizedProviders)) + for _, provider := range normalizedProviders { + counts[provider] = 0 + } + if len(normalizedProviders) == 0 { + return counts, nil + } + + type providerCount struct { + Provider string + Count int64 + } + var rows []providerCount + if err := getDb(). + Model(&model.AgentAccount{}). + Select("provider, COUNT(*) as count"). + Where("provider IN ?", normalizedProviders). + Group("provider"). + Scan(&rows).Error; err != nil { + return nil, err + } + for _, row := range rows { + counts[row.Provider] = row.Count + } + return counts, nil +} + +func normalizeProviders(providers []string) []string { + seen := make(map[string]struct{}, len(providers)) + result := make([]string, 0, len(providers)) + for _, provider := range providers { + provider = strings.TrimSpace(provider) + if provider == "" { + continue + } + if _, ok := seen[provider]; ok { + continue + } + seen[provider] = struct{}{} + result = append(result, provider) + } + return result +} diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index 121762002..fb63d2005 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -69,6 +69,7 @@ type IAgentService interface { UpdateAccount(req dto.AgentAccountUpdateReq) error SyncAgentsByAccount(account *model.AgentAccount) error PageAccounts(req dto.AgentAccountSearch) (int64, []dto.AgentAccountInfo, error) + CountAccountsByProviders(req dto.AgentAccountProviderCountReq) (map[string]int64, error) GetAccountModels(req dto.AgentAccountModelReq) ([]dto.AgentAccountModel, error) CreateAccountModel(req dto.AgentAccountModelCreateReq) error UpdateAccountModel(req dto.AgentAccountModelUpdateReq) error @@ -676,6 +677,10 @@ func (a AgentService) PageAccounts(req dto.AgentAccountSearch) (int64, []dto.Age return count, items, nil } +func (a AgentService) CountAccountsByProviders(req dto.AgentAccountProviderCountReq) (map[string]int64, error) { + return agentAccountRepo.CountByProviders(req.Providers) +} + func (a AgentService) GetAccountModels(req dto.AgentAccountModelReq) ([]dto.AgentAccountModel, error) { account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID)) if err != nil { diff --git a/agent/router/ro_ai.go b/agent/router/ro_ai.go index b62f0e9cd..68a27b252 100644 --- a/agent/router/ro_ai.go +++ b/agent/router/ro_ai.go @@ -43,6 +43,18 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/tensorrt/delete", baseApi.DeleteTensorRTLLM) aiToolsRouter.POST("/tensorrt/operate", baseApi.OperateTensorRTLLM) + aiToolsRouter.GET("/accounts/providers", baseApi.GetAgentProviders) + aiToolsRouter.POST("/accounts", baseApi.CreateAgentAccount) + aiToolsRouter.POST("/accounts/update", baseApi.UpdateAgentAccount) + aiToolsRouter.POST("/accounts/search", baseApi.PageAgentAccounts) + aiToolsRouter.POST("/accounts/counts", baseApi.CountAgentAccountsByProviders) + aiToolsRouter.POST("/accounts/models", baseApi.GetAgentAccountModels) + aiToolsRouter.POST("/accounts/models/create", baseApi.CreateAgentAccountModel) + aiToolsRouter.POST("/accounts/models/update", baseApi.UpdateAgentAccountModel) + aiToolsRouter.POST("/accounts/models/delete", baseApi.DeleteAgentAccountModel) + aiToolsRouter.POST("/accounts/verify", baseApi.VerifyAgentAccount) + aiToolsRouter.POST("/accounts/delete", baseApi.DeleteAgentAccount) + aiToolsRouter.POST("/agents", baseApi.CreateAgent) aiToolsRouter.POST("/agents/search", baseApi.PageAgents) aiToolsRouter.POST("/agents/delete/check", baseApi.DeleteCheckAgent) @@ -57,16 +69,6 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/agents/hermes/chat/sessions/rename", baseApi.RenameHermesChatSession) aiToolsRouter.POST("/agents/hermes/chat/sessions/delete", baseApi.DeleteHermesChatSession) aiToolsRouter.POST("/agents/overview", baseApi.GetAgentOverview) - aiToolsRouter.GET("/agents/providers", baseApi.GetAgentProviders) - aiToolsRouter.POST("/agents/accounts", baseApi.CreateAgentAccount) - aiToolsRouter.POST("/agents/accounts/update", baseApi.UpdateAgentAccount) - aiToolsRouter.POST("/agents/accounts/search", baseApi.PageAgentAccounts) - aiToolsRouter.POST("/agents/accounts/models", baseApi.GetAgentAccountModels) - aiToolsRouter.POST("/agents/accounts/models/create", baseApi.CreateAgentAccountModel) - aiToolsRouter.POST("/agents/accounts/models/update", baseApi.UpdateAgentAccountModel) - aiToolsRouter.POST("/agents/accounts/models/delete", baseApi.DeleteAgentAccountModel) - aiToolsRouter.POST("/agents/accounts/verify", baseApi.VerifyAgentAccount) - aiToolsRouter.POST("/agents/accounts/delete", baseApi.DeleteAgentAccount) aiToolsRouter.POST("/agents/agent/create", baseApi.CreateAgentRole) aiToolsRouter.POST("/agents/agent/delete", baseApi.DeleteAgentRole) aiToolsRouter.POST("/agents/agent/bind", baseApi.BindAgentRole) diff --git a/core/cmd/server/docs/docs.go b/core/cmd/server/docs/docs.go index ce038ad3e..0c805a4e0 100644 --- a/core/cmd/server/docs/docs.go +++ b/core/cmd/server/docs/docs.go @@ -56,7 +56,7 @@ const docTemplate = `{ ] } }, - "/ai/agents/accounts": { + "/ai/accounts": { "post": { "consumes": [ "application/json" @@ -85,13 +85,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Create Agent account", + "summary": "Create model account", "tags": [ "AI" ] } }, - "/ai/agents/accounts/delete": { + "/ai/accounts/delete": { "post": { "consumes": [ "application/json" @@ -120,13 +120,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Delete Agent account", + "summary": "Delete model account", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models": { + "/ai/accounts/models": { "post": { "consumes": [ "application/json" @@ -161,13 +161,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "List Agent account models", + "summary": "List model account models", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models/create": { + "/ai/accounts/models/create": { "post": { "consumes": [ "application/json" @@ -196,13 +196,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Create Agent account model", + "summary": "Create model account model", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models/delete": { + "/ai/accounts/models/delete": { "post": { "consumes": [ "application/json" @@ -231,13 +231,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Delete Agent account model", + "summary": "Delete model account model", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models/update": { + "/ai/accounts/models/update": { "post": { "consumes": [ "application/json" @@ -266,13 +266,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Update Agent account model", + "summary": "Update model account model", "tags": [ "AI" ] } }, - "/ai/agents/accounts/search": { + "/ai/accounts/search": { "post": { "consumes": [ "application/json" @@ -304,13 +304,54 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Page Agent accounts", + "summary": "Page model accounts", "tags": [ "AI" ] } }, - "/ai/agents/accounts/update": { + "/ai/accounts/counts": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AgentAccountProviderCountReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Count model accounts by provider", + "tags": [ + "AI" + ] + } + }, + "/ai/accounts/update": { "post": { "consumes": [ "application/json" @@ -339,13 +380,13 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Update Agent account", + "summary": "Update model account", "tags": [ "AI" ] } }, - "/ai/agents/accounts/verify": { + "/ai/accounts/verify": { "post": { "consumes": [ "application/json" @@ -374,7 +415,7 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Verify Agent account", + "summary": "Verify model account", "tags": [ "AI" ] @@ -1849,7 +1890,7 @@ const docTemplate = `{ ] } }, - "/ai/agents/providers": { + "/ai/accounts/providers": { "get": { "responses": { "200": { @@ -1870,7 +1911,7 @@ const docTemplate = `{ "Timestamp": [] } ], - "summary": "Get Providers", + "summary": "Get model account providers", "tags": [ "AI" ] @@ -25945,6 +25986,17 @@ const docTemplate = `{ ], "type": "object" }, + "dto.AgentAccountProviderCountReq": { + "properties": { + "providers": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "dto.AgentAccountUpdateReq": { "properties": { "apiKey": { diff --git a/core/cmd/server/docs/swagger.json b/core/cmd/server/docs/swagger.json index 34360b8a9..bbf423971 100644 --- a/core/cmd/server/docs/swagger.json +++ b/core/cmd/server/docs/swagger.json @@ -52,7 +52,7 @@ ] } }, - "/ai/agents/accounts": { + "/ai/accounts": { "post": { "consumes": [ "application/json" @@ -81,13 +81,13 @@ "Timestamp": [] } ], - "summary": "Create Agent account", + "summary": "Create model account", "tags": [ "AI" ] } }, - "/ai/agents/accounts/delete": { + "/ai/accounts/delete": { "post": { "consumes": [ "application/json" @@ -116,13 +116,13 @@ "Timestamp": [] } ], - "summary": "Delete Agent account", + "summary": "Delete model account", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models": { + "/ai/accounts/models": { "post": { "consumes": [ "application/json" @@ -157,13 +157,13 @@ "Timestamp": [] } ], - "summary": "List Agent account models", + "summary": "List model account models", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models/create": { + "/ai/accounts/models/create": { "post": { "consumes": [ "application/json" @@ -192,13 +192,13 @@ "Timestamp": [] } ], - "summary": "Create Agent account model", + "summary": "Create model account model", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models/delete": { + "/ai/accounts/models/delete": { "post": { "consumes": [ "application/json" @@ -227,13 +227,13 @@ "Timestamp": [] } ], - "summary": "Delete Agent account model", + "summary": "Delete model account model", "tags": [ "AI" ] } }, - "/ai/agents/accounts/models/update": { + "/ai/accounts/models/update": { "post": { "consumes": [ "application/json" @@ -262,13 +262,13 @@ "Timestamp": [] } ], - "summary": "Update Agent account model", + "summary": "Update model account model", "tags": [ "AI" ] } }, - "/ai/agents/accounts/search": { + "/ai/accounts/search": { "post": { "consumes": [ "application/json" @@ -300,13 +300,54 @@ "Timestamp": [] } ], - "summary": "Page Agent accounts", + "summary": "Page model accounts", "tags": [ "AI" ] } }, - "/ai/agents/accounts/update": { + "/ai/accounts/counts": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "description": "request", + "in": "body", + "name": "request", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AgentAccountProviderCountReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "Timestamp": [] + } + ], + "summary": "Count model accounts by provider", + "tags": [ + "AI" + ] + } + }, + "/ai/accounts/update": { "post": { "consumes": [ "application/json" @@ -335,13 +376,13 @@ "Timestamp": [] } ], - "summary": "Update Agent account", + "summary": "Update model account", "tags": [ "AI" ] } }, - "/ai/agents/accounts/verify": { + "/ai/accounts/verify": { "post": { "consumes": [ "application/json" @@ -370,7 +411,7 @@ "Timestamp": [] } ], - "summary": "Verify Agent account", + "summary": "Verify model account", "tags": [ "AI" ] @@ -1845,7 +1886,7 @@ ] } }, - "/ai/agents/providers": { + "/ai/accounts/providers": { "get": { "responses": { "200": { @@ -1866,7 +1907,7 @@ "Timestamp": [] } ], - "summary": "Get Providers", + "summary": "Get model account providers", "tags": [ "AI" ] @@ -25941,6 +25982,17 @@ ], "type": "object" }, + "dto.AgentAccountProviderCountReq": { + "properties": { + "providers": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "dto.AgentAccountUpdateReq": { "properties": { "apiKey": { diff --git a/core/constant/common.go b/core/constant/common.go index 056778622..fbeba7db9 100644 --- a/core/constant/common.go +++ b/core/constant/common.go @@ -66,16 +66,21 @@ var WebUrlMap = map[string]struct{}{ "/apps/upgrade": {}, "/apps/setting": {}, - "/ai": {}, - "/ai/ai-proxy": {}, - "/ai/benchmark": {}, - "/ai/model/account": {}, - "/ai/model/local": {}, - "/ai/gpu": {}, - "/ai/gpu/current": {}, - "/ai/gpu/history": {}, - "/ai/mcp": {}, - "/ai/agents/agent": {}, + "/ai": {}, + "/ai/ai-proxy": {}, + "/ai/ai-proxy/model-pool": {}, + "/ai/ai-proxy/api-keys": {}, + "/ai/ai-proxy/groups": {}, + "/ai/ai-proxy/usage": {}, + "/ai/ai-proxy/content": {}, + "/ai/benchmark": {}, + "/ai/model/account": {}, + "/ai/model/local": {}, + "/ai/gpu": {}, + "/ai/gpu/current": {}, + "/ai/gpu/history": {}, + "/ai/mcp": {}, + "/ai/agents/agent": {}, "/containers": {}, "/containers/container/operate": {}, diff --git a/core/init/migration/helper/menu.go b/core/init/migration/helper/menu.go index 9037afd9e..fb7033bac 100644 --- a/core/init/migration/helper/menu.go +++ b/core/init/migration/helper/menu.go @@ -93,7 +93,7 @@ func LoadMenus() string { Title: "aiTools.aiProxy.title", IsShow: true, Label: "AIProxyManagement", - Path: "/ai/ai-proxy", + Path: "/ai/ai-proxy/model-pool", Sort: 150, }, "AIModel") item[i].Children = UpsertMenuByLabel(item[i].Children, dto.ShowMenu{ diff --git a/core/init/migration/migrations/init.go b/core/init/migration/migrations/init.go index 4fff7861b..56f1d5481 100644 --- a/core/init/migration/migrations/init.go +++ b/core/init/migration/migrations/init.go @@ -962,7 +962,7 @@ func buildAiMenuChildren(children []dto.ShowMenu) []dto.ShowMenu { Disabled: false, IsShow: true, Title: "aiTools.aiProxy.title", - Path: "/ai/ai-proxy", + Path: "/ai/ai-proxy/model-pool", Sort: 150, }, "AIProxyManagement")) result = append(result, normalizeAiMenuChild(children, dto.ShowMenu{ diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index ae00c62c4..888fedd7c 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -555,6 +555,10 @@ export namespace AI { name: string; } + export interface AgentAccountProviderCountReq { + providers: string[]; + } + export interface AgentAccountItem { id: number; provider: string; diff --git a/frontend/src/api/modules/ai.ts b/frontend/src/api/modules/ai.ts index 7c4ba9949..f49ba6bba 100644 --- a/frontend/src/api/modules/ai.ts +++ b/frontend/src/api/modules/ai.ts @@ -189,48 +189,52 @@ export const updateAgentRoleMarkdownFile = (req: AI.AgentRoleMarkdownFilesUpdate }; export const getAgentProviders = () => { - return http.get(`/ai/agents/providers`); + return http.get(`/ai/accounts/providers`); }; export const createAgentAccount = (req: AI.AgentAccountCreateReq) => { - return http.post(`/ai/agents/accounts`, req); + return http.post(`/ai/accounts`, req); }; export const updateAgentAccount = (req: AI.AgentAccountUpdateReq) => { - return http.post(`/ai/agents/accounts/update`, req); + return http.post(`/ai/accounts/update`, req); }; export const pageAgentAccounts = (req: AI.AgentAccountSearch, currentNode?: string) => { return http.post>( - `/ai/agents/accounts/search`, + `/ai/accounts/search`, req, undefined, currentNode ? { CurrentNode: currentNode } : undefined, ); }; +export const countAgentAccountsByProvider = (req: AI.AgentAccountProviderCountReq) => { + return http.post>(`/ai/accounts/counts`, req); +}; + export const getAgentAccountModels = (req: AI.AgentAccountModelReq) => { - return http.post(`/ai/agents/accounts/models`, req); + return http.post(`/ai/accounts/models`, req); }; export const createAgentAccountModel = (req: AI.AgentAccountModelCreateReq) => { - return http.post(`/ai/agents/accounts/models/create`, req); + return http.post(`/ai/accounts/models/create`, req); }; export const updateAgentAccountModel = (req: AI.AgentAccountModelUpdateReq) => { - return http.post(`/ai/agents/accounts/models/update`, req); + return http.post(`/ai/accounts/models/update`, req); }; export const deleteAgentAccountModel = (req: AI.AgentAccountModelDeleteReq) => { - return http.post(`/ai/agents/accounts/models/delete`, req); + return http.post(`/ai/accounts/models/delete`, req); }; export const verifyAgentAccount = (req: AI.AgentAccountVerifyReq) => { - return http.post(`/ai/agents/accounts/verify`, req); + return http.post(`/ai/accounts/verify`, req); }; export const deleteAgentAccount = (req: AI.AgentAccountDeleteReq) => { - return http.post(`/ai/agents/accounts/delete`, req); + return http.post(`/ai/accounts/delete`, req); }; export const getAgentFeishuConfig = (req: AI.AgentFeishuConfigReq) => { diff --git a/frontend/src/views/ai/agents/agent/add/index.vue b/frontend/src/views/ai/agents/agent/add/index.vue index df3aa87e3..9810c04cf 100644 --- a/frontend/src/views/ai/agents/agent/add/index.vue +++ b/frontend/src/views/ai/agents/agent/add/index.vue @@ -108,7 +108,7 @@ import { computed, reactive, ref, watch } from 'vue'; import { FormInstance } from 'element-plus'; import { checkNumberRange, Rules } from '@/global/form-rules'; -import { createAgent, getAgentProviders, pageAgentAccounts } from '@/api/modules/ai'; +import { countAgentAccountsByProvider, createAgent, getAgentProviders, pageAgentAccounts } from '@/api/modules/ai'; import { AI } from '@/api/interface/ai'; import { getAppByKey, getAppDetail } from '@/api/modules/app'; import { getAgentSettingInfo } from '@/api/modules/setting'; @@ -147,7 +147,7 @@ const form = reactive({ appVersion: '', webUIPort: 18789, allowedOrigins: '', - provider: 'deepseek', + provider: '', accountId: undefined as unknown as number, model: '', baseURL: '', @@ -286,25 +286,41 @@ const loadProviders = async () => { }, {} as Record, ); + await loadProviderAccountCounts(providerOptions.value.map((item) => item.value)); + providerOptions.value.sort((a, b) => { + const aCount = providerAccountCount.value[a.value] || 0; + const bCount = providerAccountCount.value[b.value] || 0; + if (aCount > 0 && bCount === 0) { + return -1; + } + if (aCount === 0 && bCount > 0) { + return 1; + } + return 0; + }); if (!providerOptions.value.find((item) => item.value === form.provider) && providerOptions.value.length > 0) { form.provider = providerOptions.value[0].value; } - await loadProviderAccountCounts(providerOptions.value.map((item) => item.value)); setDefaultModel(); }; const loadProviderAccountCounts = async (providers: string[]) => { - const tasks = providers.map(async (provider) => { - const req: AI.AgentAccountSearch = { - page: 1, - pageSize: 1, - provider: provider, - name: '', - }; - const res = await pageAgentAccounts(req); - providerAccountCount.value[provider] = res.data.total || 0; + const providerList = Array.from(new Set(providers.filter(Boolean))); + providerAccountCount.value = providerList.reduce( + (acc, provider) => { + acc[provider] = 0; + return acc; + }, + {} as Record, + ); + if (providerList.length === 0) { + return; + } + const res = await countAgentAccountsByProvider({ providers: providerList }); + const counts = res.data || {}; + providerList.forEach((provider) => { + providerAccountCount.value[provider] = counts[provider] || 0; }); - await Promise.all(tasks); }; const loadAccounts = async () => { @@ -357,7 +373,7 @@ const handleAgentTypeChange = async () => { setDefaultWebUIPort(); form.appVersion = ''; form.model = ''; - form.provider = 'deepseek'; + form.provider = ''; form.accountId = undefined as unknown as number; form.baseURL = ''; if (form.agentType === 'openclaw') { diff --git a/frontend/src/views/host/file-management/index.vue b/frontend/src/views/host/file-management/index.vue index dd4dee4df..0fc7b4b3d 100644 --- a/frontend/src/views/host/file-management/index.vue +++ b/frontend/src/views/host/file-management/index.vue @@ -2733,7 +2733,7 @@ onBeforeUnmount(() => { } .file-row { - display: grid; + display: grid; grid-template-columns: 24px minmax(0, 1fr) auto auto; align-items: center; width: 100%;