Files
xinmi/internal/application/service/agent_execution.go
T

78 lines
2.7 KiB
Go
Raw Normal View History

package service
import (
"context"
"errors"
"github.com/Tencent/WeKnora/internal/accesspolicy"
apperrors "github.com/Tencent/WeKnora/internal/errors"
"github.com/Tencent/WeKnora/internal/types"
)
// PrepareAgentExecutionContext delegates only live bindings owned by the
// authorized Agent's creator. The caller's publication snapshot stays intact.
func (s *customAgentService) PrepareAgentExecutionContext(ctx context.Context, id string) (context.Context, error) {
prepared, err := s.prepareAgentExecution(ctx, id, map[string]bool{}, map[string]bool{})
if errors.Is(err, ErrAgentNotFound) {
return ctx, apperrors.NewNotFoundError("Agent 已删除或无权使用")
}
if err != nil {
return ctx, err
}
return prepared, nil
}
func (s *customAgentService) prepareAgentExecution(ctx context.Context, id string, visiting, visited map[string]bool) (context.Context, error) {
if visiting[id] {
return ctx, apperrors.NewBadRequestError("Agent 依赖存在循环或层级过多,请调整融合配置")
}
if visited[id] {
return ctx, nil
}
if len(visited) >= 64 {
return ctx, apperrors.NewBadRequestError("Agent 依赖存在循环或层级过多,请调整融合配置")
}
agent, err := s.GetAgentByID(ctx, id)
if err != nil {
return ctx, err
}
if agent == nil || !agent.Enabled || !accesspolicy.Allowed(ctx, "agents.read") {
return ctx, apperrors.NewForbiddenError("Agent 已停用或无权使用")
}
if guard, ok := s.repo.(interface {
CheckDigitalHumanAgentExecution(context.Context, *types.CustomAgent) error
}); ok {
if err := guard.CheckDigitalHumanAgentExecution(ctx, agent); err != nil {
return ctx, err
}
}
visiting[id] = true
defer delete(visiting, id)
visited[id] = true
if agent.Config.KBSelectionMode == "selected" && len(agent.Config.KnowledgeBases) > 0 && s.kbService != nil {
for _, kbID := range agent.Config.KnowledgeBases {
kb, err := s.kbService.GetRepository().GetKnowledgeBaseByIDAndTenant(ctx, kbID, agent.TenantID)
if err != nil || kb == nil {
continue
}
if kb.CreatorID != "" && kb.CreatorID == agent.CreatedBy && kb.VersionState == "" {
ctx = accesspolicy.WithExecutionDependency(ctx, agent.TenantID, "knowledge", kb.ID, kb.CreatorID)
}
}
}
for _, fusionID := range agent.Config.FusionAgentIDs {
child, err := s.repo.GetAgentByID(ctx, fusionID, agent.TenantID)
if err != nil || child == nil {
return ctx, apperrors.NewForbiddenError("融合 Agent 已删除或不可用")
}
if child.CreatedBy != "" && child.CreatedBy == agent.CreatedBy {
ctx = accesspolicy.WithExecutionDependency(ctx, agent.TenantID, "agents", child.ID, child.CreatedBy)
}
ctx, err = s.prepareAgentExecution(ctx, fusionID, visiting, visited)
if err != nil {
return ctx, err
}
}
return ctx, nil
}