Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// <auto-generated by typra-emitter>
using Xunit;

#pragma warning disable IDE0130
namespace Prompty.Core;
#pragma warning restore IDE0130


public class FailureChunkConversionTests
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// <auto-generated by typra-emitter>
using Xunit;

#pragma warning disable IDE0130
namespace Prompty.Core;
#pragma warning restore IDE0130


public class StreamFailureConversionTests
{
[Fact]
public void LoadYamlInput()
{
string yamlData = """
outcome: indeterminate
message: "SSE stream error: connection reset"

""";

var instance = StreamFailure.FromYaml(yamlData);

Assert.NotNull(instance);
Assert.Equal(StreamFailureOutcome.Indeterminate, instance.Outcome);
Assert.Equal("SSE stream error: connection reset", instance.Message);
}

[Fact]
public void LoadJsonInput()
{
string jsonData = """
{
"outcome": "indeterminate",
"message": "SSE stream error: connection reset"
}
""";

var instance = StreamFailure.FromJson(jsonData);
Assert.NotNull(instance);
Assert.Equal(StreamFailureOutcome.Indeterminate, instance.Outcome);
Assert.Equal("SSE stream error: connection reset", instance.Message);
}

[Fact]
public void RoundtripJson()
{
// Test that FromJson -> ToJson -> FromJson produces equivalent data
string jsonData = """
{
"outcome": "indeterminate",
"message": "SSE stream error: connection reset"
}
""";

var original = StreamFailure.FromJson(jsonData);
Assert.NotNull(original);

var json = original.ToJson();
Assert.False(string.IsNullOrEmpty(json));

var reloaded = StreamFailure.FromJson(json);
Assert.NotNull(reloaded);
Assert.Equal(StreamFailureOutcome.Indeterminate, reloaded.Outcome);
Assert.Equal("SSE stream error: connection reset", reloaded.Message);
}

[Fact]
public void RoundtripYaml()
{
// Test that FromYaml -> ToYaml -> FromYaml produces equivalent data
string yamlData = """
outcome: indeterminate
message: "SSE stream error: connection reset"

""";

var original = StreamFailure.FromYaml(yamlData);
Assert.NotNull(original);

var yaml = original.ToYaml();
Assert.False(string.IsNullOrEmpty(yaml));

var reloaded = StreamFailure.FromYaml(yaml);
Assert.NotNull(reloaded);
Assert.Equal(StreamFailureOutcome.Indeterminate, reloaded.Outcome);
Assert.Equal("SSE stream error: connection reset", reloaded.Message);
}

[Fact]
public void ToJsonProducesValidJson()
{
string jsonData = """
{
"outcome": "indeterminate",
"message": "SSE stream error: connection reset"
}
""";

var instance = StreamFailure.FromJson(jsonData);
var json = instance.ToJson();

// Verify it's valid JSON by parsing it
var parsed = System.Text.Json.JsonDocument.Parse(json);
Assert.NotNull(parsed);
}

[Fact]
public void ToYamlProducesValidYaml()
{
string yamlData = """
outcome: indeterminate
message: "SSE stream error: connection reset"

""";

var instance = StreamFailure.FromYaml(yamlData);
var yaml = instance.ToYaml();

// Verify it's valid YAML by parsing it
var deserializer = new YamlDotNet.Serialization.DeserializerBuilder().Build();
var parsed = deserializer.Deserialize<object>(yaml);
Assert.NotNull(parsed);
}
}
165 changes: 165 additions & 0 deletions runtime/csharp/Prompty.Core/Model/events/FailureChunk.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// <auto-generated by typra-emitter>
// Copyright (c) Microsoft. All rights reserved.
using System.Text.Json;
using YamlDotNet.Serialization;

#pragma warning disable IDE0130
namespace Prompty.Core;
#pragma warning restore IDE0130

