Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 1 addition & 11 deletions src/CodexSdk.MAF/CodexAIAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ protected override async Task<AgentResponse> RunCoreAsync(
switch (threadEvent)
{
case TurnCompletedEvent turnCompleted:
usage = CreateUsageDetails(turnCompleted.Usage);
usage = turnCompleted.Usage.ToUsageDetails();
break;

case TurnFailedEvent turnFailed:
Expand Down Expand Up @@ -200,16 +200,6 @@ await NotifyThreadStartedIfNeededAsync(
await SaveNewMessagesAsync(safeSession, mergedMessages, responseMessages, cancellationToken);
}

private static UsageDetails CreateUsageDetails(Usage usage)
{
return new UsageDetails
{
InputTokenCount = usage.InputTokens,
CachedInputTokenCount = usage.CachedInputTokens,
OutputTokenCount = usage.OutputTokens,
};
}

private async ValueTask<bool> NotifyThreadStartedIfNeededAsync(
CodexAgentSession session,
string? threadId,
Expand Down
20 changes: 13 additions & 7 deletions src/CodexSdk.MAF/Internal/ThreadEventExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ internal static class ThreadEventExtensions
return update;
}

public static UsageDetails ToUsageDetails(this Usage usage)
{
return new UsageDetails
{
InputTokenCount = usage.InputTokens,
CachedInputTokenCount = usage.CachedInputTokens,
OutputTokenCount = usage.OutputTokens,
ReasoningTokenCount = usage.ReasoningOutputTokens,
TotalTokenCount = (long)usage.InputTokens + usage.OutputTokens,
};
}

private static AgentResponseUpdate CreateLifecycleUpdate(string eventType)
{
return new AgentResponseUpdate
Expand All @@ -61,13 +73,7 @@ private static AgentResponseUpdate CreateUsageUpdate(Usage usage)
},
Contents =
[
new UsageContent(new UsageDetails
{
InputTokenCount = usage.InputTokens,
CachedInputTokenCount = usage.CachedInputTokens,
OutputTokenCount = usage.OutputTokens,
ReasoningTokenCount = usage.ReasoningOutputTokens,
})
new UsageContent(usage.ToUsageDetails())
],
};
}
Expand Down
28 changes: 28 additions & 0 deletions tests/CodexSdk.MAF.Tests/ThreadEventExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,34 @@ public void ToAgentResponseUpdate_WhenTurnStarts_ReturnsVisibleSystemContent()
Assert.False(update.ShouldSaveAsResponseMessage());
}

[Fact]
public void ToAgentResponseUpdate_WhenTurnCompletes_MapsCompleteUsage()
{
// Arrange
var threadEvent = new TurnCompletedEvent
{
Usage = new Usage
{
InputTokens = 100,
CachedInputTokens = 60,
OutputTokens = 30,
ReasoningOutputTokens = 20,
},
};

// Act
var update = threadEvent.ToAgentResponseUpdate();

// Assert
Assert.NotNull(update);
var usage = Assert.IsType<UsageContent>(Assert.Single(update.Contents)).Details;
Assert.Equal(100L, usage.InputTokenCount);
Assert.Equal(60L, usage.CachedInputTokenCount);
Assert.Equal(30L, usage.OutputTokenCount);
Assert.Equal(20L, usage.ReasoningTokenCount);
Assert.Equal(130L, usage.TotalTokenCount);
}

[Fact]
public void ToAgentResponseUpdate_WhenCommandExecutionCompletedEvent_ReturnsFunctionResultContent()
{
Expand Down