Handle settings logs agent failures
PR and Push Build/Test / build-and-test (push) Successful in 9m8s

This commit is contained in:
2026-06-09 17:10:06 +02:00
parent 8af89a622d
commit ecdd23bde7
8 changed files with 147 additions and 15 deletions
@@ -21,6 +21,7 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
private readonly TimeSpan reconnectionDelay;
private readonly LiteLlmResponsesCompactionOptions? compactionOptions;
private readonly ILogger? logger;
private readonly Action? retrying;
private int responsesRequestCount;
public LiteLlmResponsesChatClient(
@@ -33,7 +34,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
TimeSpan reconnectionDelay,
LiteLlmResponsesCompactionOptions? compactionOptions = null,
ILogger? logger = null,
bool firstRequestIsUser = true)
bool firstRequestIsUser = true,
Action? retrying = null)
: this(
new HttpClient { BaseAddress = NormalizeEndpoint(endpoint) },
apiKey,
@@ -44,7 +46,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
reconnectionDelay,
compactionOptions,
logger,
firstRequestIsUser)
firstRequestIsUser,
retrying)
{
}
@@ -58,7 +61,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
TimeSpan reconnectionDelay,
LiteLlmResponsesCompactionOptions? compactionOptions = null,
ILogger? logger = null,
bool firstRequestIsUser = true)
bool firstRequestIsUser = true,
Action? retrying = null)
{
this.httpClient = httpClient;
this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
@@ -69,6 +73,7 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
this.reconnectionDelay = reconnectionDelay > TimeSpan.Zero ? reconnectionDelay : TimeSpan.Zero;
this.compactionOptions = compactionOptions;
this.logger = logger;
this.retrying = retrying;
responsesRequestCount = firstRequestIsUser ? 0 : 1;
}
@@ -377,6 +382,7 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
lastException = exception;
}
retrying?.Invoke();
await DelayBeforeRetryAsync(cancellationToken).ConfigureAwait(false);
}
@@ -19,5 +19,6 @@ public interface IWorkflowRulesEditorChatPipeline
Task<WorkflowRulesEditorChatResult> SendAsync(
IReadOnlyList<WorkflowRulesEditorChatMessage> conversation,
string userMessage,
CancellationToken cancellationToken);
CancellationToken cancellationToken,
Action<string>? statusChanged = null);
}
@@ -58,7 +58,8 @@ public sealed class WorkflowRulesEditorChatPipeline : IWorkflowRulesEditorChatPi
public async Task<WorkflowRulesEditorChatResult> SendAsync(
IReadOnlyList<WorkflowRulesEditorChatMessage> conversation,
string userMessage,
CancellationToken cancellationToken)
CancellationToken cancellationToken,
Action<string>? statusChanged = null)
{
if (string.IsNullOrWhiteSpace(userMessage))
{
@@ -106,7 +107,8 @@ public sealed class WorkflowRulesEditorChatPipeline : IWorkflowRulesEditorChatPi
agentOptions.ReconnectionDelay,
compactionOptions,
logger,
firstRequestIsUser: true);
firstRequestIsUser: true,
retrying: () => statusChanged?.Invoke("Reconnecting..."));
var functionClient = chatClient
.AsBuilder()
.UseFunctionInvocation(loggerFactory)
@@ -17,6 +17,8 @@ public sealed class WorkflowRulesEditorChatViewModel
public bool IsThinking { get; private set; }
public string ActivityMessage { get; private set; } = "Thinking...";
public event EventHandler? Changed;
public async Task SendAsync(CancellationToken cancellationToken = default)
@@ -31,6 +33,7 @@ public sealed class WorkflowRulesEditorChatViewModel
var priorConversation = Messages.ToList();
Messages.Add(new WorkflowRulesEditorChatMessage(WorkflowRulesEditorChatRole.User, prompt));
IsThinking = true;
ActivityMessage = "Thinking...";
OnChanged();
try
@@ -38,26 +41,39 @@ public sealed class WorkflowRulesEditorChatViewModel
var result = await pipeline.SendAsync(
priorConversation,
prompt,
cancellationToken);
cancellationToken,
SetActivityMessage);
Messages.Clear();
foreach (var message in result.Conversation)
{
Messages.Add(message);
}
}
catch (Exception exception) when (exception is not OperationCanceledException)
catch (Exception exception) when (exception is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
{
Messages.Add(new WorkflowRulesEditorChatMessage(
WorkflowRulesEditorChatRole.Agent,
$"Rules editor failed: {exception.Message}"));
$"Settings and logs failed: {exception.Message}"));
}
finally
{
IsThinking = false;
ActivityMessage = "Thinking...";
OnChanged();
}
}
private void SetActivityMessage(string message)
{
if (!IsThinking || string.IsNullOrWhiteSpace(message))
{
return;
}
ActivityMessage = message;
OnChanged();
}
private void OnChanged()
{
Changed?.Invoke(this, EventArgs.Empty);
@@ -297,7 +297,7 @@ internal sealed class WorkflowRulesEditorWpfWindow : Window
{
conversationPanel.Children.Add(new TextBlock
{
Text = "Thinking...",
Text = viewModel.ActivityMessage,
Foreground = MutedText,
Margin = new Thickness(4, 2, 4, 2)
});