Skip to content

Commit 93e4a6a

Browse files
feat: change hermes channel logic
1 parent cc0ac8c commit 93e4a6a

39 files changed

Lines changed: 730 additions & 91 deletions

File tree

agent/app/api/v2/agents.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,27 @@ func (b *BaseApi) UpdateAgentDingTalkConfig(c *gin.Context) {
864864
helper.Success(c)
865865
}
866866

867+
// @Tags AI
868+
// @Summary Get Agent Weixin channel config
869+
// @Accept json
870+
// @Param request body dto.AgentIDReq true "request"
871+
// @Success 200 {object} dto.AgentWeixinConfig
872+
// @Security ApiKeyAuth
873+
// @Security Timestamp
874+
// @Router /ai/agents/channel/weixin/get [post]
875+
func (b *BaseApi) GetAgentWeixinConfig(c *gin.Context) {
876+
var req dto.AgentIDReq
877+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
878+
return
879+
}
880+
data, err := agentService.GetWeixinConfig(req)
881+
if err != nil {
882+
helper.BadRequest(c, err)
883+
return
884+
}
885+
helper.SuccessWithData(c, data)
886+
}
887+
867888
// @Tags AI
868889
// @Summary Get Agent QQ Bot channel config
869890
// @Accept json
@@ -905,6 +926,26 @@ func (b *BaseApi) UpdateAgentQQBotConfig(c *gin.Context) {
905926
helper.Success(c)
906927
}
907928

929+
// @Tags AI
930+
// @Summary Delete Agent channel config
931+
// @Accept json
932+
// @Param request body dto.AgentChannelDeleteReq true "request"
933+
// @Success 200
934+
// @Security ApiKeyAuth
935+
// @Security Timestamp
936+
// @Router /ai/agents/channel/delete [post]
937+
func (b *BaseApi) DeleteAgentChannelConfig(c *gin.Context) {
938+
var req dto.AgentChannelDeleteReq
939+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
940+
return
941+
}
942+
if err := agentService.DeleteChannelConfig(req); err != nil {
943+
helper.BadRequest(c, err)
944+
return
945+
}
946+
helper.Success(c)
947+
}
948+
908949
// @Tags AI
909950
// @Summary Install Agent plugin
910951
// @Accept json

