From f787734feb38229f758699181f14437d86c76b59 Mon Sep 17 00:00:00 2001 From: CityFun <31820853+zhengkunwang223@users.noreply.github.com> Date: Tue, 31 Mar 2026 18:08:05 +0800 Subject: [PATCH] feat: Support uninstallation and upgrades of OpenClaw plugins. (#12373) --- agent/app/api/v2/agents.go | 40 ++++ agent/app/dto/agents.go | 20 +- agent/app/service/agents.go | 4 +- agent/app/service/agents_channels.go | 211 ++++++++++++++++-- agent/app/service/agents_overview.go | 7 +- agent/app/service/agents_skills.go | 27 +-- agent/app/service/agents_utils.go | 6 + agent/router/ro_ai.go | 2 + frontend/src/api/interface/ai.ts | 16 ++ frontend/src/api/modules/ai.ts | 8 + frontend/src/lang/modules/es-es.ts | 143 ++++++------ frontend/src/lang/modules/ja.ts | 136 +++++------ frontend/src/lang/modules/ko.ts | 139 ++++++------ frontend/src/lang/modules/ms.ts | 136 +++++------ frontend/src/lang/modules/pt-br.ts | 134 +++++------ frontend/src/lang/modules/ru.ts | 125 ++++++----- frontend/src/lang/modules/tr.ts | 129 +++++------ .../tabs/channels/components/channel-bots.vue | 100 ++++++--- .../channels/components/plugin-install.vue | 92 +++++++- .../agent/config/tabs/channels/dingtalk.vue | 162 +++++++++----- .../agent/config/tabs/channels/discord.vue | 8 +- .../agent/config/tabs/channels/feishu.vue | 105 ++++++--- .../agents/agent/config/tabs/channels/qq.vue | 91 +++++--- .../agent/config/tabs/channels/telegram.vue | 8 +- .../tabs/channels/useAgentPluginChannel.ts | 105 ++++++++- .../agent/config/tabs/channels/wecom.vue | 102 ++++++--- .../agent/config/tabs/channels/weixin.vue | 51 ++++- 27 files changed, 1375 insertions(+), 732 deletions(-) diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index 2f591d5c7..01ab82575 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -742,6 +742,46 @@ func (b *BaseApi) InstallAgentPlugin(c *gin.Context) { helper.Success(c) } +// @Tags AI +// @Summary Upgrade Agent plugin +// @Accept json +// @Param request body dto.AgentPluginUpgradeReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/plugin/upgrade [post] +func (b *BaseApi) UpgradeAgentPlugin(c *gin.Context) { + var req dto.AgentPluginUpgradeReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := agentService.UpgradePlugin(req); err != nil { + helper.BadRequest(c, err) + return + } + helper.Success(c) +} + +// @Tags AI +// @Summary Uninstall Agent plugin +// @Accept json +// @Param request body dto.AgentPluginUninstallReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/plugin/uninstall [post] +func (b *BaseApi) UninstallAgentPlugin(c *gin.Context) { + var req dto.AgentPluginUninstallReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := agentService.UninstallPlugin(req); err != nil { + helper.BadRequest(c, err) + return + } + helper.Success(c) +} + // @Tags AI // @Summary Check Agent plugin installation status // @Accept json diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go index cbbef8f4b..4d0c24944 100644 --- a/agent/app/dto/agents.go +++ b/agent/app/dto/agents.go @@ -371,13 +371,29 @@ type AgentPluginInstallReq struct { TaskID string `json:"taskID" validate:"required"` } -type AgentPluginCheckReq struct { +type AgentPluginUpgradeReq struct { AgentID uint `json:"agentId" validate:"required"` Type string `json:"type" validate:"required,oneof=feishu qqbot wecom dingtalk weixin"` + TaskID string `json:"taskID" validate:"required"` +} + +type AgentPluginUninstallReq struct { + AgentID uint `json:"agentId" validate:"required"` + Type string `json:"type" validate:"required,oneof=feishu qqbot wecom dingtalk weixin"` + TaskID string `json:"taskID" validate:"required"` +} + +type AgentPluginCheckReq struct { + AgentID uint `json:"agentId" validate:"required"` + Type string `json:"type" validate:"required,oneof=feishu qqbot wecom dingtalk weixin"` + CheckLatest bool `json:"checkLatest"` } type AgentPluginStatus struct { - Installed bool `json:"installed"` + Installed bool `json:"installed"` + CurrentVersion string `json:"currentVersion"` + LatestVersion string `json:"latestVersion"` + Upgradable bool `json:"upgradable"` } type AgentDiscordConfigUpdateReq struct { diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index 8582018d2..f7d7d2994 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -76,6 +76,8 @@ type IAgentService interface { GetQQBotConfig(req dto.AgentIDReq) (*dto.AgentQQBotConfig, error) UpdateQQBotConfig(req dto.AgentQQBotConfigUpdateReq) error InstallPlugin(req dto.AgentPluginInstallReq) error + UpgradePlugin(req dto.AgentPluginUpgradeReq) error + UninstallPlugin(req dto.AgentPluginUninstallReq) error CheckPlugin(req dto.AgentPluginCheckReq) (*dto.AgentPluginStatus, error) ApproveChannelPairing(req dto.AgentChannelPairingApproveReq) error } @@ -771,7 +773,7 @@ func (a AgentService) UpdateConfigFile(req dto.AgentConfigFileUpdateReq) error { } func getOpenclawNPMRegistry(containerName string) (string, error) { - registry, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut("docker exec %s npm get registry", 20*time.Second, containerName) + registry, err := runDockerExecWithStdout(20*time.Second, containerName, "npm", "get", "registry") if err != nil { return "", err } diff --git a/agent/app/service/agents_channels.go b/agent/app/service/agents_channels.go index ba24317bb..87fd71fd9 100644 --- a/agent/app/service/agents_channels.go +++ b/agent/app/service/agents_channels.go @@ -1,7 +1,9 @@ package service import ( + "encoding/json" "fmt" + "os" "path" "sort" "strings" @@ -13,15 +15,20 @@ import ( "github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/utils/cmd" + "github.com/1Panel-dev/1Panel/agent/utils/common" ) +type openclawPluginPackage struct { + Version string `json:"version"` +} + func (a AgentService) GetFeishuConfig(req dto.AgentFeishuConfigReq) (*dto.AgentFeishuConfig, error) { _, install, conf, err := a.loadAgentConfig(req.AgentID) if err != nil { return nil, err } result := extractFeishuConfig(conf) - installed, _ := checkPluginInstalled(install.ContainerName, "feishu") + installed, _ := checkPluginInstalled(install.GetPath(), "feishu") result.Installed = installed return &result, nil } @@ -89,7 +96,7 @@ func (a AgentService) GetQQBotConfig(req dto.AgentIDReq) (*dto.AgentQQBotConfig, return nil, err } result := extractQQBotConfig(conf) - installed, _ := checkPluginInstalled(install.ContainerName, "qqbot") + installed, _ := checkPluginInstalled(install.GetPath(), "qqbot") result.Installed = installed return &result, nil } @@ -110,7 +117,7 @@ func (a AgentService) GetWecomConfig(req dto.AgentIDReq) (*dto.AgentWecomConfig, return nil, err } result := extractWecomConfig(conf) - installed, _ := checkPluginInstalled(install.ContainerName, "wecom") + installed, _ := checkPluginInstalled(install.GetPath(), "wecom") result.Installed = installed return &result, nil } @@ -133,7 +140,7 @@ func (a AgentService) GetDingTalkConfig(req dto.AgentIDReq) (*dto.AgentDingTalkC return nil, err } result := extractDingTalkConfig(conf) - installed, _ := checkPluginInstalled(install.ContainerName, "dingtalk") + installed, _ := checkPluginInstalled(install.GetPath(), "dingtalk") result.Installed = installed return &result, nil } @@ -170,9 +177,10 @@ func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error { if req.Type == "qqbot" { legacyPluginPath := path.Join(openclawPluginBaseDir, "qqbot") if err := mgr.RunBashCf("docker exec %s test -d %s", install.ContainerName, legacyPluginPath); err == nil { - if err := mgr.Run("docker", "exec", "-i", install.ContainerName, "sh", "-c", "printf 'yes\\n' | openclaw plugins uninstall qqbot"); err != nil { + if err := mgr.Run("docker", "exec", "-i", install.ContainerName, "sh", "-c", buildOpenclawPluginUninstallScript("qqbot")); err != nil { return err } + time.Sleep(2 * time.Second) } } if err := mgr.Run("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawPluginInstallScript(spec, pluginID)); err != nil { @@ -193,6 +201,76 @@ func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error { return nil } +func (a AgentService) UpgradePlugin(req dto.AgentPluginUpgradeReq) error { + agent, install, err := a.loadAgentAndInstall(req.AgentID) + if err != nil { + return err + } + spec, pluginID, err := resolvePluginMeta(req.Type) + if err != nil { + return err + } + upgradeTask, err := task.NewTaskWithOps(req.Type, task.TaskUpgrade, task.TaskScopeAI, req.TaskID, req.AgentID) + if err != nil { + return err + } + upgradeTask.AddSubTask("Upgrade OpenClaw plugin", func(t *task.Task) error { + mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute)) + if err := mgr.Run("docker", "exec", "-i", install.ContainerName, "sh", "-c", buildOpenclawPluginUninstallScript(pluginID)); err != nil { + return err + } + time.Sleep(2 * time.Second) + if err := mgr.Run("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawPluginInstallScript(spec, pluginID)); err != nil { + return err + } + conf, err := readOpenclawConfig(agent.ConfigPath) + if err != nil { + return err + } + appendPluginAllow(conf, pluginID) + return writeOpenclawConfigRaw(agent.ConfigPath, conf) + }, nil) + go func() { + if err := upgradeTask.Execute(); err != nil { + global.LOG.Errorf("upgrade openclaw plugin failed: %v", err) + } + }() + return nil +} + +func (a AgentService) UninstallPlugin(req dto.AgentPluginUninstallReq) error { + agent, install, err := a.loadAgentAndInstall(req.AgentID) + if err != nil { + return err + } + _, pluginID, err := resolvePluginMeta(req.Type) + if err != nil { + return err + } + uninstallTask, err := task.NewTaskWithOps(req.Type, task.TaskUninstall, task.TaskScopeAI, req.TaskID, req.AgentID) + if err != nil { + return err + } + uninstallTask.AddSubTask("Uninstall OpenClaw plugin", func(t *task.Task) error { + mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute)) + if err := mgr.Run("docker", "exec", "-i", install.ContainerName, "sh", "-c", buildOpenclawPluginUninstallScript(pluginID)); err != nil { + return err + } + conf, err := readOpenclawConfig(agent.ConfigPath) + if err != nil { + return err + } + cleanupOpenclawPluginConfig(conf, req.Type) + return writeOpenclawConfigRaw(agent.ConfigPath, conf) + }, nil) + go func() { + if err := uninstallTask.Execute(); err != nil { + global.LOG.Errorf("uninstall openclaw plugin failed: %v", err) + } + }() + return nil +} + func (a AgentService) LoginWeixinChannel(req dto.AgentWeixinLoginReq) error { _, install, err := a.loadAgentAndInstall(req.AgentID) if err != nil { @@ -219,11 +297,33 @@ func (a AgentService) CheckPlugin(req dto.AgentPluginCheckReq) (*dto.AgentPlugin if err != nil { return nil, err } - installed, err := checkPluginInstalled(install.ContainerName, req.Type) + installed, err := checkPluginInstalled(install.GetPath(), req.Type) if err != nil { return nil, err } - return &dto.AgentPluginStatus{Installed: installed}, nil + status := &dto.AgentPluginStatus{Installed: installed} + if !installed { + return status, nil + } + currentVersion, err := loadOpenclawPluginCurrentVersion(install.GetPath(), req.Type) + if err != nil { + global.LOG.Errorf("load openclaw plugin current version failed: %v", err) + return status, nil + } + status.CurrentVersion = currentVersion + if !req.CheckLatest { + return status, nil + } + latestVersion, err := loadOpenclawPluginLatestVersion(install.ContainerName, req.Type) + if err != nil { + global.LOG.Errorf("load openclaw plugin latest version failed: %v", err) + return status, nil + } + status.LatestVersion = latestVersion + if currentVersion != "" && latestVersion != "" { + status.Upgradable = common.CompareVersion(latestVersion, currentVersion) + } + return status, nil } func (a AgentService) ApproveChannelPairing(req dto.AgentChannelPairingApproveReq) error { @@ -717,6 +817,13 @@ func buildOpenclawPluginInstallScript(spec, pluginID string) string { ) } +func buildOpenclawPluginUninstallScript(pluginID string) string { + return fmt.Sprintf( + "set +e; printf 'yes\\n' | openclaw plugins uninstall %s; code=$?; if [ \"$code\" -eq 137 ]; then exit 0; fi; exit \"$code\"", + pluginID, + ) +} + func resolvePluginMeta(pluginType string) (string, string, error) { switch pluginType { case "qqbot": @@ -734,22 +841,94 @@ func resolvePluginMeta(pluginType string) (string, string, error) { } } -func checkPluginInstalled(containerName, pluginType string) (bool, error) { - _, pluginDir, err := resolvePluginMeta(pluginType) +func checkPluginInstalled(installPath, pluginType string) (bool, error) { + packagePath, err := resolveOpenclawPluginPackagePath(installPath, pluginType) if err != nil { return false, err } - if strings.TrimSpace(containerName) == "" { - return false, buserr.New("ErrRecordNotFound") - } - pluginPath := path.Join(openclawPluginBaseDir, pluginDir) - mgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)) - if err := mgr.RunBashCf("docker exec %s test -d %s", containerName, pluginPath); err != nil { - return false, nil + if _, err := os.Stat(packagePath); err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err } return true, nil } +func loadOpenclawPluginCurrentVersion(installPath, pluginType string) (string, error) { + packagePath, err := resolveOpenclawPluginPackagePath(installPath, pluginType) + if err != nil { + return "", err + } + content, err := os.ReadFile(packagePath) + if err != nil { + return "", err + } + var pkg openclawPluginPackage + if err := json.Unmarshal(content, &pkg); err != nil { + return "", err + } + return pkg.Version, nil +} + +func loadOpenclawPluginLatestVersion(containerName, pluginType string) (string, error) { + spec, _, err := resolvePluginMeta(pluginType) + if err != nil { + return "", err + } + output, err := runDockerExecWithStdout(20*time.Second, containerName, "npm", "view", spec, "version", "--json") + if err != nil { + return "", err + } + var version string + if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &version); err == nil { + return version, nil + } + return strings.Trim(strings.TrimSpace(output), `"`), nil +} + +func resolveOpenclawPluginPackagePath(installPath, pluginType string) (string, error) { + _, pluginID, err := resolvePluginMeta(pluginType) + if err != nil { + return "", err + } + if installPath == "" { + return "", buserr.New("ErrRecordNotFound") + } + return path.Join(installPath, "data", "conf", "extensions", pluginID, "package.json"), nil +} + +func cleanupOpenclawPluginConfig(conf map[string]interface{}, pluginType string) { + channels, _ := conf["channels"].(map[string]interface{}) + plugins, _ := conf["plugins"].(map[string]interface{}) + entries, _ := plugins["entries"].(map[string]interface{}) + + switch pluginType { + case "feishu": + delete(channels, "feishu") + delete(entries, "openclaw-lark") + delete(entries, "feishu") + case "qqbot": + delete(channels, "qqbot") + delete(entries, "openclaw-qqbot") + delete(entries, "qqbot") + case "wecom": + delete(channels, "wecom") + delete(entries, "wecom-openclaw-plugin") + case "dingtalk": + delete(channels, "dingtalk-connector") + delete(entries, "dingtalk-connector") + gateway := ensureChildMap(conf, "gateway") + httpMap := ensureChildMap(gateway, "http") + endpoints := ensureChildMap(httpMap, "endpoints") + chatCompletions := ensureChildMap(endpoints, "chatCompletions") + chatCompletions["enabled"] = false + case "weixin": + delete(channels, "weixin") + delete(entries, "openclaw-weixin") + } +} + func getChannelConfig(conf map[string]interface{}, channel string) map[string]interface{} { channels, ok := conf["channels"].(map[string]interface{}) if !ok { diff --git a/agent/app/service/agents_overview.go b/agent/app/service/agents_overview.go index 610d1fb9d..79254d4d1 100644 --- a/agent/app/service/agents_overview.go +++ b/agent/app/service/agents_overview.go @@ -10,7 +10,6 @@ import ( "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/constant" - "github.com/1Panel-dev/1Panel/agent/utils/cmd" ) const ( @@ -102,11 +101,7 @@ func countOpenclawConfiguredChannels(conf map[string]interface{}) int { } func loadOpenclawOverviewSkillStats(containerName string) (int, error) { - output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut( - "docker exec %s openclaw skills list --json 2>&1", - 30*time.Second, - containerName, - ) + output, err := runDockerExecWithStdout(30*time.Second, containerName, "sh", "-c", "openclaw skills list --json 2>&1") if err != nil { return 0, err } diff --git a/agent/app/service/agents_skills.go b/agent/app/service/agents_skills.go index e4c998eec..7b77079ab 100644 --- a/agent/app/service/agents_skills.go +++ b/agent/app/service/agents_skills.go @@ -45,11 +45,7 @@ func (a AgentService) ListSkills(req dto.AgentIDReq) ([]dto.AgentSkillItem, erro if err := ensureContainerRunning(install.ContainerName); err != nil { return nil, err } - output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut( - "docker exec %s openclaw skills list --json 2>&1", - 30*time.Second, - install.ContainerName, - ) + output, err := runDockerExecWithStdout(30*time.Second, install.ContainerName, "sh", "-c", "openclaw skills list --json 2>&1") if err != nil { return nil, err } @@ -154,19 +150,9 @@ func parseOpenclawSkillsList(output string) ([]dto.AgentSkillItem, error) { func loadOpenclawSkillSearchOutput(containerName, source, keyword string) (string, error) { switch source { case "skillhub": - return cmd.RunDefaultWithStdoutBashCfAndTimeOut( - "docker exec %s skillhub search %q --json 2>&1", - 30*time.Second, - containerName, - keyword, - ) + return runDockerExecWithStdout(30*time.Second, containerName, "skillhub", "search", keyword, "--json") default: - return cmd.RunDefaultWithStdoutBashCfAndTimeOut( - "docker exec %s clawhub search %q 2>&1", - 30*time.Second, - containerName, - keyword, - ) + return runDockerExecWithStdout(30*time.Second, containerName, "clawhub", "search", keyword) } } @@ -233,12 +219,7 @@ func buildOpenclawSkillInstallCommand(source, slug string) string { } func getOpenclawSkillKey(containerName, name string) (string, error) { - output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut( - "docker exec %s openclaw skills info %q --json 2>&1", - 30*time.Second, - containerName, - name, - ) + output, err := runDockerExecWithStdout(30*time.Second, containerName, "sh", "-c", fmt.Sprintf("openclaw skills info %q --json 2>&1", name)) if err != nil { return "", err } diff --git a/agent/app/service/agents_utils.go b/agent/app/service/agents_utils.go index 6a13fa824..c9dc74a1b 100644 --- a/agent/app/service/agents_utils.go +++ b/agent/app/service/agents_utils.go @@ -19,6 +19,7 @@ import ( "github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/global" + "github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/req_helper" @@ -59,6 +60,11 @@ func ensureContainerRunning(containerName string) error { return nil } +func runDockerExecWithStdout(timeout time.Duration, containerName string, args ...string) (string, error) { + commandArgs := append([]string{"exec", containerName}, args...) + return cmd.NewCommandMgr(cmd.WithTimeout(timeout)).RunWithStdout("docker", commandArgs...) +} + func resolveAgentAccountInput(provider, apiKey, baseURL string) (resolvedAgentAccountInput, error) { resolvedAPIKey := strings.TrimSpace(apiKey) resolvedBaseURL := strings.TrimSpace(baseURL) diff --git a/agent/router/ro_ai.go b/agent/router/ro_ai.go index 49b8568a3..6bb4e47d3 100644 --- a/agent/router/ro_ai.go +++ b/agent/router/ro_ai.go @@ -77,6 +77,8 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/agents/channel/qqbot/get", baseApi.GetAgentQQBotConfig) aiToolsRouter.POST("/agents/channel/qqbot/update", baseApi.UpdateAgentQQBotConfig) aiToolsRouter.POST("/agents/plugin/install", baseApi.InstallAgentPlugin) + aiToolsRouter.POST("/agents/plugin/upgrade", baseApi.UpgradeAgentPlugin) + aiToolsRouter.POST("/agents/plugin/uninstall", baseApi.UninstallAgentPlugin) aiToolsRouter.POST("/agents/plugin/check", baseApi.CheckAgentPlugin) aiToolsRouter.POST("/agents/security/get", baseApi.GetAgentSecurityConfig) aiToolsRouter.POST("/agents/security/update", baseApi.UpdateAgentSecurityConfig) diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index 43857b787..c78248a12 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -629,13 +629,29 @@ export namespace AI { taskID: string; } + export interface AgentPluginUpgradeReq { + agentId: number; + type: 'feishu' | 'qqbot' | 'wecom' | 'dingtalk' | 'weixin'; + taskID: string; + } + + export interface AgentPluginUninstallReq { + agentId: number; + type: 'feishu' | 'qqbot' | 'wecom' | 'dingtalk' | 'weixin'; + taskID: string; + } + export interface AgentPluginCheckReq { agentId: number; type: 'feishu' | 'qqbot' | 'wecom' | 'dingtalk' | 'weixin'; + checkLatest?: boolean; } export interface AgentPluginStatus { installed: boolean; + currentVersion: string; + latestVersion: string; + upgradable: boolean; } export interface AgentDiscordConfigReq { diff --git a/frontend/src/api/modules/ai.ts b/frontend/src/api/modules/ai.ts index b0c7d22e4..f9cbb13c1 100644 --- a/frontend/src/api/modules/ai.ts +++ b/frontend/src/api/modules/ai.ts @@ -241,6 +241,14 @@ export const installAgentPlugin = (req: AI.AgentPluginInstallReq) => { return http.post(`/ai/agents/plugin/install`, req); }; +export const upgradeAgentPlugin = (req: AI.AgentPluginUpgradeReq) => { + return http.post(`/ai/agents/plugin/upgrade`, req); +}; + +export const uninstallAgentPlugin = (req: AI.AgentPluginUninstallReq) => { + return http.post(`/ai/agents/plugin/uninstall`, req); +}; + export const checkAgentPlugin = (req: AI.AgentPluginCheckReq) => { return http.post(`/ai/agents/plugin/check`, req); }; diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 1174719c1..3622a848c 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -692,46 +692,47 @@ const message = { allowedOriginsRequired: 'Introduce al menos una dirección de acceso', allowedOriginsInvalid: 'Usa el formato http(s)://host-o-ip[:puerto]', provider: 'Proveedor de modelos', - accountModelsHelper: 'Configure the models this account exposes to OpenClaw for switching and settings', - accountModelsRequired: 'Configure at least one model', - accountModelsDuplicate: 'Duplicate models exist in the catalog', - modelPool: 'Model Pool', - modelInputTypes: 'Input Types', - reasoning: 'Reasoning Model', + accountModelsHelper: + 'Configure los modelos que esta cuenta expone a OpenClaw para el cambio y la configuración', + accountModelsRequired: 'Configure al menos un modelo', + accountModelsDuplicate: 'Existen modelos duplicados en el catálogo', + modelPool: 'Pool de modelos', + modelInputTypes: 'Tipos de entrada', + reasoning: 'Modelo de razonamiento', manualModel: 'Entrada manual de modelo', verified: 'Verificado', verifySkipped: 'Sin verificacion', - skillsTab: 'Skills', - securityTab: 'Security', - otherTab: 'Other', + skillsTab: 'Habilidades', + securityTab: 'Seguridad', + otherTab: 'Otros', timeZone: 'Zona horaria', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: 'Navegador habilitado', + npmRegistry: 'Registro NPM', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'Se usa para instalar plugins de OpenClaw. Puede elegir un registro predefinido o introducir uno personalizado.', + npmRegistryInvalid: 'Introduzca una URL válida del registro NPM que empiece por http:// o https://', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', - skillsMarketSourceClawhub: 'ClawHub (Official)', + 'Vaya a Configuración -> Otros para configurar el registro NPM y acelerar la instalación de plugins', + skillsSearchPlaceholder: 'Buscar habilidades...', + skillsEmpty: 'Sin habilidades', + skillsMarket: 'Mercado de habilidades', + skillsMarketHint: 'Seleccione una fuente y busque habilidades', + skillsMarketEmpty: 'No se encontraron habilidades relacionadas', + skillsMarketSourceClawhub: 'ClawHub (Oficial)', skillsMarketSourceSkillhub: 'SkillHub (Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: 'Puntuación', + versionUnsupportedTitle: 'Esta función no es compatible con la versión actual', + versionUnsupportedHelper: 'Actualice OpenClaw a la versión {0} o posterior.', + skillsStatusDisabled: 'Deshabilitado', + skillsGroupBuiltIn: 'Integradas', + skillsGroupExternal: 'Externas', + skillsGroupWorkspace: 'Espacio de trabajo', + switchModelSuccess: 'Modelo cambiado correctamente', + channelsTab: 'Canales', + agentRoleTab: 'Agentes', + agentRoleUnsupported: 'La gestión de roles actualmente solo es compatible con OpenClaw.', + workspace: 'Directorio del espacio de trabajo', + agentDir: 'Directorio del agente', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -759,51 +760,53 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: 'Vinculaciones', + accountIdOptional: 'ID de cuenta (opcional)', + saveAllMd: 'Guardar todo', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', + 'Guardar todos los archivos markdown actuales requiere reiniciar el contenedor para surtir efecto. Elija si reiniciar ahora o más tarde.', configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + 'Guardar el archivo de configuración requiere reiniciar inmediatamente el contenedor para surtir efecto.', + overviewSnapshot: 'Resumen', + defaultModel: 'Modelo predeterminado', + channelCount: 'Canales configurados', + skillCount: 'Habilidades', + jobCount: 'Tareas programadas', + sessionCount: 'Sesiones', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: 'El plugin no está instalado. Instálalo primero.', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', + dmPolicy: 'Política de MD', + groupPolicy: 'Política de grupo', + policyAllowlist: 'Lista permitida', + policyOpen: 'Abierto', + policyDisabled: 'Deshabilitado', bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', - botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + addBot: 'Agregar bot', + accountId: 'ID de cuenta', + setDefaultBot: 'Establecer como predeterminado', + botDuplicateAccountId: 'El ID de cuenta ya existe', + botRequired: 'Agregue al menos un bot', + botId: 'ID del bot', + allowFrom: 'Lista permitida de MD', + allowFromHelper: 'Un ID de remitente por línea. Solo se usa cuando la política de MD es Lista permitida.', + allowFromPlaceholder: 'Un ID de remitente por línea', + groupAllowFrom: 'Lista permitida de grupos', + groupAllowFromHelper: + 'Un ID de grupo por línea. Solo se usa cuando la política de grupo es Lista permitida.', + groupAllowFromPlaceholder: 'Un ID de grupo por línea', + allowFromRequired: 'Introduzca al menos una entrada en la lista permitida', + saveAndRestartGateway: 'Guardar y reiniciar gateway', + pairingCode: 'Código de emparejamiento', + pairingCodePlaceholder: 'Introduzca el código de emparejamiento', + approvePairing: 'Aprobar emparejamiento', + saveSuccess: 'Guardado correctamente', + pairingApproveSuccess: 'Emparejamiento aprobado correctamente', + scanConnect: 'Escanear para conectar', + scanConnectHelper: + 'Haga clic para iniciar la tarea de inicio de sesión por QR. El código QR aparecerá en el registro de tareas.', customProviderHelper: 'En el proveedor de modelo personalizado no se valida si la cuenta está disponible', }, model: { diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 9da886a1e..a2cbac5fb 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -687,44 +687,44 @@ const message = { provider: 'モデルプロバイダー', accountModelsHelper: 'Configure the models this account exposes to OpenClaw for switching and settings', accountModelsRequired: 'Configure at least one model', - accountModelsDuplicate: 'Duplicate models exist in the catalog', - modelPool: 'Model Pool', - modelInputTypes: 'Input Types', - reasoning: 'Reasoning Model', + accountModelsDuplicate: 'カタログに重複したモデルがあります', + modelPool: 'モデルプール', + modelInputTypes: '入力タイプ', + reasoning: '推論モデル', manualModel: '手動入力', verified: '検証済み', verifySkipped: '検証なし', - skillsTab: 'Skills', - securityTab: 'Security', - otherTab: 'Other', + skillsTab: '技能', + securityTab: 'セキュリティ', + otherTab: 'その他', timeZone: 'タイムゾーン', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: 'ブラウザ有効化', + npmRegistry: 'NPM レジストリ', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'OpenClaw プラグインのインストールに使用します。プリセットのレジストリを選択するか、カスタムのレジストリを入力できます。', + npmRegistryInvalid: 'http:// または https:// で始まる有効な NPM レジストリ URL を入力してください', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', + '設定 -> その他 で NPM レジストリを設定すると、プラグインのインストールを高速化できます', + skillsSearchPlaceholder: '技能を検索...', + skillsEmpty: '技能がありません', + skillsMarket: '技能マーケット', + skillsMarketHint: 'ソースを選択して技能を検索してください', + skillsMarketEmpty: '関連する技能が見つかりませんでした', skillsMarketSourceClawhub: 'ClawHub(公式)', skillsMarketSourceSkillhub: 'SkillHub(Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: 'スコア', + versionUnsupportedTitle: '現在のバージョンではこの機能はサポートされていません', + versionUnsupportedHelper: 'OpenClaw をバージョン {0} 以降にアップグレードしてください。', + skillsStatusDisabled: '無効', + skillsGroupBuiltIn: '内蔵', + skillsGroupExternal: '外部', + skillsGroupWorkspace: 'ワークスペース', + switchModelSuccess: 'モデルの切り替えに成功しました', + channelsTab: 'チャンネル', + agentRoleTab: 'エージェント', + agentRoleUnsupported: 'ロール管理は現在 OpenClaw のみ対応しています。', + workspace: 'ワークスペースディレクトリ', + agentDir: 'エージェントディレクトリ', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -752,51 +752,51 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: 'バインディング', + accountIdOptional: 'アカウント ID(任意)', + saveAllMd: 'すべて保存', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', - configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + '現在の markdown ファイルをすべて保存するには、反映のためコンテナの再起動が必要です。今すぐ再起動するか後で再起動するかを選択してください。', + configFileRestartHelper: '設定ファイルを保存するには、反映のため直ちにコンテナを再起動する必要があります。', + overviewSnapshot: '概要', + defaultModel: 'デフォルトモデル', + channelCount: '設定済みチャンネル数', + skillCount: '技能数', + jobCount: '定期タスク数', + sessionCount: 'セッション数', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: 'プラグインがインストールされていません。先にインストールしてください。', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', - bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', + dmPolicy: 'DM ポリシー', + groupPolicy: 'グループポリシー', + policyAllowlist: '許可リスト', + policyOpen: '開放', + policyDisabled: '無効', + bots: 'Bot', + addBot: 'Bot を追加', + accountId: 'アカウント ID', + setDefaultBot: 'デフォルトに設定', + botDuplicateAccountId: 'アカウント ID は既に存在します', + botRequired: '少なくとも 1 つの Bot を追加してください', botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + allowFrom: 'DM 許可リスト', + allowFromHelper: '1 行に 1 つの送信者 ID を入力します。DM ポリシーが許可リストの場合のみ使用されます。', + allowFromPlaceholder: '1 行に 1 つの送信者 ID', + groupAllowFrom: 'グループ許可リスト', + groupAllowFromHelper: + '1 行に 1 つのグループ ID を入力します。グループポリシーが許可リストの場合のみ使用されます。', + groupAllowFromPlaceholder: '1 行に 1 つのグループ ID', + allowFromRequired: '少なくとも 1 件の許可リスト項目を入力してください', + saveAndRestartGateway: '保存して gateway を再起動', + pairingCode: 'ペアリングコード', + pairingCodePlaceholder: 'ペアリングコードを入力', + approvePairing: 'ペアリングを承認', + saveSuccess: '保存しました', + pairingApproveSuccess: 'ペアリングに成功しました', + scanConnect: 'スキャンして接続', + scanConnectHelper: 'クリックして QR ログインタスクを開始します。QR コードはタスクログに表示されます。', customProviderHelper: 'カスタムモデルプロバイダーでは、アカウントの有効性を検証しません', }, model: { diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 4c9a9e402..ed963229b 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -679,44 +679,44 @@ const message = { provider: '모델 제공자', accountModelsHelper: 'Configure the models this account exposes to OpenClaw for switching and settings', accountModelsRequired: 'Configure at least one model', - accountModelsDuplicate: 'Duplicate models exist in the catalog', - modelPool: 'Model Pool', - modelInputTypes: 'Input Types', - reasoning: 'Reasoning Model', + accountModelsDuplicate: '카탈로그에 중복된 모델이 있습니다', + modelPool: '모델 풀', + modelInputTypes: '입력 유형', + reasoning: '추론 모델', manualModel: '수동 입력', verified: '검증됨', verifySkipped: '검증 안 함', - skillsTab: 'Skills', - securityTab: 'Security', - otherTab: 'Other', + skillsTab: '기술', + securityTab: '보안', + otherTab: '기타', timeZone: '시간대', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: '브라우저 활성화', + npmRegistry: 'NPM 레지스트리', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'OpenClaw 플러그인 설치에 사용됩니다. 사전 설정된 레지스트리를 선택하거나 사용자 지정 레지스트리를 입력할 수 있습니다.', + npmRegistryInvalid: 'http:// 또는 https:// 로 시작하는 올바른 NPM 레지스트리 URL을 입력하세요', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', - skillsMarketSourceClawhub: 'ClawHub (Official)', + '설정 -> 기타에서 NPM 레지스트리를 설정하면 플러그인 설치 속도를 높일 수 있습니다', + skillsSearchPlaceholder: '기술 검색...', + skillsEmpty: '기술 없음', + skillsMarket: '기술 마켓', + skillsMarketHint: '소스를 선택하고 기술을 검색하세요', + skillsMarketEmpty: '관련 기술을 찾을 수 없습니다', + skillsMarketSourceClawhub: 'ClawHub (공식)', skillsMarketSourceSkillhub: 'SkillHub (Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: '점수', + versionUnsupportedTitle: '현재 버전에서는 이 기능을 지원하지 않습니다', + versionUnsupportedHelper: 'OpenClaw 를 버전 {0} 이상으로 업그레이드하세요.', + skillsStatusDisabled: '비활성화됨', + skillsGroupBuiltIn: '내장', + skillsGroupExternal: '외부', + skillsGroupWorkspace: '워크스페이스', + switchModelSuccess: '모델이 성공적으로 전환되었습니다', + channelsTab: '채널', + agentRoleTab: '에이전트', + agentRoleUnsupported: '역할 관리는 현재 OpenClaw 에서만 지원됩니다.', + workspace: '워크스페이스 디렉터리', + agentDir: '에이전트 디렉터리', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -744,51 +744,50 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: '바인딩', + accountIdOptional: '계정 ID (선택 사항)', + saveAllMd: '모두 저장', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', - configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + '현재 markdown 파일을 모두 저장하려면 적용을 위해 컨테이너를 재시작해야 합니다. 지금 재시작할지 나중에 재시작할지 선택하세요.', + configFileRestartHelper: '설정 파일을 저장하려면 즉시 컨테이너를 재시작해야 적용됩니다.', + overviewSnapshot: '개요', + defaultModel: '기본 모델', + channelCount: '설정된 채널 수', + skillCount: '기술 수', + jobCount: '예약 작업 수', + sessionCount: '세션 수', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: '플러그인이 설치되지 않았습니다. 먼저 설치해 주세요.', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', - bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', - botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + dmPolicy: 'DM 정책', + groupPolicy: '그룹 정책', + policyAllowlist: '허용 목록', + policyOpen: '열림', + policyDisabled: '비활성화', + bots: '봇', + addBot: '봇 추가', + accountId: '계정 ID', + setDefaultBot: '기본값으로 설정', + botDuplicateAccountId: '계정 ID가 이미 존재합니다', + botRequired: '봇을 하나 이상 추가하세요', + botId: '봇 ID', + allowFrom: 'DM 허용 목록', + allowFromHelper: '한 줄에 하나의 발신자 ID를 입력하세요. DM 정책이 허용 목록일 때만 사용됩니다.', + allowFromPlaceholder: '한 줄에 하나의 발신자 ID', + groupAllowFrom: '그룹 허용 목록', + groupAllowFromHelper: '한 줄에 하나의 그룹 ID를 입력하세요. 그룹 정책이 허용 목록일 때만 사용됩니다.', + groupAllowFromPlaceholder: '한 줄에 하나의 그룹 ID', + allowFromRequired: '허용 목록 항목을 하나 이상 입력하세요', + saveAndRestartGateway: '저장 후 gateway 재시작', + pairingCode: '페어링 코드', + pairingCodePlaceholder: '페어링 코드를 입력하세요', + approvePairing: '페어링 승인', + saveSuccess: '저장되었습니다', + pairingApproveSuccess: '페어링이 승인되었습니다', + scanConnect: '스캔하여 연결', + scanConnectHelper: '클릭하여 QR 로그인 작업을 시작하세요. QR 코드는 작업 로그에 표시됩니다.', customProviderHelper: '사용자 정의 모델 공급자는 계정 사용 가능 여부를 검증하지 않습니다', }, model: { diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index dd678ab7d..08c4543b1 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -696,42 +696,42 @@ const message = { accountModelsRequired: 'Configure at least one model', accountModelsDuplicate: 'Duplicate models exist in the catalog', modelPool: 'Model Pool', - modelInputTypes: 'Input Types', - reasoning: 'Reasoning Model', + modelInputTypes: 'Jenis input', + reasoning: 'Model penaakulan', manualModel: 'Input manual', verified: 'Disahkan', verifySkipped: 'Tanpa pengesahan', - skillsTab: 'Skills', - securityTab: 'Security', - otherTab: 'Other', + skillsTab: 'Kemahiran', + securityTab: 'Keselamatan', + otherTab: 'Lain-lain', timeZone: 'Zon Waktu', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: 'Pelayar diaktifkan', + npmRegistry: 'Registri NPM', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'Digunakan untuk pemasangan plugin OpenClaw. Anda boleh memilih registri pratetap atau memasukkan registri tersuai.', + npmRegistryInvalid: 'Masukkan URL registri NPM yang sah bermula dengan http:// atau https://', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', - skillsMarketSourceClawhub: 'ClawHub (Official)', + 'Pergi ke Tetapan -> Lain-lain untuk mengkonfigurasi registri NPM dan mempercepat pemasangan plugin', + skillsSearchPlaceholder: 'Cari kemahiran...', + skillsEmpty: 'Tiada kemahiran', + skillsMarket: 'Pasaran kemahiran', + skillsMarketHint: 'Pilih sumber dan cari kemahiran', + skillsMarketEmpty: 'Tiada kemahiran berkaitan ditemui', + skillsMarketSourceClawhub: 'ClawHub (Rasmi)', skillsMarketSourceSkillhub: 'SkillHub (Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: 'Skor', + versionUnsupportedTitle: 'Ciri ini tidak disokong dalam versi semasa', + versionUnsupportedHelper: 'Sila naik taraf OpenClaw ke versi {0} atau lebih baharu.', + skillsStatusDisabled: 'Dilumpuhkan', + skillsGroupBuiltIn: 'Terbina dalam', + skillsGroupExternal: 'Luaran', + skillsGroupWorkspace: 'Ruang kerja', + switchModelSuccess: 'Model berjaya ditukar', + channelsTab: 'Saluran', + agentRoleTab: 'Ejen', + agentRoleUnsupported: 'Pengurusan peranan kini hanya disokong untuk OpenClaw.', + workspace: 'Direktori ruang kerja', + agentDir: 'Direktori ejen', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -759,51 +759,53 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: 'Ikatan', + accountIdOptional: 'ID akaun (pilihan)', + saveAllMd: 'Simpan semua', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', + 'Menyimpan semua fail markdown semasa memerlukan kontena dimulakan semula untuk berkuat kuasa. Pilih sama ada hendak memulakan semula sekarang atau kemudian.', configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + 'Menyimpan fail konfigurasi memerlukan kontena dimulakan semula serta-merta untuk berkuat kuasa.', + overviewSnapshot: 'Ringkasan', + defaultModel: 'Model lalai', + channelCount: 'Bilangan saluran dikonfigurasi', + skillCount: 'Bilangan kemahiran', + jobCount: 'Bilangan tugas berjadual', + sessionCount: 'Bilangan sesi', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: 'Plugin belum dipasang. Sila pasang dahulu.', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', - bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', - botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + dmPolicy: 'Dasar DM', + groupPolicy: 'Dasar kumpulan', + policyAllowlist: 'Senarai benarkan', + policyOpen: 'Terbuka', + policyDisabled: 'Dilumpuhkan', + bots: 'Bot', + addBot: 'Tambah bot', + accountId: 'ID akaun', + setDefaultBot: 'Tetapkan sebagai lalai', + botDuplicateAccountId: 'ID akaun sudah wujud', + botRequired: 'Tambah sekurang-kurangnya satu bot', + botId: 'ID bot', + allowFrom: 'Senarai benarkan DM', + allowFromHelper: + 'Satu ID penghantar setiap baris. Hanya digunakan apabila dasar DM ialah Senarai benarkan.', + allowFromPlaceholder: 'Satu ID penghantar setiap baris', + groupAllowFrom: 'Senarai benarkan kumpulan', + groupAllowFromHelper: + 'Satu ID kumpulan setiap baris. Hanya digunakan apabila dasar kumpulan ialah Senarai benarkan.', + groupAllowFromPlaceholder: 'Satu ID kumpulan setiap baris', + allowFromRequired: 'Masukkan sekurang-kurangnya satu entri senarai benarkan', + saveAndRestartGateway: 'Simpan dan mulakan semula gateway', + pairingCode: 'Kod pasangan', + pairingCodePlaceholder: 'Masukkan kod pasangan', + approvePairing: 'Luluskan pasangan', + saveSuccess: 'Berjaya disimpan', + pairingApproveSuccess: 'Pasangan berjaya diluluskan', + scanConnect: 'Imbas untuk sambung', + scanConnectHelper: 'Klik untuk memulakan tugas log masuk QR. Kod QR akan muncul dalam log tugas.', customProviderHelper: 'Penyedia model tersuai tidak mengesahkan sama ada akaun boleh digunakan', }, model: { diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 0f1d05793..a37749c7b 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -691,42 +691,42 @@ const message = { accountModelsRequired: 'Configure at least one model', accountModelsDuplicate: 'Duplicate models exist in the catalog', modelPool: 'Model Pool', - modelInputTypes: 'Input Types', - reasoning: 'Reasoning Model', + modelInputTypes: 'Tipos de entrada', + reasoning: 'Modelo de raciocínio', manualModel: 'Entrada manual', verified: 'Verificado', verifySkipped: 'Sem verificacao', - skillsTab: 'Skills', - securityTab: 'Security', - otherTab: 'Other', + skillsTab: 'Habilidades', + securityTab: 'Segurança', + otherTab: 'Outros', timeZone: 'Fuso horário', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: 'Navegador habilitado', + npmRegistry: 'Registro NPM', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'Usado para a instalação de plugins do OpenClaw. Você pode escolher um registro predefinido ou informar um personalizado.', + npmRegistryInvalid: 'Digite uma URL válida de registro NPM começando com http:// ou https://', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', - skillsMarketSourceClawhub: 'ClawHub (Official)', + 'Vá em Configurações -> Outros para configurar o registro NPM e acelerar a instalação do plugin', + skillsSearchPlaceholder: 'Pesquisar habilidades...', + skillsEmpty: 'Sem habilidades', + skillsMarket: 'Mercado de habilidades', + skillsMarketHint: 'Selecione uma fonte e pesquise habilidades', + skillsMarketEmpty: 'Nenhuma habilidade correspondente encontrada', + skillsMarketSourceClawhub: 'ClawHub (Oficial)', skillsMarketSourceSkillhub: 'SkillHub (Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: 'Pontuação', + versionUnsupportedTitle: 'Este recurso não é compatível com a versão atual', + versionUnsupportedHelper: 'Atualize o OpenClaw para a versão {0} ou superior.', + skillsStatusDisabled: 'Desativado', + skillsGroupBuiltIn: 'Integradas', + skillsGroupExternal: 'Externas', + skillsGroupWorkspace: 'Espaço de trabalho', + switchModelSuccess: 'Modelo alterado com sucesso', + channelsTab: 'Canais', + agentRoleTab: 'Agentes', + agentRoleUnsupported: 'O gerenciamento de funções atualmente é compatível apenas com o OpenClaw.', + workspace: 'Diretório do espaço de trabalho', + agentDir: 'Diretório do agente', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -754,51 +754,53 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: 'Vínculos', + accountIdOptional: 'ID da conta (opcional)', + saveAllMd: 'Salvar tudo', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', + 'Salvar todos os arquivos markdown atuais exige reiniciar o contêiner para entrar em vigor. Escolha se deseja reiniciar agora ou depois.', configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + 'Salvar o arquivo de configuração exige reiniciar imediatamente o contêiner para entrar em vigor.', + overviewSnapshot: 'Visão geral', + defaultModel: 'Modelo padrão', + channelCount: 'Canais configurados', + skillCount: 'Habilidades', + jobCount: 'Tarefas agendadas', + sessionCount: 'Sessões', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: 'O plugin não está instalado. Instale-o primeiro.', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', + dmPolicy: 'Política de DM', + groupPolicy: 'Política de grupo', + policyAllowlist: 'Lista de permissões', + policyOpen: 'Aberto', + policyDisabled: 'Desativado', bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', - botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + addBot: 'Adicionar bot', + accountId: 'ID da conta', + setDefaultBot: 'Definir como padrão', + botDuplicateAccountId: 'O ID da conta já existe', + botRequired: 'Adicione pelo menos um bot', + botId: 'ID do bot', + allowFrom: 'Lista de permissões de DM', + allowFromHelper: + 'Um ID de remetente por linha. Usado apenas quando a Política de DM é Lista de permissões.', + allowFromPlaceholder: 'Um ID de remetente por linha', + groupAllowFrom: 'Lista de permissões de grupo', + groupAllowFromHelper: + 'Um ID de grupo por linha. Usado apenas quando a Política de grupo é Lista de permissões.', + groupAllowFromPlaceholder: 'Um ID de grupo por linha', + allowFromRequired: 'Digite pelo menos uma entrada na lista de permissões', + saveAndRestartGateway: 'Salvar e reiniciar gateway', + pairingCode: 'Código de pareamento', + pairingCodePlaceholder: 'Digite o código de pareamento', + approvePairing: 'Aprovar pareamento', + saveSuccess: 'Salvo com sucesso', + pairingApproveSuccess: 'Pareamento aprovado com sucesso', + scanConnect: 'Escanear para conectar', + scanConnectHelper: 'Clique para iniciar a tarefa de login por QR. O código QR aparecerá no log da tarefa.', customProviderHelper: 'Provedores de modelo personalizados não validam se a conta está disponível', }, model: { diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index b31c41217..8a06553ba 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -697,33 +697,33 @@ const message = { securityTab: 'Security', otherTab: 'Other', timeZone: 'Часовой пояс', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: 'Браузер включен', + npmRegistry: 'Реестр NPM', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'Используется для установки плагинов OpenClaw. Вы можете выбрать предустановленный реестр или указать свой.', + npmRegistryInvalid: 'Введите корректный URL реестра NPM, начинающийся с http:// или https://', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', - skillsMarketSourceClawhub: 'ClawHub (Official)', + 'Перейдите в Настройки -> Другое, чтобы настроить реестр NPM и ускорить установку плагинов', + skillsSearchPlaceholder: 'Поиск навыков...', + skillsEmpty: 'Нет навыков', + skillsMarket: 'Рынок навыков', + skillsMarketHint: 'Выберите источник и выполните поиск навыков', + skillsMarketEmpty: 'Подходящие навыки не найдены', + skillsMarketSourceClawhub: 'ClawHub (Официальный)', skillsMarketSourceSkillhub: 'SkillHub (Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: 'Оценка', + versionUnsupportedTitle: 'Эта функция не поддерживается в текущей версии', + versionUnsupportedHelper: 'Пожалуйста, обновите OpenClaw до версии {0} или выше.', + skillsStatusDisabled: 'Отключено', + skillsGroupBuiltIn: 'Встроенные', + skillsGroupExternal: 'Внешние', + skillsGroupWorkspace: 'Рабочая область', + switchModelSuccess: 'Модель успешно переключена', + channelsTab: 'Каналы', + agentRoleTab: 'Агенты', + agentRoleUnsupported: 'Управление ролями в настоящее время поддерживается только для OpenClaw.', + workspace: 'Каталог рабочей области', + agentDir: 'Каталог агента', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -751,51 +751,52 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: 'Привязки', + accountIdOptional: 'ID аккаунта (необязательно)', + saveAllMd: 'Сохранить все', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', + 'Сохранение всех текущих markdown-файлов требует перезапуска контейнера для применения. Выберите, перезапустить сейчас или позже.', configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + 'Сохранение файла конфигурации требует немедленного перезапуска контейнера для применения.', + overviewSnapshot: 'Сводка', + defaultModel: 'Модель по умолчанию', + channelCount: 'Настроенные каналы', + skillCount: 'Навыки', + jobCount: 'Запланированные задачи', + sessionCount: 'Сессии', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: 'Плагин не установлен. Сначала установите его.', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', - bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', - botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + dmPolicy: 'Политика DM', + groupPolicy: 'Групповая политика', + policyAllowlist: 'Белый список', + policyOpen: 'Открыто', + policyDisabled: 'Отключено', + bots: 'Боты', + addBot: 'Добавить бота', + accountId: 'ID аккаунта', + setDefaultBot: 'Сделать по умолчанию', + botDuplicateAccountId: 'ID аккаунта уже существует', + botRequired: 'Добавьте хотя бы одного бота', + botId: 'ID бота', + allowFrom: 'Белый список DM', + allowFromHelper: 'Один ID отправителя на строку. Используется только когда политика DM — Белый список.', + allowFromPlaceholder: 'Один ID отправителя на строку', + groupAllowFrom: 'Белый список групп', + groupAllowFromHelper: + 'Один ID группы на строку. Используется только когда групповая политика — Белый список.', + groupAllowFromPlaceholder: 'Один ID группы на строку', + allowFromRequired: 'Введите хотя бы одну запись белого списка', + saveAndRestartGateway: 'Сохранить и перезапустить gateway', + pairingCode: 'Код сопряжения', + pairingCodePlaceholder: 'Введите код сопряжения', + approvePairing: 'Одобрить сопряжение', + saveSuccess: 'Успешно сохранено', + pairingApproveSuccess: 'Сопряжение успешно одобрено', + scanConnect: 'Сканировать для подключения', + scanConnectHelper: 'Нажмите, чтобы запустить задачу входа по QR-коду. QR-код появится в журнале задач.', customProviderHelper: 'Для пользовательского провайдера модели доступность учетной записи не проверяется', }, model: { diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 173bb2ea0..e71cf5de1 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -697,37 +697,37 @@ const message = { manualModel: 'Manuel giriş', verified: 'Doğrulandı', verifySkipped: 'Doğrulama yok', - skillsTab: 'Skills', - securityTab: 'Security', - otherTab: 'Other', + skillsTab: 'Yetenekler', + securityTab: 'Güvenlik', + otherTab: 'Diğer', timeZone: 'Saat Dilimi', - browserEnabled: 'Browser Enabled', - npmRegistry: 'NPM Registry', + browserEnabled: 'Tarayıcı etkin', + npmRegistry: 'NPM kayıt defteri', npmRegistryHelper: - 'Used for OpenClaw plugin installation. You can choose a preset registry or enter a custom one.', - npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', + 'OpenClaw eklenti kurulumu için kullanılır. Hazır bir kayıt defteri seçebilir veya özel bir tane girebilirsiniz.', + npmRegistryInvalid: 'http:// veya https:// ile başlayan geçerli bir NPM kayıt defteri URLsi girin', pluginInstallNPMRegistryHelper: - 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', - skillsSearchPlaceholder: 'Search skills...', - skillsEmpty: 'No skills', - skillsMarket: 'Skill Market', - skillsMarketHint: 'Select a source and search for skills', - skillsMarketEmpty: 'No matching skills found', - skillsMarketSourceClawhub: 'ClawHub (Official)', + 'NPM kayıt defterini yapılandırmak ve eklenti kurulumunu hızlandırmak için Ayarlar -> Diğer bölümüne gidin', + skillsSearchPlaceholder: 'Yetenek ara...', + skillsEmpty: 'Yetenek yok', + skillsMarket: 'Yetenek pazarı', + skillsMarketHint: 'Bir kaynak seçin ve yetenek arayın', + skillsMarketEmpty: 'Eşleşen yetenek bulunamadı', + skillsMarketSourceClawhub: 'ClawHub (Resmi)', skillsMarketSourceSkillhub: 'SkillHub (Tencent)', - skillsScore: 'Score', - versionUnsupportedTitle: 'This feature is not supported in the current version', - versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.', - skillsStatusDisabled: 'Disabled', - skillsGroupBuiltIn: 'Built-in', - skillsGroupExternal: 'External', - skillsGroupWorkspace: 'Workspace', - switchModelSuccess: 'Model switched successfully', - channelsTab: 'Channels', - agentRoleTab: 'Agents', - agentRoleUnsupported: 'Role management is currently supported only for OpenClaw.', - workspace: 'Workspace Directory', - agentDir: 'Agent Directory', + skillsScore: 'Puan', + versionUnsupportedTitle: 'Bu özellik mevcut sürümde desteklenmiyor', + versionUnsupportedHelper: 'Lütfen OpenClawı {0} veya üzeri bir sürüme yükseltin.', + skillsStatusDisabled: 'Devre dışı', + skillsGroupBuiltIn: 'Yerleşik', + skillsGroupExternal: 'Harici', + skillsGroupWorkspace: 'Çalışma alanı', + switchModelSuccess: 'Model başarıyla değiştirildi', + channelsTab: 'Kanallar', + agentRoleTab: 'Ajanlar', + agentRoleUnsupported: 'Rol yönetimi şu anda yalnızca OpenClaw için desteklenmektedir.', + workspace: 'Çalışma alanı dizini', + agentDir: 'Ajan dizini', roleMarkdownDescriptions: { 'AGENTS.md': [ 'Operating instructions for the agent and how it should use memory.', @@ -755,51 +755,52 @@ const message = { 'Delete it after the ritual is complete.', ], }, - bindings: 'Bindings', - accountIdOptional: 'Account ID (Optional)', - saveAllMd: 'Save All', + bindings: 'Bağlamalar', + accountIdOptional: 'Hesap ID (İsteğe bağlı)', + saveAllMd: 'Tümünü kaydet', roleMarkdownRestartHelper: - 'Saving all current markdown files requires a container restart to take effect. Choose whether to restart now or later.', + 'Mevcut tüm markdown dosyalarını kaydetmek için etkin olması adına konteynerin yeniden başlatılması gerekir. Şimdi mi sonra mı yeniden başlatılacağını seçin.', configFileRestartHelper: - 'Saving the config file requires immediately restarting the container to take effect.', - overviewSnapshot: 'Snapshot', - defaultModel: 'Default Model', - channelCount: 'Configured Channels', - skillCount: 'Skills', - jobCount: 'Scheduled Jobs', - sessionCount: 'Sessions', + 'Yapılandırma dosyasını kaydetmek, etkin olması için konteynerin hemen yeniden başlatılmasını gerektirir.', + overviewSnapshot: 'Özet', + defaultModel: 'Varsayılan model', + channelCount: 'Yapılandırılmış kanallar', + skillCount: 'Yetenekler', + jobCount: 'Zamanlanmış görevler', + sessionCount: 'Oturumlar', weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', pluginNotInstalled: 'Eklenti yüklü değil. Lütfen önce yükleyin.', - dmPolicy: 'DM Policy', - groupPolicy: 'Group Policy', - policyAllowlist: 'Allowlist', - policyOpen: 'Open', - policyDisabled: 'Disabled', - bots: 'Bots', - addBot: 'Add Bot', - accountId: 'Account ID', - setDefaultBot: 'Set as Default', - botDuplicateAccountId: 'Account ID already exists', - botRequired: 'Add at least one bot', + dmPolicy: 'DM ilkesi', + groupPolicy: 'Grup ilkesi', + policyAllowlist: 'İzin listesi', + policyOpen: 'Açık', + policyDisabled: 'Devre dışı', + bots: 'Botlar', + addBot: 'Bot ekle', + accountId: 'Hesap ID', + setDefaultBot: 'Varsayılan yap', + botDuplicateAccountId: 'Hesap ID zaten mevcut', + botRequired: 'En az bir bot ekleyin', botId: 'Bot ID', - allowFrom: 'DM Allowlist', - allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', - allowFromPlaceholder: 'One sender ID per line', - groupAllowFrom: 'Group Allowlist', - groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.', - groupAllowFromPlaceholder: 'One group ID per line', - allowFromRequired: 'Enter at least one allowlist entry', - saveAndRestartGateway: 'Save and restart gateway', - pairingCode: 'Pairing Code', - pairingCodePlaceholder: 'Enter pairing code', - approvePairing: 'Approve Pairing', - saveSuccess: 'Saved successfully', - pairingApproveSuccess: 'Pairing approved successfully', - scanConnect: 'Scan to Connect', - scanConnectHelper: 'Click to start the QR login task. The QR code will appear in the task log.', + allowFrom: 'DM izin listesi', + allowFromHelper: 'Her satıra bir gönderici ID yazın. Yalnızca DM İlkesi İzin listesi olduğunda kullanılır.', + allowFromPlaceholder: 'Her satıra bir gönderici ID', + groupAllowFrom: 'Grup izin listesi', + groupAllowFromHelper: + 'Her satıra bir grup ID yazın. Yalnızca Grup İlkesi İzin listesi olduğunda kullanılır.', + groupAllowFromPlaceholder: 'Her satıra bir grup ID', + allowFromRequired: 'En az bir izin listesi girdisi girin', + saveAndRestartGateway: 'Kaydet ve gatewayi yeniden başlat', + pairingCode: 'Eşleştirme kodu', + pairingCodePlaceholder: 'Eşleştirme kodunu girin', + approvePairing: 'Eşleştirmeyi onayla', + saveSuccess: 'Başarıyla kaydedildi', + pairingApproveSuccess: 'Eşleştirme başarıyla onaylandı', + scanConnect: 'Tara ve bağlan', + scanConnectHelper: 'QR giriş görevini başlatmak için tıklayın. QR kodu görev günlüğünde görünecektir.', customProviderHelper: 'Özel model sağlayıcısında hesabın kullanılabilirliği doğrulanmaz', }, model: { diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue index bc261fcbc..696c1a164 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue @@ -25,39 +25,46 @@ - + @@ -65,13 +72,13 @@ - + - + - + - + @@ -153,6 +163,10 @@ const props = defineProps({ type: Boolean, default: false, }, + disabled: { + type: Boolean, + default: false, + }, undeletableAccountIds: { type: Array as PropType, default: () => [], @@ -224,6 +238,10 @@ const emitBots = (bots: ChannelBotItem[]) => { emit('update:bots', nextBots); }; +const isBotActionDisabled = (bot: ChannelBotItem) => { + return props.fields.some((field) => field.required && !bot[field.prop]); +}; + const openCreate = () => { editIndex.value = -1; editingAccountId.value = ''; @@ -306,4 +324,16 @@ const updateEnabled = (index: number, enabled: boolean | string | number) => { align-items: center; gap: 8px; } + +.channel-bots__actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px 12px; + + :deep(.el-button) { + margin-left: 0; + white-space: nowrap; + } +} diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/components/plugin-install.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/plugin-install.vue index adabd8e8e..211db6825 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/components/plugin-install.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/plugin-install.vue @@ -8,25 +8,76 @@ :description="t('aiTools.agents.pluginInstallNPMRegistryHelper')" /> - + {{ t('commons.button.install') }} +
+
+
+ {{ t('app.version') }} + {{ currentVersion || '-' }} +
+ + {{ t('commons.button.uninstall') }} + +
+
+
+ {{ t('app.newVersion') }} + {{ latestVersion || '-' }} +
+ + {{ t('commons.button.upgrade') }} + +
+
+ diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/dingtalk.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/dingtalk.vue index 536c4c1ae..7b1acd225 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/dingtalk.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/dingtalk.vue @@ -1,63 +1,81 @@