mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
* refactor: Normalize Run/RunStreaming with AIAgent * refactor: Clarify Session vs. Run -level concepts * Rename RunId to SessionId to better match Run/Session terminology in AIAgent * [BREAKING]: Will break existing checkpointed sessions in CosmosDb due to field rename * refactor: Rename and simplify interface around getting typed data out of ExternalRequest/Response * Also adds hints around using value types in PortableValue * refactor: Rename AddFanInEdge to AddFanInBarrierEdge This will prevent a breaking change later when we introduce a programmable FanIn edge, analogous to the FanOut edge's EdgeSelector. The goal, in the long run is to support a number of different FanIn scenarios, with naive FanIn (no barrier) by default, similar to FanOut. * refactor: AsAgent(this Workflow, ...) => AsAIAgent(...) * misc - part1: SwitchBuilder internal --------- Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
159 lines
6.5 KiB
C#
159 lines
6.5 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Agents.AI.Workflows.Execution;
|
|
|
|
namespace Microsoft.Agents.AI.Workflows.InProc;
|
|
|
|
/// <summary>
|
|
/// Provides an in-process implementation of the workflow execution environment for running, streaming, and
|
|
/// checkpointing workflows within the current application domain.
|
|
/// </summary>
|
|
public sealed class InProcessExecutionEnvironment : IWorkflowExecutionEnvironment
|
|
{
|
|
internal InProcessExecutionEnvironment(ExecutionMode mode, bool enableConcurrentRuns = false, CheckpointManager? checkpointManager = null)
|
|
{
|
|
this.ExecutionMode = mode;
|
|
this.EnableConcurrentRuns = enableConcurrentRuns;
|
|
|
|
this.CheckpointManager = checkpointManager;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configure a new execution environment, inheriting configuration for the current one with the specified <see cref="Workflows.CheckpointManager"/>
|
|
/// for use in checkpointing.
|
|
/// </summary>
|
|
/// <param name="checkpointManager">The CheckpointManager to use for checkpointing.</param>
|
|
/// <returns>
|
|
/// A new InProcess <see cref="IWorkflowExecutionEnvironment"/> configured for checkpointing, inheriting configuration from the current
|
|
/// environment.
|
|
/// </returns>
|
|
public InProcessExecutionEnvironment WithCheckpointing(CheckpointManager? checkpointManager)
|
|
{
|
|
return new(this.ExecutionMode, this.EnableConcurrentRuns, checkpointManager);
|
|
}
|
|
|
|
internal ExecutionMode ExecutionMode { get; }
|
|
internal bool EnableConcurrentRuns { get; }
|
|
internal CheckpointManager? CheckpointManager { get; }
|
|
|
|
/// <inheritdoc/>
|
|
public bool IsCheckpointingEnabled => this.CheckpointManager != null;
|
|
|
|
internal ValueTask<AsyncRunHandle> BeginRunAsync(Workflow workflow, string? sessionId, IEnumerable<Type> knownValidInputTypes, CancellationToken cancellationToken)
|
|
{
|
|
InProcessRunner runner = InProcessRunner.CreateTopLevelRunner(workflow, this.CheckpointManager, sessionId, this.EnableConcurrentRuns, knownValidInputTypes);
|
|
return runner.BeginStreamAsync(this.ExecutionMode, cancellationToken);
|
|
}
|
|
|
|
internal ValueTask<AsyncRunHandle> ResumeRunAsync(Workflow workflow, CheckpointInfo fromCheckpoint, IEnumerable<Type> knownValidInputTypes, CancellationToken cancellationToken)
|
|
{
|
|
InProcessRunner runner = InProcessRunner.CreateTopLevelRunner(workflow, this.CheckpointManager, fromCheckpoint.SessionId, this.EnableConcurrentRuns, knownValidInputTypes);
|
|
return runner.ResumeStreamAsync(this.ExecutionMode, fromCheckpoint, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async ValueTask<StreamingRun> OpenStreamingAsync(
|
|
Workflow workflow,
|
|
string? sessionId = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
AsyncRunHandle runHandle = await this.BeginRunAsync(workflow, sessionId, [], cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
return new(runHandle);
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async ValueTask<StreamingRun> RunStreamingAsync<TInput>(
|
|
Workflow workflow,
|
|
TInput input,
|
|
string? sessionId = null,
|
|
CancellationToken cancellationToken = default) where TInput : notnull
|
|
{
|
|
AsyncRunHandle runHandle = await this.BeginRunAsync(workflow, sessionId, [], cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
return await runHandle.EnqueueAndStreamAsync(input, cancellationToken).ConfigureAwait(false);
|
|
}
|
|
|
|
[MemberNotNull(nameof(CheckpointManager))]
|
|
private void VerifyCheckpointingConfigured()
|
|
{
|
|
if (this.CheckpointManager == null)
|
|
{
|
|
throw new InvalidOperationException("Checkpointing is not configured for this execution environment. Please use the InProcessExecutionEnvironment.WithCheckpointing method to attach a CheckpointManager.");
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async ValueTask<StreamingRun> ResumeStreamingAsync(
|
|
Workflow workflow,
|
|
CheckpointInfo fromCheckpoint,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
this.VerifyCheckpointingConfigured();
|
|
|
|
AsyncRunHandle runHandle = await this.ResumeRunAsync(workflow, fromCheckpoint, [], cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
return new(runHandle);
|
|
}
|
|
|
|
private async ValueTask<AsyncRunHandle> BeginRunHandlingChatProtocolAsync<TInput>(Workflow workflow,
|
|
TInput input,
|
|
string? sessionId = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ProtocolDescriptor descriptor = await workflow.DescribeProtocolAsync(cancellationToken).ConfigureAwait(false);
|
|
AsyncRunHandle runHandle = await this.BeginRunAsync(workflow, sessionId, descriptor.Accepts, cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
await runHandle.EnqueueMessageAsync(input, cancellationToken).ConfigureAwait(false);
|
|
|
|
if (descriptor.IsChatProtocol() && input is not TurnToken)
|
|
{
|
|
await runHandle.EnqueueMessageAsync(new TurnToken(emitEvents: true), cancellationToken).ConfigureAwait(false);
|
|
}
|
|
|
|
return runHandle;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async ValueTask<Run> RunAsync<TInput>(
|
|
Workflow workflow,
|
|
TInput input,
|
|
string? sessionId = null,
|
|
CancellationToken cancellationToken = default) where TInput : notnull
|
|
{
|
|
AsyncRunHandle runHandle = await this.BeginRunHandlingChatProtocolAsync(
|
|
workflow,
|
|
input,
|
|
sessionId,
|
|
cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
Run run = new(runHandle);
|
|
await run.RunToNextHaltAsync(cancellationToken).ConfigureAwait(false);
|
|
return run;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async ValueTask<Run> ResumeAsync(
|
|
Workflow workflow,
|
|
CheckpointInfo fromCheckpoint,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
this.VerifyCheckpointingConfigured();
|
|
|
|
AsyncRunHandle runHandle = await this.ResumeRunAsync(workflow, fromCheckpoint, [], cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
return new(runHandle);
|
|
}
|
|
}
|