| | | 1 | | using Microsoft.Extensions.AI; |
| | | 2 | | |
| | | 3 | | namespace NexusLabs.Needlr.AgentFramework.Diagnostics; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Aggregated result of a multi-agent pipeline run, providing per-stage diagnostics |
| | | 7 | | /// alongside the response text from each agent. |
| | | 8 | | /// </summary> |
| | | 9 | | /// <remarks> |
| | | 10 | | /// <para> |
| | | 11 | | /// Returned by <c>RunWithDiagnosticsAsync</c> extension methods on |
| | | 12 | | /// <see cref="Microsoft.Agents.AI.Workflows.Workflow"/>. Contains the full execution |
| | | 13 | | /// timeline: each agent's response text, token usage, duration, and success/failure |
| | | 14 | | /// state. |
| | | 15 | | /// </para> |
| | | 16 | | /// </remarks> |
| | | 17 | | /// <example> |
| | | 18 | | /// <code> |
| | | 19 | | /// var result = await workflow.RunWithDiagnosticsAsync( |
| | | 20 | | /// "Write an article about roses.", |
| | | 21 | | /// diagnosticsAccessor, |
| | | 22 | | /// cancellationToken: ct); |
| | | 23 | | /// |
| | | 24 | | /// Console.WriteLine($"Pipeline {(result.Succeeded ? "succeeded" : "failed")} " + |
| | | 25 | | /// $"in {result.TotalDuration.TotalSeconds:F1}s"); |
| | | 26 | | /// Console.WriteLine($"Total tokens: {result.AggregateTokenUsage?.TotalTokens ?? 0}"); |
| | | 27 | | /// Console.WriteLine($"Stages: {result.Stages.Count}"); |
| | | 28 | | /// </code> |
| | | 29 | | /// </example> |
| | | 30 | | public interface IPipelineRunResult |
| | | 31 | | { |
| | | 32 | | /// <summary>Gets the per-stage results in execution order.</summary> |
| | | 33 | | IReadOnlyList<IAgentStageResult> Stages { get; } |
| | | 34 | | |
| | | 35 | | /// <summary> |
| | | 36 | | /// Gets the final responses as a dictionary (agent name → |
| | | 37 | | /// <see cref="ChatResponse"/>). When an agent ran multiple stages, the last |
| | | 38 | | /// stage's response wins. Values may be <see langword="null"/> for stages that |
| | | 39 | | /// produced no terminating text response. |
| | | 40 | | /// </summary> |
| | | 41 | | IReadOnlyDictionary<string, ChatResponse?> FinalResponses { get; } |
| | | 42 | | |
| | | 43 | | /// <summary>Gets the total wall-clock duration of the pipeline.</summary> |
| | | 44 | | TimeSpan TotalDuration { get; } |
| | | 45 | | |
| | | 46 | | /// <summary> |
| | | 47 | | /// Gets the aggregate token usage across all stages. |
| | | 48 | | /// <see langword="null"/> if diagnostics were not enabled. |
| | | 49 | | /// </summary> |
| | | 50 | | TokenUsage? AggregateTokenUsage { get; } |
| | | 51 | | |
| | | 52 | | /// <summary>Gets the total number of stages planned for this pipeline.</summary> |
| | | 53 | | int PlannedStageCount { get; } |
| | | 54 | | |
| | | 55 | | /// <summary>Gets whether all stages completed successfully.</summary> |
| | | 56 | | bool Succeeded { get; } |
| | | 57 | | |
| | | 58 | | /// <summary>Gets the error message if any stage failed.</summary> |
| | | 59 | | string? ErrorMessage { get; } |
| | | 60 | | |
| | | 61 | | /// <summary> |
| | | 62 | | /// Gets the exception that caused the pipeline to fail, or <see langword="null"/> |
| | | 63 | | /// on success. Preserves the full exception including inner exceptions and stack |
| | | 64 | | /// trace for diagnostic purposes. |
| | | 65 | | /// </summary> |
| | 0 | 66 | | Exception? Exception => null; |
| | | 67 | | } |