FTP und RocketChat kennen die benannten Arbeitsbereiche (#718)

Gemeinsamer Helfer NamedWorkspaces in Core statt dreier Kopien: unit: und
Bereichs-Id als Praefix, Lesen braucht Read, Herunterladen braucht Write,
Unbekanntes und Verbotenes antworten gleich. Ein Dateiname aus einer
RocketChat-Nachricht waehlt keinen Bereich.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-28 10:11:02 +02:00
co-authored by Claude Opus 5.5
parent 1bf26e9ff3
commit 88c42b244d
9 changed files with 313 additions and 81 deletions
+5 -25
View File
@@ -238,35 +238,15 @@ public sealed class FileRWTool : IAgentTool, IToolStateProbe
if (name.Equals(WorkspaceLayout.Shared, StringComparison.OrdinalIgnoreCase))
return new Area(WorkspaceLayout.Shared, context.SharedWorkspacePath, SharedAccess(context), GetProtectedPaths(context));
if (context.Organisation is not { } org)
return null;
var workspace = name.Equals(WorkspaceLayout.Unit, StringComparison.OrdinalIgnoreCase)
? org.UnitWorkspace(org.UnitOf(context.AgentId)?.Id)
: org.Workspace(name);
if (workspace is null)
return null;
var access = org.AccessTo(context.AgentId, workspace.Id);
return access == WorkspaceAccess.None
? null
: new Area(workspace.Id, WorkspaceLayout.PathOf(context.SharedWorkspacePath, workspace.Id), access,
NormaliseProtectedPaths(workspace.ProtectedPaths));
// #718: the same resolution as FTP and RocketChat.
return NamedWorkspaces.Resolve(name, context.AgentId, context.Organisation, context.SharedWorkspacePath) is { } named
? new Area(named.Workspace.Id, named.Root, named.Access, NormaliseProtectedPaths(named.Workspace.ProtectedPaths))
: null;
}
/// <summary>The answer to a name that is not a workspace this agent may use — with the ones it may.</summary>
private static string UnknownWorkspace(string requested, AgentToolContext context)
{
var names = new List<string> { WorkspaceLayout.Personal };
if (SharedAccess(context) > WorkspaceAccess.None)
names.Add(WorkspaceLayout.Shared);
if (context.Organisation is { } org)
{
names.AddRange(org.WorkspacesFor(context.AgentId).Select(g =>
g.IsOwnUnit ? $"{WorkspaceLayout.Unit} (= {g.Workspace.Id})" : g.Workspace.Id));
}
return $"Unknown workspace '{requested}'. You can use: {string.Join(", ", names)}.";
}
=> NamedWorkspaces.Unknown(requested, context.AgentId, context.Organisation, SharedAccess(context) > WorkspaceAccess.None);
/// <summary>The one shared folder, by the level the agent carries for it — as before #684.</summary>
private static WorkspaceAccess SharedAccess(AgentToolContext context)