@* Copyright (c) Microsoft. All rights reserved. *@
@namespace Microsoft.AspNetCore.Components.AI
@using Microsoft.Extensions.AI
@typeparam TState
@implements IDisposable
@ChildContent
@code {
private ResponseUpdateSubscription? _subscription;
///
/// The agent boundary context to subscribe to for state updates.
///
[CascadingParameter]
public IAgentBoundaryContext? BoundaryContext { get; set; }
///
/// The current state value. Can be set initially and will be updated by state events.
///
[Parameter]
public TState? CurrentState { get; set; }
///
/// Callback to deserialize a STATE_SNAPSHOT (application/json) into TState.
///
[Parameter]
public Func, TState?>? OnSnapshot { get; set; }
///
/// Callback to apply a STATE_DELTA (application/json-patch+json) to the current state.
/// Returns the updated state.
///
[Parameter]
public Func, TState?>? OnDelta { get; set; }
///
/// Optional callback invoked whenever state changes.
///
[Parameter]
public EventCallback CurrentStateChanged { get; set; }
///
/// Child content that will receive the cascaded state.
///
[Parameter]
public RenderFragment? ChildContent { get; set; }
protected override void OnInitialized()
{
if (BoundaryContext is not null)
{
_subscription = BoundaryContext.SubscribeToResponseUpdates(OnResponseUpdate);
}
}
private void OnResponseUpdate()
{
var update = BoundaryContext?.CurrentUpdate;
if (update?.Contents is null)
{
return;
}
foreach (var content in update.Contents)
{
if (content is DataContent dataContent)
{
if (string.Equals(dataContent.MediaType, "application/json", StringComparison.OrdinalIgnoreCase) && OnSnapshot is not null)
{
// STATE_SNAPSHOT - let app deserialize
CurrentState = OnSnapshot(dataContent.Data);
_ = CurrentStateChanged.InvokeAsync(CurrentState);
InvokeAsync(StateHasChanged);
}
else if (string.Equals(dataContent.MediaType, "application/json-patch+json", StringComparison.OrdinalIgnoreCase) && OnDelta is not null)
{
// STATE_DELTA - let app apply the patch
CurrentState = OnDelta(CurrentState, dataContent.Data);
_ = CurrentStateChanged.InvokeAsync(CurrentState);
InvokeAsync(StateHasChanged);
}
}
}
}
public void Dispose()
{
_subscription?.Dispose();
}
}