Initial commit: ClawdDotNet

Import des bestehenden Projektstands in Git.
- .NET 10 WinForms Anwendung (Multi-Agent / Tool-System)
- .gitignore fuer Build-Artefakte, Secrets und Runtime-Daten ergaenzt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-26 18:21:46 +02:00
co-authored by Claude Opus 4.8
commit 2fed388c99
154 changed files with 29736 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
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; } = "";
/// <summary>
/// Identität des Agenten (aus Identity.md geladen).
/// Definiert WER der Agent ist: Name, Rolle, Hintergrund.
/// </summary>
[JsonIgnore]
public string Identity { get; set; } = "";
/// <summary>
/// Seele des Agenten (aus Soul.md geladen).
/// Definiert WIE der Agent denkt: Persönlichkeit, Werte, Verhaltensmuster.
/// </summary>
[JsonIgnore]
public string Soul { get; set; } = "";
/// <summary>
/// Lokaler Pfad zum Workspace-Verzeichnis des Agenten.
/// Wird zur Laufzeit vom Host gesetzt.
/// </summary>
/// <summary>
/// Kurzbeschreibung der Rolle/Aufgabe des Agenten.
/// Wird aus AgentList.json geladen und bei list_agents angezeigt.
/// </summary>
[JsonIgnore]
public string Description { get; set; } = "";
/// <summary>
/// Absoluter Pfad zum Agent-Verzeichnis (Agent-XYZ).
/// Wird zur Laufzeit gesetzt und bleibt stabil auch bei DisplayName-Änderungen.
/// </summary>
[JsonIgnore]
public string AgentDir { get; set; } = "";
[JsonIgnore]
public string WorkspacePath { get; set; } = "";
/// <summary>
/// Lokaler Pfad zum geteilten Workspace-Verzeichnis (SharedWorkspace).
/// Wird zur Laufzeit vom Host gesetzt.
/// </summary>
[JsonIgnore]
public string SharedWorkspacePath { get; set; } = "";
/// <summary>
/// Baut den vollständigen System-Prompt aus Identity + Soul + SystemPrompt zusammen.
/// </summary>
[JsonIgnore]
public string FullSystemPrompt
{
get
{
var parts = new List<string>();
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<string, Dictionary<string, object?>> Tools { get; set; } = new();
[JsonPropertyName("scheduler")]
public SchedulerConfig? Scheduler { get; set; }
[JsonPropertyName("toolJobs")]
public List<ToolJobConfig> ToolJobs { get; set; } = new();
[JsonPropertyName("loopGuard")]
public LoopGuardConfig LoopGuard { get; set; } = new();
}
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;
[JsonPropertyName("maxTokens")]
public int MaxTokens { get; set; } = 80_000;
[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;
[JsonIgnore]
public TimeSpan Timeout => TimeSpan.FromSeconds(TimeoutSeconds);
}
@@ -0,0 +1,42 @@
using System.Text.Json;
namespace ClawdDotNet.Core.Config;
public static class ConfigLoader
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
PropertyNameCaseInsensitive = true
};
public static async Task<InstanceConfig> LoadAsync(string filePath, CancellationToken ct = default)
{
if (!File.Exists(filePath))
throw new FileNotFoundException($"Config file not found: {filePath}");
await using var stream = File.OpenRead(filePath);
var config = await JsonSerializer.DeserializeAsync<InstanceConfig>(stream, JsonOptions, ct)
?? throw new InvalidOperationException($"Config file is empty or invalid: {filePath}");
Validate(config, filePath);
return config;
}
private static void Validate(InstanceConfig config, string filePath)
{
if (string.IsNullOrWhiteSpace(config.OpenRouterApiKey))
throw new InvalidOperationException($"'openRouterApiKey' is required in {filePath}");
var agentIds = new HashSet<string>();
foreach (var agent in config.Agents)
{
if (string.IsNullOrWhiteSpace(agent.AgentId))
throw new InvalidOperationException($"Every agent must have an 'agentId' in {filePath}");
if (!agentIds.Add(agent.AgentId))
throw new InvalidOperationException($"Duplicate agentId '{agent.AgentId}' in {filePath}");
}
}
}
@@ -0,0 +1,48 @@
using System.Text.Json.Serialization;
namespace ClawdDotNet.Core.Config;
public sealed class InstanceConfig
{
[JsonPropertyName("instanceId")]
public string InstanceId { get; set; } = Guid.NewGuid().ToString("N")[..8];
[JsonPropertyName("instanceName")]
public string InstanceName { get; set; } = "Default";
[JsonPropertyName("openRouterApiKey")]
public string OpenRouterApiKey { get; set; } = "";
[JsonPropertyName("workingDirectory")]
public string WorkingDirectory { get; set; } = "./data/";
[JsonPropertyName("logDirectory")]
public string LogDirectory { get; set; } = "./Logs";
[JsonPropertyName("webServerPort")]
public int WebServerPort { get; set; } = 8080;
[JsonPropertyName("telegramClient")]
public TelegramClientConfig? TelegramClient { get; set; }
[JsonPropertyName("agents")]
public List<AgentConfig> Agents { get; set; } = new();
[JsonPropertyName("services")]
public List<ServiceConfig> Services { get; set; } = new();
}
public sealed class TelegramClientConfig
{
[JsonPropertyName("apiId")]
public int ApiId { get; set; }
[JsonPropertyName("apiHash")]
public string ApiHash { get; set; } = "";
[JsonPropertyName("phoneNumber")]
public string PhoneNumber { get; set; } = "";
[JsonPropertyName("password2FA")]
public string? Password2FA { get; set; }
}
@@ -0,0 +1,74 @@
using System.Text.Json.Serialization;
namespace ClawdDotNet.Core.Config;
public sealed class ServiceConfig
{
[JsonPropertyName("serviceId")]
public string ServiceId { get; set; } = Guid.NewGuid().ToString("N")[..8];
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("type")]
public string Type { get; set; } = "";
[JsonPropertyName("port")]
public int Port { get; set; }
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
[JsonPropertyName("autoStart")]
public bool AutoStart { get; set; }
[JsonPropertyName("description")]
public string Description { get; set; } = "";
[JsonPropertyName("builtIn")]
public bool BuiltIn { get; set; }
}
public static class BuiltInServices
{
public const string AgentChatWebUI = "AgentChatWebUI";
public const string AgentWebsite = "AgentWebsite";
public const string ClawdDotNetApi = "ClawdDotNetApi";
public static List<ServiceConfig> CreateDefaults() =>
[
new()
{
ServiceId = "svc_chat",
Name = "Agent Chat WebUI",
Type = AgentChatWebUI,
Port = 5080,
Enabled = true,
AutoStart = true,
BuiltIn = true,
Description = "WebUI für den Agenten-Chat (WebView2)"
},
new()
{
ServiceId = "svc_web",
Name = "Agent Website",
Type = AgentWebsite,
Port = 5081,
Enabled = false,
AutoStart = false,
BuiltIn = true,
Description = "Von Agenten entwickelte und betreute Website"
},
new()
{
ServiceId = "svc_api",
Name = "ClawdDotNet API",
Type = ClawdDotNetApi,
Port = 5082,
Enabled = true,
AutoStart = true,
BuiltIn = true,
Description = "REST-API für die Kommunikation mit der WebApp"
}
];
}
@@ -0,0 +1,24 @@
using System.Text.Json.Serialization;
namespace ClawdDotNet.Core.Config;
public sealed class ToolJobConfig
{
[JsonPropertyName("jobId")]
public string JobId { get; set; } = Guid.NewGuid().ToString("N")[..8];
[JsonPropertyName("toolName")]
public string ToolName { get; set; } = "";
[JsonPropertyName("jobTypeId")]
public string JobTypeId { get; set; } = "";
[JsonPropertyName("cron")]
public string Cron { get; set; } = "";
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
[JsonPropertyName("runOnStart")]
public bool RunOnStart { get; set; }
}