mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-13 09:53:48 +00:00
Improved the dialog for moving chats into workspaces (#796)
Build and Release / Determine run mode (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
Build and Release / Determine run mode (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
This commit is contained in:
1 parent
0b41f5eb96
commit
102b344557
13 files changed
+489
-37
No files matched your search
@@ -12,6 +12,8 @@ namespace AIStudio.Tools;
|
||||
|
||||
public static class WorkspaceBehaviour
|
||||
{
|
||||
public readonly record struct TryCreateWorkspaceResult(bool Success, WorkspaceTreeWorkspace Workspace);
|
||||
|
||||
private sealed class WorkspaceChatCacheEntry
|
||||
{
|
||||
public Guid WorkspaceId { get; init; }
|
||||
@@ -76,9 +78,9 @@ public static class WorkspaceBehaviour
|
||||
|
||||
private static readonly TimeSpan PREFETCH_DELAY_DURATION = TimeSpan.FromMilliseconds(45);
|
||||
|
||||
private static string WorkspaceRootDirectory => Path.Join(SettingsManager.DataDirectory, "workspaces");
|
||||
private static readonly string WORKSPACE_ROOT_DIRECTORY = Path.Join(SettingsManager.DataDirectory, "workspaces");
|
||||
|
||||
private static string TemporaryChatsRootDirectory => Path.Join(SettingsManager.DataDirectory, "tempChats");
|
||||
private static readonly string TEMPORARY_CHATS_ROOT_DIRECTORY = Path.Join(SettingsManager.DataDirectory, "tempChats");
|
||||
|
||||
private static SemaphoreSlim GetChatSemaphore(Guid workspaceId, Guid chatId)
|
||||
{
|
||||
@@ -156,9 +158,9 @@ public static class WorkspaceBehaviour
|
||||
private static async Task<List<WorkspaceChatCacheEntry>> ReadTemporaryChatsCoreAsync()
|
||||
{
|
||||
var chats = new List<WorkspaceChatCacheEntry>();
|
||||
Directory.CreateDirectory(TemporaryChatsRootDirectory);
|
||||
Directory.CreateDirectory(TEMPORARY_CHATS_ROOT_DIRECTORY);
|
||||
|
||||
foreach (var tempChatPath in Directory.EnumerateDirectories(TemporaryChatsRootDirectory))
|
||||
foreach (var tempChatPath in Directory.EnumerateDirectories(TEMPORARY_CHATS_ROOT_DIRECTORY))
|
||||
{
|
||||
if (!Guid.TryParse(Path.GetFileName(tempChatPath), out var chatId))
|
||||
continue;
|
||||
@@ -188,8 +190,8 @@ public static class WorkspaceBehaviour
|
||||
WORKSPACE_TREE_CACHE.Workspaces.Clear();
|
||||
WORKSPACE_TREE_CACHE.WorkspaceOrder.Clear();
|
||||
|
||||
Directory.CreateDirectory(WorkspaceRootDirectory);
|
||||
foreach (var workspacePath in Directory.EnumerateDirectories(WorkspaceRootDirectory))
|
||||
Directory.CreateDirectory(WORKSPACE_ROOT_DIRECTORY);
|
||||
foreach (var workspacePath in Directory.EnumerateDirectories(WORKSPACE_ROOT_DIRECTORY))
|
||||
{
|
||||
if (!Guid.TryParse(Path.GetFileName(workspacePath), out var workspaceId))
|
||||
continue;
|
||||
@@ -259,6 +261,13 @@ public static class WorkspaceBehaviour
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool WorkspaceNameExistsCore(string workspaceName, Guid excludedWorkspaceId = default)
|
||||
{
|
||||
return WORKSPACE_TREE_CACHE.Workspaces.Values.Any(workspace =>
|
||||
workspace.WorkspaceId != excludedWorkspaceId &&
|
||||
string.Equals(workspace.WorkspaceName.Trim(), workspaceName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static async Task<bool> ThreadContainsTermsAsync(WorkspaceTreeChat chat, IReadOnlyList<string> terms, CancellationToken token)
|
||||
{
|
||||
var (acquired, semaphore) = await TryAcquireChatSemaphoreAsync(chat.WorkspaceId, chat.ChatId, nameof(ThreadContainsTermsAsync));
|
||||
@@ -587,6 +596,100 @@ public static class WorkspaceBehaviour
|
||||
WORKSPACE_TREE_CACHE_SEMAPHORE.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static string NormalizeWorkspaceName(string workspaceName) => workspaceName.Trim();
|
||||
|
||||
public static async Task<bool> IsWorkspaceNameExistingAsync(string workspaceName, Guid excludedWorkspaceId = default)
|
||||
{
|
||||
var normalizedWorkspaceName = NormalizeWorkspaceName(workspaceName);
|
||||
if (string.IsNullOrWhiteSpace(normalizedWorkspaceName))
|
||||
return false;
|
||||
|
||||
await WORKSPACE_TREE_CACHE_SEMAPHORE.WaitAsync();
|
||||
try
|
||||
{
|
||||
await EnsureTreeShellLoadedCoreAsync();
|
||||
return WorkspaceNameExistsCore(normalizedWorkspaceName, excludedWorkspaceId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WORKSPACE_TREE_CACHE_SEMAPHORE.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<TryCreateWorkspaceResult> TryCreateWorkspaceAsync(string workspaceName)
|
||||
{
|
||||
var normalizedWorkspaceName = NormalizeWorkspaceName(workspaceName);
|
||||
if (string.IsNullOrWhiteSpace(normalizedWorkspaceName))
|
||||
return new(false, default);
|
||||
|
||||
await WORKSPACE_TREE_CACHE_SEMAPHORE.WaitAsync();
|
||||
try
|
||||
{
|
||||
await EnsureTreeShellLoadedCoreAsync();
|
||||
if (WorkspaceNameExistsCore(normalizedWorkspaceName))
|
||||
return new(false, default);
|
||||
|
||||
var workspaceId = Guid.NewGuid();
|
||||
var workspacePath = Path.Join(WORKSPACE_ROOT_DIRECTORY, workspaceId.ToString());
|
||||
Directory.CreateDirectory(workspacePath);
|
||||
|
||||
var workspaceNamePath = Path.Join(workspacePath, "name");
|
||||
await File.WriteAllTextAsync(workspaceNamePath, normalizedWorkspaceName, Encoding.UTF8);
|
||||
|
||||
var workspace = new WorkspaceCacheEntry
|
||||
{
|
||||
WorkspaceId = workspaceId,
|
||||
WorkspacePath = workspacePath,
|
||||
WorkspaceName = normalizedWorkspaceName,
|
||||
Chats = [],
|
||||
ChatsLoaded = false,
|
||||
};
|
||||
WORKSPACE_TREE_CACHE.Workspaces[workspaceId] = workspace;
|
||||
WORKSPACE_TREE_CACHE.WorkspaceOrder.Add(workspaceId);
|
||||
|
||||
return new(true, ToPublicWorkspace(workspace));
|
||||
}
|
||||
finally
|
||||
{
|
||||
WORKSPACE_TREE_CACHE_SEMAPHORE.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<bool> RenameWorkspaceAsync(Guid workspaceId, string workspaceName)
|
||||
{
|
||||
var normalizedWorkspaceName = NormalizeWorkspaceName(workspaceName);
|
||||
if (string.IsNullOrWhiteSpace(normalizedWorkspaceName))
|
||||
return false;
|
||||
|
||||
await WORKSPACE_TREE_CACHE_SEMAPHORE.WaitAsync();
|
||||
try
|
||||
{
|
||||
await EnsureTreeShellLoadedCoreAsync();
|
||||
if (!WORKSPACE_TREE_CACHE.Workspaces.TryGetValue(workspaceId, out var workspace))
|
||||
return false;
|
||||
|
||||
var workspaceNamePath = Path.Join(workspace.WorkspacePath, "name");
|
||||
if (string.Equals(workspace.WorkspaceName.Trim(), normalizedWorkspaceName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await File.WriteAllTextAsync(workspaceNamePath, normalizedWorkspaceName, Encoding.UTF8);
|
||||
workspace.WorkspaceName = normalizedWorkspaceName;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WorkspaceNameExistsCore(normalizedWorkspaceName, workspaceId))
|
||||
return false;
|
||||
|
||||
await File.WriteAllTextAsync(workspaceNamePath, normalizedWorkspaceName, Encoding.UTF8);
|
||||
workspace.WorkspaceName = normalizedWorkspaceName;
|
||||
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
WORKSPACE_TREE_CACHE_SEMAPHORE.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsChatExisting(LoadChat loadChat)
|
||||
{
|
||||
@@ -668,7 +771,7 @@ public static class WorkspaceBehaviour
|
||||
|
||||
// Not in cache — read from disk and update cache in the same semaphore scope
|
||||
// to avoid a second semaphore acquisition via UpdateWorkspaceNameInCacheAsync:
|
||||
var workspacePath = Path.Join(WorkspaceRootDirectory, workspaceId.ToString());
|
||||
var workspacePath = Path.Join(WORKSPACE_ROOT_DIRECTORY, workspaceId.ToString());
|
||||
var workspaceNamePath = Path.Join(workspacePath, "name");
|
||||
string workspaceName;
|
||||
|
||||
@@ -756,7 +859,7 @@ public static class WorkspaceBehaviour
|
||||
|
||||
private static async Task EnsureWorkspace(Guid workspaceId, string workspaceName)
|
||||
{
|
||||
var workspacePath = Path.Join(WorkspaceRootDirectory, workspaceId.ToString());
|
||||
var workspacePath = Path.Join(WORKSPACE_ROOT_DIRECTORY, workspaceId.ToString());
|
||||
var workspaceNamePath = Path.Join(workspacePath, "name");
|
||||
|
||||
if (!Path.Exists(workspacePath))
|
||||
@@ -786,4 +889,4 @@ public static class WorkspaceBehaviour
|
||||
public static async Task EnsureBiasWorkspace() => await EnsureWorkspace(KnownWorkspaces.BIAS_WORKSPACE_ID, "Bias of the Day");
|
||||
|
||||
public static async Task EnsureERIServerWorkspace() => await EnsureWorkspace(KnownWorkspaces.ERI_SERVER_WORKSPACE_ID, "ERI Servers");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user