using ClawdDotNet.App.Services;
using ClawdDotNet.App.Settings;
using ClawdDotNet.Core.Config;
using ClawdDotNet.Core.Tools;
using Microsoft.Extensions.Logging.Abstractions;
using ClawdDotNet.Core.Instances;
namespace ClawdDotNet.App.Tests.Services;
///
/// Ein ohne Engine, Scanner und Netz — genug für die
/// Verwaltungsdienste.
///
/// Möglich ist das, weil AppHost.StartAsync nur ein Weg ist, einen
/// aufzubauen: Die Eigenschaften sind required init, mehr braucht es nicht. Was
/// hier fehlt — Engine, Scanner, Staging — ist auch im Betrieb
/// regelmäßig null, und genau dieses Verhalten soll geprüft werden.
///
internal sealed class TestHost : IDisposable
{
private readonly string _root;
public AppHost Host { get; }
/// Jede Änderung, die über SaveInstance gelaufen ist.
public List 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"
};
}