Files
agent-framework/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Model/ResponseStreamEvent.cs
T
d10b44d6bb .NET: Enable access to hosted AIAgents via OpenAI Responses (#947)
* init

* wip

* wip wip wip

* wip wip

* open up API

* enable for multiple agents

* more wip

* make frontend respond.

* wip

* not sure if proper setup

* define type

* cleanup

* frontend streaming wip

* use System.Net.ServerSentEvents

* usings

* reformat via ichatclient

* merge main renaming + refactor

* fix main merge + fix sample (a2a change)

* fix sample

* some rebase (not working yet)

* make it at least build somehow

* make non-stream work without internal types

* Input without custom models

* implement streaming

* test frontend

* enable alerts and fix

* build fixes & rereview

* Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI.Responses/Microsoft.Agents.AI.Hosting.OpenAI.Responses.csproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI.Responses/Utils/ResponseItemJsonConverter.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix agent discovery

* rename

* rename project into Microsoft.Agents.AI.Hosting.OpenAI (no responses in name)

* PR address comments x1

* address PR comments x2

* correctly instantiate OpenAIResponse

* address PR comments x3

* reconfigure JSON serialization & handle AOT warnings

* fix build

* proper ref

* check update differently

* correct check

* exclude dotnet format diagnostics for IL2026 and IL3050

* space  :)

* re-review

* add comments

* remove unnecessary using

* always take last openai response item

* set responseItem Id explicitly

* add agent.name validation for uri

* cleanup

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
2025-10-07 12:39:08 +00:00

167 lines
6.8 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Text.Json.Serialization;
using OpenAI.Responses;
namespace Microsoft.Agents.AI.Hosting.OpenAI.Responses.Model;
/// <summary>
/// Abstract base class for all streaming response events in the OpenAI Responses API.
/// Provides common properties shared across all streaming event types.
/// </summary>
[JsonPolymorphic(UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization)]
[JsonDerivedType(typeof(StreamingOutputItemAddedResponse), StreamingOutputItemAddedResponse.EventType)]
[JsonDerivedType(typeof(StreamingOutputItemDoneResponse), StreamingOutputItemDoneResponse.EventType)]
[JsonDerivedType(typeof(StreamingCreatedResponse), StreamingCreatedResponse.EventType)]
[JsonDerivedType(typeof(StreamingCompletedResponse), StreamingCompletedResponse.EventType)]
internal abstract class StreamingResponseEventBase
{
/// <summary>
/// Gets or sets the type identifier for the streaming response event.
/// This property is used to discriminate between different event types during serialization.
/// </summary>
[JsonPropertyName("type")]
public string Type { get; set; }
/// <summary>
/// Gets or sets the sequence number of this event in the streaming response.
/// Events are numbered sequentially starting from 1 to maintain ordering.
/// </summary>
[JsonPropertyName("sequence_number")]
public int SequenceNumber { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="StreamingResponseEventBase"/> class.
/// </summary>
/// <param name="type">The type identifier for this streaming response event.</param>
/// <param name="sequenceNumber">The sequence number of this event in the streaming response.</param>
[JsonConstructor]
public StreamingResponseEventBase(string type, int sequenceNumber)
{
this.Type = type;
this.SequenceNumber = sequenceNumber;
}
}
/// <summary>
/// Represents a streaming response event indicating that a new output item has been added to the response.
/// This event is sent when the AI agent produces a new piece of content during streaming.
/// </summary>
internal sealed class StreamingOutputItemAddedResponse : StreamingResponseEventBase
{
/// <summary>
/// The constant event type identifier for output item added events.
/// </summary>
public const string EventType = "response.output_item.added";
/// <summary>
/// Initializes a new instance of the <see cref="StreamingOutputItemAddedResponse"/> class.
/// </summary>
/// <param name="sequenceNumber">The sequence number of this event in the streaming response.</param>
public StreamingOutputItemAddedResponse(int sequenceNumber) : base(EventType, sequenceNumber)
{
}
/// <summary>
/// Gets or sets the index of the output in the response where this item was added.
/// Multiple outputs can exist in a single response, and this identifies which one.
/// </summary>
[JsonPropertyName("output_index")]
public int OutputIndex { get; set; }
/// <summary>
/// Gets or sets the response item that was added to the output.
/// This contains the actual content or data produced by the AI agent.
/// </summary>
[JsonPropertyName("item")]
public ResponseItem? Item { get; set; }
}
/// <summary>
/// Represents a streaming response event indicating that an output item has been completed.
/// This event is sent when the AI agent finishes producing a particular piece of content.
/// </summary>
internal sealed class StreamingOutputItemDoneResponse : StreamingResponseEventBase
{
/// <summary>
/// The constant event type identifier for output item done events.
/// </summary>
public const string EventType = "response.output_item.done";
/// <summary>
/// Initializes a new instance of the <see cref="StreamingOutputItemDoneResponse"/> class.
/// </summary>
/// <param name="sequenceNumber">The sequence number of this event in the streaming response.</param>
public StreamingOutputItemDoneResponse(int sequenceNumber) : base(EventType, sequenceNumber)
{
}
/// <summary>
/// Gets or sets the index of the output in the response where this item was completed.
/// This corresponds to the same output index from the associated <see cref="StreamingOutputItemAddedResponse"/>.
/// </summary>
[JsonPropertyName("output_index")]
public int OutputIndex { get; set; }
/// <summary>
/// Gets or sets the completed response item.
/// This contains the final version of the content produced by the AI agent.
/// </summary>
[JsonPropertyName("item")]
public ResponseItem? Item { get; set; }
}
/// <summary>
/// Represents a streaming response event indicating that a new response has been created and streaming has begun.
/// This is typically the first event sent in a streaming response sequence.
/// </summary>
internal sealed class StreamingCreatedResponse : StreamingResponseEventBase
{
/// <summary>
/// The constant event type identifier for response created events.
/// </summary>
public const string EventType = "response.created";
/// <summary>
/// Initializes a new instance of the <see cref="StreamingCreatedResponse"/> class.
/// </summary>
/// <param name="sequenceNumber">The sequence number of this event in the streaming response.</param>
public StreamingCreatedResponse(int sequenceNumber) : base(EventType, sequenceNumber)
{
}
/// <summary>
/// Gets or sets the OpenAI response object that was created.
/// This contains metadata about the response including ID, creation timestamp, and other properties.
/// </summary>
[JsonPropertyName("response")]
public required OpenAIResponse Response { get; set; }
}
/// <summary>
/// Represents a streaming response event indicating that the response has been completed.
/// This is typically the last event sent in a streaming response sequence.
/// </summary>
internal sealed class StreamingCompletedResponse : StreamingResponseEventBase
{
/// <summary>
/// The constant event type identifier for response completed events.
/// </summary>
public const string EventType = "response.completed";
/// <summary>
/// Initializes a new instance of the <see cref="StreamingCompletedResponse"/> class.
/// </summary>
/// <param name="sequenceNumber">The sequence number of this event in the streaming response.</param>
public StreamingCompletedResponse(int sequenceNumber) : base(EventType, sequenceNumber)
{
}
/// <summary>
/// Gets or sets the completed OpenAI response object.
/// This contains the final state of the response including all generated content and metadata.
/// </summary>
[JsonPropertyName("response")]
public required OpenAIResponse Response { get; set; }
}