diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index c1c40840c71a..7eb90c6cf05f 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -475,6 +475,47 @@ func (b *BaseApi) UpdateAgentWecomConfig(c *gin.Context) { helper.Success(c) } +// @Tags AI +// @Summary Get Agent DingTalk channel config +// @Accept json +// @Param request body dto.AgentDingTalkConfigReq true "request" +// @Success 200 {object} dto.AgentDingTalkConfig +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/channel/dingtalk/get [post] +func (b *BaseApi) GetAgentDingTalkConfig(c *gin.Context) { + var req dto.AgentDingTalkConfigReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + data, err := agentService.GetDingTalkConfig(req) + if err != nil { + helper.BadRequest(c, err) + return + } + helper.SuccessWithData(c, data) +} + +// @Tags AI +// @Summary Update Agent DingTalk channel config +// @Accept json +// @Param request body dto.AgentDingTalkConfigUpdateReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /ai/agents/channel/dingtalk/update [post] +func (b *BaseApi) UpdateAgentDingTalkConfig(c *gin.Context) { + var req dto.AgentDingTalkConfigUpdateReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := agentService.UpdateDingTalkConfig(req); err != nil { + helper.BadRequest(c, err) + return + } + helper.Success(c) +} + // @Tags AI // @Summary Get Agent QQ Bot channel config // @Accept json diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go index fb60daeccc0a..f693b76cc293 100644 --- a/agent/app/dto/agents.go +++ b/agent/app/dto/agents.go @@ -215,7 +215,7 @@ type AgentTelegramConfig struct { type AgentChannelPairingApproveReq struct { AgentID uint `json:"agentId" validate:"required"` - Type string `json:"type" validate:"required,oneof=feishu telegram discord wecom"` + Type string `json:"type" validate:"required,oneof=feishu telegram discord wecom dingtalk-connector"` PairingCode string `json:"pairingCode" validate:"required"` } @@ -239,6 +239,32 @@ type AgentWecomConfig struct { Installed bool `json:"installed"` } +type AgentDingTalkConfigReq struct { + AgentID uint `json:"agentId" validate:"required"` +} + +type AgentDingTalkConfigUpdateReq struct { + AgentID uint `json:"agentId" validate:"required"` + Enabled bool `json:"enabled"` + ClientID string `json:"clientId" validate:"required"` + ClientSecret string `json:"clientSecret" validate:"required"` + DmPolicy string `json:"dmPolicy" validate:"required,oneof=pairing allowlist open disabled"` + AllowFrom []string `json:"allowFrom"` + GroupPolicy string `json:"groupPolicy" validate:"required,oneof=open allowlist disabled"` + GroupAllowFrom []string `json:"groupAllowFrom"` +} + +type AgentDingTalkConfig struct { + Enabled bool `json:"enabled"` + ClientID string `json:"clientId"` + ClientSecret string `json:"clientSecret"` + DmPolicy string `json:"dmPolicy"` + AllowFrom []string `json:"allowFrom"` + GroupPolicy string `json:"groupPolicy"` + GroupAllowFrom []string `json:"groupAllowFrom"` + Installed bool `json:"installed"` +} + type AgentQQBotConfigReq struct { AgentID uint `json:"agentId" validate:"required"` } @@ -259,13 +285,13 @@ type AgentQQBotConfig struct { type AgentPluginInstallReq struct { AgentID uint `json:"agentId" validate:"required"` - Type string `json:"type" validate:"required,oneof=qqbot wecom"` + Type string `json:"type" validate:"required,oneof=qqbot wecom dingtalk"` TaskID string `json:"taskID" validate:"required"` } type AgentPluginCheckReq struct { AgentID uint `json:"agentId" validate:"required"` - Type string `json:"type" validate:"required,oneof=qqbot wecom"` + Type string `json:"type" validate:"required,oneof=qqbot wecom dingtalk"` } type AgentPluginStatus struct { diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index 12391dd6d22a..b913fbed74aa 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -47,6 +47,8 @@ type IAgentService interface { UpdateDiscordConfig(req dto.AgentDiscordConfigUpdateReq) error GetWecomConfig(req dto.AgentWecomConfigReq) (*dto.AgentWecomConfig, error) UpdateWecomConfig(req dto.AgentWecomConfigUpdateReq) error + GetDingTalkConfig(req dto.AgentDingTalkConfigReq) (*dto.AgentDingTalkConfig, error) + UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error GetQQBotConfig(req dto.AgentQQBotConfigReq) (*dto.AgentQQBotConfig, error) UpdateQQBotConfig(req dto.AgentQQBotConfigUpdateReq) error InstallPlugin(req dto.AgentPluginInstallReq) error @@ -729,6 +731,32 @@ func (a AgentService) UpdateWecomConfig(req dto.AgentWecomConfigUpdateReq) error }) } +func (a AgentService) GetDingTalkConfig(req dto.AgentDingTalkConfigReq) (*dto.AgentDingTalkConfig, error) { + _, install, conf, err := a.loadAgentConfig(req.AgentID) + if err != nil { + return nil, err + } + result := extractDingTalkConfig(conf) + installed, _ := checkPluginInstalled(install.ContainerName, "dingtalk") + result.Installed = installed + return &result, nil +} + +func (a AgentService) UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error { + return a.mutateAgentConfig(req.AgentID, func(_ *model.Agent, _ *model.AppInstall, conf map[string]interface{}) error { + setDingTalkConfig(conf, dto.AgentDingTalkConfig{ + Enabled: req.Enabled, + ClientID: req.ClientID, + ClientSecret: req.ClientSecret, + DmPolicy: req.DmPolicy, + AllowFrom: req.AllowFrom, + GroupPolicy: req.GroupPolicy, + GroupAllowFrom: req.GroupAllowFrom, + }) + return nil + }) +} + func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error { _, install, err := a.loadAgentAndInstall(req.AgentID) if err != nil { diff --git a/agent/app/service/agents_utils.go b/agent/app/service/agents_utils.go index b234164e950b..daf0595080e5 100644 --- a/agent/app/service/agents_utils.go +++ b/agent/app/service/agents_utils.go @@ -544,6 +544,42 @@ func extractWecomConfig(conf map[string]interface{}) dto.AgentWecomConfig { return result } +func extractDingTalkConfig(conf map[string]interface{}) dto.AgentDingTalkConfig { + result := dto.AgentDingTalkConfig{ + Enabled: true, + DmPolicy: "pairing", + GroupPolicy: "disabled", + AllowFrom: []string{}, + GroupAllowFrom: []string{}, + } + channels, ok := conf["channels"].(map[string]interface{}) + if !ok { + return result + } + dingtalk, ok := channels["dingtalk-connector"].(map[string]interface{}) + if !ok { + return result + } + if enabled, ok := dingtalk["enabled"].(bool); ok { + result.Enabled = enabled + } + if clientID, ok := dingtalk["clientId"].(string); ok { + result.ClientID = clientID + } + if clientSecret, ok := dingtalk["clientSecret"].(string); ok { + result.ClientSecret = clientSecret + } + if dmPolicy, ok := dingtalk["dmPolicy"].(string); ok && strings.TrimSpace(dmPolicy) != "" { + result.DmPolicy = dmPolicy + } + if groupPolicy, ok := dingtalk["groupPolicy"].(string); ok && strings.TrimSpace(groupPolicy) != "" { + result.GroupPolicy = groupPolicy + } + result.AllowFrom = extractStringList(dingtalk["allowFrom"]) + result.GroupAllowFrom = extractStringList(dingtalk["groupAllowFrom"]) + return result +} + func setWecomConfig(conf map[string]interface{}, config dto.AgentWecomConfig) { channels := ensureChildMap(conf, "channels") wecom := ensureChildMap(channels, "wecom") @@ -563,6 +599,44 @@ func setWecomConfig(conf map[string]interface{}, config dto.AgentWecomConfig) { wecomEntry["enabled"] = config.Enabled } +func setDingTalkConfig(conf map[string]interface{}, config dto.AgentDingTalkConfig) { + channels := ensureChildMap(conf, "channels") + dingtalk := ensureChildMap(channels, "dingtalk-connector") + dingtalk["enabled"] = config.Enabled + dingtalk["clientId"] = strings.TrimSpace(config.ClientID) + dingtalk["clientSecret"] = strings.TrimSpace(config.ClientSecret) + dingtalk["dmPolicy"] = config.DmPolicy + dingtalk["groupPolicy"] = config.GroupPolicy + dingtalk["gatewayToken"] = extractGatewayToken(conf) + switch config.DmPolicy { + case "open": + dingtalk["allowFrom"] = []string{"*"} + case "allowlist": + dingtalk["allowFrom"] = append([]string(nil), config.AllowFrom...) + default: + delete(dingtalk, "allowFrom") + } + switch config.GroupPolicy { + case "open": + dingtalk["groupAllowFrom"] = []string{"*"} + case "allowlist": + dingtalk["groupAllowFrom"] = append([]string(nil), config.GroupAllowFrom...) + default: + delete(dingtalk, "groupAllowFrom") + } + + plugins := ensureChildMap(conf, "plugins") + entries := ensureChildMap(plugins, "entries") + dingtalkEntry := ensureChildMap(entries, "dingtalk-connector") + dingtalkEntry["enabled"] = config.Enabled + + gateway := ensureChildMap(conf, "gateway") + httpMap := ensureChildMap(gateway, "http") + endpoints := ensureChildMap(httpMap, "endpoints") + chatCompletions := ensureChildMap(endpoints, "chatCompletions") + chatCompletions["enabled"] = true +} + func setQQBotConfig(conf map[string]interface{}, config dto.AgentQQBotConfig) { channels := ensureChildMap(conf, "channels") qqbot := ensureChildMap(channels, "qqbot") @@ -583,6 +657,8 @@ func resolvePluginMeta(pluginType string) (string, string, error) { return "@sliverp/qqbot@latest", "qqbot", nil case "wecom": return "@wecom/wecom-openclaw-plugin", "wecom-openclaw-plugin", nil + case "dingtalk": + return "@dingtalk-real-ai/dingtalk-connector", "dingtalk-connector", nil default: return "", "", fmt.Errorf("unsupported plugin type") } @@ -1717,6 +1793,46 @@ func resolveServerTimezone() string { return timezone } +func extractStringList(value interface{}) []string { + switch values := value.(type) { + case []interface{}: + result := make([]string, 0, len(values)) + for _, value := range values { + text := strings.TrimSpace(fmt.Sprintf("%v", value)) + if text == "" { + continue + } + 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{} + } +} + +func extractGatewayToken(conf map[string]interface{}) string { + gateway, ok := conf["gateway"].(map[string]interface{}) + if !ok { + return "" + } + auth, ok := gateway["auth"].(map[string]interface{}) + if !ok { + return "" + } + token, _ := auth["token"].(string) + return token +} + func ensureChildMap(parent map[string]interface{}, key string) map[string]interface{} { if child, ok := parent[key].(map[string]interface{}); ok { return child diff --git a/agent/router/ro_ai.go b/agent/router/ro_ai.go index 097d1301fcd2..9a92f5534d4c 100644 --- a/agent/router/ro_ai.go +++ b/agent/router/ro_ai.go @@ -63,6 +63,8 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) { aiToolsRouter.POST("/agents/channel/discord/update", baseApi.UpdateAgentDiscordConfig) aiToolsRouter.POST("/agents/channel/wecom/get", baseApi.GetAgentWecomConfig) 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/qqbot/get", baseApi.GetAgentQQBotConfig) aiToolsRouter.POST("/agents/channel/qqbot/update", baseApi.UpdateAgentQQBotConfig) aiToolsRouter.POST("/agents/plugin/install", baseApi.InstallAgentPlugin) diff --git a/agent/utils/terminal/ai/config_runtime.go b/agent/utils/terminal/ai/config_runtime.go index eb425a66d7aa..889433d0a12b 100644 --- a/agent/utils/terminal/ai/config_runtime.go +++ b/agent/utils/terminal/ai/config_runtime.go @@ -17,6 +17,7 @@ import ( ) var agentAccountRepo = repo.NewIAgentAccountRepo() +var agentAccountModelRepo = repo.NewIAgentAccountModelRepo() type TerminalRuntimeSettings struct { AccountID uint @@ -48,9 +49,9 @@ func ResolveGeneratorConfig(accountID uint) (GeneratorConfig, time.Duration, err if provider == "" { return GeneratorConfig{}, 0, fmt.Errorf("agent account provider is required") } - model := strings.TrimSpace(account.Model) - if model == "" { - model = defaultModelForProvider(provider) + model, maxTokens, err := resolveAccountModelConfig(account.ID, provider) + if err != nil { + return GeneratorConfig{}, 0, err } baseURL := strings.TrimSpace(account.BaseURL) if baseURL == "" { @@ -71,7 +72,7 @@ func ResolveGeneratorConfig(accountID uint) (GeneratorConfig, time.Duration, err APIKey: strings.TrimSpace(apiKey), Model: model, APIType: strings.TrimSpace(account.APIType), - MaxTokens: account.MaxTokens, + MaxTokens: maxTokens, }, 30 * time.Second, nil } @@ -83,12 +84,26 @@ func lookupProviderAPIKey(provider string) string { return strings.TrimSpace(os.Getenv(envKey)) } -func defaultModelForProvider(provider string) string { +func defaultModelForProvider(provider string) (string, int) { meta, ok := providercatalog.Get(provider) if !ok || len(meta.Models) == 0 { - return "" + return "", 0 + } + return meta.Models[0].ID, meta.Models[0].MaxTokens +} + +func resolveAccountModelConfig(accountID uint, provider string) (string, int, error) { + if accountID > 0 { + rows, err := agentAccountModelRepo.List(repo.WithByAccountID(accountID), repo.WithOrderAsc("sort_order"), repo.WithOrderAsc("id")) + if err != nil { + return "", 0, err + } + if len(rows) > 0 { + return strings.TrimSpace(rows[0].Model), rows[0].MaxTokens, nil + } } - return meta.Models[0].ID + model, maxTokens := defaultModelForProvider(provider) + return model, maxTokens, nil } func ResolveGeneratorConfigFromAgentSettings() (GeneratorConfig, uint, time.Duration, error) { diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts index d2f0d606b934..74a50655ac6d 100644 --- a/frontend/src/api/interface/ai.ts +++ b/frontend/src/api/interface/ai.ts @@ -449,7 +449,7 @@ export namespace AI { export interface AgentChannelPairingApproveReq { agentId: number; - type: 'feishu' | 'telegram' | 'discord' | 'wecom'; + type: 'feishu' | 'telegram' | 'discord' | 'wecom' | 'dingtalk-connector'; pairingCode: string; } @@ -473,6 +473,32 @@ export namespace AI { secret: string; } + export interface AgentDingTalkConfigReq { + agentId: number; + } + + export interface AgentDingTalkConfig { + enabled: boolean; + clientId: string; + clientSecret: string; + dmPolicy: 'pairing' | 'allowlist' | 'open' | 'disabled'; + allowFrom: string[]; + groupPolicy: 'open' | 'allowlist' | 'disabled'; + groupAllowFrom: string[]; + installed: boolean; + } + + export interface AgentDingTalkConfigUpdateReq { + agentId: number; + enabled: boolean; + clientId: string; + clientSecret: string; + dmPolicy: 'pairing' | 'allowlist' | 'open' | 'disabled'; + allowFrom: string[]; + groupPolicy: 'open' | 'allowlist' | 'disabled'; + groupAllowFrom: string[]; + } + export interface AgentQQBotConfigReq { agentId: number; } @@ -493,13 +519,13 @@ export namespace AI { export interface AgentPluginInstallReq { agentId: number; - type: 'qqbot' | 'wecom'; + type: 'qqbot' | 'wecom' | 'dingtalk'; taskID: string; } export interface AgentPluginCheckReq { agentId: number; - type: 'qqbot' | 'wecom'; + type: 'qqbot' | 'wecom' | 'dingtalk'; } export interface AgentPluginStatus { diff --git a/frontend/src/api/modules/ai.ts b/frontend/src/api/modules/ai.ts index d5cb46ff7dd1..6641dd0317cf 100644 --- a/frontend/src/api/modules/ai.ts +++ b/frontend/src/api/modules/ai.ts @@ -185,6 +185,14 @@ export const updateAgentWecomConfig = (req: AI.AgentWecomConfigUpdateReq) => { return http.post(`/ai/agents/channel/wecom/update`, req); }; +export const getAgentDingTalkConfig = (req: AI.AgentDingTalkConfigReq) => { + return http.post(`/ai/agents/channel/dingtalk/get`, req); +}; + +export const updateAgentDingTalkConfig = (req: AI.AgentDingTalkConfigUpdateReq) => { + return http.post(`/ai/agents/channel/dingtalk/update`, req); +}; + export const getAgentQQBotConfig = (req: AI.AgentQQBotConfigReq) => { return http.post(`/ai/agents/channel/qqbot/get`, req); }; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 6d464197e69e..602ba634cba2 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -710,17 +710,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index bb381a49efe1..4b530d96bec3 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -718,17 +718,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 9b4ebec2a027..a4279832a900 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -711,17 +711,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 2f259c72c9f5..d9bc3cf78081 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -703,17 +703,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index fe1d73737852..8d54489f6c33 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -718,17 +718,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index c548dbd6cf78..3162edddc6d0 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -713,17 +713,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 1287edacaafc..9a889ef90332 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -710,17 +710,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index b27f75f0f4a7..3e132dde6329 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -714,17 +714,28 @@ const message = { switchModelSuccess: 'Model switched successfully', channelsTab: 'Channels', wecom: 'WeCom', + dingtalk: 'DingTalk', feishu: 'Feishu', 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', + 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', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 8838e7f24405..7f5b8af5ddc7 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -677,17 +677,28 @@ const message = { switchModelSuccess: '模型切換成功', channelsTab: '頻道', wecom: '企業微信', + dingtalk: '釘釘', feishu: '飛書', 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: '一行一個發送方識別碼', + groupAllowFrom: '群組白名單', + groupAllowFromHelper: '一行一個群組識別碼,僅在群組策略為白名單時生效', + groupAllowFromPlaceholder: '一行一個群組識別碼', + allowFromRequired: '請至少填寫一個白名單項', saveAndRestartGateway: '保存並重新啟動網關', pairingCode: '配對碼', pairingCodePlaceholder: '請輸入配對碼', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 4e8d771b14da..acd0cedcdf04 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -676,17 +676,28 @@ const message = { switchModelSuccess: '模型切换成功', channelsTab: '频道', wecom: '企业微信', + dingtalk: '钉钉', feishu: '飞书', 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: '一行一个发送方标识', + groupAllowFrom: '群组白名单', + groupAllowFromHelper: '一行一个群组标识,仅在群组策略为白名单时生效', + groupAllowFromPlaceholder: '一行一个群组标识', + allowFromRequired: '请至少填写一个白名单项', pairingCode: '配对码', pairingCodePlaceholder: '请输入配对码', approvePairing: '批准配对', 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 90e1dfbc25d2..9d8be6baf5fa 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels.vue @@ -6,6 +6,9 @@ + + + @@ -26,6 +29,7 @@ import TelegramTab from './channels/telegram.vue'; import DiscordTab from './channels/discord.vue'; import QQBotTab from './channels/qq.vue'; import WecomTab from './channels/wecom.vue'; +import DingTalkTab from './channels/dingtalk.vue'; const { t } = useI18n(); const activeTab = ref('qqbot'); @@ -35,6 +39,7 @@ const telegramRef = ref(); const discordRef = ref(); const qqbotRef = ref(); const wecomRef = ref(); +const dingtalkRef = ref(); const loadCurrentTab = async () => { if (agentId.value <= 0) { @@ -53,6 +58,10 @@ const loadCurrentTab = async () => { await wecomRef.value?.load(agentId.value); return; } + if (activeTab.value === 'dingtalk') { + await dingtalkRef.value?.load(agentId.value); + return; + } if (activeTab.value === 'qqbot') { await qqbotRef.value?.load(agentId.value); return; 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 new file mode 100644 index 000000000000..df4152440820 --- /dev/null +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/dingtalk.vue @@ -0,0 +1,266 @@ + + + + + diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/qq.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/qq.vue index 864093230989..51e2a89827b0 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/qq.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/qq.vue @@ -22,7 +22,7 @@ - + {{ t('commons.button.save') }} diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/wecom.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/wecom.vue index a49270a04aaf..5cd391aafe38 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/wecom.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/wecom.vue @@ -28,7 +28,7 @@ - + {{ t('commons.button.save') }} @@ -39,7 +39,7 @@ - + {{ t('aiTools.agents.approvePairing') }}