#643: Entscheidungen wecken den Agenten nur noch bei Ablehnung oder gescheiterter Ausfuehrung, gesammelt in einer Aufgabe je Agent (5 min Ruhefenster), frisch per @new:agent statt im fortgefuehrten Chatverlauf. Eine einmalige Aufgabe, deren Lauf wegen Budget oder Herunterfahren gar nicht stattfand, bleibt faellig (Wiedervorlage nach 30 min) statt mit gesetztem Marker liegenzubleiben. #641: Rechte stehen in der Werkzeugkonfiguration des Agenten (erlaubt/verboten). Erlaubtes laeuft, Nicht-Erlaubtes wird einzeln vorgelegt statt verweigert, Verbotenes gar nicht erst. "Gleichartiges kuenftig erlauben" erteilt eine widerrufbare Dauerfreigabe je Agent/Werkzeug/Operation; nach drei gleichartigen Freigaben schlaegt die Oberflaeche sie vor. Aenderungen an Agenten bleiben ausnahmslos freigabepflichtig. Database: Operation ist das SQL-Schluesselwort; die eigene Zugriffspruefung greift nur noch ohne Freigabestelle (AgentToolContext.FreigabeGeprueft). WebUI: Rechte-Tabelle je Werkzeug, Dauerfreigaben mit Widerruf. Version 0.1.11. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -522,7 +522,8 @@ public sealed class AppHost : IAsyncDisposable
|
||||
var taskRepository = new SqliteTaskRepository(storage);
|
||||
var audit = new SqliteAuditRepository(storage);
|
||||
var stagingRepository = new SqliteStagingRepository(storage);
|
||||
var stagingGate = new StagingGate(new StagingPolicy(), stagingRepository);
|
||||
var dauerfreigaben = new SqliteDauerfreigabeRepository(storage);
|
||||
var stagingGate = new StagingGate(new StagingPolicy(), stagingRepository, dauerfreigaben: dauerfreigaben);
|
||||
var usage = new SqliteUsageRepository(storage);
|
||||
|
||||
// Preise fürs Budget: Ohne sie greift nur die Token-Grenze.
|
||||
@@ -555,7 +556,7 @@ public sealed class AppHost : IAsyncDisposable
|
||||
|
||||
var (scanner, staging, board) = BuildTaskboard(
|
||||
instance, taskRepository, engine, tools, stateStore, audit,
|
||||
stagingRepository, loggerFactory, logger);
|
||||
stagingRepository, dauerfreigaben, loggerFactory, logger);
|
||||
|
||||
var host = new AppHost
|
||||
{
|
||||
@@ -681,6 +682,7 @@ public sealed class AppHost : IAsyncDisposable
|
||||
SqliteStateStore stateStore,
|
||||
SqliteAuditRepository audit,
|
||||
SqliteStagingRepository stagingRepository,
|
||||
SqliteDauerfreigabeRepository dauerfreigaben,
|
||||
ILoggerFactory loggerFactory,
|
||||
ILogger logger)
|
||||
{
|
||||
@@ -693,7 +695,8 @@ public sealed class AppHost : IAsyncDisposable
|
||||
|
||||
var board = new TaskboardService(taskRepository, Path.Combine(sharedWorkspace, "tasks"));
|
||||
|
||||
var staging = new StagingService(stagingRepository, engine, board, loggerFactory, audit);
|
||||
var staging = new StagingService(stagingRepository, engine, board, loggerFactory, audit,
|
||||
dauerfreigaben: dauerfreigaben);
|
||||
|
||||
var dispatcher = new EngineTaskDispatcher(
|
||||
engine, () => instance.Agents, instance.InstanceId, tools, stateStore, loggerFactory);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using ClawdDotNet.Core.Config;
|
||||
using ClawdDotNet.Core.Instances;
|
||||
using ClawdDotNet.Core.Staging;
|
||||
|
||||
namespace ClawdDotNet.App.Services;
|
||||
|
||||
@@ -202,12 +203,62 @@ public sealed class AgentAdministration(AppHost host)
|
||||
/// <para>Einstellungen zu schreiben heißt, das Werkzeug zu wollen: Es wird dabei
|
||||
/// zugelassen, falls es das noch nicht war.</para>
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Schreibt die Rechte eines Werkzeugs (#641): was ohne Rueckfrage laeuft
|
||||
/// (<paramref name="erlaubt"/>) und was gar nicht erst vorgelegt wird
|
||||
/// (<paramref name="verboten"/>). Alles andere wird einzeln zur Freigabe vorgelegt.
|
||||
/// <paramref name="erlaubt"/> <c>null</c> entfernt die Liste - dann gilt wieder die
|
||||
/// Vorgabe des Werkzeugs.
|
||||
/// </summary>
|
||||
public AdminResult SetToolRights(
|
||||
string agentId, string toolName, IReadOnlyCollection<string>? erlaubt, IReadOnlyCollection<string> verboten)
|
||||
{
|
||||
if (Find(agentId) is not { } agent)
|
||||
return AdminResult.Failure($"Kein Agent mit der ID '{agentId}'.");
|
||||
|
||||
if (!agent.Tools.TryGetValue(toolName, out var settings))
|
||||
return AdminResult.Failure($"Werkzeug '{toolName}' ist '{agent.DisplayName}' nicht zugewiesen.");
|
||||
|
||||
static string[] Liste(IEnumerable<string> werte) => werte
|
||||
.Where(w => !string.IsNullOrWhiteSpace(w))
|
||||
.Select(Werkzeugrechte.Normalisiere)
|
||||
.Distinct()
|
||||
.Order()
|
||||
.ToArray();
|
||||
|
||||
var verbotenListe = Liste(verboten);
|
||||
var erlaubtListe = erlaubt is null ? null : Liste(erlaubt).Except(verbotenListe).ToArray();
|
||||
|
||||
if (erlaubtListe is null) settings.Remove(Werkzeugrechte.ErlaubtSchluessel);
|
||||
else settings[Werkzeugrechte.ErlaubtSchluessel] = erlaubtListe;
|
||||
|
||||
if (verbotenListe.Length == 0) settings.Remove(Werkzeugrechte.VerbotenSchluessel);
|
||||
else settings[Werkzeugrechte.VerbotenSchluessel] = verbotenListe;
|
||||
|
||||
PersistAgent(agent);
|
||||
host.SaveInstance(new InstanceChange(InstanceChangeKind.Agents, agentId));
|
||||
|
||||
return AdminResult.Success($"Rechte für '{toolName}' ({agent.DisplayName}) gespeichert.");
|
||||
}
|
||||
|
||||
public AdminResult SetToolSettings(
|
||||
string agentId, string toolName, Dictionary<string, object?> settings)
|
||||
{
|
||||
if (Find(agentId) is not { } agent)
|
||||
return AdminResult.Failure($"Kein Agent mit der ID '{agentId}'.");
|
||||
|
||||
// #641: Die Einstellungsmasken kennen die Rechte nicht und schreiben ein frisches
|
||||
// Woerterbuch. Ohne diese Uebernahme loeschte jedes Speichern still "erlaubt" und
|
||||
// "verboten" - und damit die Rechte des Agenten.
|
||||
if (agent.Tools.TryGetValue(toolName, out var bisher))
|
||||
{
|
||||
foreach (var schluessel in new[] { Werkzeugrechte.ErlaubtSchluessel, Werkzeugrechte.VerbotenSchluessel })
|
||||
{
|
||||
if (!settings.ContainsKey(schluessel) && bisher.TryGetValue(schluessel, out var wert))
|
||||
settings[schluessel] = wert;
|
||||
}
|
||||
}
|
||||
|
||||
agent.Tools[toolName] = settings;
|
||||
|
||||
PersistAgent(agent);
|
||||
|
||||
Reference in New Issue
Block a user