- ClawdDotNet.Web: Kestrel im Prozess der Anwendung, Token-Absicherung (TokenGate mit FixedTimeEquals), Endpunkte unter /api, Ereignisstrom unter /events (Server-Sent Events) und fortlaufendes Log-Streaming. - Weboberflaeche (wwwroot/): Vollstaendiges Single-Page-Frontend mit nativem HTML5, CSS3 und ES-Modulen ohne Buildschritt (strikt textContent, #-Routing, sofortiger Login-Sprung bei fehlendem Token, Light/Dark-Theme, lokale Barlow-Schriften). - ClawdDotNet.App: Fachlogik aus den Avalonia-ViewModels in Dienste herausgeloest (AgentAdministration, JobAdministration, ServiceAdministration, RunCoordinator) und ueber InstanceChange synchronisiert. - Tests: ClawdDotNet.Web.Tests und ClawdDotNet.App.Tests hinzugefuegt, alle 684 Tests erfolgreich.
68 lines
2.3 KiB
C#
68 lines
2.3 KiB
C#
using ClawdDotNet.App.Services;
|
|
using ClawdDotNet.App.Settings;
|
|
using ClawdDotNet.Core.Config;
|
|
using ClawdDotNet.Core.Tools;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
namespace ClawdDotNet.App.Tests.Services;
|
|
|
|
/// <summary>
|
|
/// Ein <see cref="AppHost"/> ohne Engine, Scanner und Netz — genug für die
|
|
/// Verwaltungsdienste.
|
|
///
|
|
/// <para>Möglich ist das, weil <c>AppHost.StartAsync</c> nur <em>ein</em> Weg ist, einen
|
|
/// aufzubauen: Die Eigenschaften sind <c>required init</c>, mehr braucht es nicht. Was
|
|
/// hier fehlt — <c>Engine</c>, <c>Scanner</c>, <c>Staging</c> — ist auch im Betrieb
|
|
/// regelmäßig null, und genau dieses Verhalten soll geprüft werden.</para>
|
|
/// </summary>
|
|
internal sealed class TestHost : IDisposable
|
|
{
|
|
private readonly string _root;
|
|
|
|
public AppHost Host { get; }
|
|
|
|
/// <summary>Jede Änderung, die über <c>SaveInstance</c> gelaufen ist.</summary>
|
|
public List<InstanceChange> Changes { get; } = [];
|
|
|
|
public TestHost(params AgentConfig[] agents)
|
|
{
|
|
_root = Path.Combine(
|
|
Path.GetTempPath(), "clawd-tests", "host-" + Guid.NewGuid().ToString("N")[..8]);
|
|
|
|
var instancesDir = Path.Combine(_root, "Instances");
|
|
var instancePath = Path.Combine(instancesDir, "Test");
|
|
|
|
Directory.CreateDirectory(instancePath);
|
|
|
|
var instance = new InstanceConfig { InstanceName = "Test" };
|
|
instance.Agents.AddRange(agents);
|
|
|
|
Host = new AppHost
|
|
{
|
|
Settings = new SettingsManager(_root),
|
|
Directories = new InstanceDirectoryManager(instancesDir),
|
|
Instance = instance,
|
|
InstancePath = instancePath,
|
|
LogDirectory = Path.Combine(_root, "Logs"),
|
|
LoggerFactory = NullLoggerFactory.Instance,
|
|
Tools = new ToolRegistry()
|
|
};
|
|
|
|
Host.InstanceChanged += Changes.Add;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try { Directory.Delete(_root, recursive: true); }
|
|
catch { /* Ein liegengebliebener Testordner ist kein Grund, einen Lauf rot zu färben. */ }
|
|
}
|
|
|
|
public static AgentConfig Agent(string agentId, string displayName = "")
|
|
=> new()
|
|
{
|
|
AgentId = agentId,
|
|
DisplayName = displayName.Length == 0 ? agentId : displayName,
|
|
Model = "anthropic/claude-sonnet-4-5"
|
|
};
|
|
}
|