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

@@ -26,6 +26,8 @@
IsSecondToLastBlock="@isSecondLastBlock"
RegenerateFunc="@this.RegenerateBlock"
RegenerateEnabled="@(() => this.IsProviderSelected && this.ChatThread.IsLLMProviderAllowed(this.Provider))"
RollbackFunc="@this.RollbackBlock"
RollbackEnabled="@(!this.IsCurrentChatStreaming)"
EditLastBlockFunc="@this.EditLastBlock"
EditLastUserBlockFunc="@this.EditLastUserBlock"/>
}
@@ -1394,6 +1394,24 @@ public partial class ChatComponent : MSGComponentBase
await this.SendMessage(reuseLastUserPrompt: true);
}
private async Task RollbackBlock(IContent aiBlock)
{
if (this.ChatThread is null || this.IsCurrentChatStreaming)
return;
if (!this.ChatThread.RemoveBlocksAfter(aiBlock))
return;
this.ChatThread.AugmentedData = string.Empty;
this.ChatThread.AISelectedDataSources = [];
this.dataSourceSelectionComponent?.ChangeOptionWithoutSaving(this.ChatThread.DataSourceOptions, this.ChatThread.AISelectedDataSources);
this.hasUnsavedChanges = true;
await this.SaveThread();
this.tokenTracker?.Nudge();
this.StateHasChanged();
await this.inputField.FocusAsync();
}
private Task EditLastUserBlock(IContent block)
{
@@ -81,6 +81,10 @@ else
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Size="Size.Medium" Color="Color.Inherit" Disabled="@this.IsChatTreeItemBusy(treeItem)" OnClick="@(() => this.MoveChatAsync(treeItem.Path))"/>
</MudTooltip>
<MudTooltip Text="@T("Copy chat")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Size="Size.Medium" Color="Color.Inherit" Disabled="@this.IsChatTreeItemBusy(treeItem)" OnClick="@(() => this.CopyChatAsync(treeItem.Path))"/>
</MudTooltip>
<MudTooltip Text="@T("Rename")" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Medium" Color="Color.Inherit" Disabled="@this.IsChatTreeItemBusy(treeItem)" OnClick="@(() => this.RenameChatAsync(treeItem.Path))"/>
</MudTooltip>
@@ -148,4 +152,4 @@ else
}
</ItemTemplate>
</MudTreeView>
}
}
@@ -781,6 +781,37 @@ public partial class Workspaces : MSGComponentBase
await this.LoadTreeItemsAsync(startPrefetch: false);
}
private async Task CopyChatAsync(string? chatPath)
{
var chat = await this.LoadChatAsync(chatPath, false);
if (chat is null)
return;
var mediaOwner = MediaImportOwner.ForChat(chat.ChatId);
if (this.AIJobService.IsChatGenerationActive(chat.ChatId) || this.MediaTranscriptionService.IsBusy(mediaOwner))
return;
if (await MessageBus.INSTANCE.SendMessageUseFirstResult<bool, bool>(this, Event.HAS_CHAT_UNSAVED_CHANGES))
{
var dialogParameters = new DialogParameters<ConfirmDialog>
{
{ x => x.Message, T("Are you sure you want to load another chat? All unsaved changes will be lost.") },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Copy Chat"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
}
var sourceChat = this.CurrentChatThread is { } currentChat && currentChat.ChatId == chat.ChatId ? currentChat : chat;
var copy = await WorkspaceBehaviour.CopyChatAsync(sourceChat);
await this.LoadTreeItemsAsync(startPrefetch: false);
this.CurrentChatThread = copy;
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
}
private async Task RenameWorkspaceAsync(string? workspacePath)
{
if (workspacePath is null)