Added the ability to roll back to certain chat messages and to copy an entire chat

This commit is contained in:
Peer Hogeterp committed 2026-09-22 14:22:38 +02:00
1 parent c95cc5bacc
commit 601fe727ba
12 files changed
+251 -2

No files matched your search

+21
View File
@@ -350,6 +350,27 @@ public sealed record ChatThread
this.Blocks.Remove(block);
}
/// <summary>
/// Removes every content block after the selected content in conversation order.
/// </summary>
/// <param name="content">The content to keep as the last block.</param>
/// <returns>True when one or more later blocks were removed.</returns>
public bool RemoveBlocksAfter(IContent content)
{
var sortedBlocks = this.Blocks.OrderBy(x => x.Time).ToList();
var blockIndex = sortedBlocks.FindIndex(block => ReferenceEquals(block.Content, content));
if (blockIndex < 0 || blockIndex == sortedBlocks.Count - 1)
return false;
foreach (var block in sortedBlocks.Skip(blockIndex + 1))
{
DeleteManagedAttachments(block);
this.Blocks.Remove(block);
}
return true;
}
private static void DeleteManagedAttachments(ContentBlock block)
{
if (block.Content is not ContentText textContent)
@@ -70,6 +70,12 @@
<MudIconButton Icon="@Icons.Material.Filled.Recycling" Color="Color.Default" Disabled="@(!this.RegenerateEnabled())" OnClick="@this.RegenerateBlock"/>
</MudTooltip>
}
@if (!this.IsLastContentBlock && this.Role is ChatRole.AI && this.RollbackFunc is not null)
{
<MudTooltip Text="@T("Roll back to this response")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Restore" Color="Color.Default" Disabled="@(!this.RollbackEnabled)" OnClick="@this.RollbackBlock"/>
</MudTooltip>
}
@if (this.RemoveBlockFunc is not null)
{
<MudTooltip Text="@T("Removes this block")" Placement="Placement.Bottom">
@@ -76,6 +76,9 @@ public partial class ContentBlockComponent : MSGComponentBase
[Parameter]
public Func<IContent, Task>? RegenerateFunc { get; set; }
[Parameter]
public Func<IContent, Task>? RollbackFunc { get; set; }
[Parameter]
public Func<IContent, Task>? EditLastBlockFunc { get; set; }
@@ -86,6 +89,9 @@ public partial class ContentBlockComponent : MSGComponentBase
[Parameter]
public Func<bool> RegenerateEnabled { get; set; } = () => false;
[Parameter]
public bool RollbackEnabled { get; set; }
/// <summary>
/// What the export offers, used both as the label of the export button and as the title of
/// the save dialog.
@@ -780,6 +786,21 @@ public partial class ContentBlockComponent : MSGComponentBase
if (regenerate.HasValue && regenerate.Value)
await this.RegenerateFunc(this.Content);
}
private async Task RollbackBlock()
{
if (this.RollbackFunc is null || this.Role is not ChatRole.AI || !this.RollbackEnabled)
return;
var rollback = await this.DialogService.ShowMessageBox(
T("Roll Back Chat"),
T("Do you really want to roll back this chat to this AI response? All later messages and their attachments will be permanently removed."),
T("Yes, roll back the chat"),
T("No, keep it"));
if (rollback.HasValue && rollback.Value)
await this.RollbackFunc(this.Content);
}
private async Task EditLastBlock()
{
@@ -852,4 +873,4 @@ public partial class ContentBlockComponent : MSGComponentBase
await this.DisposeMathContainerIfNeededAsync();
}
}
}