mirror of
https://github.com/davidkaya/aryx.git
synced 2026-07-29 07:58:47 +02:00
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
651 lines
23 KiB
C#
651 lines
23 KiB
C#
using System.Collections.Concurrent;
|
|
using Aryx.AgentHost.Contracts;
|
|
using GitHub.Copilot.SDK;
|
|
using Microsoft.Extensions.AI;
|
|
|
|
namespace Aryx.AgentHost.Services;
|
|
|
|
internal sealed class CopilotTurnExecutionState
|
|
{
|
|
private readonly RunTurnCommandDto _command;
|
|
private readonly HashSet<string> _startedAgents = new(StringComparer.OrdinalIgnoreCase);
|
|
private readonly HashSet<string> _reclassifiedMessageIds = new(StringComparer.Ordinal);
|
|
private readonly ConcurrentQueue<SidecarEventDto> _pendingEvents = new();
|
|
private readonly ConcurrentQueue<McpOauthRequiredEventDto> _pendingMcpOauthRequests = new();
|
|
private readonly ConcurrentDictionary<string, AgentIdentity> _observedAgentsByMessageId = new(StringComparer.Ordinal);
|
|
private readonly StreamingTranscriptBuffer _transcriptBuffer = new();
|
|
private int _fallbackMessageIndex;
|
|
private string? _lastObservedMessageId;
|
|
|
|
public CopilotTurnExecutionState(RunTurnCommandDto command)
|
|
{
|
|
_command = command;
|
|
}
|
|
|
|
public ConcurrentDictionary<string, string> ToolNamesByCallId { get; } = new(StringComparer.Ordinal);
|
|
|
|
public AgentIdentity? ActiveAgent { get; private set; }
|
|
|
|
public List<ChatMessageDto> CompletedMessages { get; private set; } = [];
|
|
|
|
public bool HasPendingExitPlanModeRequest { get; private set; }
|
|
|
|
public bool SuppressHookLifecycleEvents { get; set; }
|
|
|
|
public async Task EmitThinkingIfNeeded(
|
|
AgentIdentity agent,
|
|
Func<SidecarEventDto, Task> onEvent)
|
|
{
|
|
AgentActivityEventDto? thinkingActivity = CreateThinkingActivityIfNeeded(agent);
|
|
if (thinkingActivity is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
await onEvent(thinkingActivity).ConfigureAwait(false);
|
|
}
|
|
|
|
public void QueueThinkingIfNeeded(AgentIdentity agent)
|
|
{
|
|
AgentActivityEventDto? thinkingActivity = CreateThinkingActivityIfNeeded(agent);
|
|
if (thinkingActivity is not null)
|
|
{
|
|
_pendingEvents.Enqueue(thinkingActivity);
|
|
}
|
|
}
|
|
|
|
public void ApplyEvent(SidecarEventDto evt)
|
|
{
|
|
if (evt is AgentActivityEventDto activity
|
|
&& string.Equals(activity.ActivityType, "handoff", StringComparison.Ordinal)
|
|
&& !string.IsNullOrWhiteSpace(activity.AgentId)
|
|
&& !string.IsNullOrWhiteSpace(activity.AgentName))
|
|
{
|
|
ActiveAgent = new AgentIdentity(activity.AgentId, activity.AgentName);
|
|
}
|
|
}
|
|
|
|
public void ObserveSessionEvent(PatternAgentDefinitionDto agentDefinition, SessionEvent sessionEvent)
|
|
{
|
|
AgentIdentity agent = AgentIdentityResolver.ResolveAgentIdentity(
|
|
_command.Pattern,
|
|
agentDefinition.Id,
|
|
agentDefinition.Name);
|
|
|
|
switch (sessionEvent)
|
|
{
|
|
case AssistantMessageDeltaEvent messageDelta when !string.IsNullOrWhiteSpace(messageDelta.Data?.MessageId):
|
|
RecordObservedAgentForMessage(agent, messageDelta.Data!.MessageId);
|
|
QueueThinkingIfNeeded(agent);
|
|
break;
|
|
case AssistantMessageEvent assistantMessage when !string.IsNullOrWhiteSpace(assistantMessage.Data?.MessageId):
|
|
RecordObservedAgentForMessage(agent, assistantMessage.Data!.MessageId);
|
|
QueueThinkingIfNeeded(agent);
|
|
if (assistantMessage.Data?.ToolRequests is { Length: > 0 })
|
|
{
|
|
QueueMessageReclassifiedIfNeeded(assistantMessage.Data.MessageId);
|
|
}
|
|
break;
|
|
case ToolExecutionStartEvent toolExecutionStart
|
|
when !string.IsNullOrWhiteSpace(toolExecutionStart.Data?.ToolCallId)
|
|
&& !string.IsNullOrWhiteSpace(toolExecutionStart.Data?.ToolName):
|
|
string toolCallId = toolExecutionStart.Data.ToolCallId.Trim();
|
|
string toolName = toolExecutionStart.Data.ToolName.Trim();
|
|
ToolNamesByCallId[toolCallId] = toolName;
|
|
ActiveAgent = agent;
|
|
AgentActivityEventDto? toolActivity = CreateToolCallingActivity(agent, toolName, toolCallId);
|
|
if (toolActivity is not null)
|
|
{
|
|
_pendingEvents.Enqueue(toolActivity);
|
|
}
|
|
|
|
QueueMessageReclassifiedIfNeeded(_lastObservedMessageId);
|
|
break;
|
|
case AssistantIntentEvent intentEvent:
|
|
ActiveAgent = agent;
|
|
QueueThinkingIfNeeded(agent);
|
|
AssistantIntentEventDto? assistantIntent = CreateAssistantIntentEvent(agent, intentEvent.Data);
|
|
if (assistantIntent is not null)
|
|
{
|
|
_pendingEvents.Enqueue(assistantIntent);
|
|
}
|
|
break;
|
|
case AssistantReasoningDeltaEvent reasoningDelta:
|
|
ActiveAgent = agent;
|
|
QueueThinkingIfNeeded(agent);
|
|
ReasoningDeltaEventDto? reasoningDeltaEvent = CreateReasoningDeltaEvent(agent, reasoningDelta.Data);
|
|
if (reasoningDeltaEvent is not null)
|
|
{
|
|
_pendingEvents.Enqueue(reasoningDeltaEvent);
|
|
}
|
|
break;
|
|
case SubagentStartedEvent started:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateSubagentEvent(agent, "started", started.Data));
|
|
break;
|
|
case SubagentCompletedEvent completed:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateSubagentCompletedEvent(agent, completed.Data));
|
|
break;
|
|
case SubagentFailedEvent failed:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateSubagentFailedEvent(agent, failed.Data));
|
|
break;
|
|
case SubagentSelectedEvent selected:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateSubagentSelectedEvent(agent, selected.Data));
|
|
break;
|
|
case SubagentDeselectedEvent:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateSubagentDeselectedEvent(agent));
|
|
break;
|
|
case SkillInvokedEvent skillInvoked:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateSkillInvokedEvent(agent, skillInvoked.Data));
|
|
break;
|
|
case HookStartEvent hookStart:
|
|
ActiveAgent = agent;
|
|
if (!SuppressHookLifecycleEvents)
|
|
{
|
|
_pendingEvents.Enqueue(CreateHookLifecycleEvent(agent, "start", hookStart.Data));
|
|
}
|
|
break;
|
|
case HookEndEvent hookEnd:
|
|
ActiveAgent = agent;
|
|
if (!SuppressHookLifecycleEvents)
|
|
{
|
|
_pendingEvents.Enqueue(CreateHookLifecycleEvent(agent, "end", hookEnd.Data));
|
|
}
|
|
break;
|
|
case AssistantUsageEvent assistantUsage:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateAssistantUsageEvent(agent, assistantUsage.Data));
|
|
break;
|
|
case SessionUsageInfoEvent usageInfo:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateUsageEvent(agent, usageInfo.Data));
|
|
break;
|
|
case SessionCompactionStartEvent compactionStart:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateCompactionStartEvent(agent, compactionStart.Data));
|
|
break;
|
|
case SessionCompactionCompleteEvent compactionComplete:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreateCompactionCompleteEvent(agent, compactionComplete.Data));
|
|
break;
|
|
case PendingMessagesModifiedEvent:
|
|
ActiveAgent = agent;
|
|
_pendingEvents.Enqueue(CreatePendingMessagesModifiedEvent(agent));
|
|
break;
|
|
case McpOauthRequiredEvent:
|
|
ActiveAgent = agent;
|
|
break;
|
|
case ExitPlanModeRequestedEvent:
|
|
HasPendingExitPlanModeRequest = true;
|
|
ActiveAgent = agent;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public IReadOnlyList<SidecarEventDto> DrainPendingEvents()
|
|
{
|
|
List<SidecarEventDto> pending = [];
|
|
while (_pendingEvents.TryDequeue(out SidecarEventDto? pendingEvent))
|
|
{
|
|
pending.Add(pendingEvent);
|
|
}
|
|
|
|
return pending;
|
|
}
|
|
|
|
public void EnqueuePendingMcpOauthRequest(McpOauthRequiredEventDto request)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(request);
|
|
_pendingMcpOauthRequests.Enqueue(request);
|
|
}
|
|
|
|
public IReadOnlyList<McpOauthRequiredEventDto> DrainPendingMcpOauthRequests()
|
|
{
|
|
List<McpOauthRequiredEventDto> pending = [];
|
|
while (_pendingMcpOauthRequests.TryDequeue(out McpOauthRequiredEventDto? request))
|
|
{
|
|
pending.Add(request);
|
|
}
|
|
|
|
return pending;
|
|
}
|
|
|
|
public bool TryResolveObservedAgentForMessage(string? messageId, out AgentIdentity agent)
|
|
{
|
|
agent = default;
|
|
return !string.IsNullOrWhiteSpace(messageId)
|
|
&& _observedAgentsByMessageId.TryGetValue(messageId, out agent);
|
|
}
|
|
|
|
public string CreateMessageId(string? messageId)
|
|
{
|
|
return messageId ?? $"{_command.RequestId}-delta-{_fallbackMessageIndex++}";
|
|
}
|
|
|
|
public TranscriptSegment AppendDelta(
|
|
string messageId,
|
|
string authorName,
|
|
string delta)
|
|
{
|
|
return _transcriptBuffer.AppendDelta(messageId, authorName, delta);
|
|
}
|
|
|
|
public void ClearActiveAgentIfMatching(AgentIdentity completedAgent)
|
|
{
|
|
if (ActiveAgent.HasValue
|
|
&& string.Equals(ActiveAgent.Value.AgentId, completedAgent.AgentId, StringComparison.Ordinal))
|
|
{
|
|
ActiveAgent = null;
|
|
}
|
|
}
|
|
|
|
private void RecordObservedAgentForMessage(AgentIdentity agent, string messageId)
|
|
{
|
|
ActiveAgent = agent;
|
|
_observedAgentsByMessageId[messageId] = agent;
|
|
_lastObservedMessageId = messageId;
|
|
}
|
|
|
|
private void QueueMessageReclassifiedIfNeeded(string? messageId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(messageId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
string normalizedMessageId = messageId.Trim();
|
|
if (!_reclassifiedMessageIds.Add(normalizedMessageId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
_pendingEvents.Enqueue(CreateMessageReclassifiedEvent(normalizedMessageId));
|
|
}
|
|
|
|
private AgentActivityEventDto? CreateThinkingActivityIfNeeded(AgentIdentity agent)
|
|
{
|
|
ActiveAgent = agent;
|
|
|
|
if (!_startedAgents.Add(agent.AgentId))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new AgentActivityEventDto
|
|
{
|
|
Type = "agent-activity",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
ActivityType = "thinking",
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
};
|
|
}
|
|
|
|
private AgentActivityEventDto? CreateToolCallingActivity(
|
|
AgentIdentity agent,
|
|
string toolName,
|
|
string toolCallId)
|
|
{
|
|
if (toolName.StartsWith("handoff_to_", StringComparison.Ordinal))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new AgentActivityEventDto
|
|
{
|
|
Type = "agent-activity",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
ActivityType = "tool-calling",
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
ToolName = toolName,
|
|
ToolCallId = toolCallId,
|
|
};
|
|
}
|
|
|
|
private MessageReclassifiedEventDto CreateMessageReclassifiedEvent(string messageId)
|
|
{
|
|
return new MessageReclassifiedEventDto
|
|
{
|
|
Type = "message-reclassified",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
MessageId = messageId,
|
|
NewKind = "thinking",
|
|
};
|
|
}
|
|
|
|
public void UpdateCompletedMessages(
|
|
IReadOnlyList<ChatMessage> allMessages,
|
|
IReadOnlyList<ChatMessage> inputMessages)
|
|
{
|
|
List<ChatMessage> newMessages = WorkflowTranscriptProjector.SelectNewOutputMessages(allMessages, inputMessages);
|
|
CompletedMessages = WorkflowTranscriptProjector.ProjectCompletedMessagesFromSegments(
|
|
_command,
|
|
newMessages,
|
|
_transcriptBuffer.Snapshot(),
|
|
ActiveAgent);
|
|
}
|
|
|
|
public IReadOnlyList<ChatMessageDto> FinalizeCompletedMessages()
|
|
{
|
|
if (CompletedMessages.Count == 0 && _transcriptBuffer.Count > 0)
|
|
{
|
|
CompletedMessages = WorkflowTranscriptProjector.ProjectCompletedMessagesFromSegments(
|
|
_command,
|
|
[],
|
|
_transcriptBuffer.Snapshot(),
|
|
ActiveAgent);
|
|
}
|
|
|
|
foreach (ChatMessageDto message in CompletedMessages)
|
|
{
|
|
if (_reclassifiedMessageIds.Contains(message.Id))
|
|
{
|
|
message.MessageKind = "thinking";
|
|
}
|
|
}
|
|
|
|
return CompletedMessages;
|
|
}
|
|
|
|
private SubagentEventDto CreateSubagentEvent(
|
|
AgentIdentity agent,
|
|
string eventKind,
|
|
SubagentStartedData? data)
|
|
{
|
|
return new SubagentEventDto
|
|
{
|
|
Type = "subagent-event",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
EventKind = eventKind,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
ToolCallId = data?.ToolCallId,
|
|
CustomAgentName = data?.AgentName,
|
|
CustomAgentDisplayName = data?.AgentDisplayName,
|
|
CustomAgentDescription = data?.AgentDescription,
|
|
};
|
|
}
|
|
|
|
private SubagentEventDto CreateSubagentCompletedEvent(
|
|
AgentIdentity agent,
|
|
SubagentCompletedData? data)
|
|
{
|
|
return new SubagentEventDto
|
|
{
|
|
Type = "subagent-event",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
EventKind = "completed",
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
ToolCallId = data?.ToolCallId,
|
|
CustomAgentName = data?.AgentName,
|
|
CustomAgentDisplayName = data?.AgentDisplayName,
|
|
};
|
|
}
|
|
|
|
private SubagentEventDto CreateSubagentFailedEvent(
|
|
AgentIdentity agent,
|
|
SubagentFailedData? data)
|
|
{
|
|
return new SubagentEventDto
|
|
{
|
|
Type = "subagent-event",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
EventKind = "failed",
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
ToolCallId = data?.ToolCallId,
|
|
CustomAgentName = data?.AgentName,
|
|
CustomAgentDisplayName = data?.AgentDisplayName,
|
|
Error = data?.Error,
|
|
};
|
|
}
|
|
|
|
private SubagentEventDto CreateSubagentSelectedEvent(
|
|
AgentIdentity agent,
|
|
SubagentSelectedData? data)
|
|
{
|
|
return new SubagentEventDto
|
|
{
|
|
Type = "subagent-event",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
EventKind = "selected",
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
CustomAgentName = data?.AgentName,
|
|
CustomAgentDisplayName = data?.AgentDisplayName,
|
|
Tools = data?.Tools,
|
|
};
|
|
}
|
|
|
|
private SubagentEventDto CreateSubagentDeselectedEvent(AgentIdentity agent)
|
|
{
|
|
return new SubagentEventDto
|
|
{
|
|
Type = "subagent-event",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
EventKind = "deselected",
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
};
|
|
}
|
|
|
|
private AssistantIntentEventDto? CreateAssistantIntentEvent(
|
|
AgentIdentity agent,
|
|
AssistantIntentData? data)
|
|
{
|
|
string? intent = data?.Intent?.Trim();
|
|
if (string.IsNullOrWhiteSpace(intent))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new AssistantIntentEventDto
|
|
{
|
|
Type = "assistant-intent",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
Intent = intent,
|
|
};
|
|
}
|
|
|
|
private ReasoningDeltaEventDto? CreateReasoningDeltaEvent(
|
|
AgentIdentity agent,
|
|
AssistantReasoningDeltaData? data)
|
|
{
|
|
if (data is null
|
|
|| string.IsNullOrWhiteSpace(data.ReasoningId)
|
|
|| string.IsNullOrEmpty(data.DeltaContent))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new ReasoningDeltaEventDto
|
|
{
|
|
Type = "reasoning-delta",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
ReasoningId = data.ReasoningId,
|
|
ContentDelta = data.DeltaContent,
|
|
};
|
|
}
|
|
|
|
private SkillInvokedEventDto CreateSkillInvokedEvent(
|
|
AgentIdentity agent,
|
|
SkillInvokedData? data)
|
|
{
|
|
return new SkillInvokedEventDto
|
|
{
|
|
Type = "skill-invoked",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
SkillName = data?.Name ?? string.Empty,
|
|
Path = data?.Path ?? string.Empty,
|
|
Content = data?.Content ?? string.Empty,
|
|
AllowedTools = data?.AllowedTools,
|
|
PluginName = data?.PluginName,
|
|
PluginVersion = data?.PluginVersion,
|
|
};
|
|
}
|
|
|
|
private HookLifecycleEventDto CreateHookLifecycleEvent(
|
|
AgentIdentity agent,
|
|
string phase,
|
|
HookStartData? data)
|
|
{
|
|
return new HookLifecycleEventDto
|
|
{
|
|
Type = "hook-lifecycle",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
HookInvocationId = data?.HookInvocationId ?? string.Empty,
|
|
HookType = data?.HookType ?? string.Empty,
|
|
Phase = phase,
|
|
Input = data?.Input,
|
|
};
|
|
}
|
|
|
|
private HookLifecycleEventDto CreateHookLifecycleEvent(
|
|
AgentIdentity agent,
|
|
string phase,
|
|
HookEndData? data)
|
|
{
|
|
return new HookLifecycleEventDto
|
|
{
|
|
Type = "hook-lifecycle",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
HookInvocationId = data?.HookInvocationId ?? string.Empty,
|
|
HookType = data?.HookType ?? string.Empty,
|
|
Phase = phase,
|
|
Success = data?.Success,
|
|
Output = data?.Output,
|
|
Error = data?.Error?.Message,
|
|
};
|
|
}
|
|
|
|
private AssistantUsageEventDto CreateAssistantUsageEvent(
|
|
AgentIdentity agent,
|
|
AssistantUsageData? data)
|
|
{
|
|
return new AssistantUsageEventDto
|
|
{
|
|
Type = "assistant-usage",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
Model = data?.Model ?? string.Empty,
|
|
InputTokens = data?.InputTokens,
|
|
OutputTokens = data?.OutputTokens,
|
|
CacheReadTokens = data?.CacheReadTokens,
|
|
CacheWriteTokens = data?.CacheWriteTokens,
|
|
Cost = data?.Cost,
|
|
Duration = data?.Duration,
|
|
TotalNanoAiu = data?.CopilotUsage?.TotalNanoAiu,
|
|
QuotaSnapshots = QuotaSnapshotMapper.MapOrNull(data?.QuotaSnapshots),
|
|
};
|
|
}
|
|
|
|
private SessionUsageEventDto CreateUsageEvent(AgentIdentity agent, SessionUsageInfoData? data)
|
|
{
|
|
return new SessionUsageEventDto
|
|
{
|
|
Type = "session-usage",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
TokenLimit = data?.TokenLimit ?? 0,
|
|
CurrentTokens = data?.CurrentTokens ?? 0,
|
|
MessagesLength = data?.MessagesLength ?? 0,
|
|
SystemTokens = data?.SystemTokens,
|
|
ConversationTokens = data?.ConversationTokens,
|
|
ToolDefinitionsTokens = data?.ToolDefinitionsTokens,
|
|
IsInitial = data?.IsInitial,
|
|
};
|
|
}
|
|
|
|
private SessionCompactionEventDto CreateCompactionStartEvent(
|
|
AgentIdentity agent,
|
|
SessionCompactionStartData? data)
|
|
{
|
|
return new SessionCompactionEventDto
|
|
{
|
|
Type = "session-compaction",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
Phase = "start",
|
|
SystemTokens = data?.SystemTokens,
|
|
ConversationTokens = data?.ConversationTokens,
|
|
ToolDefinitionsTokens = data?.ToolDefinitionsTokens,
|
|
};
|
|
}
|
|
|
|
private SessionCompactionEventDto CreateCompactionCompleteEvent(
|
|
AgentIdentity agent,
|
|
SessionCompactionCompleteData? data)
|
|
{
|
|
return new SessionCompactionEventDto
|
|
{
|
|
Type = "session-compaction",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
Phase = "complete",
|
|
Success = data?.Success,
|
|
Error = data?.Error,
|
|
SystemTokens = data?.SystemTokens,
|
|
ConversationTokens = data?.ConversationTokens,
|
|
ToolDefinitionsTokens = data?.ToolDefinitionsTokens,
|
|
PreCompactionTokens = data?.PreCompactionTokens,
|
|
PostCompactionTokens = data?.PostCompactionTokens,
|
|
PreCompactionMessagesLength = data?.PreCompactionMessagesLength,
|
|
MessagesRemoved = data?.MessagesRemoved,
|
|
TokensRemoved = data?.TokensRemoved,
|
|
SummaryContent = data?.SummaryContent,
|
|
CheckpointNumber = data?.CheckpointNumber,
|
|
CheckpointPath = data?.CheckpointPath,
|
|
};
|
|
}
|
|
|
|
private PendingMessagesModifiedEventDto CreatePendingMessagesModifiedEvent(AgentIdentity agent)
|
|
{
|
|
return new PendingMessagesModifiedEventDto
|
|
{
|
|
Type = "pending-messages-modified",
|
|
RequestId = _command.RequestId,
|
|
SessionId = _command.SessionId,
|
|
AgentId = agent.AgentId,
|
|
AgentName = agent.AgentName,
|
|
};
|
|
}
|
|
}
|