feat(ui): complete Avalonia UI port with 7 main pages, tool settings & top MenuBar
This commit is contained in:
+84
-17
@@ -3,7 +3,6 @@ using ClawdDotNet.Core.Config;
|
||||
using ClawdDotNet.Core.Engine;
|
||||
using ClawdDotNet.Core.Logging;
|
||||
using ClawdDotNet.Core.Security;
|
||||
using ClawdDotNet.Core.Scheduling;
|
||||
using ClawdDotNet.Core.Tools;
|
||||
using ClawdDotNet.Core.State;
|
||||
using ClawdDotNet.Core.Storage;
|
||||
@@ -106,6 +105,13 @@ internal static class Program
|
||||
instanceConfig.InstanceName, instanceConfig.InstanceId);
|
||||
coreLogger.LogInformation("Instanz-Verzeichnis: {Path}", instancePath);
|
||||
|
||||
// ─── 5b. Lizenzprüfung ───
|
||||
// Entfällt in dieser Fassung. Startprüfung, laufende Nachprüfung und die
|
||||
// Deploymentcenter-Anbindung (Watchdog, Updates, Fehler-Stream, Bugtracker)
|
||||
// liegen in ClawdDotNet.App (AppHost); Einstiegspunkt ist
|
||||
// src/ClawdDotNet.Desktop. Diese Datei ist nur noch Vorlage — siehe
|
||||
// ClawdDotNet.slnx.
|
||||
|
||||
// ─── 6. Core-Komponenten erzeugen ───
|
||||
var toolRegistry = new ToolRegistry();
|
||||
toolRegistry.Register(new FileRWTool());
|
||||
@@ -121,6 +127,7 @@ internal static class Program
|
||||
toolRegistry.Register(new AgentSpawnTool());
|
||||
toolRegistry.Register(new AgentEditorTool());
|
||||
toolRegistry.Register(new ClawdDotNet.Tools.Memory.MemoryTool());
|
||||
toolRegistry.Register(new ClawdDotNet.Tools.Taskboard.TaskboardTool());
|
||||
|
||||
// ─── 6a. TelegramClient (MTProto User-API) ───
|
||||
TelegramClientManager? tgClientManager = null;
|
||||
@@ -142,8 +149,9 @@ internal static class Program
|
||||
|
||||
OpenRouterClient? openRouterClient = null;
|
||||
AgentEngine? agentEngine = null;
|
||||
AgentScheduler? agentScheduler = null;
|
||||
ToolJobScheduler? toolJobScheduler = null;
|
||||
ClawdDotNet.Core.Tasks.TaskScanner? taskScanner = null;
|
||||
ClawdDotNet.Core.Staging.StagingService? stagingService = null;
|
||||
SqliteUsageRepository? usageRepository = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(instanceConfig.OpenRouterApiKey))
|
||||
{
|
||||
@@ -159,7 +167,12 @@ internal static class Program
|
||||
var storage = new SqliteStorage(Path.Combine(instancePath, "state.db"));
|
||||
var stateStore = new SqliteStateStore(storage);
|
||||
var memoryRepository = new SqliteMemoryRepository(storage);
|
||||
var usageRepository = new SqliteUsageRepository(storage);
|
||||
var taskRepository = new ClawdDotNet.Core.Tasks.SqliteTaskRepository(storage);
|
||||
var auditRepository = new ClawdDotNet.Core.Audit.SqliteAuditRepository(storage);
|
||||
var stagingRepository = new ClawdDotNet.Core.Staging.SqliteStagingRepository(storage);
|
||||
var stagingGate = new ClawdDotNet.Core.Staging.StagingGate(
|
||||
new ClawdDotNet.Core.Staging.StagingPolicy(), stagingRepository);
|
||||
usageRepository = new SqliteUsageRepository(storage);
|
||||
|
||||
// Preise fürs Budget: Ohne sie greift nur die Token-Grenze.
|
||||
var pricingCatalog = new ModelPricingCatalog();
|
||||
@@ -171,7 +184,7 @@ internal static class Program
|
||||
|
||||
agentEngine = new AgentEngine(
|
||||
openRouterClient, toolRegistry, permissionGate, stateStore, loggerFactory,
|
||||
memoryRepository, usageRepository, pricingCatalog)
|
||||
memoryRepository, usageRepository, pricingCatalog, taskRepository, auditRepository, stagingGate)
|
||||
{
|
||||
InstanceBudget = instanceConfig.Budget
|
||||
};
|
||||
@@ -185,13 +198,65 @@ internal static class Program
|
||||
return string.IsNullOrWhiteSpace(agent.AgentDir) ? null : agent.AgentDir;
|
||||
});
|
||||
agentEngine.LoadPersistedChats();
|
||||
agentScheduler = new AgentScheduler(agentEngine, instanceConfig.InstanceId, loggerFactory);
|
||||
agentScheduler.RegisterAll(instanceConfig.Agents);
|
||||
|
||||
toolJobScheduler = new ToolJobScheduler(agentEngine, toolRegistry, stateStore, loggerFactory, instanceConfig.InstanceId);
|
||||
toolJobScheduler.RegisterAll(instanceConfig.Agents);
|
||||
// ─── Taskboard: Dateien in die DB spiegeln (Reconciliation beim Start) ───
|
||||
// Verwaiste Claims eines abgestürzten Laufs lösen, dann alle Task-Dateien
|
||||
// importieren. Nicht blockierend — der Start soll nicht auf das Dateisystem warten.
|
||||
var sharedWorkspace = instanceConfig.Agents
|
||||
.Select(a => a.SharedWorkspacePath)
|
||||
.FirstOrDefault(p => !string.IsNullOrWhiteSpace(p));
|
||||
if (!string.IsNullOrWhiteSpace(sharedWorkspace))
|
||||
{
|
||||
var board = new ClawdDotNet.Core.Tasks.TaskboardService(
|
||||
taskRepository, Path.Combine(sharedWorkspace, "tasks"));
|
||||
|
||||
coreLogger.LogInformation("AgentEngine und Scheduler erstellt, Chat-Verläufe geladen");
|
||||
// Staging (A2): Freigabe-/Ablehnungs-Dienst für die Review-Oberfläche.
|
||||
// Weckt den Agenten nach der Entscheidung über einen Folge-Task (A1).
|
||||
stagingService = new ClawdDotNet.Core.Staging.StagingService(
|
||||
stagingRepository, agentEngine, board, loggerFactory, auditRepository);
|
||||
|
||||
// Scanner (A1): der Taktgeber. Startet erst, wenn die Reconciliation durch
|
||||
// ist — sonst könnte er einen noch nicht bereinigten Claim antreffen.
|
||||
// Der Scanner ist der EINZIGE periodische Treiber (A1) — er ersetzt die
|
||||
// früheren AgentScheduler/ToolJobScheduler. Geplante Agent-Läufe wie auch
|
||||
// Tool-Job-Polls sind jetzt Tasks.
|
||||
var dispatcher = new ClawdDotNet.Core.Tasks.EngineTaskDispatcher(
|
||||
agentEngine, () => instanceConfig.Agents, instanceConfig.InstanceId,
|
||||
toolRegistry, stateStore, loggerFactory);
|
||||
taskScanner = new ClawdDotNet.Core.Tasks.TaskScanner(
|
||||
taskRepository, dispatcher, loggerFactory);
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var reset = await taskRepository.ReleaseStaleClaimsAsync(
|
||||
DateTime.UtcNow.AddMinutes(-15), DateTime.UtcNow, CancellationToken.None);
|
||||
|
||||
// Einmalige Übernahme der alten coordination/task_*-Dateien …
|
||||
var coordMigration = new ClawdDotNet.Core.Tasks.CoordinationMigration(
|
||||
board, Path.Combine(sharedWorkspace, "coordination"), loggerFactory);
|
||||
var migratedCoord = await coordMigration.RunAsync(CancellationToken.None);
|
||||
|
||||
// … und der alten scheduler/toolJobs-Konfiguration in Tasks.
|
||||
var schedMigration = new ClawdDotNet.Core.Tasks.SchedulerTaskMigration(
|
||||
board, taskRepository, loggerFactory);
|
||||
var migratedSched = await schedMigration.RunAsync(instanceConfig.Agents, CancellationToken.None);
|
||||
|
||||
var imported = await board.ImportAllAsync(CancellationToken.None);
|
||||
coreLogger.LogInformation(
|
||||
"Taskboard bereit: {Imported} Aufgabe(n), migriert {Coord} coordination + {Sched} scheduler, {Reset} verwaiste Claims zurückgesetzt",
|
||||
imported, migratedCoord, migratedSched, reset);
|
||||
taskScanner.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
coreLogger.LogWarning(ex, "Taskboard-Reconciliation beim Start fehlgeschlagen");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
coreLogger.LogInformation("AgentEngine und Scanner erstellt, Chat-Verläufe geladen");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -234,6 +299,11 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 6c. Instanz-Watchdog ───
|
||||
// Entfällt hier ebenfalls. Der Heartbeat ans Deploymentcenter (ein Monitor je
|
||||
// Instanz, mit Gesundheitsprüfungen und angekündigtem Ende) steht in
|
||||
// ClawdDotNet.App/Services/DeploymentcenterService.cs.
|
||||
|
||||
// ─── 7. MainForm starten ───
|
||||
var form = new frm_main(
|
||||
settingsManager,
|
||||
@@ -244,19 +314,16 @@ internal static class Program
|
||||
toolRegistry,
|
||||
dirManager,
|
||||
agentEngine,
|
||||
agentScheduler,
|
||||
toolJobScheduler);
|
||||
taskScanner,
|
||||
stagingService);
|
||||
|
||||
Application.Run(form);
|
||||
|
||||
// ─── 8. Aufräumen ───
|
||||
coreLogger.LogInformation("ClawdDotNet wird beendet");
|
||||
|
||||
if (toolJobScheduler is not null)
|
||||
toolJobScheduler.DisposeAsync().AsTask().GetAwaiter().GetResult();
|
||||
|
||||
if (agentScheduler is not null)
|
||||
agentScheduler.DisposeAsync().AsTask().GetAwaiter().GetResult();
|
||||
if (taskScanner is not null)
|
||||
taskScanner.DisposeAsync().AsTask().GetAwaiter().GetResult();
|
||||
|
||||
if (tgClientManager is not null)
|
||||
tgClientManager.DisposeAsync().AsTask().GetAwaiter().GetResult();
|
||||
|
||||
Reference in New Issue
Block a user