// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; namespace Microsoft.Agents.AI.Workflows; /// /// Event triggered when a workflow executor yields output. /// [JsonDerivedType(typeof(AgentResponseEvent))] [JsonDerivedType(typeof(AgentResponseUpdateEvent))] public class WorkflowOutputEvent : WorkflowEvent { private readonly HashSet _tags; /// /// Initializes a new instance of the class with no tags. /// /// The output data. /// The identifier of the executor that yielded this output. public WorkflowOutputEvent(object data, string executorId) : this(data, executorId, tags: null) { } /// /// Initializes a new instance of the class carrying the /// given output tag. /// /// The output data. /// The identifier of the executor that yielded this output. /// The single output tag to associate with this event. public WorkflowOutputEvent(object data, string executorId, OutputTag tag) : this(data, executorId, tags: new[] { tag }) { } /// /// Initializes a new instance of the class carrying the /// given output tags (deduplicated). /// /// The output data. /// The identifier of the executor that yielded this output. /// The output tags to associate with this event. May be or empty (the event is then untagged). public WorkflowOutputEvent(object data, string executorId, IEnumerable? tags) : base(data) { this.ExecutorId = executorId; this._tags = tags is null ? new HashSet() : new HashSet(tags); } /// /// The unique identifier of the executor that yielded this output. /// public string ExecutorId { get; } /// /// The unique identifier of the executor that yielded this output. /// [Obsolete("Use ExecutorId instead.")] [JsonIgnore] public string SourceId => this.ExecutorId; /// /// The set of output tags associated with this event. Never ; /// empty for terminal/regular outputs. The presence of /// marks this event as an intermediate output. /// public IEnumerable Tags => this._tags; /// /// Returns if this event carries the given tag. /// public bool HasTag(OutputTag tag) => this._tags.Contains(tag); /// /// Determines whether the underlying data is of the specified type or a derived type. /// /// The type to compare with the type of the underlying data. /// true if the underlying data is assignable to type T; otherwise, false. public bool Is() => this.IsType(typeof(T)); /// /// Determines whether the underlying data is of the specified type or a derived type, and /// returns it as that type if it is. /// /// The type to compare with the type of the underlying data. /// true if the underlying data is assignable to type T; otherwise, false. public bool Is([NotNullWhen(true)] out T? maybeValue) { if (this.Data is T value) { maybeValue = value; return true; } maybeValue = default; return false; } /// /// Determines whether the underlying data is of the specified type or a derived type. /// /// The type to compare with the type of the underlying data. /// true if the underlying data is assignable to type T; otherwise, false. public bool IsType(Type type) => this.Data is { } data && type.IsInstanceOfType(data); /// /// Attempts to retrieve the underlying data as the specified type. /// /// The type to which to cast. /// The value of Data as to the target type. public T? As() => this.Data is T value ? value : default; /// /// Attempts to retrieve the underlying data as the specified type. /// /// The type to which to cast. /// The value of Data as to the target type. public object? AsType(Type type) => this.IsType(type) ? this.Data : null; }