using ClawdDotNet.Core.Config;
namespace ClawdDotNet.Core.Organisation;
/// #684: A workspace an agent may use, and how far.
/// The workspace of the agent's own unit — reachable as unit.
public sealed record WorkspaceGrant(WorkspaceConfig Workspace, WorkspaceAccess Access, bool IsOwnUnit);
///
/// #684: Where the workspaces live on disk, and which names are taken.
///
/// The instance's one shared folder is Agents/SharedWorkspace, and it stays
/// there: FTP, RocketChat, the agent editor, the task files and the backups all find it by
/// that path. The workspaces with member lists live beside it, one folder each under
/// Agents/SharedWorkspaces/. Found from the shared folder's path, which every tool
/// context already carries, so nothing new has to be passed around.
///
public static class WorkspaceLayout
{
public const string Personal = "personal";
public const string Shared = "shared";
/// The own unit's workspace, without having to know the unit's id.
public const string Unit = "unit";
/// The folder next to SharedWorkspace that holds the workspaces.
public const string ContainerFolder = "SharedWorkspaces";
/// Names a workspace cannot have — they mean something else in FileRW.
public static readonly IReadOnlyList Reserved = [Personal, Shared, Unit];
/// Letters, digits, '-' and '_' — the same rule as for unit ids, since a unit's
/// workspace carries the unit's id — and not one of the reserved names.
public static bool IsValidId(string? id)
=> !string.IsNullOrWhiteSpace(id)
&& id.Length <= 64
&& id.All(c => char.IsLetterOrDigit(c) || c is '-' or '_')
&& !Reserved.Contains(id, StringComparer.OrdinalIgnoreCase);
///
/// The folder of a workspace, from the path of the instance's shared folder;
/// null when that is not configured or the id is not valid.
///
public static string? PathOf(string? sharedWorkspacePath, string workspaceId)
{
if (string.IsNullOrWhiteSpace(sharedWorkspacePath) || !IsValidId(workspaceId))
return null;
var shared = Path.GetFullPath(sharedWorkspacePath)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var agentsDirectory = Path.GetDirectoryName(shared);
return agentsDirectory is null
? null
: Path.Combine(agentsDirectory, ContainerFolder, workspaceId);
}
}