mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-11-10 21:21:13 +08:00
feat: QwenPaw support config username/password (#13478)
This commit is contained in:
1 parent
9dfa451fae
commit
83a3675a0c
35 files changed
+346
-89
No files matched your search
@@ -730,9 +730,9 @@ type AgentSecurityConfig struct {
|
||||
|
||||
type AgentOtherConfigUpdateReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
UserTimezone string `json:"userTimezone" validate:"required"`
|
||||
UserTimezone string `json:"userTimezone"`
|
||||
BrowserEnabled bool `json:"browserEnabled"`
|
||||
NPMRegistry string `json:"npmRegistry" validate:"required"`
|
||||
NPMRegistry string `json:"npmRegistry"`
|
||||
DashboardUsername string `json:"dashboardUsername"`
|
||||
DashboardPassword string `json:"dashboardPassword"`
|
||||
}
|
||||
|
||||
+31
-10
@@ -181,7 +181,7 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
|
||||
var allowedOrigins []string
|
||||
var account *model.AgentAccount
|
||||
var installHooks *appInstallHooks
|
||||
var hermesAuth hermesDashboardAuth
|
||||
var dashboardAuth agentDashboardAuth
|
||||
|
||||
if agentType == constant.AppOpenclaw || agentType == constant.AppHermesAgent {
|
||||
if req.AccountID == 0 {
|
||||
@@ -226,15 +226,17 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
|
||||
},
|
||||
}
|
||||
} else if agentType == constant.AppHermesAgent {
|
||||
hermesAuth = normalizeHermesDashboardAuth(req.DashboardUsername, req.DashboardPassword)
|
||||
dashboardAuth = normalizeAgentDashboardAuth(req.DashboardUsername, req.DashboardPassword)
|
||||
installHooks = &appInstallHooks{
|
||||
AfterCopyData: func(appInstall *model.AppInstall) error {
|
||||
if err := prepareHermesInstallFiles(appInstall, account, storedModel); err != nil {
|
||||
return err
|
||||
}
|
||||
return writeHermesDashboardAuthEnv(path.Join(appInstall.GetPath(), ".env"), hermesAuth, false)
|
||||
return writeAgentDashboardAuthEnv(appInstall.GetEnvPath(), agentType, dashboardAuth, false)
|
||||
},
|
||||
}
|
||||
} else if agentType == constant.AppCopaw {
|
||||
dashboardAuth = normalizeAgentDashboardAuth(req.DashboardUsername, req.DashboardPassword)
|
||||
}
|
||||
|
||||
params := map[string]interface{}{
|
||||
@@ -254,9 +256,12 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
|
||||
params["API_KEY"] = apiKey
|
||||
params["OPENCLAW_GATEWAY_TOKEN"] = token
|
||||
}
|
||||
if agentType == constant.AppHermesAgent {
|
||||
params[hermesDashboardUsernameEnvKey] = hermesAuth.Username
|
||||
params[hermesDashboardPasswordEnvKey] = hermesAuth.Password
|
||||
if usernameKey, passwordKey, ok := agentDashboardAuthEnvKeys(agentType); ok {
|
||||
params[usernameKey] = dashboardAuth.Username
|
||||
params[passwordKey] = dashboardAuth.Password
|
||||
if agentType == constant.AppCopaw {
|
||||
params[qwenPawAuthEnabledEnvKey] = "true"
|
||||
}
|
||||
}
|
||||
|
||||
if req.EditCompose && strings.TrimSpace(req.DockerCompose) == "" {
|
||||
@@ -1435,7 +1440,7 @@ func (a AgentService) GetOtherConfig(req dto.AgentIDReq) (*dto.AgentOtherConfig,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
auth := readHermesDashboardAuthFromInstall(install)
|
||||
auth := readAgentDashboardAuthFromInstall(install, agent.AgentType)
|
||||
return &dto.AgentOtherConfig{
|
||||
UserTimezone: cfg.Timezone,
|
||||
BrowserEnabled: true,
|
||||
@@ -1444,6 +1449,13 @@ func (a AgentService) GetOtherConfig(req dto.AgentIDReq) (*dto.AgentOtherConfig,
|
||||
DashboardPassword: auth.Password,
|
||||
}, nil
|
||||
}
|
||||
if agent.AgentType == constant.AppCopaw {
|
||||
auth := readAgentDashboardAuthFromInstall(install, agent.AgentType)
|
||||
return &dto.AgentOtherConfig{
|
||||
DashboardUsername: auth.Username,
|
||||
DashboardPassword: auth.Password,
|
||||
}, nil
|
||||
}
|
||||
conf, err := readOpenclawConfig(agent.ConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1462,16 +1474,19 @@ func (a AgentService) UpdateOtherConfig(req dto.AgentOtherConfigUpdateReq) error
|
||||
return err
|
||||
}
|
||||
if agent.AgentType == constant.AppHermesAgent {
|
||||
if strings.TrimSpace(req.UserTimezone) == "" {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
account, err := agentAccountRepo.GetFirst(repo.WithByID(agent.AccountID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
previousAuth := readHermesDashboardAuthFromInstall(install)
|
||||
nextAuth := normalizeHermesDashboardAuth(req.DashboardUsername, req.DashboardPassword)
|
||||
previousAuth := readAgentDashboardAuthFromInstall(install, agent.AgentType)
|
||||
nextAuth := normalizeAgentDashboardAuth(req.DashboardUsername, req.DashboardPassword)
|
||||
if err := writeHermesConfig(path.Dir(agent.ConfigPath), account, agent.Model, strings.TrimSpace(req.UserTimezone)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeHermesDashboardAuthEnv(path.Join(install.GetPath(), ".env"), nextAuth, true); err != nil {
|
||||
if err := writeAgentDashboardAuthEnv(install.GetEnvPath(), agent.AgentType, nextAuth, true); err != nil {
|
||||
return err
|
||||
}
|
||||
operate := constant.Restart
|
||||
@@ -1483,6 +1498,12 @@ func (a AgentService) UpdateOtherConfig(req dto.AgentOtherConfigUpdateReq) error
|
||||
Operate: operate,
|
||||
})
|
||||
}
|
||||
if agent.AgentType == constant.AppCopaw {
|
||||
return updateQwenPawDashboardAuth(install, normalizeAgentDashboardAuth(req.DashboardUsername, req.DashboardPassword))
|
||||
}
|
||||
if strings.TrimSpace(req.UserTimezone) == "" || strings.TrimSpace(req.NPMRegistry) == "" {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
if err := ensureContainerRunning(install.ContainerName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
)
|
||||
|
||||
type qwenPawAuthStatus struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
HasUsers bool `json:"has_users"`
|
||||
}
|
||||
|
||||
type qwenPawLoginResponse struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func updateQwenPawDashboardAuth(install *model.AppInstall, next agentDashboardAuth) error {
|
||||
if install == nil || install.ID == 0 {
|
||||
return buserr.New("ErrRecordNotFound")
|
||||
}
|
||||
current, err := readAgentDashboardAuthEnv(install.GetEnvPath(), constant.AppCopaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if current == next {
|
||||
return writeAgentDashboardAuthEnv(install.GetEnvPath(), constant.AppCopaw, next, true)
|
||||
}
|
||||
if err := ensureContainerRunning(install.ContainerName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
baseURL := fmt.Sprintf("http://127.0.0.1:%d/api/auth", install.HttpPort)
|
||||
var status qwenPawAuthStatus
|
||||
if _, err := requestQwenPawAuth(http.MethodGet, baseURL+"/status", nil, "", &status); err != nil {
|
||||
return buserr.WithMap("ErrQwenPawAuthRequest", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
if !status.Enabled {
|
||||
return buserr.New("ErrQwenPawAuthDisabled")
|
||||
}
|
||||
|
||||
if !status.HasUsers {
|
||||
payload := map[string]string{"username": next.Username, "password": next.Password}
|
||||
if _, err := requestQwenPawAuth(http.MethodPost, baseURL+"/register", payload, "", nil); err != nil {
|
||||
return buserr.WithMap("ErrQwenPawAuthRequest", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
} else {
|
||||
var login qwenPawLoginResponse
|
||||
payload := map[string]string{"username": current.Username, "password": current.Password}
|
||||
statusCode, err := requestQwenPawAuth(http.MethodPost, baseURL+"/login", payload, "", &login)
|
||||
if statusCode == http.StatusUnauthorized {
|
||||
return buserr.New("ErrQwenPawAuthOutOfSync")
|
||||
}
|
||||
if err != nil {
|
||||
return buserr.WithMap("ErrQwenPawAuthRequest", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
payload = map[string]string{"current_password": current.Password}
|
||||
if current.Username != next.Username {
|
||||
payload["new_username"] = next.Username
|
||||
}
|
||||
if current.Password != next.Password {
|
||||
payload["new_password"] = next.Password
|
||||
}
|
||||
if _, err := requestQwenPawAuth(http.MethodPost, baseURL+"/update-profile", payload, login.Token, nil); err != nil {
|
||||
return buserr.WithMap("ErrQwenPawAuthRequest", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
}
|
||||
return writeAgentDashboardAuthEnv(install.GetEnvPath(), constant.AppCopaw, next, true)
|
||||
}
|
||||
|
||||
func requestQwenPawAuth(method, reqURL string, payload interface{}, token string, result interface{}) (int, error) {
|
||||
var body io.Reader
|
||||
if payload != nil {
|
||||
data, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
body = bytes.NewReader(data)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
resp, err := (&http.Client{Timeout: 10 * time.Second}).Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
|
||||
if err != nil {
|
||||
return resp.StatusCode, err
|
||||
}
|
||||
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
|
||||
detail := strings.TrimSpace(string(data))
|
||||
var errorResponse struct {
|
||||
Detail string `json:"detail"`
|
||||
}
|
||||
if json.Unmarshal(data, &errorResponse) == nil && strings.TrimSpace(errorResponse.Detail) != "" {
|
||||
detail = strings.TrimSpace(errorResponse.Detail)
|
||||
}
|
||||
if detail == "" {
|
||||
detail = resp.Status
|
||||
}
|
||||
return resp.StatusCode, errors.New(detail)
|
||||
}
|
||||
if result != nil && len(data) > 0 {
|
||||
if err := json.Unmarshal(data, result); err != nil {
|
||||
return resp.StatusCode, err
|
||||
}
|
||||
}
|
||||
return resp.StatusCode, nil
|
||||
}
|
||||
@@ -19,13 +19,6 @@ import (
|
||||
|
||||
const hermesWorkspaceDir = "/opt/data/workspace"
|
||||
const hermesExecutablePath = "/opt/hermes/.venv/bin/hermes"
|
||||
const hermesDashboardUsernameEnvKey = "HERMES_DASHBOARD_USERNAME"
|
||||
const hermesDashboardPasswordEnvKey = "HERMES_DASHBOARD_PASSWORD"
|
||||
|
||||
type hermesDashboardAuth struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
type hermesConfig struct {
|
||||
Model hermesModelConfig `yaml:"model"`
|
||||
@@ -117,52 +110,6 @@ func prepareHermesInstallFiles(appInstall *model.AppInstall, account *model.Agen
|
||||
return files.NewFileOp().ChownR(dataDir, "1000", "1000", true)
|
||||
}
|
||||
|
||||
func normalizeHermesDashboardAuth(username, password string) hermesDashboardAuth {
|
||||
auth := hermesDashboardAuth{
|
||||
Username: strings.TrimSpace(username),
|
||||
Password: strings.TrimSpace(password),
|
||||
}
|
||||
if auth.Username == "" {
|
||||
auth.Username = "admin"
|
||||
}
|
||||
if auth.Password == "" {
|
||||
auth.Password = common.RandStr(8)
|
||||
}
|
||||
return auth
|
||||
}
|
||||
|
||||
func writeHermesDashboardAuthEnv(envPath string, auth hermesDashboardAuth, overwrite bool) error {
|
||||
return upsertAgentEnv(envPath, map[string]string{
|
||||
hermesDashboardUsernameEnvKey: auth.Username,
|
||||
hermesDashboardPasswordEnvKey: auth.Password,
|
||||
}, []string{
|
||||
hermesDashboardUsernameEnvKey,
|
||||
hermesDashboardPasswordEnvKey,
|
||||
}, overwrite)
|
||||
}
|
||||
|
||||
func readHermesDashboardAuthEnv(envPath string) (hermesDashboardAuth, error) {
|
||||
envMap, err := readAgentEnvMap(envPath)
|
||||
if err != nil {
|
||||
return hermesDashboardAuth{}, err
|
||||
}
|
||||
return hermesDashboardAuth{
|
||||
Username: strings.TrimSpace(envMap[hermesDashboardUsernameEnvKey]),
|
||||
Password: strings.TrimSpace(envMap[hermesDashboardPasswordEnvKey]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func readHermesDashboardAuthFromInstall(appInstall *model.AppInstall) hermesDashboardAuth {
|
||||
if appInstall == nil || appInstall.ID == 0 {
|
||||
return hermesDashboardAuth{}
|
||||
}
|
||||
auth, err := readHermesDashboardAuthEnv(path.Join(appInstall.GetPath(), ".env"))
|
||||
if err != nil {
|
||||
return hermesDashboardAuth{}
|
||||
}
|
||||
return auth
|
||||
}
|
||||
|
||||
func readHermesConfig(configPath string) (*hermesConfig, error) {
|
||||
content, err := files.NewFileOp().GetContent(configPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -422,8 +422,8 @@ func buildAgentItem(agent *model.Agent, appInstall *model.AppInstall, envMap map
|
||||
item.BridgePort = toInt(bridge)
|
||||
}
|
||||
}
|
||||
if agentType == constant.AppHermesAgent {
|
||||
auth := readHermesDashboardAuthFromInstall(appInstall)
|
||||
if _, _, ok := agentDashboardAuthEnvKeys(agentType); ok {
|
||||
auth := readAgentDashboardAuthFromInstall(appInstall, agentType)
|
||||
item.DashboardUsername = auth.Username
|
||||
item.DashboardPassword = auth.Password
|
||||
}
|
||||
@@ -1463,6 +1463,87 @@ func readInstallEnv(envStr string) map[string]interface{} {
|
||||
return data
|
||||
}
|
||||
|
||||
const (
|
||||
hermesDashboardUsernameEnvKey = "HERMES_DASHBOARD_USERNAME"
|
||||
hermesDashboardPasswordEnvKey = "HERMES_DASHBOARD_PASSWORD"
|
||||
qwenPawAuthEnabledEnvKey = "QWENPAW_AUTH_ENABLED"
|
||||
qwenPawAuthUsernameEnvKey = "QWENPAW_AUTH_USERNAME"
|
||||
qwenPawAuthPasswordEnvKey = "QWENPAW_AUTH_PASSWORD"
|
||||
)
|
||||
|
||||
type agentDashboardAuth struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
func normalizeAgentDashboardAuth(username, password string) agentDashboardAuth {
|
||||
auth := agentDashboardAuth{
|
||||
Username: strings.TrimSpace(username),
|
||||
Password: strings.TrimSpace(password),
|
||||
}
|
||||
if auth.Username == "" {
|
||||
auth.Username = "admin"
|
||||
}
|
||||
if auth.Password == "" {
|
||||
auth.Password = common.RandStr(8)
|
||||
}
|
||||
return auth
|
||||
}
|
||||
|
||||
func agentDashboardAuthEnvKeys(agentType string) (string, string, bool) {
|
||||
switch agentType {
|
||||
case constant.AppHermesAgent:
|
||||
return hermesDashboardUsernameEnvKey, hermesDashboardPasswordEnvKey, true
|
||||
case constant.AppCopaw:
|
||||
return qwenPawAuthUsernameEnvKey, qwenPawAuthPasswordEnvKey, true
|
||||
default:
|
||||
return "", "", false
|
||||
}
|
||||
}
|
||||
|
||||
func writeAgentDashboardAuthEnv(envPath, agentType string, auth agentDashboardAuth, overwrite bool) error {
|
||||
usernameKey, passwordKey, ok := agentDashboardAuthEnvKeys(agentType)
|
||||
if !ok {
|
||||
return fmt.Errorf("dashboard auth is not supported for %s", agentType)
|
||||
}
|
||||
values := map[string]string{
|
||||
usernameKey: auth.Username,
|
||||
passwordKey: auth.Password,
|
||||
}
|
||||
order := []string{usernameKey, passwordKey}
|
||||
if agentType == constant.AppCopaw {
|
||||
values[qwenPawAuthEnabledEnvKey] = "true"
|
||||
order = append([]string{qwenPawAuthEnabledEnvKey}, order...)
|
||||
}
|
||||
return upsertAgentEnv(envPath, values, order, overwrite)
|
||||
}
|
||||
|
||||
func readAgentDashboardAuthEnv(envPath, agentType string) (agentDashboardAuth, error) {
|
||||
usernameKey, passwordKey, ok := agentDashboardAuthEnvKeys(agentType)
|
||||
if !ok {
|
||||
return agentDashboardAuth{}, fmt.Errorf("dashboard auth is not supported for %s", agentType)
|
||||
}
|
||||
envMap, err := readAgentEnvMap(envPath)
|
||||
if err != nil {
|
||||
return agentDashboardAuth{}, err
|
||||
}
|
||||
return agentDashboardAuth{
|
||||
Username: strings.TrimSpace(envMap[usernameKey]),
|
||||
Password: strings.TrimSpace(envMap[passwordKey]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func readAgentDashboardAuthFromInstall(appInstall *model.AppInstall, agentType string) agentDashboardAuth {
|
||||
if appInstall == nil || appInstall.ID == 0 {
|
||||
return agentDashboardAuth{}
|
||||
}
|
||||
auth, err := readAgentDashboardAuthEnv(appInstall.GetEnvPath(), agentType)
|
||||
if err != nil {
|
||||
return agentDashboardAuth{}
|
||||
}
|
||||
return auth
|
||||
}
|
||||
|
||||
func readAgentEnvMap(envPath string) (map[string]string, error) {
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(envPath) {
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'This agent is already bound to a website'
|
||||
ErrAgentWebsiteTypeUnsupported: 'Only proxy or static websites can be bound'
|
||||
ErrAgentWebsiteInUse: 'This website is already bound to another agent'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'Deployment websites cannot be unbound manually'
|
||||
ErrQwenPawAuthRequest: 'Failed to update QwenPaw credentials: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'The current QwenPaw credentials do not match the 1Panel record. Reset the QwenPaw password or restore the credentials in the application .env file'
|
||||
ErrQwenPawAuthDisabled: 'Login authentication is not enabled in QwenPaw'
|
||||
ErrHermesPairingCodeUnavailable: 'The pairing code is temporarily unavailable in Hermes, possibly due to network issues. Please try again later.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'When the Feishu group policy is Allowlist, the DM policy cannot be Pairing Code.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'Este agente ya está vinculado a un sitio web'
|
||||
ErrAgentWebsiteTypeUnsupported: 'Solo se pueden vincular sitios proxy o estáticos'
|
||||
ErrAgentWebsiteInUse: 'Este sitio web ya está vinculado a otro agente'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'Los sitios web de despliegue no se pueden desvincular manualmente'
|
||||
ErrQwenPawAuthRequest: 'No se pudieron actualizar las credenciales de QwenPaw: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'Las credenciales actuales de QwenPaw no coinciden con el registro de 1Panel. Restablezca la contraseña de QwenPaw o restaure las credenciales en el archivo .env de la aplicación'
|
||||
ErrQwenPawAuthDisabled: 'La autenticación de inicio de sesión no está habilitada en QwenPaw'
|
||||
ErrHermesPairingCodeUnavailable: 'El código de emparejamiento no está disponible temporalmente en Hermes, posiblemente por un problema de red. Inténtalo de nuevo más tarde.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Cuando la política de grupo de Feishu es Lista permitida, la política de MD no puede ser Código de emparejamiento.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'این عامل قبلاً به یک وبسایت مت
|
||||
ErrAgentWebsiteTypeUnsupported: 'فقط وبسایتهای پراکسی یا استاتیک قابل اتصال هستند'
|
||||
ErrAgentWebsiteInUse: 'این وبسایت قبلاً به عامل دیگری متصل است'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'وبسایتهای استقرار یافته را نمیتوان به صورت دستی قطع اتصال کرد'
|
||||
ErrQwenPawAuthRequest: 'بهروزرسانی اطلاعات ورود QwenPaw ناموفق بود: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'اطلاعات ورود فعلی QwenPaw با رکورد 1Panel مطابقت ندارد. گذرواژه QwenPaw را بازنشانی کنید یا اطلاعات ورود فایل .env برنامه را بازیابی کنید'
|
||||
ErrQwenPawAuthDisabled: 'احراز هویت ورود در QwenPaw فعال نشده است'
|
||||
ErrHermesPairingCodeUnavailable: 'کد جفتسازی به طور موقت در هرمس در دسترس نیست، احتمالاً به دلیل مشکلات شبکه. لطفاً بعداً دوباره تلاش کنید.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'وقتی خط مشی گروه فیشو لیست سفید باشد، خط مشی DM نمیتواند کد جفتسازی باشد.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'このエージェントはすでにサイトに関連付
|
||||
ErrAgentWebsiteTypeUnsupported: '関連付けできるのはプロキシサイトまたは静的サイトのみです'
|
||||
ErrAgentWebsiteInUse: 'このサイトはすでに別のエージェントに関連付けられています'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'ワンクリックデプロイのサイトは手動で関連解除できません'
|
||||
ErrQwenPawAuthRequest: 'QwenPaw 認証情報の更新に失敗しました: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: '現在の QwenPaw 認証情報が 1Panel の記録と一致しません。QwenPaw のパスワードをリセットするか、アプリケーションの .env にある認証情報を復元してください'
|
||||
ErrQwenPawAuthDisabled: 'QwenPaw でログイン認証が有効になっていません'
|
||||
ErrHermesPairingCodeUnavailable: 'Hermes でペアリングコードが一時的に見つかりません。ネットワーク要因の可能性があるため、しばらくしてから再試行してください。'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu のグループポリシーが許可リストの場合、DM ポリシーをペアリングコードにはできません。'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: '이 에이전트는 이미 웹사이트에 연결되어
|
||||
ErrAgentWebsiteTypeUnsupported: '프록시 또는 정적 웹사이트만 연결할 수 있습니다'
|
||||
ErrAgentWebsiteInUse: '이 웹사이트는 이미 다른 에이전트에 연결되어 있습니다'
|
||||
ErrAgentWebsiteUnbindUnsupported: '원클릭 배포 웹사이트는 수동으로 연결 해제할 수 없습니다'
|
||||
ErrQwenPawAuthRequest: 'QwenPaw 인증 정보 업데이트에 실패했습니다: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: '현재 QwenPaw 자격 증명이 1Panel 기록과 일치하지 않습니다. QwenPaw 비밀번호를 재설정하거나 애플리케이션 .env의 자격 증명을 복원하세요'
|
||||
ErrQwenPawAuthDisabled: 'QwenPaw에서 로그인 인증이 활성화되어 있지 않습니다'
|
||||
ErrHermesPairingCodeUnavailable: 'Hermes에서 페어링 코드가 일시적으로 존재하지 않습니다. 네트워크 문제일 수 있으니 잠시 후 다시 시도해 주세요.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu 그룹 정책이 허용 목록이면 DM 정책을 페어링 코드로 설정할 수 없습니다.'
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@ ErrAgentWebsiteBound: 'ຕົວແທນນີ້ຖືກຜູກມັດກ
|
||||
ErrAgentWebsiteTypeUnsupported: 'ສາມາດຜູກມັດໄດ້ສະເພາະເວັບໄຊປະເພດ Proxy ຫຼື Static ເທົ່ານັ້ນ'
|
||||
ErrAgentWebsiteInUse: 'ເວັບໄຊນີ້ຖືກຜູກມັດກັບຕົວແທນອື່ນແລ້ວ'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'ເວັບໄຊທີ່ຕິດຕັ້ງແລ້ວບໍ່ສາມາດຍົກເລີກການຜູກມັດດ້ວຍຕົນເອງໄດ້'
|
||||
ErrQwenPawAuthRequest: 'ອັບເດດຂໍ້ມູນຢືນຢັນ QwenPaw ບໍ່ສຳເລັດ: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'ຂໍ້ມູນຢືນຢັນ QwenPaw ປັດຈຸບັນບໍ່ກົງກັບບັນທຶກຂອງ 1Panel. ກະລຸນາຣີເຊັດລະຫັດຜ່ານ QwenPaw ຫຼືກູ້ຄືນຂໍ້ມູນໃນໄຟລ໌ .env ຂອງແອັບ'
|
||||
ErrQwenPawAuthDisabled: 'QwenPaw ຍັງບໍ່ໄດ້ເປີດໃຊ້ການຢືນຢັນການເຂົ້າລະບົບ'
|
||||
ErrHermesPairingCodeUnavailable: 'ລະຫັດການຈັບຄູ່ໃນ Hermes ບໍ່ສາມາດໃຊ້ງານໄດ້ຊົ່ວຄາວ, ອາດຈະເກີດຈາກບັນຫາເຄືອຂ່າຍ. ກະລຸນາລອງໃໝ່ພາຍຫຼັງ.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'ເມື່ອນະໂຍບາຍກຸ່ມ Feishu ແມ່ນ Allowlist, ນະໂຍບາຍ DM ບໍ່ສາມາດເປັນ Pairing Code ໄດ້.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'Ejen ini sudah dipautkan ke laman web'
|
||||
ErrAgentWebsiteTypeUnsupported: 'Hanya laman web proxy atau statik boleh dipautkan'
|
||||
ErrAgentWebsiteInUse: 'Laman web ini sudah dipautkan ke ejen lain'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'Laman web one-click deployment tidak menyokong nyahikat manual'
|
||||
ErrQwenPawAuthRequest: 'Gagal mengemas kini kelayakan QwenPaw: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'Kelayakan QwenPaw semasa tidak sepadan dengan rekod 1Panel. Tetapkan semula kata laluan QwenPaw atau pulihkan kelayakan dalam fail .env aplikasi'
|
||||
ErrQwenPawAuthDisabled: 'Pengesahan log masuk belum didayakan dalam QwenPaw'
|
||||
ErrHermesPairingCodeUnavailable: 'Kod pasangan buat sementara waktu tidak wujud dalam Hermes, mungkin disebabkan masalah rangkaian. Sila cuba lagi sebentar nanti.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Apabila dasar kumpulan Feishu ialah senarai benarkan, dasar DM tidak boleh menggunakan kod pasangan.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'Este agente já está vinculado a um site'
|
||||
ErrAgentWebsiteTypeUnsupported: 'Somente sites proxy ou estáticos podem ser vinculados'
|
||||
ErrAgentWebsiteInUse: 'Este site já está vinculado a outro agente'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'Sites implantados em um clique não podem ser desvinculados manualmente'
|
||||
ErrQwenPawAuthRequest: 'Falha ao atualizar as credenciais do QwenPaw: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'As credenciais atuais do QwenPaw não correspondem ao registro do 1Panel. Redefina a senha do QwenPaw ou restaure as credenciais no arquivo .env do aplicativo'
|
||||
ErrQwenPawAuthDisabled: 'A autenticação de login não está ativada no QwenPaw'
|
||||
ErrHermesPairingCodeUnavailable: 'O código de pareamento está temporariamente indisponível no Hermes, possivelmente por causa de rede. Tente novamente mais tarde.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Quando a política de grupo do Feishu é Lista de permissões, a política de DM não pode ser Código de pareamento.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'Этот агент уже связан с сайтом'
|
||||
ErrAgentWebsiteTypeUnsupported: 'Можно связывать только proxy- или static-сайты'
|
||||
ErrAgentWebsiteInUse: 'Этот сайт уже связан с другим агентом'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'Сайты one-click deployment нельзя отвязать вручную'
|
||||
ErrQwenPawAuthRequest: 'Не удалось обновить учетные данные QwenPaw: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'Текущие учетные данные QwenPaw не совпадают с записью 1Panel. Сбросьте пароль QwenPaw или восстановите учетные данные в файле .env приложения'
|
||||
ErrQwenPawAuthDisabled: 'В QwenPaw не включена аутентификация при входе'
|
||||
ErrHermesPairingCodeUnavailable: 'Код сопряжения временно недоступен в Hermes, возможно из-за проблем с сетью. Повторите попытку позже.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Когда групповая политика Feishu — белый список, политика личных сообщений не может быть кодом сопряжения.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: 'Bu ajan zaten bir web sitesine bağlı'
|
||||
ErrAgentWebsiteTypeUnsupported: 'Yalnızca proxy veya statik web siteleri bağlanabilir'
|
||||
ErrAgentWebsiteInUse: 'Bu web sitesi zaten başka bir ajana bağlı'
|
||||
ErrAgentWebsiteUnbindUnsupported: 'Tek tıkla dağıtılan web sitelerinin bağlantısı manuel olarak kaldırılamaz'
|
||||
ErrQwenPawAuthRequest: 'QwenPaw kimlik bilgileri güncellenemedi: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'Geçerli QwenPaw kimlik bilgileri 1Panel kaydıyla eşleşmiyor. QwenPaw parolasını sıfırlayın veya uygulamanın .env dosyasındaki kimlik bilgilerini geri yükleyin'
|
||||
ErrQwenPawAuthDisabled: 'QwenPaw oturum açma kimlik doğrulaması etkin değil'
|
||||
ErrHermesPairingCodeUnavailable: 'Eşleştirme kodu Hermes içinde geçici olarak bulunamıyor; bu durum ağ kaynaklı olabilir. Lütfen daha sonra tekrar deneyin.'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu grup ilkesi izin listesi olduğunda, DM ilkesi eşleştirme kodu olamaz.'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: '該智能體已關聯網站'
|
||||
ErrAgentWebsiteTypeUnsupported: '只能關聯反向代理或靜態網站'
|
||||
ErrAgentWebsiteInUse: '該網站已被其他智能體關聯'
|
||||
ErrAgentWebsiteUnbindUnsupported: '一鍵部署網站不支援手動解綁'
|
||||
ErrQwenPawAuthRequest: 'QwenPaw 驗證資訊更新失敗: {{ .err }}'
|
||||
ErrQwenPawAuthOutOfSync: 'QwenPaw 目前憑據與 1Panel 記錄不一致,請先重設 QwenPaw 密碼或還原應用程式 .env 中的憑據'
|
||||
ErrQwenPawAuthDisabled: 'QwenPaw 尚未啟用登入驗證'
|
||||
ErrHermesPairingCodeUnavailable: '配對碼在 Hermes 中暫時不存在,可能是由於網路原因,請稍後再試'
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: '飛書群組策略為白名單時,私聊策略不能為配對碼'
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ ErrAgentWebsiteBound: "该智能体已关联网站"
|
||||
ErrAgentWebsiteTypeUnsupported: "只能关联反向代理或静态网站"
|
||||
ErrAgentWebsiteInUse: "该网站已被其他智能体关联"
|
||||
ErrAgentWebsiteUnbindUnsupported: "一键部署网站不支持手动解绑"
|
||||
ErrQwenPawAuthRequest: "QwenPaw 认证信息更新失败: {{ .err }}"
|
||||
ErrQwenPawAuthOutOfSync: "QwenPaw 当前凭据与 1Panel 记录不一致,请先重置 QwenPaw 密码或恢复应用 .env 中的凭据"
|
||||
ErrQwenPawAuthDisabled: "QwenPaw 尚未启用登录认证"
|
||||
ErrHermesPairingCodeUnavailable: "配对码在 hermes 中暂时不存在,可能是由于网络原因,请稍后尝试"
|
||||
ErrHermesFeishuGroupAllowlistRequiresAllowlist: "飞书群组策略为白名单时,私聊策略不能为配对码"
|
||||
|
||||
|
||||
@@ -969,9 +969,9 @@ export namespace AI {
|
||||
|
||||
export interface AgentOtherConfigUpdateReq {
|
||||
agentId: number;
|
||||
userTimezone: string;
|
||||
userTimezone?: string;
|
||||
browserEnabled: boolean;
|
||||
npmRegistry: string;
|
||||
npmRegistry?: string;
|
||||
dashboardUsername?: string;
|
||||
dashboardPassword?: string;
|
||||
}
|
||||
|
||||
@@ -922,6 +922,8 @@ const message = {
|
||||
channelAutoRestartHelper: 'Saving will automatically restart the container so the changes take effect.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Saving the username or password will automatically rebuild the container so the changes take effect.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Saving updates the QwenPaw login credentials immediately without restarting the container.',
|
||||
channelDeleteConfirm: 'Delete the {0} channel configuration?',
|
||||
apiTypeBaseURLHelper: 'This type sends requests to {0}. Recommended Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -925,6 +925,8 @@ const message = {
|
||||
'Al guardar, el contenedor se reiniciará automáticamente para que la configuración surta efecto.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Al guardar el usuario o la contraseña, el contenedor se reconstruirá automáticamente para que los cambios surtan efecto.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Al guardar, las credenciales de QwenPaw se actualizan de inmediato sin reiniciar el contenedor.',
|
||||
channelDeleteConfirm: '¿Eliminar la configuración del canal {0}?',
|
||||
apiTypeBaseURLHelper: 'Este tipo envía solicitudes a {0}. Base URL recomendada: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -910,6 +910,8 @@ const message = {
|
||||
channelAutoRestartHelper: 'ذخیره به طور خودکار کانتینر را مجدداً راهاندازی میکند تا تغییرات اعمال شوند.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'ذخیره نام کاربری یا رمز عبور، کانتینر را بهطور خودکار بازسازی میکند تا تغییرات اعمال شوند.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'با ذخیرهسازی، اطلاعات ورود QwenPaw بدون راهاندازی مجدد کانتینر فوراً بهروزرسانی میشود.',
|
||||
channelDeleteConfirm: 'پیکربندی کانال {0} حذف شود؟',
|
||||
apiTypeBaseURLHelper: 'این نوع درخواستها را به {0} ارسال میکند. Base URL پیشنهادی: {1}',
|
||||
apiTypeBaseURLMismatch: 'Base URL فعلی شبیه مسیر {0} است، اما {1} انتخاب شده است. URL پیشنهادی: {2}',
|
||||
|
||||
@@ -914,6 +914,8 @@ const message = {
|
||||
channelAutoRestartHelper: '保存後、設定を反映するためにコンテナが自動で再起動されます。',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'ユーザー名またはパスワードを保存すると、変更を反映するためにコンテナが自動で再作成されます。',
|
||||
dashboardAuthImmediateHelper:
|
||||
'保存すると QwenPaw のログイン認証情報がすぐに更新され、コンテナの再起動は不要です。',
|
||||
channelDeleteConfirm: '{0} チャンネルの設定を削除しますか?',
|
||||
apiTypeBaseURLHelper: 'このタイプは最終的に {0} にリクエストします。推奨 Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -904,6 +904,8 @@ const message = {
|
||||
channelAutoRestartHelper: '저장하면 설정 적용을 위해 컨테이너가 자동으로 재시작됩니다.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'사용자 이름 또는 비밀번호를 저장하면 변경 사항 적용을 위해 컨테이너가 자동으로 재생성됩니다.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'저장하면 컨테이너를 다시 시작하지 않고 QwenPaw 로그인 자격 증명이 즉시 업데이트됩니다.',
|
||||
channelDeleteConfirm: '{0} 채널 구성을 삭제하시겠습니까?',
|
||||
apiTypeBaseURLHelper: '이 유형은 최종적으로 {0}에 요청합니다. 권장 Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -904,6 +904,8 @@ const message = {
|
||||
channelAutoRestartHelper: 'ການບັນທຶກຈະຣີສະຕາດຄອນເທນເນີອັດຕະໂນມັດເພື່ອໃຫ້ການປ່ຽນແປງມີຜົນ.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'ການບັນທຶກຊື່ຜູ້ໃຊ້ ຫຼື ລະຫັດຜ່ານ Dashboard ຈະສ້າງຄອນເທນເນີໃໝ່ອັດຕະໂນມັດເພື່ອໃຫ້ການປ່ຽນແປງມີຜົນ.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'ເມື່ອບັນທຶກ ຂໍ້ມູນເຂົ້າລະບົບ QwenPaw ຈະຖືກອັບເດດທັນທີໂດຍບໍ່ຕ້ອງຣີສະຕາດຄອນເທນເນີ.',
|
||||
channelDeleteConfirm: 'ລຶບການຕັ້ງຄ່າຊ່ອງທາງ {0}?',
|
||||
apiTypeBaseURLHelper: 'ປະເພດນີ້ຈະສົ່ງການຮ້ອງຂໍໄປທີ່ {0}. Base URL ທີ່ແນະນຳ: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -933,6 +933,8 @@ const message = {
|
||||
'Menyimpan akan memulakan semula bekas secara automatik supaya konfigurasi berkuat kuasa.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Menyimpan nama pengguna atau kata laluan akan membina semula bekas secara automatik supaya perubahan berkuat kuasa.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Apabila disimpan, kelayakan log masuk QwenPaw dikemas kini serta-merta tanpa memulakan semula bekas.',
|
||||
channelDeleteConfirm: 'Padam konfigurasi saluran {0}?',
|
||||
apiTypeBaseURLHelper: 'Jenis ini menghantar permintaan ke {0}. Base URL yang disyorkan: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -929,6 +929,8 @@ const message = {
|
||||
'Ao salvar, o contêiner será reiniciado automaticamente para que a configuração entre em vigor.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Ao salvar o usuário ou a senha, o contêiner será reconstruído automaticamente para que as alterações entrem em vigor.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Ao salvar, as credenciais do QwenPaw são atualizadas imediatamente, sem reiniciar o contêiner.',
|
||||
channelDeleteConfirm: 'Excluir a configuração do canal {0}?',
|
||||
apiTypeBaseURLHelper: 'Este tipo envia requisições para {0}. Base URL recomendada: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -922,6 +922,8 @@ const message = {
|
||||
'После сохранения контейнер будет автоматически перезапущен, чтобы настройки вступили в силу.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'После сохранения имени пользователя или пароля контейнер будет автоматически пересобран, чтобы изменения вступили в силу.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'После сохранения учетные данные QwenPaw обновляются сразу, без перезапуска контейнера.',
|
||||
channelDeleteConfirm: 'Удалить конфигурацию канала {0}?',
|
||||
apiTypeBaseURLHelper: 'Этот тип отправляет запросы в {0}. Рекомендуемый Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -931,6 +931,8 @@ const message = {
|
||||
'Kaydettiğinizde ayarların etkili olması için konteyner otomatik olarak yeniden başlatılır.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Kullanıcı adı veya parola kaydedildiğinde değişikliklerin etkili olması için konteyner otomatik olarak yeniden oluşturulur.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Kaydedildiğinde QwenPaw oturum açma bilgileri konteyner yeniden başlatılmadan hemen güncellenir.',
|
||||
channelDeleteConfirm: '{0} kanal yapılandırması silinsin mi?',
|
||||
apiTypeBaseURLHelper: 'Bu tür istekleri {0} yoluna gönderir. Önerilen Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -877,6 +877,7 @@ const message = {
|
||||
scanConnectHelper: '點擊後將在任務日誌中顯示 QR Code,掃碼確認成功後將自動重新啟動容器。',
|
||||
channelAutoRestartHelper: '保存後將自動重新啟動容器以使設定生效。',
|
||||
dashboardAuthAutoRebuildHelper: '保存使用者名稱或密碼後將自動重建容器以使設定生效。',
|
||||
dashboardAuthImmediateHelper: '保存後將立即更新 QwenPaw 登入憑據,無需重新啟動容器。',
|
||||
channelDeleteConfirm: '確認刪除 {0} 頻道設定?',
|
||||
apiTypeBaseURLHelper: '目前類型最終請求 {0},Base URL 建議填寫 {1}',
|
||||
customImageURLHelper: 'Custom 圖片帳號請填寫完整的圖片產生介面 URL,系統不會自動補全路徑,例如:{0}',
|
||||
|
||||
@@ -890,6 +890,7 @@ const message = {
|
||||
scanConnectHelper: '点击后将在任务日志中显示二维码,扫码确认成功后将自动重启容器。',
|
||||
channelAutoRestartHelper: '保存后将自动重启容器以使配置生效。',
|
||||
dashboardAuthAutoRebuildHelper: '保存用户名密码后将自动重建容器以使配置生效。',
|
||||
dashboardAuthImmediateHelper: '保存后将立即更新 QwenPaw 登录凭据,无需重启容器。',
|
||||
channelDeleteConfirm: '确认删除 {0} 频道配置?',
|
||||
apiTypeBaseURLHelper: '当前类型最终请求 {0},Base URL 建议填写 {1}',
|
||||
customImageURLHelper: 'Custom 图片账号请填写完整的图片生成接口 URL,系统不会自动补全路径,例如:{0}',
|
||||
|
||||
@@ -26,6 +26,10 @@ export const supportsAgentToken = (agentType: string): boolean => {
|
||||
return agentType === 'openclaw';
|
||||
};
|
||||
|
||||
export const supportsAgentDashboardAuth = (agentType: string): boolean => {
|
||||
return agentType === 'hermes-agent' || agentType === 'copaw';
|
||||
};
|
||||
|
||||
export const isOpenclawHTTPSWindowVersion = (version: string): boolean => {
|
||||
return compareVersion(version, openclawHTTPSVersion) && !compareVersion(version, openclawHTTPVersion);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<el-form-item :label="$t('aiTools.agents.webuiPort')" prop="webUIPort">
|
||||
<el-input-number v-model="form.webUIPort" :min="1" :max="65535" />
|
||||
</el-form-item>
|
||||
<template v-if="form.agentType === 'hermes-agent'">
|
||||
<template v-if="supportsAgentDashboardAuth(form.agentType)">
|
||||
<el-form-item :label="$t('commons.login.username')" prop="dashboardUsername">
|
||||
<el-input v-model="form.dashboardUsername" />
|
||||
</el-form-item>
|
||||
@@ -131,6 +131,7 @@ import {
|
||||
buildDefaultAllowedOrigin,
|
||||
getAgentProviderDisplayName,
|
||||
parseAllowedOriginsInput,
|
||||
supportsAgentDashboardAuth,
|
||||
validateAllowedOriginsInput,
|
||||
} from '@/utils/agent';
|
||||
import { App } from '@/api/interface/app';
|
||||
@@ -187,8 +188,8 @@ const generateDashboardPassword = () => {
|
||||
form.dashboardPassword = getRandomStr(8);
|
||||
};
|
||||
|
||||
const ensureHermesDashboardAuth = () => {
|
||||
if (form.agentType !== 'hermes-agent') {
|
||||
const ensureDashboardAuth = () => {
|
||||
if (!supportsAgentDashboardAuth(form.agentType)) {
|
||||
return;
|
||||
}
|
||||
if (!form.dashboardUsername) {
|
||||
@@ -411,7 +412,7 @@ const handleAgentTypeChange = async () => {
|
||||
form.provider = '';
|
||||
form.accountId = undefined as unknown as number;
|
||||
form.baseURL = '';
|
||||
ensureHermesDashboardAuth();
|
||||
ensureDashboardAuth();
|
||||
if (form.agentType === 'openclaw') {
|
||||
await loadSystemIP();
|
||||
allowedOriginsAutoFilled.value = true;
|
||||
@@ -487,8 +488,8 @@ const submit = async () => {
|
||||
model: showModelConfig.value ? form.model : undefined,
|
||||
accountId: showModelConfig.value ? form.accountId : undefined,
|
||||
token: form.agentType === 'openclaw' ? form.token : undefined,
|
||||
dashboardUsername: form.agentType === 'hermes-agent' ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: form.agentType === 'hermes-agent' ? form.dashboardPassword : undefined,
|
||||
dashboardUsername: supportsAgentDashboardAuth(form.agentType) ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: supportsAgentDashboardAuth(form.agentType) ? form.dashboardPassword : undefined,
|
||||
taskID: taskID,
|
||||
advanced: form.advanced,
|
||||
containerName: form.containerName,
|
||||
@@ -536,7 +537,7 @@ const openDrawer = async (agentType?: AI.AgentType) => {
|
||||
form.agentType = targetType;
|
||||
setDefaultWebUIPort();
|
||||
form.token = getRandomStr(32).toLowerCase();
|
||||
ensureHermesDashboardAuth();
|
||||
ensureDashboardAuth();
|
||||
if (form.agentType === 'copaw') {
|
||||
form.allowedOrigins = '';
|
||||
lastAutoAllowedOrigins.value = '';
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
>
|
||||
<ChannelsTab ref="channelsRef" :app-version="appVersion" :agent-type="agentType" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="t('aiTools.model.model')" name="model">
|
||||
<el-tab-pane v-if="supportsAgentModelConfig(agentType)" :label="t('aiTools.model.model')" name="model">
|
||||
<ModelTab ref="modelRef" @updated="handleModelUpdated" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="agentType === 'openclaw'" :label="t('aiTools.agents.agentRoleTab')" name="agent">
|
||||
@@ -26,7 +26,7 @@
|
||||
<PluginsTab ref="pluginsRef" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
v-if="agentType === 'openclaw' || agentType === 'hermes-agent'"
|
||||
v-if="agentType === 'openclaw' || agentType === 'hermes-agent' || agentType === 'copaw'"
|
||||
:label="t('file.setting')"
|
||||
name="settings"
|
||||
>
|
||||
@@ -48,6 +48,7 @@ import AgentTab from './tabs/agents/index.vue';
|
||||
import SkillsTab from './tabs/skills.vue';
|
||||
import PluginsTab from './tabs/plugins.vue';
|
||||
import SettingsTab from './tabs/settings.vue';
|
||||
import { supportsAgentModelConfig } from '@/utils/agent';
|
||||
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['updated']);
|
||||
@@ -165,13 +166,13 @@ const openDrawer = async (agent: AI.AgentItem) => {
|
||||
configPath.value = agent.configPath;
|
||||
agentType.value = agent.agentType;
|
||||
header.value = `${agent.name} - ${t('menu.config')}`;
|
||||
activeTab.value = agent.agentType === 'openclaw' || agent.agentType === 'hermes-agent' ? 'channels' : 'model';
|
||||
activeTab.value = agent.agentType === 'copaw' ? 'settings' : 'channels';
|
||||
open.value = true;
|
||||
if (agent.agentType === 'openclaw' || agent.agentType === 'hermes-agent') {
|
||||
await loadChannels();
|
||||
return;
|
||||
}
|
||||
await loadModel();
|
||||
await loadSettings();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
</el-select>
|
||||
<span class="input-help">{{ t('aiTools.agents.npmRegistryHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('aiTools.agents.timeZone')" prop="userTimezone">
|
||||
<el-form-item v-if="agentType !== 'copaw'" :label="t('aiTools.agents.timeZone')" prop="userTimezone">
|
||||
<el-input v-model="form.userTimezone" />
|
||||
</el-form-item>
|
||||
<template v-if="agentType === 'hermes-agent'">
|
||||
<template v-if="supportsAgentDashboardAuth(agentType)">
|
||||
<el-form-item :label="t('commons.login.username')" prop="dashboardUsername">
|
||||
<el-input v-model="form.dashboardUsername" />
|
||||
</el-form-item>
|
||||
@@ -33,7 +33,9 @@
|
||||
{{
|
||||
agentType === 'hermes-agent'
|
||||
? t('aiTools.agents.dashboardAuthAutoRebuildHelper')
|
||||
: t('aiTools.agents.channelAutoRestartHelper')
|
||||
: agentType === 'copaw'
|
||||
? t('aiTools.agents.dashboardAuthImmediateHelper')
|
||||
: t('aiTools.agents.channelAutoRestartHelper')
|
||||
}}
|
||||
</span>
|
||||
</el-form>
|
||||
@@ -47,6 +49,7 @@ import { Rules } from '@/global/form-rules';
|
||||
import { AI } from '@/api/interface/ai';
|
||||
import { getAgentOtherConfig, updateAgentOtherConfig } from '@/api/modules/ai';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { supportsAgentDashboardAuth } from '@/utils/agent';
|
||||
|
||||
const { t } = useI18n();
|
||||
const loading = ref(false);
|
||||
@@ -71,6 +74,16 @@ const npmRegistryOptions = [
|
||||
'https://repo.huaweicloud.com/repository/npm/',
|
||||
];
|
||||
|
||||
const resetForm = () => {
|
||||
Object.assign(form, {
|
||||
userTimezone: '',
|
||||
browserEnabled: true,
|
||||
npmRegistry: defaultNPMRegistry,
|
||||
dashboardUsername: 'admin',
|
||||
dashboardPassword: '',
|
||||
});
|
||||
};
|
||||
|
||||
const validateNPMRegistry = (_rule: any, value: string, callback: (error?: Error) => void) => {
|
||||
if (!value) {
|
||||
callback(new Error(t('commons.rule.requiredInput')));
|
||||
@@ -93,11 +106,12 @@ const rules = reactive({
|
||||
const load = async (params: { agentId: number; agentType: AI.AgentType }) => {
|
||||
agentId.value = params.agentId;
|
||||
agentType.value = params.agentType;
|
||||
resetForm();
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getAgentOtherConfig({ agentId: params.agentId });
|
||||
Object.assign(form, res.data || {});
|
||||
if (params.agentType === 'hermes-agent' && !form.dashboardUsername) {
|
||||
if (supportsAgentDashboardAuth(params.agentType) && !form.dashboardUsername) {
|
||||
form.dashboardUsername = 'admin';
|
||||
}
|
||||
} finally {
|
||||
@@ -114,11 +128,11 @@ const saveConfig = async () => {
|
||||
try {
|
||||
await updateAgentOtherConfig({
|
||||
agentId: agentId.value,
|
||||
userTimezone: form.userTimezone,
|
||||
userTimezone: agentType.value === 'copaw' ? undefined : form.userTimezone,
|
||||
browserEnabled: form.browserEnabled,
|
||||
npmRegistry: agentType.value === 'openclaw' ? form.npmRegistry : defaultNPMRegistry,
|
||||
dashboardUsername: agentType.value === 'hermes-agent' ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: agentType.value === 'hermes-agent' ? form.dashboardPassword : undefined,
|
||||
dashboardUsername: supportsAgentDashboardAuth(agentType.value) ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: supportsAgentDashboardAuth(agentType.value) ? form.dashboardPassword : undefined,
|
||||
});
|
||||
MsgSuccess(t('aiTools.agents.saveSuccess'));
|
||||
} finally {
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
</el-button>
|
||||
</el-space>
|
||||
<el-space
|
||||
v-else-if="row.agentType === 'hermes-agent'"
|
||||
v-else-if="supportsAgentDashboardAuth(row.agentType)"
|
||||
direction="vertical"
|
||||
alignment="start"
|
||||
:size="2"
|
||||
@@ -303,6 +303,7 @@ import {
|
||||
getOpenclawAccessScheme,
|
||||
supportsAgentModelConfig,
|
||||
supportsAgentToken,
|
||||
supportsAgentDashboardAuth,
|
||||
} from '@/utils/agent';
|
||||
import { routerToFileWithPath } from '@/utils/router';
|
||||
import { listDomains } from '@/api/modules/website';
|
||||
@@ -356,7 +357,8 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('menu.config'),
|
||||
click: (row: AI.AgentItem) => openConfig(row),
|
||||
show: (row: AI.AgentItem) => supportsAgentModelConfig(row.agentType),
|
||||
show: (row: AI.AgentItem) =>
|
||||
supportsAgentModelConfig(row.agentType) || supportsAgentDashboardAuth(row.agentType),
|
||||
disabled: (row: AI.AgentItem) => row.status !== 'Running',
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user