diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index 3c767ded8..45935d820 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -680,6 +680,47 @@ func (b *BaseApi) UpdateAgentOtherConfig(c *gin.Context) { helper.Success(c) } +// @Tags AI +// @Summary List Agent skills +// @Accept json +// @Param request body dto.AgentSkillsReq true "request" +// @Success 200 {array} dto.AgentSkillItem +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/skills/list [post] +func (b *BaseApi) ListAgentSkills(c *gin.Context) { + var req dto.AgentSkillsReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + data, err := agentService.ListSkills(req) + if err != nil { + helper.BadRequest(c, err) + return + } + helper.SuccessWithData(c, data) +} + +// @Tags AI +// @Summary Update Agent skill status +// @Accept json +// @Param request body dto.AgentSkillUpdateReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/skills/update [post] +func (b *BaseApi) UpdateAgentSkill(c *gin.Context) { + var req dto.AgentSkillUpdateReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := agentService.UpdateSkill(req); err != nil { + helper.BadRequest(c, err) + return + } + helper.Success(c) +} + // @Tags AI // @Summary Login Agent Weixin channel // @Accept json diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go index 74e3d26bf..c6fe72178 100644 --- a/agent/app/dto/agents.go +++ b/agent/app/dto/agents.go @@ -353,3 +353,21 @@ type AgentOtherConfig struct { BrowserEnabled bool `json:"browserEnabled"` NPMRegistry string `json:"npmRegistry"` } + +type AgentSkillsReq struct { + AgentID uint `json:"agentId" validate:"required"` +} + +type AgentSkillItem struct { + Name string `json:"name"` + Description string `json:"description"` + Source string `json:"source"` + Bundled bool `json:"bundled"` + Disabled bool `json:"disabled"` +} + +type AgentSkillUpdateReq struct { + AgentID uint `json:"agentId" validate:"required"` + Name string `json:"name" validate:"required"` + Enabled bool `json:"enabled"` +} diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index 168e16fc1..d913a491a 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -33,6 +33,8 @@ type IAgentService interface { UpdateSecurityConfig(req dto.AgentSecurityConfigUpdateReq) error GetOtherConfig(req dto.AgentOtherConfigReq) (*dto.AgentOtherConfig, error) UpdateOtherConfig(req dto.AgentOtherConfigUpdateReq) error + ListSkills(req dto.AgentSkillsReq) ([]dto.AgentSkillItem, error) + UpdateSkill(req dto.AgentSkillUpdateReq) error CreateAccount(req dto.AgentAccountCreateReq) error UpdateAccount(req dto.AgentAccountUpdateReq) error diff --git a/agent/app/service/agents_channels.go b/agent/app/service/agents_channels.go index a1bc8c3f9..e78c122cb 100644 --- a/agent/app/service/agents_channels.go +++ b/agent/app/service/agents_channels.go @@ -166,6 +166,14 @@ func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error { } installTask.AddSubTask("Install OpenClaw plugin", func(t *task.Task) error { mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute)) + 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.RunBashCf("printf 'yes\\n' | docker exec -i %s openclaw plugins uninstall qqbot", install.ContainerName); err != nil { + return err + } + } + } if err := mgr.RunBashCf("docker exec %s openclaw plugins install %s", install.ContainerName, spec); err != nil { return err } @@ -539,7 +547,7 @@ func setQQBotConfig(conf map[string]interface{}, config dto.AgentQQBotConfig) { plugins := ensureChildMap(conf, "plugins") entries := ensureChildMap(plugins, "entries") - qqbotEntry := ensureChildMap(entries, "qqbot") + qqbotEntry := ensureChildMap(entries, "openclaw-qqbot") qqbotEntry["enabled"] = config.Enabled } @@ -571,7 +579,7 @@ func appendPluginAllow(conf map[string]interface{}, pluginID string) { func resolvePluginMeta(pluginType string) (string, string, error) { switch pluginType { case "qqbot": - return "@sliverp/qqbot@latest", "qqbot", nil + return "@tencent-connect/openclaw-qqbot@latest", "openclaw-qqbot", nil case "wecom": return "@wecom/wecom-openclaw-plugin", "wecom-openclaw-plugin", nil case "dingtalk": diff --git a/agent/app/service/agents_skills.go b/agent/app/service/agents_skills.go new file mode 100644 index 000000000..13d7d5488 --- /dev/null +++ b/agent/app/service/agents_skills.go @@ -0,0 +1,133 @@ +package service + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/1Panel-dev/1Panel/agent/app/dto" + "github.com/1Panel-dev/1Panel/agent/constant" + "github.com/1Panel-dev/1Panel/agent/utils/cmd" +) + +type openclawSkillsList struct { + Skills []openclawSkillListItem `json:"skills"` +} + +type openclawSkillListItem struct { + Name string `json:"name"` + Description string `json:"description"` + Source string `json:"source"` + Bundled bool `json:"bundled"` + Disabled bool `json:"disabled"` +} + +type openclawSkillInfo struct { + SkillKey string `json:"skillKey"` +} + +func (a AgentService) ListSkills(req dto.AgentSkillsReq) ([]dto.AgentSkillItem, error) { + agent, install, err := a.loadAgentAndInstall(req.AgentID) + if err != nil { + return nil, err + } + if agent.AgentType != constant.AppOpenclaw { + return nil, fmt.Errorf("copaw does not support skills") + } + status, err := checkContainerStatus(install.ContainerName) + if err != nil { + return nil, err + } + if status != "running" { + return nil, fmt.Errorf("container %s is not running, please check and retry", install.ContainerName) + } + output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut( + "docker exec %s openclaw skills list --json 2>&1", + 30*time.Second, + install.ContainerName, + ) + if err != nil { + return nil, err + } + if len(output) == 0 { + return nil, nil + } + return parseOpenclawSkillsList(output) +} + +func (a AgentService) UpdateSkill(req dto.AgentSkillUpdateReq) error { + agent, install, err := a.loadAgentAndInstall(req.AgentID) + if err != nil { + return err + } + if agent.AgentType != constant.AppOpenclaw { + return fmt.Errorf("copaw does not support skills") + } + status, err := checkContainerStatus(install.ContainerName) + if err != nil { + return err + } + if status != "running" { + return fmt.Errorf("container %s is not running, please check and retry", install.ContainerName) + } + conf, err := readOpenclawConfig(agent.ConfigPath) + if err != nil { + return err + } + skillKey, err := getOpenclawSkillKey(install.ContainerName, req.Name) + if err != nil { + return err + } + setOpenclawSkillEnabled(conf, skillKey, req.Enabled) + return writeOpenclawConfigRaw(agent.ConfigPath, conf) +} + +func parseOpenclawSkillsList(output string) ([]dto.AgentSkillItem, error) { + var payload openclawSkillsList + if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &payload); err != nil { + return nil, err + } + items := make([]dto.AgentSkillItem, 0, len(payload.Skills)) + for _, item := range payload.Skills { + items = append(items, dto.AgentSkillItem{ + Name: item.Name, + Description: item.Description, + Source: item.Source, + Bundled: item.Bundled, + Disabled: item.Disabled, + }) + } + return items, nil +} + +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, + ) + if err != nil { + return "", err + } + return parseOpenclawSkillKey(name, output) +} + +func parseOpenclawSkillKey(name, output string) (string, error) { + var payload openclawSkillInfo + if err := json.Unmarshal([]byte(strings.TrimSpace(output)), &payload); err != nil { + return "", err + } + if payload.SkillKey == "" { + return "", fmt.Errorf("skill %s does not have a skillKey", name) + } + return payload.SkillKey, nil +} + +func setOpenclawSkillEnabled(conf map[string]interface{}, skillKey string, enabled bool) { + skills := ensureChildMap(conf, "skills") + entries := ensureChildMap(skills, "entries") + entry := ensureChildMap(entries, skillKey) + entry["enabled"] = enabled +} diff --git a/agent/router/ro_ai.go b/agent/router/ro_ai.go index f8be0c19d..3600120aa 100644 --- a/agent/router/ro_ai.go +++ b/agent/router/ro_ai.go @@ -74,6 +74,8 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/agents/security/update", baseApi.UpdateAgentSecurityConfig) aiToolsRouter.POST("/agents/other/get", baseApi.GetAgentOtherConfig) aiToolsRouter.POST("/agents/other/update", baseApi.UpdateAgentOtherConfig) + aiToolsRouter.POST("/agents/skills/list", baseApi.ListAgentSkills) + aiToolsRouter.POST("/agents/skills/update", baseApi.UpdateAgentSkill) aiToolsRouter.POST("/agents/channel/pairing/approve", baseApi.ApproveAgentChannelPairing) } } diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index 3368ad4ee..3525e4263 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -587,4 +587,22 @@ export namespace AI { browserEnabled: boolean; npmRegistry: string; } + + export interface AgentSkillsReq { + agentId: number; + } + + export interface AgentSkillItem { + name: string; + description: string; + source: string; + bundled: boolean; + disabled: boolean; + } + + export interface AgentSkillUpdateReq { + agentId: number; + name: string; + enabled: boolean; + } } diff --git a/frontend/src/api/modules/ai.ts b/frontend/src/api/modules/ai.ts index ca5109222..9cf362a6b 100644 --- a/frontend/src/api/modules/ai.ts +++ b/frontend/src/api/modules/ai.ts @@ -229,6 +229,14 @@ export const updateAgentOtherConfig = (req: AI.AgentOtherConfigUpdateReq) => { return http.post(`/ai/agents/other/update`, req); }; +export const listAgentSkills = (req: AI.AgentSkillsReq) => { + return http.post(`/ai/agents/skills/list`, req); +}; + +export const updateAgentSkill = (req: AI.AgentSkillUpdateReq) => { + return http.post(`/ai/agents/skills/update`, req); +}; + export const approveAgentChannelPairing = (req: AI.AgentChannelPairingApproveReq) => { return http.post(`/ai/agents/channel/pairing/approve`, req); }; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 76f9dbb18..a531a559f 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -670,7 +670,6 @@ const message = { }, aiTools: { agents: { - agents: 'Agents', agent: 'Agent', account: 'Model Account', noAccountHint: 'Choose an existing model account or add a new one.', @@ -688,21 +687,16 @@ const message = { allowedOriginsRequired: 'Enter at least one access address', allowedOriginsInvalid: 'Use the format http(s)://host-or-ip[:port]', provider: 'Provider', - apiKey: 'API Key', - baseUrl: 'Base URL', - accountModels: 'Model Catalog', 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', - token: 'Token', manualModel: 'Manual input', verified: 'Verified', verifySkipped: 'No verification', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'Time Zone', @@ -713,6 +707,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -722,16 +722,12 @@ const message = { pluginNotInstalled: 'Plugin is not installed. Please install it first.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -743,14 +739,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Enter pairing code', 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.', customProviderHelper: 'Custom model providers do not validate whether the account is available.', - feishuSaveSuccess: 'Saved to Feishu', }, model: { model: 'Models', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 52e8a4e1a..842045526 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -678,7 +678,6 @@ const message = { }, aiTools: { agents: { - agents: 'Agentes', agent: 'Agente', account: 'Cuenta de modelo', noAccountHint: 'Selecciona una cuenta de modelo existente o agrega una nueva.', @@ -696,21 +695,16 @@ 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', - apiKey: 'Clave API', - baseUrl: 'URL base', - accountModels: 'Model Catalog', 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', - token: 'Token', manualModel: 'Entrada manual de modelo', verified: 'Verificado', verifySkipped: 'Sin verificacion', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'Zona horaria', @@ -721,6 +715,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -730,16 +730,12 @@ const message = { pluginNotInstalled: 'El plugin no está instalado. Instálalo primero.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -751,14 +747,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: 'En el proveedor de modelo personalizado no se valida si la cuenta está disponible', - feishuSaveSuccess: 'Guardado en Feishu', }, model: { model: 'Modelo', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 95c8e7b8a..5e0c10d63 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -671,7 +671,6 @@ const message = { }, aiTools: { agents: { - agents: 'エージェント', agent: 'エージェント', account: 'モデルアカウント', noAccountHint: '既存のモデルアカウントを選択するか、新規に追加してください。', @@ -689,21 +688,16 @@ const message = { allowedOriginsRequired: '少なくとも 1 つのアクセスアドレスを入力してください', allowedOriginsInvalid: 'http(s)://host-or-ip[:port] の形式で入力してください', provider: 'モデルプロバイダー', - apiKey: 'API キー', - baseUrl: 'ベースURL', - accountModels: 'Model Catalog', 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', - token: 'トークン', manualModel: '手動入力', verified: '検証済み', verifySkipped: '検証なし', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'タイムゾーン', @@ -714,6 +708,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -723,16 +723,12 @@ const message = { pluginNotInstalled: 'プラグインがインストールされていません。先にインストールしてください。', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -744,14 +740,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: 'カスタムモデルプロバイダーでは、アカウントの有効性を検証しません', - feishuSaveSuccess: 'Feishuに保存済み', }, model: { model: 'モデル', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 7b0d4d527..58590853d 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -663,7 +663,6 @@ const message = { }, aiTools: { agents: { - agents: '에이전트', agent: '에이전트', account: '모델 계정', noAccountHint: '기존 모델 계정을 선택하거나 새로 추가하세요.', @@ -681,21 +680,16 @@ const message = { allowedOriginsRequired: '접속 주소를 하나 이상 입력하세요', allowedOriginsInvalid: 'http(s)://host-or-ip[:port] 형식으로 입력하세요', provider: '모델 제공자', - apiKey: 'API 키', - baseUrl: '기본 URL', - accountModels: 'Model Catalog', 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', - token: '토큰', manualModel: '수동 입력', verified: '검증됨', verifySkipped: '검증 안 함', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: '시간대', @@ -706,6 +700,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -715,16 +715,12 @@ const message = { pluginNotInstalled: '플러그인이 설치되지 않았습니다. 먼저 설치해 주세요.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -736,14 +732,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: '사용자 정의 모델 공급자는 계정 사용 가능 여부를 검증하지 않습니다', - feishuSaveSuccess: 'Feishu에 저장됨', }, model: { model: '모델', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 83f320c52..49eadb121 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -678,7 +678,6 @@ const message = { }, aiTools: { agents: { - agents: 'Agen', agent: 'Agen', account: 'Akaun model', noAccountHint: 'Pilih akaun model sedia ada atau tambah yang baharu.', @@ -696,21 +695,16 @@ const message = { allowedOriginsRequired: 'Masukkan sekurang-kurangnya satu alamat akses', allowedOriginsInvalid: 'Gunakan format http(s)://hos-atau-ip[:port]', provider: 'Penyedia model', - apiKey: 'Kunci API', - baseUrl: 'URL asas', - accountModels: 'Model Catalog', 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', - token: 'Token', manualModel: 'Input manual', verified: 'Disahkan', verifySkipped: 'Tanpa pengesahan', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'Zon Waktu', @@ -721,6 +715,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -730,16 +730,12 @@ const message = { pluginNotInstalled: 'Plugin belum dipasang. Sila pasang dahulu.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -751,14 +747,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: 'Penyedia model tersuai tidak mengesahkan sama ada akaun boleh digunakan', - feishuSaveSuccess: 'Disimpan ke Feishu', }, model: { model: 'Model', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 7ee23e343..1c8a2942d 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -673,7 +673,6 @@ const message = { }, aiTools: { agents: { - agents: 'Agentes', agent: 'Agente', account: 'Conta de modelo', noAccountHint: 'Selecione uma conta de modelo existente ou adicione uma nova.', @@ -691,21 +690,16 @@ const message = { allowedOriginsRequired: 'Informe pelo menos um endereço de acesso', allowedOriginsInvalid: 'Use o formato http(s)://host-ou-ip[:porta]', provider: 'Provedor de modelos', - apiKey: 'Chave API', - baseUrl: 'URL base', - accountModels: 'Model Catalog', 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', - token: 'Token', manualModel: 'Entrada manual', verified: 'Verificado', verifySkipped: 'Sem verificacao', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'Fuso horário', @@ -716,6 +710,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -725,16 +725,12 @@ const message = { pluginNotInstalled: 'O plugin não está instalado. Instale-o primeiro.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -746,14 +742,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: 'Provedores de modelo personalizados não validam se a conta está disponível', - feishuSaveSuccess: 'Salvo no Feishu', }, model: { model: 'Modelo', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 592f46dde..ea3326b36 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -670,7 +670,6 @@ const message = { }, aiTools: { agents: { - agents: 'Агенты', agent: 'Агент', account: 'Аккаунт модели', noAccountHint: 'Выберите существующий аккаунт модели или добавьте новый.', @@ -688,21 +687,16 @@ const message = { allowedOriginsRequired: 'Укажите хотя бы один адрес доступа', allowedOriginsInvalid: 'Используйте формат http(s)://host-or-ip[:port]', provider: 'Поставщик моделей', - apiKey: 'API ключ', - baseUrl: 'Базовый URL', - accountModels: 'Model Catalog', 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', - token: 'Токен', manualModel: 'Ручной ввод', verified: 'Проверено', verifySkipped: 'Без проверки', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'Часовой пояс', @@ -713,6 +707,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -722,16 +722,12 @@ const message = { pluginNotInstalled: 'Плагин не установлен. Сначала установите его.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -743,14 +739,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: 'Для пользовательского провайдера модели доступность учетной записи не проверяется', - feishuSaveSuccess: 'Сохранено в Feishu', }, model: { model: 'Модель', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 82a812110..dec32f2e9 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -674,7 +674,6 @@ const message = { }, aiTools: { agents: { - agents: 'Ajanlar', agent: 'Ajan', account: 'Model hesabı', noAccountHint: 'Mevcut bir model hesabını seçin veya yeni bir tane ekleyin.', @@ -692,21 +691,16 @@ const message = { allowedOriginsRequired: 'En az bir erişim adresi girin', allowedOriginsInvalid: 'http(s)://host-veya-ip[:port] biçimini kullanın', provider: 'Model sağlayıcı', - apiKey: 'API anahtarı', - baseUrl: 'Temel URL', - accountModels: 'Model Catalog', 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', - token: 'Token', manualModel: 'Manuel giriş', verified: 'Doğrulandı', verifySkipped: 'Doğrulama yok', - configTitle: 'Configuration', - settingsTab: 'Settings', + skillsTab: 'Skills', securityTab: 'Security', otherTab: 'Other', timeZone: 'Saat Dilimi', @@ -717,6 +711,12 @@ const message = { npmRegistryInvalid: 'Enter a valid NPM registry URL starting with http:// or https://', pluginInstallNPMRegistryHelper: 'Go to Settings -> Other to configure the NPM registry and speed up plugin installation', + skillsSearchPlaceholder: 'Search skills...', + skillsEmpty: 'No skills', + skillsStatusDisabled: 'Disabled', + skillsGroupBuiltIn: 'Built-in', + skillsGroupExternal: 'External', + skillsGroupWorkspace: 'Workspace', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', weixin: 'Weixin', @@ -726,16 +726,12 @@ const message = { pluginNotInstalled: 'Eklenti yüklü değil. Lütfen önce yükleyin.', dmPolicy: 'DM Policy', groupPolicy: 'Group Policy', - policyPairing: 'Pairing', - policyAllowlist: 'Allowlist', policyOpen: 'Open', policyDisabled: 'Disabled', botName: 'Bot Name', botId: 'Bot ID', appId: 'App ID', appSecret: 'App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: 'DM Allowlist', allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.', allowFromPlaceholder: 'One sender ID per line', @@ -747,14 +743,11 @@ const message = { pairingCode: 'Pairing Code', pairingCodePlaceholder: 'Enter pairing code', approvePairing: 'Approve Pairing', - feishuRequired: 'Please fill botName / appId / appSecret', saveSuccess: 'Saved successfully', - pairingCodeRequired: 'Please enter pairing code', 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.', customProviderHelper: 'Özel model sağlayıcısında hesabın kullanılabilirliği doğrulanmaz', - feishuSaveSuccess: "Feishu'ya kaydedildi", }, model: { model: 'Model', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 1d89f4325..d9348238d 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -638,7 +638,6 @@ const message = { }, aiTools: { agents: { - agents: '智能體', agent: '智能體', account: '模型帳號', noAccountHint: '選擇已有模型帳號,或直接建立', @@ -656,21 +655,16 @@ const message = { allowedOriginsRequired: '請至少填寫一個訪問地址', allowedOriginsInvalid: '訪問地址格式錯誤,請輸入 http(s)://網域或IP[:埠]', provider: '模型供應商', - apiKey: 'API Key', - baseUrl: 'Base URL', - accountModels: '模型池', accountModelsHelper: '配置該帳號可提供給 OpenClaw 使用與切換的模型列表', accountModelsRequired: '請至少配置一個模型', accountModelsDuplicate: '模型池中存在重複模型,請檢查後重試', modelPool: '模型池', modelInputTypes: '輸入類型', reasoning: '推理模型', - token: 'Token', manualModel: '手動輸入模型', verified: '驗證狀態', verifySkipped: '不驗證', - configTitle: '設定', - settingsTab: '設定', + skillsTab: '技能', securityTab: '安全', otherTab: '其他', timeZone: '時區', @@ -679,6 +673,12 @@ const message = { npmRegistryHelper: '用於 OpenClaw 外掛安裝時的 npm registry,可選擇預設來源或手動輸入自訂來源', npmRegistryInvalid: '請輸入正確的 NPM 源地址,需以 http:// 或 https:// 開頭', pluginInstallNPMRegistryHelper: '可前往 設定 -> 其他 設定 NPM 源,以加速外掛安裝', + skillsSearchPlaceholder: '搜尋技能...', + skillsEmpty: '暫無技能', + skillsStatusDisabled: '已禁用', + skillsGroupBuiltIn: '內置', + skillsGroupExternal: '外部', + skillsGroupWorkspace: '工作區', switchModelSuccess: '模型切換成功', channelsTab: '頻道', weixin: '微信', @@ -688,16 +688,12 @@ const message = { pluginNotInstalled: '插件未安裝,請先安裝插件', dmPolicy: '私聊策略', groupPolicy: '群組策略', - policyPairing: '配對', - policyAllowlist: '白名單', policyOpen: '開放', policyDisabled: '禁用', botName: '機器人名稱', botId: 'Bot ID', appId: '應用 App ID', appSecret: '應用 App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: '私聊白名單', allowFromHelper: '一行一個發送方識別碼,僅在私聊策略為白名單時生效', allowFromPlaceholder: '一行一個發送方識別碼', @@ -709,14 +705,11 @@ const message = { pairingCode: '配對碼', pairingCodePlaceholder: '請輸入配對碼', approvePairing: '批准配對', - feishuRequired: '請填寫 botName / appId / appSecret', saveSuccess: '保存成功', - pairingCodeRequired: '請輸入配對碼', pairingApproveSuccess: '配對成功', scanConnect: '掃碼對接', scanConnectHelper: '點擊後將在任務日誌中顯示 QR Code,掃碼確認後即可完成登入', customProviderHelper: '自訂模型供應商不驗證帳號是否可用', - feishuSaveSuccess: '儲存成功', }, model: { model: '模型', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index c1aa7191f..8892ce1ee 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -637,7 +637,6 @@ const message = { }, aiTools: { agents: { - agents: '智能体', agent: '智能体', account: '模型账号', noAccountHint: '选择已有模型账号,或直接创建', @@ -655,21 +654,16 @@ const message = { allowedOriginsRequired: '请至少填写一个访问地址', allowedOriginsInvalid: '访问地址格式错误,请输入 http(s)://域名或IP[:端口]', provider: '模型供应商', - apiKey: 'API Key', - baseUrl: 'Base URL', - accountModels: '模型池', accountModelsHelper: '配置账号可提供给 OpenClaw 使用和切换的模型列表', accountModelsRequired: '请至少配置一个模型', accountModelsDuplicate: '模型池中存在重复模型,请检查后重试', modelPool: '模型池', modelInputTypes: '输入类型', reasoning: '推理模型', - token: 'Token', manualModel: '手动输入模型', verified: '验证状态', verifySkipped: '不验证', - configTitle: '配置', - settingsTab: '设置', + skillsTab: '技能', securityTab: '安全', otherTab: '其他', timeZone: '时区', @@ -678,6 +672,12 @@ const message = { npmRegistryHelper: '用于 OpenClaw 插件安装时的 npm registry,可选择预设源或手动输入自定义源', npmRegistryInvalid: '请输入正确的 NPM 源地址,需以 http:// 或 https:// 开头', pluginInstallNPMRegistryHelper: '可前往 设置 -> 其他 配置 NPM 源,以加速插件安装', + skillsSearchPlaceholder: '搜索技能...', + skillsEmpty: '暂无技能', + skillsStatusDisabled: '已禁用', + skillsGroupBuiltIn: '内置', + skillsGroupExternal: '外部', + skillsGroupWorkspace: '工作区', switchModelSuccess: '模型切换成功', channelsTab: '频道', weixin: '微信', @@ -687,16 +687,12 @@ const message = { pluginNotInstalled: '插件未安装,请先安装插件', dmPolicy: '私聊策略', groupPolicy: '群组策略', - policyPairing: '配对码', - policyAllowlist: '白名单', policyOpen: '开放', policyDisabled: '禁用', botName: '机器人名称', botId: 'Bot ID', appId: '应用 App ID', appSecret: '应用 App Secret', - clientId: 'Client ID', - clientSecret: 'Client Secret', allowFrom: '私聊白名单', allowFromHelper: '一行一个发送方标识,仅在私聊策略为白名单时生效', allowFromPlaceholder: '一行一个发送方标识', @@ -707,10 +703,7 @@ const message = { pairingCode: '配对码', pairingCodePlaceholder: '请输入配对码', approvePairing: '批准配对', - feishuRequired: '请填写 botName / appId / appSecret', saveSuccess: '保存成功', - feishuSaveSuccess: '保存成功', - pairingCodeRequired: '请输入配对码', pairingApproveSuccess: '配对成功', scanConnect: '扫码对接', scanConnectHelper: '点击后将在任务日志中显示二维码,扫码确认后即可完成登录', diff --git a/frontend/src/routers/modules/ai.ts b/frontend/src/routers/modules/ai.ts index 5faf02479..3514d73a1 100644 --- a/frontend/src/routers/modules/ai.ts +++ b/frontend/src/routers/modules/ai.ts @@ -26,7 +26,7 @@ const databaseRouter = { component: () => import('@/views/ai/agents/agent/index.vue'), meta: { icon: 'p-jiqiren2', - title: 'aiTools.agents.agents', + title: 'aiTools.agents.agent', requiresAuth: true, }, }, diff --git a/frontend/src/views/ai/agents/agent/add/index.vue b/frontend/src/views/ai/agents/agent/add/index.vue index 5d8e78175..69b9897e8 100644 --- a/frontend/src/views/ai/agents/agent/add/index.vue +++ b/frontend/src/views/ai/agents/agent/add/index.vue @@ -5,7 +5,7 @@ - + @@ -76,10 +76,10 @@ {{ $t('aiTools.agents.accountModelsHelper') }} - + - +