FileRW: Loeschen ueber den Dateiverlauf umkehrbar, ohne Freigabe; Ordner und Unaufhebbares bleiben beim Menschen (#195)
Der Dateiverlauf (#719) haelt die Vorfassung jeder geloeschten Datei - ein eigener Papierkorb waere doppelt. delete einer Datei, die der Verlauf aufhebt, laeuft ohne Freigabe; Ordner nur mit recursive:true (delete_folder, Freigabe); zu grosse Dateien oder Verlauf aus (delete_unkept, Freigabe); die Wurzel nie. Neue Aktionen deleted und restore mit voller Pfad-/Endungspruefung. IAgentTool.StagingAktion bekommt eine Ueberladung mit Kontext. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2a225129e9
commit
5de60c3b21
@@ -1655,7 +1655,7 @@ public sealed class AgentEngine : IAgentMessageRouter, Staging.IFrozenCallExecut
|
||||
if (_stagingGate is not null)
|
||||
{
|
||||
// #641: Die Rechte stehen in der Werkzeugkonfiguration des Agenten.
|
||||
var operation = tool.StagingAktion(input) ?? Staging.StagingGate.ExtractAction(arguments);
|
||||
var operation = tool.StagingAktion(input, context) ?? Staging.StagingGate.ExtractAction(arguments);
|
||||
var intercept = await _stagingGate.InterceptAsync(
|
||||
agentConfig.AgentId, instanceId, runId, toolName, arguments, ct,
|
||||
operation,
|
||||
|
||||
@@ -107,6 +107,24 @@ public sealed class FileHistory
|
||||
public bool Covers(string fullPath)
|
||||
=> !IsInside(Path.GetFullPath(fullPath), Path.Combine(_agentsDirectory, FolderName));
|
||||
|
||||
/// <summary>
|
||||
/// #195: Whether a delete of this file can be undone — the history is on, covers the file
|
||||
/// and keeps content of its size. Only then is deleting it no irreversible act.
|
||||
/// </summary>
|
||||
public bool CanKeep(string fullPath)
|
||||
{
|
||||
fullPath = Path.GetFullPath(fullPath);
|
||||
return Enabled && Covers(fullPath) && File.Exists(fullPath)
|
||||
&& new FileInfo(fullPath).Length <= (long)_settings().MaxObjectMegabytes * 1024 * 1024;
|
||||
}
|
||||
|
||||
/// <summary>#195: Whether the content of a version is still kept.</summary>
|
||||
public bool CanKeepContent(string? hash)
|
||||
=> !string.IsNullOrWhiteSpace(hash) && hash.Length == 64 && hash.All(Uri.IsHexDigit) && File.Exists(ObjectPath(hash.ToLowerInvariant()));
|
||||
|
||||
/// <summary>#195: How long a deleted file's content stays restorable.</summary>
|
||||
public int RetentionDays => Math.Max(1, _settings().RetentionDays);
|
||||
|
||||
// ─── Recording ───
|
||||
|
||||
/// <summary>Keeps the version the file has now, before a tool changes it.</summary>
|
||||
|
||||
@@ -58,6 +58,9 @@ public sealed class StagingPolicy
|
||||
["Database.truncate"] = StagingDecision.Approve,
|
||||
|
||||
["FileRW.delete"] = StagingDecision.Approve,
|
||||
// #195: FileRW names these itself — a folder at once, or a file the history cannot keep.
|
||||
["FileRW.delete_folder"] = StagingDecision.Approve,
|
||||
["FileRW.delete_unkept"] = StagingDecision.Approve,
|
||||
["FTP.upload"] = StagingDecision.Approve,
|
||||
["FTP.delete"] = StagingDecision.Approve,
|
||||
|
||||
|
||||
@@ -77,6 +77,13 @@ public interface IAgentTool
|
||||
/// </summary>
|
||||
string? StagingAktion(JsonElement input) => null;
|
||||
|
||||
/// <summary>
|
||||
/// #195: The staging key with the call's context — for a key that depends on what the call
|
||||
/// meets (FileRW: a file the history keeps, a folder, a file too large to keep). Default:
|
||||
/// <see cref="StagingAktion(JsonElement)"/>.
|
||||
/// </summary>
|
||||
string? StagingAktion(JsonElement input, AgentToolContext context) => StagingAktion(input);
|
||||
|
||||
/// <summary>
|
||||
/// Die Operationen, die sich in der Werkzeugkonfiguration eines Agenten erlauben oder
|
||||
/// verbieten lassen (#641) - dieselben Schluessel, die <see cref="StagingAktion"/> bzw. das
|
||||
|
||||
Reference in New Issue
Block a user