using System.Text.Json.Serialization; namespace ClawdDotNet.Core.Config; public sealed class AgentConfig { [JsonPropertyName("agentId")] public string AgentId { get; set; } = ""; [JsonPropertyName("displayName")] public string DisplayName { get; set; } = ""; [JsonPropertyName("model")] public string Model { get; set; } = "anthropic/claude-sonnet-4-5"; [JsonPropertyName("systemPrompt")] public string SystemPrompt { get; set; } = ""; /// /// Identität des Agenten (aus Identity.md geladen). /// Definiert WER der Agent ist: Name, Rolle, Hintergrund. /// [JsonIgnore] public string Identity { get; set; } = ""; /// /// Seele des Agenten (aus Soul.md geladen). /// Definiert WIE der Agent denkt: Persönlichkeit, Werte, Verhaltensmuster. /// [JsonIgnore] public string Soul { get; set; } = ""; /// /// Lokaler Pfad zum Workspace-Verzeichnis des Agenten. /// Wird zur Laufzeit vom Host gesetzt. /// /// /// Kurzbeschreibung der Rolle/Aufgabe des Agenten. /// Wird aus AgentList.json geladen und bei list_agents angezeigt. /// [JsonIgnore] public string Description { get; set; } = ""; /// /// Absoluter Pfad zum Agent-Verzeichnis (Agent-XYZ). /// Wird zur Laufzeit gesetzt und bleibt stabil auch bei DisplayName-Änderungen. /// [JsonIgnore] public string AgentDir { get; set; } = ""; [JsonIgnore] public string WorkspacePath { get; set; } = ""; /// /// Lokaler Pfad zum geteilten Workspace-Verzeichnis (SharedWorkspace). /// Wird zur Laufzeit vom Host gesetzt. /// [JsonIgnore] public string SharedWorkspacePath { get; set; } = ""; /// /// Baut den vollständigen System-Prompt aus Identity + Soul + SystemPrompt zusammen. /// [JsonIgnore] public string FullSystemPrompt { get { var parts = new List(); if (!string.IsNullOrWhiteSpace(Identity)) parts.Add($"# Identity\n{Identity}"); if (!string.IsNullOrWhiteSpace(Soul)) parts.Add($"# Soul\n{Soul}"); if (!string.IsNullOrWhiteSpace(SystemPrompt)) parts.Add(SystemPrompt); return string.Join("\n\n", parts); } } [JsonPropertyName("tools")] public Dictionary> Tools { get; set; } = new(); [JsonPropertyName("scheduler")] public SchedulerConfig? Scheduler { get; set; } [JsonPropertyName("toolJobs")] public List ToolJobs { get; set; } = new(); [JsonPropertyName("loopGuard")] public LoopGuardConfig LoopGuard { get; set; } = new(); /// /// Prompt-Caching: "auto" (Default), "on" oder "off". /// /// Bei "auto" wird es für Modelle aktiviert, die cache_control unterstützen. /// Der Nutzen ist erheblich, weil jeder Schritt eines Runs den kompletten Prompt /// erneut sendet — System-Prompt und Tool-Definitionen also dutzendfach. /// [JsonPropertyName("promptCaching")] public string PromptCaching { get; set; } = "auto"; /// /// Maximale Länge eines einzelnen Tool-Ergebnisses in Zeichen, bevor es gekürzt in /// den Kontext wandert. Ohne Grenze kann ein einziger Abruf den gesamten Kontext /// sprengen (ein WebFetch mit 512 KB entspricht etwa 130.000 Tokens). /// [JsonPropertyName("maxToolResultChars")] public int MaxToolResultChars { get; set; } = 16_000; } public sealed class SchedulerConfig { [JsonPropertyName("cron")] public string Cron { get; set; } = ""; [JsonPropertyName("runOnStart")] public bool RunOnStart { get; set; } [JsonPropertyName("taskMessage")] public string TaskMessage { get; set; } = "Führe deine zugewiesenen Aufgaben aus."; } public sealed class LoopGuardConfig { [JsonPropertyName("maxSteps")] public int MaxSteps { get; set; } = 20; /// /// Kostenbudget für einen kompletten Run: Summe der abgerechneten Tokens über /// ALLE Schritte hinweg. /// /// Achtung — dieser Wert ist nicht mit der Kontextgröße zu verwechseln: Da jeder /// Schritt den vollständigen Kontext erneut sendet, wächst die Summe quadratisch. /// Ein Agent mit stabilem 20k-Kontext verbraucht über 10 Schritte bereits ~200k. /// Der Default ist deshalb bewusst großzügig; für die Kontextgröße ist /// zuständig. /// [JsonPropertyName("maxCumulativeTokens")] public int MaxCumulativeTokens { get; set; } = 500_000; /// /// Veraltet: hieß früher "maxTokens" und wurde fälschlich als Kontextgrenze /// verstanden, obwohl er kumulativ zählt. Wird nur noch für die Migration alter /// Konfigurationen gelesen — siehe . /// [JsonPropertyName("maxTokens")] public int? LegacyMaxTokens { get; set; } [JsonPropertyName("timeoutSeconds")] public int TimeoutSeconds { get; set; } = 600; [JsonPropertyName("maxContextTokens")] public int MaxContextTokens { get; set; } = 100_000; [JsonPropertyName("compactionThreshold")] public double CompactionThreshold { get; set; } = 0.80; /// /// Modell für die Zusammenfassung beim Kompaktieren. Leer = Modell des Agenten. /// /// Zusammenfassen ist eine anspruchslose Aufgabe; sie mit einem teuren Modell zu /// erledigen kostet leicht mehr als der halbe Run, weil bis zu 30.000 Zeichen /// verarbeitet werden. /// [JsonPropertyName("summaryModel")] public string SummaryModel { get; set; } = "google/gemini-2.5-flash"; [JsonIgnore] public TimeSpan Timeout => TimeSpan.FromSeconds(TimeoutSeconds); }