From 7bafe6164963e3b1581a0201b77b990473693038 Mon Sep 17 00:00:00 2001 From: zhengkunwang223 <1paneldev@sina.com> Date: Mon, 23 Mar 2026 14:58:33 +0800 Subject: [PATCH] feat: add wenxin channel for openclaw --- agent/app/api/v2/agents.go | 20 +++++ agent/app/dto/agents.go | 9 ++- agent/app/provider/catalog.go | 8 +- agent/app/service/agents.go | 1 + agent/app/service/agents_channels.go | 62 ++++++++++++++- agent/app/service/agents_utils.go | 16 ---- agent/router/ro_ai.go | 1 + frontend/src/api/interface/ai.ts | 9 ++- frontend/src/api/modules/ai.ts | 4 + frontend/src/components/log/file/index.vue | 45 ++++++++--- frontend/src/lang/modules/en.ts | 3 + frontend/src/lang/modules/es-es.ts | 3 + frontend/src/lang/modules/ja.ts | 3 + frontend/src/lang/modules/ko.ts | 3 + frontend/src/lang/modules/ms.ts | 3 + frontend/src/lang/modules/pt-br.ts | 3 + frontend/src/lang/modules/ru.ts | 3 + frontend/src/lang/modules/tr.ts | 3 + frontend/src/lang/modules/zh-Hant.ts | 3 + frontend/src/lang/modules/zh.ts | 3 + .../src/views/ai/agents/agent/add/index.vue | 2 +- .../ai/agents/agent/config/tabs/channels.vue | 9 +++ .../channels/components/plugin-install.vue | 23 ++++++ .../agent/config/tabs/channels/dingtalk.vue | 78 ++++--------------- .../agents/agent/config/tabs/channels/qq.vue | 66 ++++------------ .../tabs/channels/useAgentPluginChannel.ts | 56 +++++++++++++ .../agent/config/tabs/channels/wecom.vue | 75 ++++-------------- .../agent/config/tabs/channels/weixin.vue | 58 ++++++++++++++ 28 files changed, 361 insertions(+), 211 deletions(-) create mode 100644 frontend/src/views/ai/agents/agent/config/tabs/channels/components/plugin-install.vue create mode 100644 frontend/src/views/ai/agents/agent/config/tabs/channels/useAgentPluginChannel.ts create mode 100644 frontend/src/views/ai/agents/agent/config/tabs/channels/weixin.vue diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index 7eb90c6cf05f..3c767ded8bf5 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -680,6 +680,26 @@ func (b *BaseApi) UpdateAgentOtherConfig(c *gin.Context) { helper.Success(c) } +// @Tags AI +// @Summary Login Agent Weixin channel +// @Accept json +// @Param request body dto.AgentWeixinLoginReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/channel/weixin/login [post] +func (b *BaseApi) LoginAgentWeixinChannel(c *gin.Context) { + var req dto.AgentWeixinLoginReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := agentService.LoginWeixinChannel(req); err != nil { + helper.BadRequest(c, err) + return + } + helper.Success(c) +} + // @Tags AI // @Summary Approve Agent channel pairing code // @Accept json diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go index fcf358a485cf..cef78edef5fe 100644 --- a/agent/app/dto/agents.go +++ b/agent/app/dto/agents.go @@ -265,6 +265,11 @@ type AgentDingTalkConfig struct { Installed bool `json:"installed"` } +type AgentWeixinLoginReq struct { + AgentID uint `json:"agentId" validate:"required"` + TaskID string `json:"taskID" validate:"required"` +} + type AgentQQBotConfigReq struct { AgentID uint `json:"agentId" validate:"required"` } @@ -285,13 +290,13 @@ type AgentQQBotConfig struct { type AgentPluginInstallReq struct { AgentID uint `json:"agentId" validate:"required"` - Type string `json:"type" validate:"required,oneof=qqbot wecom dingtalk"` + Type string `json:"type" validate:"required,oneof=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=qqbot wecom dingtalk"` + Type string `json:"type" validate:"required,oneof=qqbot wecom dingtalk weixin"` } type AgentPluginStatus struct { diff --git a/agent/app/provider/catalog.go b/agent/app/provider/catalog.go index a13a15ce4e9c..c311e89b857f 100644 --- a/agent/app/provider/catalog.go +++ b/agent/app/provider/catalog.go @@ -199,7 +199,7 @@ var catalog = map[string]Meta{ APIType: "openai-completions", ContextWindow: 256000, MaxTokens: 8192, - Input: []string{"text"}, + Input: []string{"text", "image"}, }, Models: []Model{ {ID: "kimi/kimi-k2.5", Name: "Kimi K2.5", Reasoning: true}, @@ -233,7 +233,7 @@ var catalog = map[string]Meta{ APIType: "openai-completions", ContextWindow: 256000, MaxTokens: 8192, - Input: []string{"text"}, + Input: []string{"text", "image"}, }, Models: []Model{ {ID: "openai/codex-mini-latest", Name: "Codex Mini", Reasoning: true}, @@ -270,7 +270,7 @@ var catalog = map[string]Meta{ APIType: "openai-completions", ContextWindow: 256000, MaxTokens: 8192, - Input: []string{"text"}, + Input: []string{"text", "image"}, }, Models: []Model{ {ID: "anthropic/claude-3-haiku-20240307", Name: "Claude 3 Haiku"}, @@ -290,7 +290,7 @@ var catalog = map[string]Meta{ APIType: "openai-completions", ContextWindow: 256000, MaxTokens: 8192, - Input: []string{"text"}, + Input: []string{"text", "image"}, }, Models: []Model{ {ID: "google/gemini-3-flash-preview", Name: "Gemini 3 Flash Preview", Reasoning: true}, diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index 49db550635dc..194258c455fb 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -53,6 +53,7 @@ type IAgentService interface { UpdateWecomConfig(req dto.AgentWecomConfigUpdateReq) error GetDingTalkConfig(req dto.AgentDingTalkConfigReq) (*dto.AgentDingTalkConfig, error) UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error + LoginWeixinChannel(req dto.AgentWeixinLoginReq) error GetQQBotConfig(req dto.AgentQQBotConfigReq) (*dto.AgentQQBotConfig, error) UpdateQQBotConfig(req dto.AgentQQBotConfigUpdateReq) error InstallPlugin(req dto.AgentPluginInstallReq) error diff --git a/agent/app/service/agents_channels.go b/agent/app/service/agents_channels.go index e11fa8086e0b..a1bc8c3f98b9 100644 --- a/agent/app/service/agents_channels.go +++ b/agent/app/service/agents_channels.go @@ -152,11 +152,11 @@ func (a AgentService) UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) } func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error { - _, install, err := a.loadAgentAndInstall(req.AgentID) + agent, install, err := a.loadAgentAndInstall(req.AgentID) if err != nil { return err } - spec, _, err := resolvePluginMeta(req.Type) + spec, pluginID, err := resolvePluginMeta(req.Type) if err != nil { return err } @@ -166,7 +166,15 @@ 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)) - return mgr.RunBashCf("docker exec %s openclaw plugins install %s", install.ContainerName, spec) + if err := mgr.RunBashCf("docker exec %s openclaw plugins install %s", install.ContainerName, spec); 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 := installTask.Execute(); err != nil { @@ -176,6 +184,27 @@ func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error { return nil } +func (a AgentService) LoginWeixinChannel(req dto.AgentWeixinLoginReq) error { + _, install, err := a.loadAgentAndInstall(req.AgentID) + if err != nil { + return err + } + loginTask, err := task.NewTaskWithOps("weixin", task.TaskExec, task.TaskScopeAI, req.TaskID, req.AgentID) + if err != nil { + return err + } + loginTask.AddSubTask("Login OpenClaw Weixin channel", func(t *task.Task) error { + mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(30*time.Minute)) + return mgr.RunBashCf("docker exec %s openclaw channels login --channel openclaw-weixin", install.ContainerName) + }, nil) + go func() { + if err := loginTask.Execute(); err != nil { + global.LOG.Errorf("login openclaw weixin channel failed: %v", err) + } + }() + return nil +} + func (a AgentService) CheckPlugin(req dto.AgentPluginCheckReq) (*dto.AgentPluginStatus, error) { _, install, err := a.loadAgentAndInstall(req.AgentID) if err != nil { @@ -514,6 +543,31 @@ func setQQBotConfig(conf map[string]interface{}, config dto.AgentQQBotConfig) { qqbotEntry["enabled"] = config.Enabled } +func appendPluginAllow(conf map[string]interface{}, pluginID string) { + plugins := ensureChildMap(conf, "plugins") + allow := make([]string, 0, 4) + seen := map[string]struct{}{} + switch values := plugins["allow"].(type) { + case []interface{}: + for _, value := range values { + text, ok := value.(string) + if !ok || text == "" { + continue + } + if _, ok := seen[text]; ok { + continue + } + seen[text] = struct{}{} + allow = append(allow, text) + } + } + if _, ok := seen[pluginID]; ok { + plugins["allow"] = allow + return + } + plugins["allow"] = append(allow, pluginID) +} + func resolvePluginMeta(pluginType string) (string, string, error) { switch pluginType { case "qqbot": @@ -522,6 +576,8 @@ func resolvePluginMeta(pluginType string) (string, string, error) { return "@wecom/wecom-openclaw-plugin", "wecom-openclaw-plugin", nil case "dingtalk": return "@dingtalk-real-ai/dingtalk-connector", "dingtalk-connector", nil + case "weixin": + return "@tencent-weixin/openclaw-weixin", "openclaw-weixin", nil default: return "", "", fmt.Errorf("unsupported plugin type") } diff --git a/agent/app/service/agents_utils.go b/agent/app/service/agents_utils.go index 080ad90f2fb0..e885dfdfbb0c 100644 --- a/agent/app/service/agents_utils.go +++ b/agent/app/service/agents_utils.go @@ -157,12 +157,6 @@ func extractSecurityConfig(conf map[string]interface{}) dto.AgentSecurityConfig result.AllowedOrigins = append(result.AllowedOrigins, strings.TrimSpace(text)) } } - case []string: - for _, value := range values { - if strings.TrimSpace(value) != "" { - result.AllowedOrigins = append(result.AllowedOrigins, strings.TrimSpace(value)) - } - } } return result } @@ -1359,16 +1353,6 @@ func extractStringList(value interface{}) []string { result = append(result, text) } return result - case []string: - result := make([]string, 0, len(values)) - for _, value := range values { - text := strings.TrimSpace(value) - if text == "" { - continue - } - result = append(result, text) - } - return result default: return []string{} } diff --git a/agent/router/ro_ai.go b/agent/router/ro_ai.go index 9a92f5534d4c..f8be0c19d8e5 100644 --- a/agent/router/ro_ai.go +++ b/agent/router/ro_ai.go @@ -65,6 +65,7 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/agents/channel/wecom/update", baseApi.UpdateAgentWecomConfig) aiToolsRouter.POST("/agents/channel/dingtalk/get", baseApi.GetAgentDingTalkConfig) aiToolsRouter.POST("/agents/channel/dingtalk/update", baseApi.UpdateAgentDingTalkConfig) + aiToolsRouter.POST("/agents/channel/weixin/login", baseApi.LoginAgentWeixinChannel) aiToolsRouter.POST("/agents/channel/qqbot/get", baseApi.GetAgentQQBotConfig) aiToolsRouter.POST("/agents/channel/qqbot/update", baseApi.UpdateAgentQQBotConfig) aiToolsRouter.POST("/agents/plugin/install", baseApi.InstallAgentPlugin) diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index 74a50655ac6d..77867139f0e2 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -499,6 +499,11 @@ export namespace AI { groupAllowFrom: string[]; } + export interface AgentWeixinLoginReq { + agentId: number; + taskID: string; + } + export interface AgentQQBotConfigReq { agentId: number; } @@ -519,13 +524,13 @@ export namespace AI { export interface AgentPluginInstallReq { agentId: number; - type: 'qqbot' | 'wecom' | 'dingtalk'; + type: 'qqbot' | 'wecom' | 'dingtalk' | 'weixin'; taskID: string; } export interface AgentPluginCheckReq { agentId: number; - type: 'qqbot' | 'wecom' | 'dingtalk'; + type: 'qqbot' | 'wecom' | 'dingtalk' | 'weixin'; } export interface AgentPluginStatus { diff --git a/frontend/src/api/modules/ai.ts b/frontend/src/api/modules/ai.ts index 6641dd0317cf..ca510922297f 100644 --- a/frontend/src/api/modules/ai.ts +++ b/frontend/src/api/modules/ai.ts @@ -193,6 +193,10 @@ export const updateAgentDingTalkConfig = (req: AI.AgentDingTalkConfigUpdateReq) return http.post(`/ai/agents/channel/dingtalk/update`, req); }; +export const loginAgentWeixinChannel = (req: AI.AgentWeixinLoginReq) => { + return http.post(`/ai/agents/channel/weixin/login`, req); +}; + export const getAgentQQBotConfig = (req: AI.AgentQQBotConfigReq) => { return http.post(`/ai/agents/channel/qqbot/get`, req); }; diff --git a/frontend/src/components/log/file/index.vue b/frontend/src/components/log/file/index.vue index 2fa44b741367..7e8ecd638d0c 100644 --- a/frontend/src/components/log/file/index.vue +++ b/frontend/src/components/log/file/index.vue @@ -27,13 +27,18 @@ -
+
@@ -146,7 +151,8 @@ const isTailDisabled = ref(); const firstLoading = ref(false); const logs = ref([]); const logContainer = ref(null); -const logHeight = 23; +const isTaskMode = computed(() => props.config.colorMode === 'task'); +const logHeight = computed(() => (isTaskMode.value ? 16 : 23)); const containerHeight = ref(500); const scrollTop = ref(0); const lastScrollTop = ref(0); @@ -155,16 +161,16 @@ const totalPages = ref(0); let resizeObserver: ResizeObserver | null = null; const isEndOfFile = ref(false); -const totalHeight = computed(() => logs.value.length * logHeight); +const totalHeight = computed(() => logs.value.length * logHeight.value); const visibleCount = computed(() => { const buffer = 5; - return Math.ceil(containerHeight.value / logHeight) + buffer * 2; + return Math.ceil(containerHeight.value / logHeight.value) + buffer * 2; }); const startIndex = computed(() => { const buffer = 5; - const index = Math.floor(scrollTop.value / logHeight) - buffer; + const index = Math.floor(scrollTop.value / logHeight.value) - buffer; return Math.max(0, index); }); @@ -177,7 +183,7 @@ const visibleLogs = computed(() => { }); const offsetY = computed(() => { - return startIndex.value * logHeight; + return startIndex.value * logHeight.value; }); const updateContainerHeight = () => { @@ -333,7 +339,7 @@ const getContent = async (pre: boolean) => { if (pre) { if (readReq.page > 1) { const addedLines = newLogs.length; - const newScrollPosition = lastScrollTop.value + addedLines * logHeight; + const newScrollPosition = lastScrollTop.value + addedLines * logHeight.value; logContainer.value.scrollTop = newScrollPosition; } } else { @@ -361,7 +367,7 @@ const getContent = async (pre: boolean) => { } if (logs.value && logs.value.length > 3000) { const removedCount = readReq.pageSize; - const currentScrollRatio = scrollTop.value / (logs.value.length * logHeight); + const currentScrollRatio = scrollTop.value / (logs.value.length * logHeight.value); if (pre) { logs.value.splice(logs.value.length - removedCount, removedCount); @@ -373,8 +379,8 @@ const getContent = async (pre: boolean) => { logs.value.splice(0, removedCount); nextTick(() => { if (logContainer.value) { - const newScrollTop = currentScrollRatio * (logs.value.length * logHeight); - logContainer.value.scrollTop = Math.max(0, newScrollTop - removedCount * logHeight); + const newScrollTop = currentScrollRatio * (logs.value.length * logHeight.value); + logContainer.value.scrollTop = Math.max(0, newScrollTop - removedCount * logHeight.value); } }); if (minPage.value > 1) { @@ -497,6 +503,23 @@ defineExpose({ changeTail, onDownload, clearLog }); white-space: nowrap; } +.log-item.task-mode { + padding: 0 5px; + font-family: 'SFMono-Regular', 'SF Mono', Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + font-size: 14px; + line-height: 16px; + letter-spacing: 0; + font-variant-ligatures: none; +} + +.log-container.task-mode :deep(.token), +.log-container.task-mode :deep(.whitespace-pre) { + font-family: inherit; + line-height: inherit; + letter-spacing: inherit; + font-variant-ligatures: inherit; +} + .log-content { font-size: 14px; line-height: 20px; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 1b235bb83d83..aea596d6210d 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -709,6 +709,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -740,6 +741,8 @@ const message = { 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', }, diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index ddbeb1c6b3cc..f116eeb5e0ae 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -717,6 +717,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -748,6 +749,8 @@ const message = { 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', }, diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 1d1fadb37ca6..927f75b48f8e 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -710,6 +710,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -741,6 +742,8 @@ const message = { 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に保存済み', }, diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index faf21a270046..e6bb27e9f14c 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -702,6 +702,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -733,6 +734,8 @@ const message = { 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에 저장됨', }, diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index c1ca8972581f..536a7d7188fc 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -717,6 +717,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -748,6 +749,8 @@ const message = { 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', }, diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 33b5233fc3c8..2415c6251bb1 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -712,6 +712,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -743,6 +744,8 @@ const message = { 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', }, diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 01de5ace98c9..5339d6d94507 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -709,6 +709,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -740,6 +741,8 @@ const message = { 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', }, diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index bbe1f601c8b6..604a9d26cf03 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -713,6 +713,7 @@ const message = { browserEnabled: 'Browser Enabled', switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', + weixin: 'Weixin', wecom: 'WeCom', dingtalk: 'DingTalk', feishu: 'Feishu', @@ -744,6 +745,8 @@ const message = { 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", }, diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 41f1dbdfbbb9..1d202a402abc 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -677,6 +677,7 @@ const message = { browserEnabled: '瀏覽器開關', switchModelSuccess: '模型切換成功', channelsTab: '頻道', + weixin: '微信', wecom: '企業微信', dingtalk: '釘釘', feishu: '飛書', @@ -708,6 +709,8 @@ const message = { saveSuccess: '保存成功', pairingCodeRequired: '請輸入配對碼', pairingApproveSuccess: '配對成功', + scanConnect: '掃碼對接', + scanConnectHelper: '點擊後將在任務日誌中顯示 QR Code,掃碼確認後即可完成登入', customProviderHelper: '自訂模型供應商不驗證帳號是否可用', feishuSaveSuccess: '儲存成功', }, diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 1125086779d7..3bb1aba4820a 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -676,6 +676,7 @@ const message = { browserEnabled: '浏览器开关', switchModelSuccess: '模型切换成功', channelsTab: '频道', + weixin: '微信', wecom: '企业微信', dingtalk: '钉钉', feishu: '飞书', @@ -707,6 +708,8 @@ const message = { feishuSaveSuccess: '保存成功', pairingCodeRequired: '请输入配对码', pairingApproveSuccess: '配对成功', + scanConnect: '扫码对接', + scanConnectHelper: '点击后将在任务日志中显示二维码,扫码确认后即可完成登录', customProviderHelper: '自定义模型供应商不验证账号是否可用', }, model: { diff --git a/frontend/src/views/ai/agents/agent/add/index.vue b/frontend/src/views/ai/agents/agent/add/index.vue index 968aa0cdf4c8..5d8e781755ea 100644 --- a/frontend/src/views/ai/agents/agent/add/index.vue +++ b/frontend/src/views/ai/agents/agent/add/index.vue @@ -166,7 +166,7 @@ const setDefaultWebUIPort = () => { }; const rules = reactive({ - name: [Rules.requiredInput], + name: [Rules.appName], agentType: [Rules.requiredSelect], appVersion: [Rules.requiredSelect], webUIPort: [Rules.requiredInput], diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels.vue index 9d8be6baf5fa..ccf2e219a9e2 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels.vue @@ -3,6 +3,9 @@ + + + @@ -28,6 +31,7 @@ import FeishuTab from './channels/feishu.vue'; import TelegramTab from './channels/telegram.vue'; import DiscordTab from './channels/discord.vue'; import QQBotTab from './channels/qq.vue'; +import WeixinTab from './channels/weixin.vue'; import WecomTab from './channels/wecom.vue'; import DingTalkTab from './channels/dingtalk.vue'; @@ -38,6 +42,7 @@ const feishuRef = ref(); const telegramRef = ref(); const discordRef = ref(); const qqbotRef = ref(); +const weixinRef = ref(); const wecomRef = ref(); const dingtalkRef = ref(); @@ -58,6 +63,10 @@ const loadCurrentTab = async () => { await wecomRef.value?.load(agentId.value); return; } + if (activeTab.value === 'weixin') { + await weixinRef.value?.load(agentId.value); + return; + } if (activeTab.value === 'dingtalk') { await dingtalkRef.value?.load(agentId.value); return; 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 new file mode 100644 index 000000000000..89b6fc217d79 --- /dev/null +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/plugin-install.vue @@ -0,0 +1,23 @@ + + + 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 df4152440820..21ae4c8c4103 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,17 +1,6 @@