feat(agent): harden loop recovery and permission hook lifecycle
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
This commit is contained in:
@@ -580,12 +580,10 @@ public sealed class ChatSessionStateService
|
||||
conversation.AgentRunHistory ??= new List<ChatAgentRunRecord>();
|
||||
conversation.DraftQueueItems ??= new List<DraftQueueItem>();
|
||||
|
||||
var orderedEvents = conversation.ExecutionEvents
|
||||
.OrderBy(evt => evt.Timestamp == default ? DateTime.MinValue : evt.Timestamp)
|
||||
.ToList();
|
||||
if (!conversation.ExecutionEvents.SequenceEqual(orderedEvents))
|
||||
var normalizedEvents = NormalizeExecutionEventsForResume(conversation.ExecutionEvents);
|
||||
if (!conversation.ExecutionEvents.SequenceEqual(normalizedEvents))
|
||||
{
|
||||
conversation.ExecutionEvents = orderedEvents;
|
||||
conversation.ExecutionEvents = normalizedEvents;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -640,6 +638,55 @@ public sealed class ChatSessionStateService
|
||||
return delta <= TimeSpan.FromSeconds(2);
|
||||
}
|
||||
|
||||
private static List<ChatExecutionEvent> NormalizeExecutionEventsForResume(IEnumerable<ChatExecutionEvent>? source)
|
||||
{
|
||||
if (source == null)
|
||||
return new List<ChatExecutionEvent>();
|
||||
|
||||
var ordered = source
|
||||
.Where(evt => evt != null)
|
||||
.OrderBy(evt => evt.Timestamp == default ? DateTime.MinValue : evt.Timestamp)
|
||||
.ThenBy(evt => evt.Iteration)
|
||||
.ThenBy(evt => evt.ElapsedMs)
|
||||
.ToList();
|
||||
|
||||
var result = new List<ChatExecutionEvent>(ordered.Count);
|
||||
foreach (var evt in ordered)
|
||||
{
|
||||
if (result.Count == 0)
|
||||
{
|
||||
result.Add(evt);
|
||||
continue;
|
||||
}
|
||||
|
||||
var last = result[^1];
|
||||
if (!IsNearDuplicateExecutionEvent(last, evt))
|
||||
{
|
||||
result.Add(evt);
|
||||
continue;
|
||||
}
|
||||
|
||||
last.Timestamp = evt.Timestamp;
|
||||
last.ElapsedMs = Math.Max(last.ElapsedMs, evt.ElapsedMs);
|
||||
last.InputTokens = Math.Max(last.InputTokens, evt.InputTokens);
|
||||
last.OutputTokens = Math.Max(last.OutputTokens, evt.OutputTokens);
|
||||
last.StepCurrent = Math.Max(last.StepCurrent, evt.StepCurrent);
|
||||
last.StepTotal = Math.Max(last.StepTotal, evt.StepTotal);
|
||||
last.Iteration = Math.Max(last.Iteration, evt.Iteration);
|
||||
if (string.IsNullOrWhiteSpace(last.FilePath))
|
||||
last.FilePath = evt.FilePath;
|
||||
if (!string.IsNullOrWhiteSpace(evt.Summary) && evt.Summary.Length >= (last.Summary?.Length ?? 0))
|
||||
last.Summary = evt.Summary;
|
||||
if (evt.Steps is { Count: > 0 })
|
||||
last.Steps = evt.Steps.ToList();
|
||||
if (!string.IsNullOrWhiteSpace(evt.ToolInput))
|
||||
last.ToolInput = evt.ToolInput;
|
||||
last.Success = last.Success && evt.Success;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void TouchConversation(ChatStorageService? storage, string tab)
|
||||
{
|
||||
var conv = EnsureCurrentConversation(tab);
|
||||
|
||||
Reference in New Issue
Block a user