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 }