/// <summary>
/// A classified failure chunk from the LLM response stream.
/// </summary>
public partial class FailureChunk : StreamChunk
{
/// <summary>
/// The shorthand property name for this type, if any.
/// </summary>
public new static string? ShorthandProperty => null;

/// <summary>
/// Initializes a new instance of <see cref="FailureChunk"/>.
/// </summary>
#pragma warning disable CS8618
public FailureChunk()
{
}
#pragma warning restore CS8618

/// <summary>
/// The kind identifier for classified failure chunks
/// </summary>
public override string Kind { get; set; } = "failure";

/// <summary>
/// The classified stream failure
/// </summary>
public StreamFailure Failure { get; set; }



#region Load Methods

/// <summary>
/// Load a FailureChunk instance from a dictionary.
/// </summary>
/// <param name="data">The dictionary containing the data.</param>
/// <param name="context">Optional context with pre/post processing callbacks.</param>
/// <returns>The loaded FailureChunk instance.</returns>
public new static FailureChunk Load(Dictionary<string, object?> data, LoadContext? context = null)
{
if (context is not null)
{
data = context.ProcessInput(data);
}


// Create new instance
var instance = new FailureChunk();


if (data.TryGetValue("kind", out var kindValue) && kindValue is not null)
{
instance.Kind = kindValue?.ToString()!;

@sethjuarez Seth Juarez (sethjuarez) Aug 4, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is generated by Typra 0.4.2, and the same ?.ToString()! emitter pattern occurs broadly across the generated C# target (359 occurrences in 130 files). Hand-editing this one generated class would be overwritten by deterministic regeneration and would make this schema-only PR non-reproducible. The coordinated Typra 0.4.4 consolidation will update the emitter pin and regenerate the combined schema after this PR lands; CodeQL itself passes in this PR.

}

if (data.TryGetValue("failure", out var failureValue) && failureValue is not null)
{
instance.Failure = StreamFailure.Load(failureValue.GetDictionary(StreamFailure.ShorthandProperty), context);
}

if (context is not null)
{
instance = context.ProcessOutput(instance);
}
return instance;
}


#endregion

#region Save Methods

/// <summary>
/// Save the FailureChunk instance to a dictionary.
/// </summary>
/// <param name="context">Optional context with pre/post processing callbacks.</param>
/// <returns>The dictionary representation of this instance.</returns>
public override Dictionary<string, object?> Save(SaveContext? context = null)
{
var obj = this;
if (context is not null)
{
obj = context.ProcessObject(obj);
}


// Start with parent class properties
var result = base.Save(context);


result["kind"] = obj.Kind;


result["failure"] = obj.Failure?.Save(context);


return result;
}


/// <summary>
/// Convert the FailureChunk instance to a YAML string.
/// </summary>
/// <param name="context">Optional context with pre/post processing callbacks.</param>
/// <returns>The YAML string representation of this instance.</returns>
public new string ToYaml(SaveContext? context = null)
{
context ??= new SaveContext();
return context.ToYaml(Save(context));
}

/// <summary>
/// Convert the FailureChunk instance to a JSON string.
/// </summary>
/// <param name="context">Optional context with pre/post processing callbacks.</param>
/// <param name="indent">Whether to indent the output. Defaults to true.</param>
/// <returns>The JSON string representation of this instance.</returns>
public new string ToJson(SaveContext? context = null, bool indent = true)
{
context ??= new SaveContext();
return context.ToJson(Save(context), indent);
}

/// <summary>
/// Load a FailureChunk instance from a JSON string.
/// </summary>
/// <param name="json">The JSON string to parse.</param>
/// <param name="context">Optional context with pre/post processing callbacks.</param>
/// <returns>The loaded FailureChunk instance.</returns>
public new static FailureChunk FromJson(string json, LoadContext? context = null)
{
using var doc = JsonDocument.Parse(json);
Dictionary<string, object?> dict;
dict = JsonSerializer.Deserialize<Dictionary<string, object?>>(json, JsonUtils.Options)
?? throw new ArgumentException("Failed to parse JSON as dictionary");

return Load(dict, context);
}

/// <summary>
/// Load a FailureChunk instance from a YAML string.
/// </summary>
/// <param name="yaml">The YAML string to parse.</param>
/// <param name="context">Optional context with pre/post processing callbacks.</param>
/// <returns>The loaded FailureChunk instance.</returns>
public new static FailureChunk FromYaml(string yaml, LoadContext? context = null)
{
var dict = YamlUtils.Deserializer.Deserialize<Dictionary<string, object?>>(yaml)
?? throw new ArgumentException("Failed to parse YAML as dictionary");

return Load(dict, context);
}

#endregion
}
1 change: 1 addition & 0 deletions runtime/csharp/Prompty.Core/Model/events/StreamChunk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ private static StreamChunk LoadKind(Dictionary<string, object?> data, LoadContex
"tool" => ToolChunk.Load(data, context),
"usage" => UsageChunk.Load(data, context),
"error" => ErrorChunk.Load(data, context),
"failure" => FailureChunk.Load(data, context),
_ => throw new ArgumentException($"Unknown StreamChunk discriminator value: {discriminator}"),
};
}
Expand Down
Loading
Loading