// 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;
}