mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 11:59:48 +00:00
Implemented feature to start new chats from a workspace
This commit is contained in:
parent
ce8f50ee66
commit
733b2b1ac9
@ -14,7 +14,16 @@
|
|||||||
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="() => this.LoadChat(treeItem.Path, true)">
|
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="() => this.LoadChat(treeItem.Path, true)">
|
||||||
<BodyContent>
|
<BodyContent>
|
||||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||||
<MudText Style="justify-self: start;">@treeItem.Text</MudText>
|
<MudText Style="justify-self: start;">
|
||||||
|
@if (string.IsNullOrWhiteSpace(treeItem.Text))
|
||||||
|
{
|
||||||
|
@("Empty chat")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@treeItem.Text
|
||||||
|
}
|
||||||
|
</MudText>
|
||||||
<div style="justify-self: end;">
|
<div style="justify-self: end;">
|
||||||
|
|
||||||
<MudTooltip Text="Move to workspace" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
<MudTooltip Text="Move to workspace" Placement="@WORKSPACE_ITEM_TOOLTIP_PLACEMENT">
|
||||||
|
@ -20,12 +20,18 @@ public partial class Workspaces : ComponentBase
|
|||||||
[Inject]
|
[Inject]
|
||||||
private IDialogService DialogService { get; set; } = null!;
|
private IDialogService DialogService { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public Random RNG { get; set; } = null!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public ChatThread? CurrentChatThread { get; set; }
|
public ChatThread? CurrentChatThread { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<ChatThread> CurrentChatThreadChanged { get; set; }
|
public EventCallback<ChatThread> CurrentChatThreadChanged { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Func<Task> LoadedChatWasChanged { get; set; } = () => Task.CompletedTask;
|
||||||
|
|
||||||
private const Placement WORKSPACE_ITEM_TOOLTIP_PLACEMENT = Placement.Bottom;
|
private const Placement WORKSPACE_ITEM_TOOLTIP_PLACEMENT = Placement.Bottom;
|
||||||
|
|
||||||
private static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
private static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||||
@ -123,7 +129,7 @@ public partial class Workspaces : ComponentBase
|
|||||||
return tempChildren;
|
return tempChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> LoadWorkspaceName(Guid workspaceId)
|
public async Task<string> LoadWorkspaceName(Guid workspaceId)
|
||||||
{
|
{
|
||||||
if(workspaceId == Guid.Empty)
|
if(workspaceId == Guid.Empty)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
@ -238,6 +244,7 @@ public partial class Workspaces : ComponentBase
|
|||||||
{
|
{
|
||||||
this.CurrentChatThread = chat;
|
this.CurrentChatThread = chat;
|
||||||
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
||||||
|
await this.LoadedChatWasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
return chat;
|
return chat;
|
||||||
@ -289,6 +296,7 @@ public partial class Workspaces : ComponentBase
|
|||||||
{
|
{
|
||||||
this.CurrentChatThread = null;
|
this.CurrentChatThread = null;
|
||||||
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
||||||
|
await this.LoadedChatWasChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,11 +437,12 @@ public partial class Workspaces : ComponentBase
|
|||||||
// Update the chat's workspace:
|
// Update the chat's workspace:
|
||||||
chat.WorkspaceId = workspaceId;
|
chat.WorkspaceId = workspaceId;
|
||||||
|
|
||||||
// Handle the case, where the chat is the active chat:
|
// Handle the case where the chat is the active chat:
|
||||||
if (this.CurrentChatThread?.ChatId == chat.ChatId)
|
if (this.CurrentChatThread?.ChatId == chat.ChatId)
|
||||||
{
|
{
|
||||||
this.CurrentChatThread = chat;
|
this.CurrentChatThread = chat;
|
||||||
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
||||||
|
await this.LoadedChatWasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.StoreChat(chat);
|
await this.StoreChat(chat);
|
||||||
@ -441,6 +450,21 @@ public partial class Workspaces : ComponentBase
|
|||||||
|
|
||||||
private async Task AddChat(string workspacePath)
|
private async Task AddChat(string workspacePath)
|
||||||
{
|
{
|
||||||
|
var workspaceId = Guid.Parse(Path.GetFileName(workspacePath));
|
||||||
|
var chat = new ChatThread
|
||||||
|
{
|
||||||
|
WorkspaceId = workspaceId,
|
||||||
|
ChatId = Guid.NewGuid(),
|
||||||
|
Name = string.Empty,
|
||||||
|
Seed = this.RNG.Next(),
|
||||||
|
SystemPrompt = "You are a helpful assistant!",
|
||||||
|
Blocks = [],
|
||||||
|
};
|
||||||
|
|
||||||
|
var chatPath = Path.Join(workspacePath, chat.ChatId.ToString());
|
||||||
|
|
||||||
|
await this.StoreChat(chat);
|
||||||
|
await this.LoadChat(chatPath, switchToChat: true);
|
||||||
|
await this.LoadTreeItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,14 @@
|
|||||||
@using AIStudio.Settings
|
@using AIStudio.Settings
|
||||||
|
|
||||||
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||||
Chats
|
@if (this.chatThread is not null && this.chatThread.WorkspaceId != Guid.Empty)
|
||||||
|
{
|
||||||
|
@($"Chat in Workspace \"{this.currentWorkspaceName}\"")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@("Temporary Chat")
|
||||||
|
}
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
<MudSelect T="Provider" @bind-Value="@this.selectedProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-2 rounded-lg" Variant="Variant.Outlined">
|
<MudSelect T="Provider" @bind-Value="@this.selectedProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-2 rounded-lg" Variant="Variant.Outlined">
|
||||||
@ -67,7 +74,7 @@
|
|||||||
</MudStack>
|
</MudStack>
|
||||||
</MudDrawerHeader>
|
</MudDrawerHeader>
|
||||||
<MudDrawerContainer Class="ml-6">
|
<MudDrawerContainer Class="ml-6">
|
||||||
<Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread"/>
|
<Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread" LoadedChatWasChanged="this.LoadedChatChanged"/>
|
||||||
</MudDrawerContainer>
|
</MudDrawerContainer>
|
||||||
</MudDrawer>
|
</MudDrawer>
|
||||||
}
|
}
|
@ -36,6 +36,7 @@ public partial class Chat : ComponentBase, IAsyncDisposable
|
|||||||
private bool hasUnsavedChanges;
|
private bool hasUnsavedChanges;
|
||||||
private bool isStreaming;
|
private bool isStreaming;
|
||||||
private string userInput = string.Empty;
|
private string userInput = string.Empty;
|
||||||
|
private string currentWorkspaceName = string.Empty;
|
||||||
private bool workspacesVisible;
|
private bool workspacesVisible;
|
||||||
private Workspaces? workspaces;
|
private Workspaces? workspaces;
|
||||||
|
|
||||||
@ -71,15 +72,25 @@ public partial class Chat : ComponentBase, IAsyncDisposable
|
|||||||
|
|
||||||
// Create a new chat thread if necessary:
|
// Create a new chat thread if necessary:
|
||||||
var threadName = this.ExtractThreadName(this.userInput);
|
var threadName = this.ExtractThreadName(this.userInput);
|
||||||
this.chatThread ??= new()
|
|
||||||
|
if (this.chatThread is null)
|
||||||
{
|
{
|
||||||
WorkspaceId = Guid.Empty,
|
this.chatThread = new()
|
||||||
ChatId = Guid.NewGuid(),
|
{
|
||||||
Name = threadName,
|
WorkspaceId = Guid.Empty,
|
||||||
Seed = this.RNG.Next(),
|
ChatId = Guid.NewGuid(),
|
||||||
SystemPrompt = "You are a helpful assistant!",
|
Name = threadName,
|
||||||
Blocks = [],
|
Seed = this.RNG.Next(),
|
||||||
};
|
SystemPrompt = "You are a helpful assistant!",
|
||||||
|
Blocks = [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set the thread name if it is empty:
|
||||||
|
if (string.IsNullOrWhiteSpace(this.chatThread.Name))
|
||||||
|
this.chatThread.Name = threadName;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Add the user message to the thread:
|
// Add the user message to the thread:
|
||||||
@ -226,6 +237,7 @@ public partial class Chat : ComponentBase, IAsyncDisposable
|
|||||||
this.isStreaming = false;
|
this.isStreaming = false;
|
||||||
this.hasUnsavedChanges = false;
|
this.hasUnsavedChanges = false;
|
||||||
this.userInput = string.Empty;
|
this.userInput = string.Empty;
|
||||||
|
this.currentWorkspaceName = string.Empty;
|
||||||
await this.inputField.Clear();
|
await this.inputField.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +279,21 @@ public partial class Chat : ComponentBase, IAsyncDisposable
|
|||||||
|
|
||||||
this.chatThread!.WorkspaceId = workspaceId;
|
this.chatThread!.WorkspaceId = workspaceId;
|
||||||
await this.SaveThread();
|
await this.SaveThread();
|
||||||
|
|
||||||
|
this.currentWorkspaceName = await this.workspaces.LoadWorkspaceName(this.chatThread.WorkspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadedChatChanged()
|
||||||
|
{
|
||||||
|
if(this.workspaces is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.isStreaming = false;
|
||||||
|
this.hasUnsavedChanges = false;
|
||||||
|
this.userInput = string.Empty;
|
||||||
|
this.currentWorkspaceName = this.chatThread is null ? string.Empty : await this.workspaces.LoadWorkspaceName(this.chatThread.WorkspaceId);
|
||||||
|
|
||||||
|
await this.inputField.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Implementation of IAsyncDisposable
|
#region Implementation of IAsyncDisposable
|
||||||
|
Loading…
Reference in New Issue
Block a user