agent/app/dto/agents.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,16 @@ type AgentTelegramConfig struct {
376376

377377
type AgentChannelPairingApproveReq struct {
378378
AgentID uint `json:"agentId" validate:"required"`
379-
Type string `json:"type" validate:"required,oneof=feishu telegram discord wecom qqbot"`
379+
Type string `json:"type" validate:"required,oneof=feishu telegram discord wecom qqbot dingtalk"`
380380
PairingCode string `json:"pairingCode" validate:"required"`
381381
AccountID string `json:"accountId"`
382382
}
383383

384+
type AgentChannelDeleteReq struct {
385+
AgentID uint `json:"agentId" validate:"required"`
386+
Type string `json:"type" validate:"required,oneof=feishu telegram discord wecom qqbot dingtalk weixin"`
387+
}
388+
384389
type AgentWecomConfigUpdateReq struct {
385390
AgentID uint `json:"agentId" validate:"required"`
386391
Enabled bool `json:"enabled"`
@@ -406,7 +411,7 @@ type AgentWecomConfig struct {
406411
type AgentDingTalkConfigUpdateReq struct {
407412
AgentID uint `json:"agentId" validate:"required"`
408413
Enabled bool `json:"enabled"`
409-
DmPolicy string `json:"dmPolicy" validate:"required,oneof=allowlist open disabled"`
414+
DmPolicy string `json:"dmPolicy" validate:"required,oneof=pairing allowlist open disabled"`
410415
AllowFrom []string `json:"allowFrom"`
411416
GroupPolicy string `json:"groupPolicy" validate:"required,oneof=open allowlist disabled"`
412417
GroupAllowFrom []string `json:"groupAllowFrom"`
@@ -438,6 +443,10 @@ type AgentWeixinLoginReq struct {
438443
TaskID string `json:"taskID" validate:"required"`
439444
}
440445

446+
type AgentWeixinConfig struct {
447+
Enabled bool `json:"enabled"`
448+
}
449+
441450
type AgentQQBotConfigUpdateReq struct {
442451
AgentID uint `json:"agentId" validate:"required"`
443452
Enabled bool `json:"enabled"`

agent/app/service/agents.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ type IAgentService interface {
8686
UpdateWecomConfig(req dto.AgentWecomConfigUpdateReq) error
8787
GetDingTalkConfig(req dto.AgentIDReq) (*dto.AgentDingTalkConfig, error)
8888
UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error
89+
GetWeixinConfig(req dto.AgentIDReq) (*dto.AgentWeixinConfig, error)
8990
LoginWeixinChannel(req dto.AgentWeixinLoginReq) error
9091
GetQQBotConfig(req dto.AgentIDReq) (*dto.AgentQQBotConfig, error)
9192
UpdateQQBotConfig(req dto.AgentQQBotConfigUpdateReq) error
93+
DeleteChannelConfig(req dto.AgentChannelDeleteReq) error
9294
InstallPlugin(req dto.AgentPluginInstallReq) error
9395
UpgradePlugin(req dto.AgentPluginUpgradeReq) error
9496
UninstallPlugin(req dto.AgentPluginUninstallReq) error

agent/app/service/agents_channels.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,17 @@ func (a AgentService) GetDingTalkConfig(req dto.AgentIDReq) (*dto.AgentDingTalkC
306306
return &result, nil
307307
}
308308

309+
func (a AgentService) GetWeixinConfig(req dto.AgentIDReq) (*dto.AgentWeixinConfig, error) {
310+
agent, _, err := a.loadAgentAndInstall(req.AgentID)
311+
if err != nil {
312+
return nil, err
313+
}
314+
if agent.AgentType == constant.AppHermesAgent {
315+
return readHermesWeixinChannelConfig(path.Dir(agent.ConfigPath))
316+
}
317+
return nil, fmt.Errorf("%s does not support", agent.AgentType)
318+
}
319+
309320
func (a AgentService) UpdateDingTalkConfig(req dto.AgentDingTalkConfigUpdateReq) error {
310321
agent, install, err := a.loadAgentAndInstall(req.AgentID)
311322
if err != nil {
@@ -495,6 +506,36 @@ func (a AgentService) LoginWeixinChannel(req dto.AgentWeixinLoginReq) error {
495506
return nil
496507
}
497508

509+
func (a AgentService) DeleteChannelConfig(req dto.AgentChannelDeleteReq) error {
510+
agent, install, err := a.loadAgentAndInstall(req.AgentID)
511+
if err != nil {
512+
return err
513+
}
514+
if agent.AgentType != constant.AppHermesAgent {
515+
return fmt.Errorf("%s does not support", agent.AgentType)
516+
}
517+
return updateHermesChannelConfig(agent, install, func(confDir string) error {
518+
switch req.Type {
519+
case "telegram":
520+
return deleteHermesTelegramChannelConfig(confDir)
521+
case "discord":
522+
return deleteHermesDiscordChannelConfig(confDir)
523+
case "qqbot":
524+
return deleteHermesQQBotChannelConfig(confDir)
525+
case "wecom":
526+
return deleteHermesWecomChannelConfig(confDir)
527+
case "dingtalk":
528+
return deleteHermesDingTalkChannelConfig(confDir)
529+
case "feishu":
530+
return deleteHermesFeishuChannelConfig(confDir)
531+
case "weixin":
532+
return deleteHermesWeixinChannelConfig(confDir)
533+
default:
534+
return fmt.Errorf("unsupported channel type: %s", req.Type)
535+
}
536+
})
537+
}
538+
498539
func (a AgentService) CheckPlugin(req dto.AgentPluginCheckReq) (*dto.AgentPluginStatus, error) {
499540
_, install, err := a.loadAgentAndInstall(req.AgentID)
500541
if err != nil {
@@ -535,14 +576,12 @@ func (a AgentService) ApproveChannelPairing(req dto.AgentChannelPairingApproveRe
535576
return err
536577
}
537578
if agent.AgentType == constant.AppHermesAgent {
538-
output, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout(
579+
mgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
580+
output, err := mgr.RunWithStdout(
539581
"docker",
540582
buildHermesDockerExecArgs(install.ContainerName, "pairing", "approve", req.Type, req.PairingCode)...,
541583
)
542-
if err != nil {
543-
return err
544-
}
545-
return validateHermesPairingApproveOutput(output)
584+
return validateHermesPairingApproveResult(output, err)
546585
}
547586
if req.AccountID != "" {
548587
return cmd.RunDefaultBashCf(

agent/app/service/agents_hermes.go

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,64 @@ func writeHermesDiscordChannelConfig(confDir string, config dto.AgentDiscordConf
326326
return writeHermesConfigMap(configPath, cfg)
327327
}
328328

329+
func deleteHermesEnvKeys(confDir string, keys ...string) error {
330+
envPath := path.Join(confDir, ".env")
331+
envMap, err := readHermesEnvMap(envPath)
332+
if err != nil {
333+
return err
334+
}
335+
for _, key := range keys {
336+
delete(envMap, key)
337+
}
338+
return writeHermesEnvMap(envPath, envMap, keys)
339+
}
340+
341+
func deleteHermesConfigSections(confDir string, topLevelKeys []string, platformKeys []string) error {
342+
configPath := path.Join(confDir, "config.yaml")
343+
cfg, err := readHermesConfigMap(configPath)
344+
if err != nil {
345+
return err
346+
}
347+
for _, key := range topLevelKeys {
348+
delete(cfg, key)
349+
}
350+
if len(platformKeys) > 0 {
351+
if platforms, ok := cfg["platforms"].(map[string]interface{}); ok {
352+
for _, key := range platformKeys {
353+
delete(platforms, key)
354+
}
355+
if len(platforms) == 0 {
356+
delete(cfg, "platforms")
357+
}
358+
}
359+
}
360+
return writeHermesConfigMap(configPath, cfg)
361+
}
362+
363+
func deleteHermesTelegramChannelConfig(confDir string) error {
364+
if err := deleteHermesEnvKeys(confDir,
365+
"TELEGRAM_BOT_TOKEN",
366+
"TELEGRAM_ALLOWED_USERS",
367+
"TELEGRAM_ALLOW_ALL_USERS",
368+
"TELEGRAM_HOME_CHANNEL",
369+
); err != nil {
370+
return err
371+
}
372+
return deleteHermesConfigSections(confDir, []string{"telegram"}, []string{"telegram"})
373+
}
374+
375+
func deleteHermesDiscordChannelConfig(confDir string) error {
376+
if err := deleteHermesEnvKeys(confDir,
377+
"DISCORD_BOT_TOKEN",
378+
"DISCORD_ALLOWED_USERS",
379+
"DISCORD_ALLOW_ALL_USERS",
380+
"DISCORD_HOME_CHANNEL",
381+
); err != nil {
382+
return err
383+
}
384+
return deleteHermesConfigSections(confDir, []string{"discord"}, []string{"discord"})
385+
}
386+
329387
func normalizeHermesTimezone(timezone string) string {
330388
timezone = strings.TrimSpace(timezone)
331389
if timezone == "" {
@@ -566,13 +624,21 @@ func extractHermesEnvBool(envMap map[string]string, key string, defaultValue boo
566624
return strings.EqualFold(value, "true")
567625
}
568626

569-
func validateHermesPairingApproveOutput(output string) error {
570-
text := strings.TrimSpace(output)
571-
if text == "" {
627+
func validateHermesPairingApproveResult(output string, err error) error {
628+
if strings.Contains(output, "Approved!") {
572629
return nil
573630
}
574-
if strings.Contains(text, "not found or expired for platform") {
575-
return errors.New(text)
631+
if strings.Contains(output, "not found or expired for platform") {
632+
return buserr.New("ErrHermesPairingCodeUnavailable")
633+
}
634+
if err == nil {
635+
if strings.TrimSpace(output) == "" {
636+
return fmt.Errorf("unexpected hermes pairing approve result")
637+
}
638+
return errors.New(strings.TrimSpace(output))
639+
}
640+
if strings.Contains(err.Error(), "not found or expired for platform") {
641+
return buserr.New("ErrHermesPairingCodeUnavailable")
576642
}
577-
return nil
643+
return err
578644
}

0 commit comments

Comments
 (0)