-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStreamingEventMapperTests.cs
More file actions
91 lines (80 loc) · 3.46 KB
/
StreamingEventMapperTests.cs
File metadata and controls
91 lines (80 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using ManagedCode.ClaudeCodeSharpSDK.Extensions.AI.Internal;
using ManagedCode.ClaudeCodeSharpSDK.Models;
using Microsoft.Extensions.AI;
namespace ManagedCode.ClaudeCodeSharpSDK.Extensions.AI.Tests;
public class StreamingEventMapperTests
{
private const string ThreadId = "thread-1";
private const string MessageId = "msg-1";
private const string AssistantText = "Hello";
private const string StopReason = "end_turn";
private const string AuthenticationFailedMessage = "authentication failed";
private const string WorkspaceDirectory = "/workspace";
private const string DefaultPermissionMode = "default";
private const string CliVersion = "2.0.75";
private const string DefaultOutputStyle = "default";
private const string NoneCostMode = "none";
private const string AllowedToolRead = "Read";
[Test]
public async Task ToUpdates_MapsThreadStartAssistantMessageAndUsage()
{
var updates = await CollectUpdates(
ToAsyncEnumerable(
CreateThreadStartedEvent(ThreadId),
new ItemCompletedEvent(new AssistantMessageItem(MessageId, ClaudeModels.ClaudeSonnet45Alias, AssistantText, [], null, StopReason, null)),
new TurnCompletedEvent(new Usage(10, 2, 3, 4), AssistantText, null, null, null, 1)));
await Assert.That(updates.Count).IsEqualTo(3);
await Assert.That(updates[0].ConversationId).IsEqualTo(ThreadId);
await Assert.That(updates[1].Text).IsEqualTo(AssistantText);
await Assert.That(updates[1].Role).IsEqualTo(ChatRole.Assistant);
var usageContent = updates[2].Contents.OfType<UsageContent>().Single();
await Assert.That(updates[2].FinishReason).IsEqualTo(ChatFinishReason.Stop);
await Assert.That(usageContent.Details.InputTokenCount).IsEqualTo(10);
await Assert.That(usageContent.Details.OutputTokenCount).IsEqualTo(4);
await Assert.That(usageContent.Details.CachedInputTokenCount).IsEqualTo(5);
}
[Test]
public async Task ToUpdates_TurnFailed_ThrowsInvalidOperationException()
{
var exception = await Assert.That(async () =>
await CollectUpdates(ToAsyncEnumerable(new TurnFailedEvent(new ThreadError(AuthenticationFailedMessage)))))
.ThrowsException();
await Assert.That(exception).IsTypeOf<InvalidOperationException>();
await Assert.That(exception!.Message).Contains(AuthenticationFailedMessage);
}
private static ThreadStartedEvent CreateThreadStartedEvent(string sessionId)
{
return new ThreadStartedEvent(new SessionInfo(
sessionId,
WorkspaceDirectory,
ClaudeModels.Sonnet,
DefaultPermissionMode,
CliVersion,
DefaultOutputStyle,
NoneCostMode,
[AllowedToolRead],
[],
[],
[],
[],
[]));
}
private static async IAsyncEnumerable<ThreadEvent> ToAsyncEnumerable(
params ThreadEvent[] events)
{
foreach (var evt in events)
{
yield return evt;
await Task.Yield();
}
}
private static async Task<List<ChatResponseUpdate>> CollectUpdates(IAsyncEnumerable<ThreadEvent> events)
{
var updates = new List<ChatResponseUpdate>();
await foreach (var update in StreamingEventMapper.ToUpdates(events).ConfigureAwait(false))
{
updates.Add(update);
}
return updates;
}
}