mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-11-10 21:21:13 +08:00
feat: add some translate (#12940)
This commit is contained in:
1 parent
758eb9dfda
commit
4a734b5bb6
35 files changed
+820
-38
No files matched your search
@@ -27,6 +27,69 @@ func (b *BaseApi) CreateAgent(c *gin.Context) {
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Batch install Agent
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentBatchInstallReq true "request"
|
||||
// @Success 200 {object} dto.AgentItem
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/batch/install [post]
|
||||
func (b *BaseApi) BatchInstallAgent(c *gin.Context) {
|
||||
var req dto.AgentBatchInstallReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := agentService.BatchInstall(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Batch upgrade Agent
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentBatchUpgradeReq true "request"
|
||||
// @Success 200 {array} dto.AgentBatchUpgradeResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/batch/upgrade [post]
|
||||
func (b *BaseApi) BatchUpgradeAgent(c *gin.Context) {
|
||||
var req dto.AgentBatchUpgradeReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := agentService.BatchUpgrade(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Batch install Agent Skill
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentBatchSkillInstallReq true "request"
|
||||
// @Success 200 {array} dto.AgentBatchSkillInstallResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/batch/skill/install [post]
|
||||
func (b *BaseApi) BatchInstallAgentSkill(c *gin.Context) {
|
||||
var req dto.AgentBatchSkillInstallReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := agentService.BatchInstallSkill(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Page Agents
|
||||
// @Accept json
|
||||
|
||||
+75
-12
@@ -27,6 +27,68 @@ type AgentCreateReq struct {
|
||||
DockerCompose string `json:"dockerCompose"`
|
||||
}
|
||||
|
||||
type AgentBatchInstallReq struct {
|
||||
Name string `json:"name"`
|
||||
Remark string `json:"remark"`
|
||||
AppVersion string `json:"appVersion" validate:"required"`
|
||||
WebUIPort int `json:"webUIPort" validate:"required,min=1,max=65535"`
|
||||
BridgePort int `json:"bridgePort"`
|
||||
AllowedOrigins []string `json:"allowedOrigins"`
|
||||
AgentType string `json:"agentType" validate:"required,oneof=openclaw copaw hermes-agent"`
|
||||
Model string `json:"model"`
|
||||
AccountID uint `json:"accountId"`
|
||||
Token string `json:"token"`
|
||||
TaskID string `json:"taskID"`
|
||||
Advanced bool `json:"advanced"`
|
||||
ContainerName string `json:"containerName"`
|
||||
AllowPort bool `json:"allowPort"`
|
||||
SpecifyIP string `json:"specifyIP"`
|
||||
RestartPolicy string `json:"restartPolicy"`
|
||||
CpuQuota float64 `json:"cpuQuota"`
|
||||
MemoryLimit float64 `json:"memoryLimit"`
|
||||
MemoryUnit string `json:"memoryUnit"`
|
||||
PullImage bool `json:"pullImage"`
|
||||
EditCompose bool `json:"editCompose"`
|
||||
DockerCompose string `json:"dockerCompose"`
|
||||
MasterAccountID uint `json:"masterAccountId"`
|
||||
FallbackAccessHost string `json:"fallbackAccessHost"`
|
||||
AccountSnapshot AgentAccountInfo `json:"accountSnapshot"`
|
||||
AccountModels []AgentAccountModel `json:"accountModels"`
|
||||
}
|
||||
|
||||
type AgentBatchUpgradeReq struct {
|
||||
AgentType string `json:"agentType" validate:"required,oneof=openclaw copaw hermes-agent"`
|
||||
TargetVersion string `json:"targetVersion" validate:"required"`
|
||||
Backup bool `json:"backup"`
|
||||
PullImage bool `json:"pullImage"`
|
||||
TaskID string `json:"taskID"`
|
||||
}
|
||||
|
||||
type AgentBatchUpgradeResult struct {
|
||||
AgentID uint `json:"agentID"`
|
||||
AgentName string `json:"agentName"`
|
||||
AppInstallID uint `json:"appInstallID"`
|
||||
Success bool `json:"success"`
|
||||
Skipped bool `json:"skipped"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type AgentBatchSkillInstallReq struct {
|
||||
AgentType string `json:"agentType" validate:"required,oneof=openclaw hermes-agent"`
|
||||
SkillName string `json:"skillName" validate:"required"`
|
||||
PackagePath string `json:"packagePath" validate:"required"`
|
||||
TaskID string `json:"taskID"`
|
||||
}
|
||||
|
||||
type AgentBatchSkillInstallResult struct {
|
||||
AgentID uint `json:"agentID"`
|
||||
AgentName string `json:"agentName"`
|
||||
AppInstallID uint `json:"appInstallID"`
|
||||
Success bool `json:"success"`
|
||||
Skipped bool `json:"skipped"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type AgentItem struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -279,18 +341,19 @@ type AgentAccountProviderCountReq struct {
|
||||
}
|
||||
|
||||
type AgentAccountInfo struct {
|
||||
ID uint `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderName string `json:"providerName"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Models []AgentAccountModel `json:"models"`
|
||||
APIType string `json:"apiType"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
ID uint `json:"id"`
|
||||
MasterAccountID uint `json:"masterAccountId"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderName string `json:"providerName"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Models []AgentAccountModel `json:"models"`
|
||||
APIType string `json:"apiType"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
type ProviderModelInfo struct {
|
||||
|
||||
@@ -2,14 +2,15 @@ package model
|
||||
|
||||
type AgentAccount struct {
|
||||
BaseModel
|
||||
Provider string `json:"provider"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
APIType string `json:"apiType"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
Provider string `json:"provider"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
APIType string `json:"apiType"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
MasterAccountID uint `json:"masterAccountId" gorm:"index"`
|
||||
}
|
||||
|
||||
func (AgentAccount) TableName() string {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AgentAccountRepo struct{}
|
||||
@@ -11,6 +12,7 @@ type AgentAccountRepo struct{}
|
||||
type IAgentAccountRepo interface {
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.AgentAccount, error)
|
||||
GetFirst(opts ...DBOption) (*model.AgentAccount, error)
|
||||
WithByMasterAccountID(masterID uint) DBOption
|
||||
Create(account *model.AgentAccount) error
|
||||
Save(account *model.AgentAccount) error
|
||||
DeleteByID(id uint) error
|
||||
@@ -39,6 +41,12 @@ func (a AgentAccountRepo) GetFirst(opts ...DBOption) (*model.AgentAccount, error
|
||||
return &account, nil
|
||||
}
|
||||
|
||||
func (a AgentAccountRepo) WithByMasterAccountID(masterID uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("master_account_id = ?", masterID)
|
||||
}
|
||||
}
|
||||
|
||||
func (a AgentAccountRepo) Create(account *model.AgentAccount) error {
|
||||
return getDb().Create(account).Error
|
||||
}
|
||||
|
||||
+360
-12
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
providercatalog "github.com/1Panel-dev/1Panel/agent/app/provider"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -30,6 +32,9 @@ import (
|
||||
|
||||
type IAgentService interface {
|
||||
Create(req dto.AgentCreateReq) (*dto.AgentItem, error)
|
||||
BatchInstall(req dto.AgentBatchInstallReq) (*dto.AgentItem, error)
|
||||
BatchUpgrade(req dto.AgentBatchUpgradeReq) ([]dto.AgentBatchUpgradeResult, error)
|
||||
BatchInstallSkill(req dto.AgentBatchSkillInstallReq) ([]dto.AgentBatchSkillInstallResult, error)
|
||||
Page(req dto.SearchWithPage) (int64, []dto.AgentItem, error)
|
||||
DeleteCheck(req dto.AgentIDReq) ([]dto.AppResource, error)
|
||||
Delete(req dto.AgentDeleteReq) error
|
||||
@@ -99,6 +104,11 @@ type IAgentService interface {
|
||||
ApproveChannelPairing(req dto.AgentChannelPairingApproveReq) error
|
||||
}
|
||||
|
||||
type batchUpgradePlan struct {
|
||||
agent model.Agent
|
||||
req request.AppInstallUpgrade
|
||||
}
|
||||
|
||||
const (
|
||||
defaultBrowserExecutablePath = "/home/node/.cache/ms-playwright/openclaw-browser"
|
||||
defaultBrowserProfile = "openclaw"
|
||||
@@ -291,6 +301,343 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (a AgentService) BatchInstall(req dto.AgentBatchInstallReq) (*dto.AgentItem, error) {
|
||||
accountID, err := a.ensureBatchInstallAccount(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createReq := buildCreateReqFromBatchInstallReq(req)
|
||||
createReq.AccountID = accountID
|
||||
if strings.TrimSpace(createReq.Name) == "" {
|
||||
name, err := buildBatchInstallAgentName(createReq.AgentType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createReq.Name = name
|
||||
}
|
||||
if createReq.AgentType == constant.AppOpenclaw && len(createReq.AllowedOrigins) == 0 {
|
||||
allowedOrigin, err := buildBatchInstallOpenclawAllowedOrigin(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createReq.AllowedOrigins = []string{allowedOrigin}
|
||||
}
|
||||
return a.Create(createReq)
|
||||
}
|
||||
|
||||
func (a AgentService) BatchUpgrade(req dto.AgentBatchUpgradeReq) ([]dto.AgentBatchUpgradeResult, error) {
|
||||
plans, results, err := buildBatchUpgradePlans(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, plan := range plans {
|
||||
result := dto.AgentBatchUpgradeResult{
|
||||
AgentID: plan.agent.ID,
|
||||
AgentName: plan.agent.Name,
|
||||
AppInstallID: plan.agent.AppInstallID,
|
||||
}
|
||||
if err := upgradeInstall(plan.req); err != nil {
|
||||
result.Message = err.Error()
|
||||
} else {
|
||||
result.Success = true
|
||||
}
|
||||
results = append(results, result)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (a AgentService) BatchInstallSkill(req dto.AgentBatchSkillInstallReq) ([]dto.AgentBatchSkillInstallResult, error) {
|
||||
if req.AgentType != constant.AppOpenclaw && req.AgentType != constant.AppHermesAgent {
|
||||
return nil, fmt.Errorf("%s does not support skill batch install", req.AgentType)
|
||||
}
|
||||
packagePath, err := validateLocalSkillPackagePath(req.PackagePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if format, err := localSkillPackageFormat(packagePath); err != nil {
|
||||
return nil, err
|
||||
} else if format != "zip" {
|
||||
return nil, fmt.Errorf("only .zip skill packages can be installed")
|
||||
}
|
||||
skillName := sanitizeLocalSkillDirName(req.SkillName, packagePath, req.SkillName)
|
||||
agents, err := agentRepo.List(func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("agent_type = ?", req.AgentType).Order("id ASC")
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results := make([]dto.AgentBatchSkillInstallResult, 0, len(agents))
|
||||
for _, agent := range agents {
|
||||
result := dto.AgentBatchSkillInstallResult{
|
||||
AgentID: agent.ID,
|
||||
AgentName: agent.Name,
|
||||
AppInstallID: agent.AppInstallID,
|
||||
}
|
||||
if agent.AppInstallID == 0 {
|
||||
result.Message = "agent app install id is empty"
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
install, err := appInstallRepo.GetFirst(repo.WithByID(agent.AppInstallID))
|
||||
if err != nil {
|
||||
result.Message = err.Error()
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
result.AppInstallID = install.ID
|
||||
if install.App.Key != req.AgentType {
|
||||
result.Message = fmt.Sprintf("app key %s does not match agent type %s", install.App.Key, req.AgentType)
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
if install.Status == constant.StatusInstalling || install.Status == constant.StatusUpgrading {
|
||||
result.Message = fmt.Sprintf("agent status is %s", install.Status)
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
if err := ensureContainerRunning(install.ContainerName); err != nil {
|
||||
result.Message = err.Error()
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
installTask, err := task.NewTaskWithOps(skillName, task.TaskInstall, task.TaskScopeAI, buildBatchSkillInstallTaskID(req.TaskID, agent.ID), agent.ID)
|
||||
if err != nil {
|
||||
result.Message = err.Error()
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
currentAgent := agent
|
||||
currentInstall := install
|
||||
installTask.AddSubTask("Install local skill", func(t *task.Task) error {
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(20*time.Minute))
|
||||
return installLocalSkillPackage(mgr, currentInstall.ContainerName, currentAgent.AgentType, currentAgent.ConfigPath, packagePath, skillName)
|
||||
}, nil)
|
||||
go func() {
|
||||
if err := installTask.Execute(); err != nil {
|
||||
global.LOG.Errorf("batch install local skill failed: %v", err)
|
||||
}
|
||||
}()
|
||||
result.Success = true
|
||||
results = append(results, result)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func buildBatchUpgradePlans(req dto.AgentBatchUpgradeReq) ([]batchUpgradePlan, []dto.AgentBatchUpgradeResult, error) {
|
||||
agents, err := agentRepo.List(func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("agent_type = ?", req.AgentType).Order("id ASC")
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
plans := make([]batchUpgradePlan, 0, len(agents))
|
||||
results := make([]dto.AgentBatchUpgradeResult, 0)
|
||||
for _, agent := range agents {
|
||||
result := dto.AgentBatchUpgradeResult{
|
||||
AgentID: agent.ID,
|
||||
AgentName: agent.Name,
|
||||
AppInstallID: agent.AppInstallID,
|
||||
}
|
||||
if agent.AppInstallID == 0 {
|
||||
result.Message = "agent app install id is empty"
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
install, err := appInstallRepo.GetFirst(repo.WithByID(agent.AppInstallID))
|
||||
if err != nil {
|
||||
result.Message = err.Error()
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
result.AppInstallID = install.ID
|
||||
if install.App.Key != req.AgentType {
|
||||
result.Message = fmt.Sprintf("app key %s does not match agent type %s", install.App.Key, req.AgentType)
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
if install.Status == constant.StatusInstalling || install.Status == constant.StatusUpgrading {
|
||||
result.Message = fmt.Sprintf("agent status is %s", install.Status)
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
if install.Version == req.TargetVersion {
|
||||
result.Success = true
|
||||
result.Skipped = true
|
||||
result.Message = "already target version"
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
detail, err := appDetailRepo.GetFirst(appDetailRepo.WithAppId(install.AppId), appDetailRepo.WithVersion(req.TargetVersion))
|
||||
if err != nil {
|
||||
result.Message = err.Error()
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
if detail.ID == 0 {
|
||||
result.Message = fmt.Sprintf("target version %s not found", req.TargetVersion)
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
plans = append(plans, batchUpgradePlan{
|
||||
agent: agent,
|
||||
req: request.AppInstallUpgrade{
|
||||
InstallID: install.ID,
|
||||
DetailID: detail.ID,
|
||||
Backup: req.Backup,
|
||||
PullImage: req.PullImage,
|
||||
TaskID: buildBatchUpgradeTaskID(req.TaskID, install.ID),
|
||||
},
|
||||
})
|
||||
}
|
||||
return plans, results, nil
|
||||
}
|
||||
|
||||
func buildBatchUpgradeTaskID(taskID string, appInstallID uint) string {
|
||||
taskID = strings.TrimSpace(taskID)
|
||||
if taskID == "" {
|
||||
taskID = fmt.Sprintf("batch-upgrade-%d-%d", appInstallID, time.Now().UnixNano())
|
||||
}
|
||||
return fmt.Sprintf("%s-%d", taskID, appInstallID)
|
||||
}
|
||||
|
||||
func buildBatchSkillInstallTaskID(taskID string, agentID uint) string {
|
||||
taskID = strings.TrimSpace(taskID)
|
||||
if taskID == "" {
|
||||
taskID = fmt.Sprintf("batch-skill-install-%d-%d", agentID, time.Now().UnixNano())
|
||||
}
|
||||
return fmt.Sprintf("%s-%d", taskID, agentID)
|
||||
}
|
||||
|
||||
func buildCreateReqFromBatchInstallReq(req dto.AgentBatchInstallReq) dto.AgentCreateReq {
|
||||
return dto.AgentCreateReq{
|
||||
Name: req.Name,
|
||||
Remark: req.Remark,
|
||||
AppVersion: req.AppVersion,
|
||||
WebUIPort: req.WebUIPort,
|
||||
BridgePort: req.BridgePort,
|
||||
AllowedOrigins: req.AllowedOrigins,
|
||||
AgentType: req.AgentType,
|
||||
Model: req.Model,
|
||||
AccountID: req.AccountID,
|
||||
Token: req.Token,
|
||||
TaskID: req.TaskID,
|
||||
Advanced: req.Advanced,
|
||||
ContainerName: req.ContainerName,
|
||||
AllowPort: req.AllowPort,
|
||||
SpecifyIP: req.SpecifyIP,
|
||||
RestartPolicy: req.RestartPolicy,
|
||||
CpuQuota: req.CpuQuota,
|
||||
MemoryLimit: req.MemoryLimit,
|
||||
MemoryUnit: req.MemoryUnit,
|
||||
PullImage: req.PullImage,
|
||||
EditCompose: req.EditCompose,
|
||||
DockerCompose: req.DockerCompose,
|
||||
}
|
||||
}
|
||||
|
||||
func buildBatchInstallAgentName(agentType string) (string, error) {
|
||||
prefix := strings.ToLower(strings.TrimSpace(agentType))
|
||||
if prefix == "" {
|
||||
prefix = "agent"
|
||||
}
|
||||
for i := 1; i <= 10000; i++ {
|
||||
name := fmt.Sprintf("%s-%d", prefix, i)
|
||||
exists, err := agentNameExists(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !exists {
|
||||
return name, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no available agent name")
|
||||
}
|
||||
|
||||
func agentNameExists(name string) (bool, error) {
|
||||
if exist, err := agentRepo.GetFirst(repo.WithByLowerName(name)); err == nil && exist != nil && exist.ID > 0 {
|
||||
return true, nil
|
||||
} else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return false, err
|
||||
}
|
||||
installs, err := appInstallRepo.ListBy(context.Background(), repo.WithByLowerName(name))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(installs) > 0, nil
|
||||
}
|
||||
|
||||
func buildBatchInstallOpenclawAllowedOrigin(req dto.AgentBatchInstallReq) (string, error) {
|
||||
host := ""
|
||||
if value, err := settingRepo.GetValueByKey("SystemIP"); err == nil {
|
||||
host = strings.TrimSpace(value)
|
||||
}
|
||||
if host == "" {
|
||||
host = strings.TrimSpace(req.FallbackAccessHost)
|
||||
}
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
return buildOpenclawAllowedOrigin(openclawAllowedOriginScheme(req.AppVersion), host, req.WebUIPort)
|
||||
}
|
||||
|
||||
func (a AgentService) ensureBatchInstallAccount(req dto.AgentBatchInstallReq) (uint, error) {
|
||||
if !requiresAgentAccount(req.AgentType) {
|
||||
return 0, nil
|
||||
}
|
||||
if req.MasterAccountID == 0 {
|
||||
return 0, buserr.New("ErrInvalidParams")
|
||||
}
|
||||
snapshot := req.AccountSnapshot
|
||||
account, err := agentAccountRepo.GetFirst(agentAccountRepo.WithByMasterAccountID(req.MasterAccountID))
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return 0, err
|
||||
}
|
||||
if account == nil && global.IsMaster {
|
||||
account, err = agentAccountRepo.GetFirst(repo.WithByID(req.MasterAccountID))
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if account == nil {
|
||||
account = &model.AgentAccount{
|
||||
MasterAccountID: req.MasterAccountID,
|
||||
}
|
||||
}
|
||||
account.MasterAccountID = req.MasterAccountID
|
||||
account.Provider = snapshot.Provider
|
||||
account.Name = snapshot.Name
|
||||
account.APIKey = snapshot.APIKey
|
||||
account.RememberAPIKey = snapshot.RememberAPIKey
|
||||
account.BaseURL = snapshot.BaseURL
|
||||
account.APIType = snapshot.APIType
|
||||
account.Remark = snapshot.Remark
|
||||
account.Verified = true
|
||||
|
||||
initialModels, err := buildInitialAgentAccountModels(account, req.AccountModels)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := global.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if account.ID == 0 {
|
||||
if err := tx.Create(account).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := tx.Save(account).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return replacePersistedAgentAccountModelsWithTx(tx, account.ID, initialModels)
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return account.ID, nil
|
||||
}
|
||||
|
||||
func requiresAgentAccount(agentType string) bool {
|
||||
return agentType != constant.AppCopaw
|
||||
}
|
||||
|
||||
func setAgentWebUIParams(params map[string]interface{}, agentType, appVersion string, webUIPort int) {
|
||||
if agentType == constant.AppOpenclaw && isOpenclawHTTPSWindowVersion(appVersion) {
|
||||
params["PANEL_APP_PORT_HTTPS"] = webUIPort
|
||||
@@ -653,18 +1000,19 @@ func (a AgentService) PageAccounts(req dto.AgentAccountSearch) (int64, []dto.Age
|
||||
apiKey = item.APIKey
|
||||
}
|
||||
items = append(items, dto.AgentAccountInfo{
|
||||
ID: item.ID,
|
||||
Provider: item.Provider,
|
||||
ProviderName: providercatalog.DisplayName(item.Provider),
|
||||
Name: item.Name,
|
||||
APIKey: apiKey,
|
||||
RememberAPIKey: item.RememberAPIKey,
|
||||
BaseURL: item.BaseURL,
|
||||
Models: nil,
|
||||
APIType: item.APIType,
|
||||
Verified: item.Verified,
|
||||
Remark: item.Remark,
|
||||
CreatedAt: item.CreatedAt,
|
||||
ID: item.ID,
|
||||
MasterAccountID: item.MasterAccountID,
|
||||
Provider: item.Provider,
|
||||
ProviderName: providercatalog.DisplayName(item.Provider),
|
||||
Name: item.Name,
|
||||
APIKey: apiKey,
|
||||
RememberAPIKey: item.RememberAPIKey,
|
||||
BaseURL: item.BaseURL,
|
||||
Models: nil,
|
||||
APIType: item.APIType,
|
||||
Verified: item.Verified,
|
||||
Remark: item.Remark,
|
||||
CreatedAt: item.CreatedAt,
|
||||
})
|
||||
}
|
||||
for i := range items {
|
||||
|
||||
@@ -912,7 +912,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
}
|
||||
}
|
||||
|
||||
upgradeTask.AddSubTaskWithOps(task.GetTaskName(install.Name, task.TaskScopeApp, task.TaskUpgrade), upgradeApp, rollBackApp, 0, 1*time.Hour)
|
||||
upgradeTask.AddSubTaskWithOps(task.GetTaskName(install.Name, task.TaskUpgrade, task.TaskScopeApp), upgradeApp, rollBackApp, 0, 1*time.Hour)
|
||||
|
||||
go func() {
|
||||
err = upgradeTask.Execute()
|
||||
|
||||
@@ -75,6 +75,7 @@ func InitAgentDB() {
|
||||
migrations.NormalizeAgentAccountVerifiedStatus,
|
||||
migrations.NormalizeOllamaAccountAPIType,
|
||||
migrations.InitAgentAccountModelPool,
|
||||
migrations.AddAgentAccountMasterID,
|
||||
migrations.AddHostTable,
|
||||
migrations.AddAITerminalSettings,
|
||||
migrations.UpdateAgentQuickJumpTitle,
|
||||
|
||||
@@ -1118,6 +1118,13 @@ var InitAgentAccountModelPool = &gormigrate.Migration{
|
||||
},
|
||||
}
|
||||
|
||||
var AddAgentAccountMasterID = &gormigrate.Migration{
|
||||
ID: "20260401-add-agent-account-master-id",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.AgentAccount{})
|
||||
},
|
||||
}
|
||||
|
||||
var AddHostTable = &gormigrate.Migration{
|
||||
ID: "20260318-add-host-table",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
|
||||
@@ -56,6 +56,9 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
aiToolsRouter.POST("/accounts/delete", baseApi.DeleteAgentAccount)
|
||||
|
||||
aiToolsRouter.POST("/agents", baseApi.CreateAgent)
|
||||
aiToolsRouter.POST("/agents/batch/install", baseApi.BatchInstallAgent)
|
||||
aiToolsRouter.POST("/agents/batch/upgrade", baseApi.BatchUpgradeAgent)
|
||||
aiToolsRouter.POST("/agents/batch/skill/install", baseApi.BatchInstallAgentSkill)
|
||||
aiToolsRouter.POST("/agents/search", baseApi.PageAgents)
|
||||
aiToolsRouter.POST("/agents/delete/check", baseApi.DeleteCheckAgent)
|
||||
aiToolsRouter.POST("/agents/delete", baseApi.DeleteAgent)
|
||||
|
||||
@@ -135,6 +135,12 @@ TaskUpgrade: "Upgrade"
|
||||
TaskSync: 'Sync'
|
||||
TaskSyncForNode: "Sync node data"
|
||||
TaskBackup: "Backup"
|
||||
BatchInstallAgent: "Batch install agent"
|
||||
DispatchAgentInstallTasks: "Dispatch agent install tasks"
|
||||
BatchUpgradeAgent: "Batch upgrade agent"
|
||||
DispatchAgentUpgradeTasks: "Dispatch agent upgrade tasks"
|
||||
BatchInstallAgentSkill: "Batch distribute Skill"
|
||||
DispatchAgentSkillInstallTasks: "Dispatch Skill install tasks"
|
||||
AIBenchmarkRun: "Run AI benchmark"
|
||||
SuccessStatus: "{{ .name }} succeeded"
|
||||
FailedStatus: "{{ .name }} failed {{ .err }}"
|
||||
|
||||
@@ -135,6 +135,12 @@ TaskUpgrade: "Actualizar"
|
||||
TaskSync: 'Sincronizar'
|
||||
TaskSyncForNode: "Sincronizar Datos del Nodo"
|
||||
TaskBackup: "Respaldar"
|
||||
BatchInstallAgent: "Instalación masiva de agentes"
|
||||
DispatchAgentInstallTasks: "Enviar tareas de instalación de agentes"
|
||||
BatchUpgradeAgent: "Actualización masiva de agentes"
|
||||
DispatchAgentUpgradeTasks: "Enviar tareas de actualización de agentes"
|
||||
BatchInstallAgentSkill: "Distribuir Skill por lotes"
|
||||
DispatchAgentSkillInstallTasks: "Enviar tareas de instalación de Skill"
|
||||
SuccessStatus: "{{ .name }} correcta"
|
||||
FailedStatus: "{{ .name }} fallida {{ .err }}"
|
||||
Start: "Iniciar"
|
||||
|
||||
@@ -130,6 +130,12 @@ TaskUpgrade: "アップグレード"
|
||||
TaskSync: '同期'
|
||||
TaskSyncForNode: "ノードデータを同期"
|
||||
TaskBackup: "バックアップ"
|
||||
BatchInstallAgent: "エージェントの一括インストール"
|
||||
DispatchAgentInstallTasks: "エージェントインストールタスクを配信"
|
||||
BatchUpgradeAgent: "エージェントの一括アップグレード"
|
||||
DispatchAgentUpgradeTasks: "エージェントアップグレードタスクを配信"
|
||||
BatchInstallAgentSkill: "Skill 一括配布"
|
||||
DispatchAgentSkillInstallTasks: "Skill インストールタスクを配信"
|
||||
SuccessStatus: "{{ .name }} 成功"
|
||||
FailedStatus: "{{ .name }} 失敗 {{ .err }}"
|
||||
Start: "開始"
|
||||
|
||||
@@ -129,6 +129,12 @@ TaskUpgrade: "업그레이드"
|
||||
TaskSync: '동기화'
|
||||
TaskSyncForNode: "노드 데이터 동기화"
|
||||
TaskBackup: "백업"
|
||||
BatchInstallAgent: "에이전트 일괄 설치"
|
||||
DispatchAgentInstallTasks: "에이전트 설치 작업 배포"
|
||||
BatchUpgradeAgent: "에이전트 일괄 업그레이드"
|
||||
DispatchAgentUpgradeTasks: "에이전트 업그레이드 작업 배포"
|
||||
BatchInstallAgentSkill: "Skill 일괄 배포"
|
||||
DispatchAgentSkillInstallTasks: "Skill 설치 작업 배포"
|
||||
SuccessStatus: "{{ .name }} 성공"
|
||||
FailedStatus: "{{ .name }} 실패 {{ .err }}"
|
||||
Start: "시작"
|
||||
|
||||
@@ -124,6 +124,12 @@ TaskUpgrade: "Kemas kini"
|
||||
TaskSync: 'Selaraskan'
|
||||
TaskSyncForNode: "Segerakan Data Nod"
|
||||
TaskBackup: "Sandaran"
|
||||
BatchInstallAgent: "Pasang ejen secara pukal"
|
||||
DispatchAgentInstallTasks: "Hantar tugas pemasangan ejen"
|
||||
BatchUpgradeAgent: "Naik taraf ejen secara pukal"
|
||||
DispatchAgentUpgradeTasks: "Hantar tugas naik taraf ejen"
|
||||
BatchInstallAgentSkill: "Hantar Skill secara pukal"
|
||||
DispatchAgentSkillInstallTasks: "Hantar tugas pemasangan Skill"
|
||||
SuccessStatus: "{{ .name }} berjaya"
|
||||
FailedStatus: "{{ .name }} gagal {{ .err }}"
|
||||
Start: "Mula"
|
||||
|
||||
@@ -129,6 +129,12 @@ TaskUpgrade: "Atualizar"
|
||||
TaskSync: 'Sincronizar'
|
||||
TaskSyncForNode: "Sincronizar Dados do Nó"
|
||||
TaskBackup: "Backup"
|
||||
BatchInstallAgent: "Instalar agentes em lote"
|
||||
DispatchAgentInstallTasks: "Distribuir tarefas de instalação de agentes"
|
||||
BatchUpgradeAgent: "Atualizar agentes em lote"
|
||||
DispatchAgentUpgradeTasks: "Distribuir tarefas de atualização de agentes"
|
||||
BatchInstallAgentSkill: "Distribuir Skill em lote"
|
||||
DispatchAgentSkillInstallTasks: "Distribuir tarefas de instalação de Skill"
|
||||
SuccessStatus: "{{ .name }} bem-sucedido"
|
||||
FailedStatus: "{{ .name }} falhou {{ .err }}"
|
||||
Start: "Iniciar"
|
||||
|
||||
@@ -129,6 +129,12 @@ TaskUpgrade: "Обновить"
|
||||
TaskSync: 'Синхронизация'
|
||||
TaskSyncForNode: "Синхронизировать Данные Узла"
|
||||
TaskBackup: "Резервная копия"
|
||||
BatchInstallAgent: "Пакетная установка агентов"
|
||||
DispatchAgentInstallTasks: "Отправить задачи установки агентов"
|
||||
BatchUpgradeAgent: "Пакетное обновление агентов"
|
||||
DispatchAgentUpgradeTasks: "Отправить задачи обновления агентов"
|
||||
BatchInstallAgentSkill: "Пакетная отправка Skill"
|
||||
DispatchAgentSkillInstallTasks: "Отправить задачи установки Skill"
|
||||
SuccessStatus: "{{ .name }} успешно"
|
||||
FailedStatus: "{{ .name }} не удалось {{ .err }}"
|
||||
Start: "Начать"
|
||||
|
||||
@@ -128,6 +128,12 @@ TaskUpgrade: "Yükseltme"
|
||||
TaskSync: 'Senkronize'
|
||||
TaskSyncForNode: "Düğüm Verilerini Senkronize Et"
|
||||
TaskBackup: "Yedekleme"
|
||||
BatchInstallAgent: "Aracıları toplu kur"
|
||||
DispatchAgentInstallTasks: "Aracı kurulum görevlerini gönder"
|
||||
BatchUpgradeAgent: "Aracıları toplu yükselt"
|
||||
DispatchAgentUpgradeTasks: "Aracı yükseltme görevlerini gönder"
|
||||
BatchInstallAgentSkill: "Skill toplu dağıt"
|
||||
DispatchAgentSkillInstallTasks: "Skill kurulum görevlerini gönder"
|
||||
SuccessStatus: "{{ .name }} başarılı"
|
||||
FailedStatus: "{{ .name }} başarısız {{ .err }}"
|
||||
Start: "Başla"
|
||||
|
||||
@@ -129,6 +129,12 @@ TaskUpgrade: "升級"
|
||||
TaskSync: "同步"
|
||||
TaskSyncForNode: "同步節點資料"
|
||||
TaskBackup: "備份"
|
||||
BatchInstallAgent: "批量安裝智能體"
|
||||
DispatchAgentInstallTasks: "下發智能體安裝任務"
|
||||
BatchUpgradeAgent: "批量升級智能體"
|
||||
DispatchAgentUpgradeTasks: "下發智能體升級任務"
|
||||
BatchInstallAgentSkill: "批量下發 Skill"
|
||||
DispatchAgentSkillInstallTasks: "下發 Skill 安裝任務"
|
||||
AIBenchmarkRun: "執行 AI 基準測試"
|
||||
SuccessStatus: "{{ .name }} 成功"
|
||||
FailedStatus: "{{ .name }} 失敗 {{ .err }}"
|
||||
|
||||
@@ -135,6 +135,12 @@ TaskUpgrade: "升级"
|
||||
TaskSync: "同步"
|
||||
TaskSyncForNode: "同步节点数据"
|
||||
TaskBackup: "备份"
|
||||
BatchInstallAgent: "批量安装智能体"
|
||||
DispatchAgentInstallTasks: "下发智能体安装任务"
|
||||
BatchUpgradeAgent: "批量升级智能体"
|
||||
DispatchAgentUpgradeTasks: "下发智能体升级任务"
|
||||
BatchInstallAgentSkill: "批量下发 Skill"
|
||||
DispatchAgentSkillInstallTasks: "下发 Skill 安装任务"
|
||||
AIBenchmarkRun: "执行 AI 基准测试"
|
||||
SuccessStatus: "{{ .name }} 成功"
|
||||
FailedStatus: "{{ .name }} 失败 {{ .err }}"
|
||||
|
||||
@@ -56,6 +56,7 @@ import { readTaskLogByLine } from '@/api/modules/log';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import bus from '@/global/bus';
|
||||
import Highlight from '@/components/log/custom-highlight/index.vue';
|
||||
import { translateTaskText } from '@/utils/task';
|
||||
const { currentNode } = useGlobalStore();
|
||||
|
||||
interface LogProps {
|
||||
@@ -304,7 +305,7 @@ const getContent = async (pre: boolean) => {
|
||||
return String.fromCharCode(parseInt(grp, 16));
|
||||
}),
|
||||
);
|
||||
const newLogs = res.data.lines;
|
||||
const newLogs = res.data.lines.map((line) => translateTaskText(line));
|
||||
if (tailLog.value && newLogs.length === readReq.pageSize && readReq.page < res.data.total) {
|
||||
readReq.page++;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@ const showTail = ref(true);
|
||||
|
||||
const openWithTaskID = (id: string, tail?: boolean, operateNode?: string) => {
|
||||
config.taskID = id;
|
||||
config.type = 'task';
|
||||
config.taskType = '';
|
||||
config.taskOperate = '';
|
||||
config.resourceID = 0;
|
||||
if (tail === undefined) {
|
||||
config.tail = true;
|
||||
} else {
|
||||
@@ -57,6 +61,8 @@ const openWithTaskID = (id: string, tail?: boolean, operateNode?: string) => {
|
||||
};
|
||||
|
||||
const openWithResourceID = (taskType: string, taskOperate: string, resourceID: number, operateNode?: string) => {
|
||||
config.taskID = '';
|
||||
config.type = 'task';
|
||||
config.taskType = taskType;
|
||||
config.resourceID = resourceID;
|
||||
config.taskOperate = taskOperate;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
</template>
|
||||
<template #main>
|
||||
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search" :heightDiff="320">
|
||||
<el-table-column :label="$t('logs.taskName')" prop="name" min-width="180px"></el-table-column>
|
||||
<el-table-column :label="$t('logs.taskName')" prop="name" min-width="180px">
|
||||
<template #default="{ row }">
|
||||
{{ translateTaskText(row.name) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.table.status')" prop="status" max-width="80px">
|
||||
<template #default="{ row }">
|
||||
<Status :status="row.status" :msg="row.errorMsg" />
|
||||
@@ -57,6 +61,7 @@ import { reactive, ref } from 'vue';
|
||||
import { Log } from '@/api/interface/log';
|
||||
import bus from '@/global/bus';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import { translateTaskText } from '@/utils/task';
|
||||
const { currentNode } = useGlobalStore();
|
||||
|
||||
const open = ref(false);
|
||||
|
||||
@@ -680,6 +680,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'Agent',
|
||||
account: 'Model Account',
|
||||
batchOperation: 'Batch Operation',
|
||||
operationType: 'Operation Type',
|
||||
batchInstall: 'Batch Install',
|
||||
batchUpgrade: 'Batch Upgrade',
|
||||
batchSkillInstall: 'Batch Distribute Skill',
|
||||
batchInstallAgent: 'Batch install agent',
|
||||
dispatchAgentInstallTasks: 'Dispatch agent install tasks',
|
||||
batchUpgradeAgent: 'Batch upgrade agent',
|
||||
dispatchAgentUpgradeTasks: 'Dispatch agent upgrade tasks',
|
||||
batchInstallAgentSkill: 'Batch distribute Skill',
|
||||
dispatchAgentSkillInstallTasks: 'Dispatch Skill install tasks',
|
||||
allNodes: 'All Nodes',
|
||||
targetVersion: 'Target Version',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: 'Batch install task has been submitted',
|
||||
batchUpgradeTaskSubmitted: 'Batch upgrade task has been submitted',
|
||||
batchSkillInstallTaskSubmitted: 'Batch Skill distribution task has been submitted',
|
||||
noAccountHint: 'Choose an existing model account or add a new one.',
|
||||
accountCount: '{0} model accounts',
|
||||
syncAgents: 'Sync related agents',
|
||||
|
||||
@@ -686,6 +686,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'Agente',
|
||||
account: 'Cuenta de modelo',
|
||||
batchOperation: 'Operación por lotes',
|
||||
operationType: 'Tipo de operación',
|
||||
batchInstall: 'Instalación por lotes',
|
||||
batchUpgrade: 'Actualización por lotes',
|
||||
batchSkillInstall: 'Distribuir Skill por lotes',
|
||||
batchInstallAgent: 'Instalación masiva de agentes',
|
||||
dispatchAgentInstallTasks: 'Enviar tareas de instalación de agentes',
|
||||
batchUpgradeAgent: 'Actualización masiva de agentes',
|
||||
dispatchAgentUpgradeTasks: 'Enviar tareas de actualización de agentes',
|
||||
batchInstallAgentSkill: 'Distribuir Skill por lotes',
|
||||
dispatchAgentSkillInstallTasks: 'Enviar tareas de instalación de Skill',
|
||||
allNodes: 'Todos los nodos',
|
||||
targetVersion: 'Versión de destino',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: 'Tarea de instalación por lotes enviada',
|
||||
batchUpgradeTaskSubmitted: 'Tarea de actualización por lotes enviada',
|
||||
batchSkillInstallTaskSubmitted: 'Tarea de distribución de Skill por lotes enviada',
|
||||
noAccountHint: 'Selecciona una cuenta de modelo existente o agrega una nueva.',
|
||||
accountCount: '{0} cuentas de modelo',
|
||||
syncAgents: 'Sincronizar agentes vinculados',
|
||||
|
||||
@@ -681,6 +681,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'エージェント',
|
||||
account: 'モデルアカウント',
|
||||
batchOperation: '一括操作',
|
||||
operationType: '操作タイプ',
|
||||
batchInstall: '一括インストール',
|
||||
batchUpgrade: '一括アップグレード',
|
||||
batchSkillInstall: 'Skill 一括配布',
|
||||
batchInstallAgent: 'エージェントの一括インストール',
|
||||
dispatchAgentInstallTasks: 'エージェントインストールタスクを配信',
|
||||
batchUpgradeAgent: 'エージェントの一括アップグレード',
|
||||
dispatchAgentUpgradeTasks: 'エージェントアップグレードタスクを配信',
|
||||
batchInstallAgentSkill: 'Skill 一括配布',
|
||||
dispatchAgentSkillInstallTasks: 'Skill インストールタスクを配信',
|
||||
allNodes: 'すべてのノード',
|
||||
targetVersion: 'ターゲットバージョン',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: '一括インストールタスクを送信しました',
|
||||
batchUpgradeTaskSubmitted: '一括アップグレードタスクを送信しました',
|
||||
batchSkillInstallTaskSubmitted: 'Skill 一括配布タスクを送信しました',
|
||||
noAccountHint: '既存のモデルアカウントを選択するか、新規に追加してください。',
|
||||
accountCount: 'モデルアカウント {0} 件',
|
||||
syncAgents: '関連エージェントを同期',
|
||||
|
||||
@@ -673,6 +673,23 @@ const message = {
|
||||
agents: {
|
||||
agent: '에이전트',
|
||||
account: '모델 계정',
|
||||
batchOperation: '일괄 작업',
|
||||
operationType: '작업 유형',
|
||||
batchInstall: '일괄 설치',
|
||||
batchUpgrade: '일괄 업그레이드',
|
||||
batchSkillInstall: 'Skill 일괄 배포',
|
||||
batchInstallAgent: '에이전트 일괄 설치',
|
||||
dispatchAgentInstallTasks: '에이전트 설치 작업 배포',
|
||||
batchUpgradeAgent: '에이전트 일괄 업그레이드',
|
||||
dispatchAgentUpgradeTasks: '에이전트 업그레이드 작업 배포',
|
||||
batchInstallAgentSkill: 'Skill 일괄 배포',
|
||||
dispatchAgentSkillInstallTasks: 'Skill 설치 작업 배포',
|
||||
allNodes: '모든 노드',
|
||||
targetVersion: '대상 버전',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: '일괄 설치 작업이 전송되었습니다',
|
||||
batchUpgradeTaskSubmitted: '일괄 업그레이드 작업이 전송되었습니다',
|
||||
batchSkillInstallTaskSubmitted: 'Skill 일괄 배포 작업이 전송되었습니다',
|
||||
noAccountHint: '기존 모델 계정을 선택하거나 새로 추가하세요.',
|
||||
accountCount: '모델 계정 {0}개',
|
||||
syncAgents: '관련 에이전트 동기화',
|
||||
|
||||
@@ -688,6 +688,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'Agen',
|
||||
account: 'Akaun model',
|
||||
batchOperation: 'Operasi pukal',
|
||||
operationType: 'Jenis operasi',
|
||||
batchInstall: 'Pemasangan pukal',
|
||||
batchUpgrade: 'Naik taraf pukal',
|
||||
batchSkillInstall: 'Hantar Skill secara pukal',
|
||||
batchInstallAgent: 'Pasang ejen secara pukal',
|
||||
dispatchAgentInstallTasks: 'Hantar tugas pemasangan ejen',
|
||||
batchUpgradeAgent: 'Naik taraf ejen secara pukal',
|
||||
dispatchAgentUpgradeTasks: 'Hantar tugas naik taraf ejen',
|
||||
batchInstallAgentSkill: 'Hantar Skill secara pukal',
|
||||
dispatchAgentSkillInstallTasks: 'Hantar tugas pemasangan Skill',
|
||||
allNodes: 'Semua nod',
|
||||
targetVersion: 'Versi sasaran',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: 'Tugas pemasangan pukal telah dihantar',
|
||||
batchUpgradeTaskSubmitted: 'Tugas naik taraf pukal telah dihantar',
|
||||
batchSkillInstallTaskSubmitted: 'Tugas penghantaran Skill pukal telah dihantar',
|
||||
noAccountHint: 'Pilih akaun model sedia ada atau tambah yang baharu.',
|
||||
accountCount: 'Akaun model {0}',
|
||||
syncAgents: 'Segerakkan agen berkaitan',
|
||||
|
||||
@@ -682,6 +682,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'Agente',
|
||||
account: 'Conta de modelo',
|
||||
batchOperation: 'Operação em lote',
|
||||
operationType: 'Tipo de operação',
|
||||
batchInstall: 'Instalação em lote',
|
||||
batchUpgrade: 'Atualização em lote',
|
||||
batchSkillInstall: 'Distribuir Skill em lote',
|
||||
batchInstallAgent: 'Instalar agentes em lote',
|
||||
dispatchAgentInstallTasks: 'Distribuir tarefas de instalação de agentes',
|
||||
batchUpgradeAgent: 'Atualizar agentes em lote',
|
||||
dispatchAgentUpgradeTasks: 'Distribuir tarefas de atualização de agentes',
|
||||
batchInstallAgentSkill: 'Distribuir Skill em lote',
|
||||
dispatchAgentSkillInstallTasks: 'Distribuir tarefas de instalação de Skill',
|
||||
allNodes: 'Todos os nós',
|
||||
targetVersion: 'Versão de destino',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: 'Tarefa de instalação em lote enviada',
|
||||
batchUpgradeTaskSubmitted: 'Tarefa de atualização em lote enviada',
|
||||
batchSkillInstallTaskSubmitted: 'Tarefa de distribuição de Skill enviada',
|
||||
noAccountHint: 'Selecione uma conta de modelo existente ou adicione uma nova.',
|
||||
accountCount: '{0} contas de modelo',
|
||||
syncAgents: 'Sincronizar agentes vinculados',
|
||||
|
||||
@@ -680,6 +680,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'Агент',
|
||||
account: 'Аккаунт модели',
|
||||
batchOperation: 'Пакетная операция',
|
||||
operationType: 'Тип операции',
|
||||
batchInstall: 'Пакетная установка',
|
||||
batchUpgrade: 'Пакетное обновление',
|
||||
batchSkillInstall: 'Пакетная отправка Skill',
|
||||
batchInstallAgent: 'Пакетная установка агентов',
|
||||
dispatchAgentInstallTasks: 'Отправить задачи установки агентов',
|
||||
batchUpgradeAgent: 'Пакетное обновление агентов',
|
||||
dispatchAgentUpgradeTasks: 'Отправить задачи обновления агентов',
|
||||
batchInstallAgentSkill: 'Пакетная отправка Skill',
|
||||
dispatchAgentSkillInstallTasks: 'Отправить задачи установки Skill',
|
||||
allNodes: 'Все узлы',
|
||||
targetVersion: 'Целевая версия',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: 'Задача пакетной установки отправлена',
|
||||
batchUpgradeTaskSubmitted: 'Задача пакетного обновления отправлена',
|
||||
batchSkillInstallTaskSubmitted: 'Задача пакетной отправки Skill отправлена',
|
||||
noAccountHint: 'Выберите существующий аккаунт модели или добавьте новый.',
|
||||
accountCount: '{0} аккаунтов модели',
|
||||
syncAgents: 'Синхронизировать связанные агенты',
|
||||
|
||||
@@ -684,6 +684,23 @@ const message = {
|
||||
agents: {
|
||||
agent: 'Ajan',
|
||||
account: 'Model hesabı',
|
||||
batchOperation: 'Toplu işlem',
|
||||
operationType: 'İşlem türü',
|
||||
batchInstall: 'Toplu kurulum',
|
||||
batchUpgrade: 'Toplu yükseltme',
|
||||
batchSkillInstall: 'Skill toplu dağıt',
|
||||
batchInstallAgent: 'Aracıları toplu kur',
|
||||
dispatchAgentInstallTasks: 'Aracı kurulum görevlerini gönder',
|
||||
batchUpgradeAgent: 'Aracıları toplu yükselt',
|
||||
dispatchAgentUpgradeTasks: 'Aracı yükseltme görevlerini gönder',
|
||||
batchInstallAgentSkill: 'Skill toplu dağıt',
|
||||
dispatchAgentSkillInstallTasks: 'Skill kurulum görevlerini gönder',
|
||||
allNodes: 'Tüm düğümler',
|
||||
targetVersion: 'Hedef sürüm',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: 'Toplu kurulum görevi gönderildi',
|
||||
batchUpgradeTaskSubmitted: 'Toplu yükseltme görevi gönderildi',
|
||||
batchSkillInstallTaskSubmitted: 'Skill toplu dağıtım görevi gönderildi',
|
||||
noAccountHint: 'Mevcut bir model hesabını seçin veya yeni bir tane ekleyin.',
|
||||
accountCount: '{0} model hesabı',
|
||||
syncAgents: 'İlişkili ajanları senkronize et',
|
||||
|
||||
@@ -650,6 +650,23 @@ const message = {
|
||||
agents: {
|
||||
agent: '智能體',
|
||||
account: '模型帳號',
|
||||
batchOperation: '批量操作',
|
||||
operationType: '操作類型',
|
||||
batchInstall: '批量安裝',
|
||||
batchUpgrade: '批量升級',
|
||||
batchSkillInstall: '批量下發 Skill',
|
||||
batchInstallAgent: '批量安裝智能體',
|
||||
dispatchAgentInstallTasks: '下發智能體安裝任務',
|
||||
batchUpgradeAgent: '批量升級智能體',
|
||||
dispatchAgentUpgradeTasks: '下發智能體升級任務',
|
||||
batchInstallAgentSkill: '批量下發 Skill',
|
||||
dispatchAgentSkillInstallTasks: '下發 Skill 安裝任務',
|
||||
allNodes: '所有節點',
|
||||
targetVersion: '目標版本',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: '批量安裝任務已下發',
|
||||
batchUpgradeTaskSubmitted: '批量升級任務已下發',
|
||||
batchSkillInstallTaskSubmitted: '批量下發 Skill 任務已下發',
|
||||
noAccountHint: '選擇已有模型帳號,或直接建立',
|
||||
accountCount: '模型帳號 {0} 個',
|
||||
syncAgents: '同步關聯智能體',
|
||||
|
||||
@@ -647,6 +647,23 @@ const message = {
|
||||
agents: {
|
||||
agent: '智能体',
|
||||
account: '模型账号',
|
||||
batchOperation: '批量操作',
|
||||
operationType: '操作类型',
|
||||
batchInstall: '批量安装',
|
||||
batchUpgrade: '批量升级',
|
||||
batchSkillInstall: '批量下发 Skill',
|
||||
batchInstallAgent: '批量安装智能体',
|
||||
dispatchAgentInstallTasks: '下发智能体安装任务',
|
||||
batchUpgradeAgent: '批量升级智能体',
|
||||
dispatchAgentUpgradeTasks: '下发智能体升级任务',
|
||||
batchInstallAgentSkill: '批量下发 Skill',
|
||||
dispatchAgentSkillInstallTasks: '下发 Skill 安装任务',
|
||||
allNodes: '所有节点',
|
||||
targetVersion: '目标版本',
|
||||
skill: 'Skill',
|
||||
batchInstallTaskSubmitted: '批量安装任务已下发',
|
||||
batchUpgradeTaskSubmitted: '批量升级任务已下发',
|
||||
batchSkillInstallTaskSubmitted: '批量下发 Skill 任务已下发',
|
||||
noAccountHint: '选择已有模型账号,或直接创建',
|
||||
accountCount: '模型账号 {0} 个',
|
||||
syncAgents: '同步关联智能体',
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import i18n from '@/lang';
|
||||
|
||||
const taskTextMap: Record<string, string> = {
|
||||
BatchInstallAgent: 'aiTools.agents.batchInstallAgent',
|
||||
DispatchAgentInstallTasks: 'aiTools.agents.dispatchAgentInstallTasks',
|
||||
BatchUpgradeAgent: 'aiTools.agents.batchUpgradeAgent',
|
||||
DispatchAgentUpgradeTasks: 'aiTools.agents.dispatchAgentUpgradeTasks',
|
||||
BatchInstallAgentSkill: 'aiTools.agents.batchInstallAgentSkill',
|
||||
DispatchAgentSkillInstallTasks: 'aiTools.agents.dispatchAgentSkillInstallTasks',
|
||||
};
|
||||
|
||||
export const translateTaskText = (value?: string) => {
|
||||
if (!value) {
|
||||
return value || '';
|
||||
}
|
||||
return Object.entries(taskTextMap).reduce((text, [key, localeKey]) => {
|
||||
return text.replaceAll(key, i18n.global.t(localeKey));
|
||||
}, value);
|
||||
};
|
||||
@@ -7,6 +7,7 @@
|
||||
<el-button v-permission type="primary" @click="openCreate" :disabled="noApp">
|
||||
{{ $t('commons.button.create') }}
|
||||
</el-button>
|
||||
<EnterpriseBatchInstall @success="search" @task="openTaskLog" />
|
||||
</template>
|
||||
<template #rightToolBar>
|
||||
<TableSearch v-model:searchName="searchName" @search="search" />
|
||||
@@ -35,7 +36,14 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.table.status')" prop="status" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-dropdown placement="bottom">
|
||||
<Status
|
||||
v-if="isAgentTaskRunning(row)"
|
||||
v-permission
|
||||
:status="row.status"
|
||||
class="cursor-pointer"
|
||||
@click="openLog(row)"
|
||||
/>
|
||||
<el-dropdown v-else placement="bottom">
|
||||
<Status v-permission :status="row.status" :operate="true" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
@@ -221,7 +229,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { deleteAgentCheck, pageAgents, resetAgentToken, unbindAgentWebsite, updateAgentRemark } from '@/api/modules/ai';
|
||||
import { checkAppInstalled, installedOp, searchApp, searchAppInstalled } from '@/api/modules/app';
|
||||
@@ -260,8 +268,13 @@ import openclawIcon from '@/assets/images/ai-agent-openclaw.svg';
|
||||
import copawIcon from '@/assets/images/ai-agent-copaw.svg';
|
||||
import hermesIcon from '@/assets/images/ai-agent-hermes-agent.svg';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import { loadOptionalComponent } from '@/extensions/optional';
|
||||
import { useOperateNodeContext } from '@/composables/useOperateNodeContext';
|
||||
|
||||
const EnterpriseBatchInstall = defineAsyncComponent(() =>
|
||||
loadOptionalComponent('/src/enterprise/views/ai/agents/batch-install/index.vue'),
|
||||
);
|
||||
|
||||
const items = ref<AI.AgentItem[]>([]);
|
||||
const loading = ref(false);
|
||||
const addRef = ref();
|
||||
@@ -448,6 +461,11 @@ const openTaskLog = (taskID: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
const isAgentTaskRunning = (row: AI.AgentItem) => {
|
||||
const status = row.status?.toLowerCase();
|
||||
return status === 'installing' || status === 'upgrading';
|
||||
};
|
||||
|
||||
const checkStatus = (operate: string, row: AI.AgentItem) => {
|
||||
const status = row.status.toLowerCase();
|
||||
switch (operate) {
|
||||
@@ -482,6 +500,10 @@ const openLog = (row: AI.AgentItem) => {
|
||||
taskLogRef.value?.openWithResourceID('App', 'TaskInstall', row.appInstallId);
|
||||
return;
|
||||
}
|
||||
if (row.status === 'Upgrading') {
|
||||
taskLogRef.value?.openWithResourceID('App', 'TaskUpgrade', row.appInstallId);
|
||||
return;
|
||||
}
|
||||
composeLogRef.value?.acceptParams({
|
||||
compose: `${row.path}/docker-compose.yml`,
|
||||
resource: row.name,
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
</template>
|
||||
<template #main>
|
||||
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search" :heightDiff="370">
|
||||
<el-table-column :label="$t('logs.taskName')" prop="name" min-width="180px"></el-table-column>
|
||||
<el-table-column :label="$t('logs.taskName')" prop="name" min-width="180px">
|
||||
<template #default="{ row }">
|
||||
{{ translateTaskText(row.name) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.table.status')" prop="status" max-width="100px">
|
||||
<template #default="{ row }">
|
||||
<Status :status="row.status" :msg="row.errorMsg" />
|
||||
@@ -52,6 +56,7 @@ import { onMounted, reactive, ref } from 'vue';
|
||||
import { Log } from '@/api/interface/log';
|
||||
import TaskLog from '@/components/log/task/index.vue';
|
||||
import bus from '@/global/bus';
|
||||
import { translateTaskText } from '@/utils/task';
|
||||
|
||||
const loading = ref();
|
||||
const data = ref();
|
||||
|
||||
Reference in new issue
Block a user