mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-13 13:33:48 +00:00
Merge branch 'main' into custom-tokenizer
This commit is contained in:
commit
e3cb7e9734
165 files changed
+4739
-1738
No files matched your search
@@ -70,6 +70,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
private string currentWorkspaceName = string.Empty;
|
||||
private Guid currentWorkspaceId = Guid.Empty;
|
||||
private Guid currentChatThreadId = Guid.Empty;
|
||||
private int workspaceHeaderSyncVersion;
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
private HashSet<FileAttachment> chatDocumentPaths = [];
|
||||
private string tokenCount = "0";
|
||||
@@ -97,6 +98,10 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
this.currentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(Tools.Components.CHAT);
|
||||
this.userInput = this.currentChatTemplate.PredefinedUserPrompt;
|
||||
|
||||
var deferredInput = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_CHAT_INPUT).FirstOrDefault();
|
||||
if (!string.IsNullOrWhiteSpace(deferredInput))
|
||||
this.userInput = deferredInput;
|
||||
|
||||
// Apply template's file attachments, if any:
|
||||
foreach (var attachment in this.currentChatTemplate.FileAttachments)
|
||||
this.chatDocumentPaths.Add(attachment.Normalize());
|
||||
@@ -213,12 +218,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
// workspace name is loaded:
|
||||
//
|
||||
if (this.ChatThread is not null)
|
||||
{
|
||||
this.currentChatThreadId = this.ChatThread.ChatId;
|
||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
}
|
||||
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||
|
||||
// Select the correct provider:
|
||||
await this.SelectProviderWhenLoadingChat();
|
||||
@@ -235,10 +235,8 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
await this.Workspaces.StoreChatAsync(this.ChatThread);
|
||||
else
|
||||
await WorkspaceBehaviour.StoreChatAsync(this.ChatThread);
|
||||
|
||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
|
||||
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||
}
|
||||
|
||||
if (firstRender && this.mustLoadChat)
|
||||
@@ -251,9 +249,8 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
{
|
||||
await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
|
||||
this.Logger.LogInformation($"The chat '{this.ChatThread!.ChatId}' with title '{this.ChatThread.Name}' ({this.ChatThread.Blocks.Count} messages) was loaded successfully.");
|
||||
|
||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
|
||||
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||
await this.SelectProviderWhenLoadingChat();
|
||||
}
|
||||
else
|
||||
@@ -288,40 +285,59 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
private async Task SyncWorkspaceHeaderWithChatThreadAsync()
|
||||
{
|
||||
if (this.ChatThread is null)
|
||||
var syncVersion = Interlocked.Increment(ref this.workspaceHeaderSyncVersion);
|
||||
var currentChatThread = this.ChatThread;
|
||||
if (currentChatThread is null)
|
||||
{
|
||||
if (this.currentChatThreadId != Guid.Empty || this.currentWorkspaceId != Guid.Empty || !string.IsNullOrWhiteSpace(this.currentWorkspaceName))
|
||||
{
|
||||
this.currentChatThreadId = Guid.Empty;
|
||||
this.currentWorkspaceId = Guid.Empty;
|
||||
this.currentWorkspaceName = string.Empty;
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
}
|
||||
|
||||
this.ClearWorkspaceHeaderState();
|
||||
return;
|
||||
}
|
||||
|
||||
// Guard: If ChatThread ID and WorkspaceId haven't changed, skip entirely.
|
||||
// Using ID-based comparison instead of name-based to correctly handle
|
||||
// temporary chats where the workspace name is always empty.
|
||||
if (this.currentChatThreadId == this.ChatThread.ChatId
|
||||
&& this.currentWorkspaceId == this.ChatThread.WorkspaceId)
|
||||
if (this.currentChatThreadId == currentChatThread.ChatId
|
||||
&& this.currentWorkspaceId == currentChatThread.WorkspaceId)
|
||||
return;
|
||||
|
||||
this.currentChatThreadId = this.ChatThread.ChatId;
|
||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||
var loadedWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||
var chatThreadId = currentChatThread.ChatId;
|
||||
var workspaceId = currentChatThread.WorkspaceId;
|
||||
var loadedWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(workspaceId);
|
||||
|
||||
// Only notify the parent when the name actually changed to prevent
|
||||
// an infinite render loop: WorkspaceName → UpdateWorkspaceName →
|
||||
// StateHasChanged → re-render → OnParametersSetAsync → WorkspaceName → ...
|
||||
if (this.currentWorkspaceName != loadedWorkspaceName)
|
||||
{
|
||||
this.currentWorkspaceName = loadedWorkspaceName;
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
}
|
||||
// A newer sync request was started while awaiting IO. Ignore stale results.
|
||||
if (syncVersion != this.workspaceHeaderSyncVersion)
|
||||
return;
|
||||
|
||||
// The active chat changed while loading the workspace name.
|
||||
if (this.ChatThread is null
|
||||
|| this.ChatThread.ChatId != chatThreadId
|
||||
|| this.ChatThread.WorkspaceId != workspaceId)
|
||||
return;
|
||||
|
||||
this.currentChatThreadId = chatThreadId;
|
||||
this.currentWorkspaceId = workspaceId;
|
||||
this.PublishWorkspaceNameIfChanged(loadedWorkspaceName);
|
||||
}
|
||||
|
||||
|
||||
private void ClearWorkspaceHeaderState()
|
||||
{
|
||||
this.currentChatThreadId = Guid.Empty;
|
||||
this.currentWorkspaceId = Guid.Empty;
|
||||
this.PublishWorkspaceNameIfChanged(string.Empty);
|
||||
}
|
||||
|
||||
private void PublishWorkspaceNameIfChanged(string workspaceName)
|
||||
{
|
||||
// Only notify the parent when the name actually changed to prevent
|
||||
// an infinite render loop: WorkspaceName -> UpdateWorkspaceName ->
|
||||
// StateHasChanged -> re-render -> OnParametersSetAsync -> WorkspaceName -> ...
|
||||
if (this.currentWorkspaceName == workspaceName)
|
||||
return;
|
||||
|
||||
this.currentWorkspaceName = workspaceName;
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
}
|
||||
|
||||
private bool IsProviderSelected => this.Provider.UsedLLMProvider != LLMProviders.NONE;
|
||||
|
||||
private string ProviderPlaceholder => this.IsProviderSelected ? T("Type your input here...") : T("Select a provider first");
|
||||
@@ -747,10 +763,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
// to reset the chat thread:
|
||||
//
|
||||
this.ChatThread = null;
|
||||
this.currentChatThreadId = Guid.Empty;
|
||||
this.currentWorkspaceId = Guid.Empty;
|
||||
this.currentWorkspaceName = string.Empty;
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
this.ClearWorkspaceHeaderState();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -826,10 +839,8 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
this.ChatThread!.WorkspaceId = workspaceId;
|
||||
await this.SaveThread();
|
||||
|
||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
|
||||
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||
}
|
||||
|
||||
private async Task LoadedChatChanged()
|
||||
@@ -840,18 +851,12 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
if (this.ChatThread is not null)
|
||||
{
|
||||
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
|
||||
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
this.currentChatThreadId = this.ChatThread.ChatId;
|
||||
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||
this.dataSourceSelectionComponent?.ChangeOptionWithoutSaving(this.ChatThread.DataSourceOptions, this.ChatThread.AISelectedDataSources);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.currentChatThreadId = Guid.Empty;
|
||||
this.currentWorkspaceId = Guid.Empty;
|
||||
this.currentWorkspaceName = string.Empty;
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
this.ClearWorkspaceHeaderState();
|
||||
this.ApplyStandardDataSourceOptions();
|
||||
}
|
||||
|
||||
@@ -870,11 +875,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
this.isStreaming = false;
|
||||
this.hasUnsavedChanges = false;
|
||||
this.userInput = string.Empty;
|
||||
this.currentChatThreadId = Guid.Empty;
|
||||
this.currentWorkspaceId = Guid.Empty;
|
||||
|
||||
this.currentWorkspaceName = string.Empty;
|
||||
this.WorkspaceName(this.currentWorkspaceName);
|
||||
this.ClearWorkspaceHeaderState();
|
||||
|
||||
this.ChatThread = null;
|
||||
this.ApplyStandardDataSourceOptions();
|
||||
@@ -887,22 +888,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
var chatProfile = this.ChatThread?.SelectedProfile;
|
||||
var chatChatTemplate = this.ChatThread?.SelectedChatTemplate;
|
||||
|
||||
switch (this.SettingsManager.ConfigurationData.Chat.LoadingProviderBehavior)
|
||||
{
|
||||
default:
|
||||
case LoadingChatProviderBehavior.USE_CHAT_PROVIDER_IF_AVAILABLE:
|
||||
this.Provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.CHAT, chatProvider);
|
||||
break;
|
||||
|
||||
case LoadingChatProviderBehavior.ALWAYS_USE_DEFAULT_CHAT_PROVIDER:
|
||||
this.Provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.CHAT);
|
||||
break;
|
||||
|
||||
case LoadingChatProviderBehavior.ALWAYS_USE_LATEST_CHAT_PROVIDER:
|
||||
if(this.Provider == AIStudio.Settings.Provider.NONE)
|
||||
this.Provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.CHAT);
|
||||
break;
|
||||
}
|
||||
this.Provider = this.SettingsManager.GetChatProviderForLoadedChat(chatProvider);
|
||||
|
||||
await this.ProviderChanged.InvokeAsync(this.Provider);
|
||||
|
||||
|
||||
Reference in new issue
Block a user