Freigabe-Hygiene (#631, #579, #609, #610) und JSON-Filter fuer WebFetch (#632)

#631: Derselbe Vorschlag (gleicher Agent, gleiches Werkzeug, gleiche Argumente unabhaengig
von Schluesselreihenfolge) wird nicht erneut angelegt - der Agent erfaehrt die bestehende
Nummer. Offene Vorschlaege verfallen nach 24 h (Status Expired).

#609: Werkzeuge koennen den Freigabeschluessel aus dem Inhalt bestimmen
(IAgentTool.StagingAktion). Database: SELECT/SHOW/DESCRIBE -> query, INSERT/UPDATE/DELETE
-> write, DDL -> schema; write und schema sind freigabepflichtig. Ausgefuehrt wird nach
Statement-Art, schreibende Statements melden die Zeilenzahl.

#579: Database-Vorpruefung (Zugriffsebene, Tabellenfreigabe, SqlGuard) - was das Werkzeug
ablehnen wuerde, kommt nicht mehr in die Freigabeliste.

#610: SqlGuard ueberspringt IF [NOT] EXISTS und erkennt DESCRIBE/DESC <tabelle>.

#632: WebFetch fetch mit filter liefert aus JSON/JSONP nur passende Eintraege; beim
Blaettern durch grosses JSON empfiehlt der Hinweis den filter.

Version 0.1.10.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-18 18:51:06 +02:00
co-authored by Claude Opus 5
parent f5731c50f8
commit f74e49ba35
18 changed files with 727 additions and 29 deletions
@@ -49,4 +49,27 @@ internal sealed class InMemoryStagingRepository : IStagingRepository
public Task<int> CountPendingAsync(CancellationToken ct)
=> Task.FromResult(_calls.Values.Count(c => c.Status == StagingStatus.Pending));
public Task<IReadOnlyList<StagedCall>> ListPendingForAgentAsync(string agentId, string tool, CancellationToken ct)
=> Task.FromResult<IReadOnlyList<StagedCall>>(
_calls.Values.Where(c => c.Status == StagingStatus.Pending && c.AgentId == agentId && c.Tool == tool)
.OrderBy(c => c.Id).ToList());
public Task<int> ExpirePendingAsync(DateTime createdBefore, DateTime now, CancellationToken ct)
{
lock (_lock)
{
var alt = _calls.Values.Where(c => c.Status == StagingStatus.Pending && c.CreatedAt < createdBefore).ToList();
foreach (var c in alt)
_calls[c.Id] = c with { Status = StagingStatus.Expired, DecidedAt = now, DecidedBy = "system" };
return Task.FromResult(alt.Count);
}
}
/// <summary>Verschiebt den Anlagezeitpunkt eines Vorschlags in die Vergangenheit - fuer Verfallstests.</summary>
public void Altern(long id, TimeSpan um)
{
if (_calls.TryGetValue(id, out var call))
_calls[id] = call with { CreatedAt = call.CreatedAt - um };
}
}