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:
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Eintrag in der AgentList.json – Basisinformationen zu einem Agenten.
|
||||
/// Liegt im Agents/-Ordner einer Instanz.
|
||||
/// </summary>
|
||||
public sealed class AgentListItem
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("folderName")]
|
||||
public string FolderName { get; set; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Root-Objekt der AgentList.json
|
||||
/// </summary>
|
||||
public sealed class AgentListFile
|
||||
{
|
||||
[JsonPropertyName("agents")]
|
||||
public List<AgentListItem> Agents { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
using System.ComponentModel;
|
||||
using ClawdDotNet.Core.Config;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public sealed class AgentSettingsViewModel
|
||||
{
|
||||
private readonly AgentConfig _config;
|
||||
|
||||
public AgentSettingsViewModel(AgentConfig config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
// ──────────────── Identity ────────────────
|
||||
|
||||
[Category("1 - Identity")]
|
||||
[DisplayName("Agent-ID")]
|
||||
[Description("Eindeutige ID des Agenten. Wird intern und in Logs verwendet.")]
|
||||
[ReadOnly(true)]
|
||||
public string AgentId => _config.AgentId;
|
||||
|
||||
[Category("1 - Identity")]
|
||||
[DisplayName("Anzeigename")]
|
||||
[Description("Freundlicher Name des Agenten (z.B. 'Marktanalyst').")]
|
||||
public string DisplayName
|
||||
{
|
||||
get => _config.DisplayName;
|
||||
set => _config.DisplayName = value;
|
||||
}
|
||||
|
||||
[Category("1 - Identity")]
|
||||
[DisplayName("Modell")]
|
||||
[Description("LLM-Modell das dieser Agent verwendet. Dropdown zeigt verfügbare Modelle von OpenRouter.")]
|
||||
[TypeConverter(typeof(ModelTypeConverter))]
|
||||
public string Model
|
||||
{
|
||||
get => _config.Model;
|
||||
set => _config.Model = value;
|
||||
}
|
||||
|
||||
[Category("1 - Identity")]
|
||||
[DisplayName("Identity")]
|
||||
[Description("Aus Identity.md geladen – definiert WER der Agent ist. Bearbeitung über den Toolbar-Button 'Identity bearbeiten'.")]
|
||||
[ReadOnly(true)]
|
||||
public string IdentityStatus =>
|
||||
string.IsNullOrWhiteSpace(_config.Identity) ? "(nicht definiert)" : $"✔ {_config.Identity.Split('\n').Length} Zeilen";
|
||||
|
||||
[Category("1 - Identity")]
|
||||
[DisplayName("Soul")]
|
||||
[Description("Aus Soul.md geladen – definiert WIE der Agent denkt. Bearbeitung über den Toolbar-Button 'Soul bearbeiten'.")]
|
||||
[ReadOnly(true)]
|
||||
public string SoulStatus =>
|
||||
string.IsNullOrWhiteSpace(_config.Soul) ? "(nicht definiert)" : $"✔ {_config.Soul.Split('\n').Length} Zeilen";
|
||||
|
||||
// ──────────────── Loop-Schutz ────────────────
|
||||
|
||||
[Category("2 - Loop-Schutz")]
|
||||
[DisplayName("Max. Schritte pro Run")]
|
||||
[Description("Maximale Anzahl LLM-Aufrufe pro Run. Verhindert Endlosschleifen bei fehlerhaften Tool-Calls.")]
|
||||
public int MaxSteps
|
||||
{
|
||||
get => _config.LoopGuard.MaxSteps;
|
||||
set => _config.LoopGuard.MaxSteps = Math.Max(1, value);
|
||||
}
|
||||
|
||||
[Category("2 - Loop-Schutz")]
|
||||
[DisplayName("Max. Tokens pro Run")]
|
||||
[Description("Maximale Token-Anzahl pro einzelnem Run (Summe aller Schritte). Schützt vor unkontrollierten Kosten.")]
|
||||
public int MaxTokens
|
||||
{
|
||||
get => _config.LoopGuard.MaxTokens;
|
||||
set => _config.LoopGuard.MaxTokens = Math.Max(1000, value);
|
||||
}
|
||||
|
||||
[Category("2 - Loop-Schutz")]
|
||||
[DisplayName("Timeout (Sekunden)")]
|
||||
[Description("Maximale Laufzeit pro Run in Sekunden. Danach wird der Run abgebrochen.")]
|
||||
public int TimeoutSeconds
|
||||
{
|
||||
get => _config.LoopGuard.TimeoutSeconds;
|
||||
set => _config.LoopGuard.TimeoutSeconds = Math.Max(10, value);
|
||||
}
|
||||
|
||||
// ──────────────── Kontext-Management ────────────────
|
||||
|
||||
[Category("3 - Kontext-Management")]
|
||||
[DisplayName("Max. Kontext-Tokens")]
|
||||
[Description("Maximales Token-Budget für den gesamten Konversationskontext. Bei Überschreitung wird automatisch kompaktiert.")]
|
||||
public int MaxContextTokens
|
||||
{
|
||||
get => _config.LoopGuard.MaxContextTokens;
|
||||
set => _config.LoopGuard.MaxContextTokens = Math.Max(10_000, value);
|
||||
}
|
||||
|
||||
[Category("3 - Kontext-Management")]
|
||||
[DisplayName("Kompaktierungs-Schwelle (%)")]
|
||||
[Description("Ab welchem Prozentsatz der Max. Kontext-Tokens wird kompaktiert. 80 = bei 80% Auslastung. Stufe 1: Tool-Results kürzen. Stufe 2: LLM-Zusammenfassung.")]
|
||||
public int CompactionThresholdPercent
|
||||
{
|
||||
get => (int)(_config.LoopGuard.CompactionThreshold * 100);
|
||||
set => _config.LoopGuard.CompactionThreshold = Math.Clamp(value, 50, 95) / 100.0;
|
||||
}
|
||||
|
||||
// ──────────────── Tools (Read-Only) ────────────────
|
||||
|
||||
[Category("4 - Tools")]
|
||||
[DisplayName("Zugewiesene Tools")]
|
||||
[Description("Liste der Tool-Namen, die diesem Agent zugewiesen sind. Zuweisung über die Tabelle unten.")]
|
||||
[ReadOnly(true)]
|
||||
public string AssignedTools =>
|
||||
_config.Tools.Count == 0
|
||||
? "(keine)"
|
||||
: string.Join(", ", _config.Tools.Keys);
|
||||
|
||||
[Category("4 - Tools")]
|
||||
[DisplayName("Anzahl")]
|
||||
[ReadOnly(true)]
|
||||
public int ToolCount => _config.Tools.Count;
|
||||
|
||||
// ──────────────── Intern ────────────────
|
||||
|
||||
[Browsable(false)]
|
||||
public AgentConfig UnderlyingConfig => _config;
|
||||
|
||||
public override string ToString() =>
|
||||
string.IsNullOrWhiteSpace(_config.DisplayName) ? _config.AgentId : _config.DisplayName;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
public sealed class AgentToolDisplayEntry
|
||||
{
|
||||
public bool Assigned { get; set; }
|
||||
public string ToolName { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public sealed class AppSettings
|
||||
{
|
||||
[Category("Allgemein")]
|
||||
[DisplayName("Log-Verzeichnis")]
|
||||
[Description("Pfad zum Verzeichnis, in dem Log-Dateien gespeichert werden.")]
|
||||
[JsonPropertyName("logDirectory")]
|
||||
public string LogDirectory { get; set; } = "./Logs";
|
||||
|
||||
[Category("Allgemein")]
|
||||
[DisplayName("Instanzen-Verzeichnis")]
|
||||
[Description("Pfad zum Verzeichnis, in dem alle Instanz-Ordner liegen.")]
|
||||
[JsonPropertyName("instancesDirectory")]
|
||||
public string InstancesDirectory { get; set; } = "./Instances";
|
||||
|
||||
[Category("Allgemein")]
|
||||
[DisplayName("Standard-Konfigurations-Datei")]
|
||||
[Description("Pfad zur Standard-Instanz-Konfiguration (Legacy). Neue Instanzen nutzen das Instanzen-Verzeichnis.")]
|
||||
[JsonPropertyName("defaultConfigPath")]
|
||||
public string DefaultConfigPath { get; set; } = "./configs/config.json";
|
||||
|
||||
[Category("Allgemein")]
|
||||
[DisplayName("Minimaler Log-Level")]
|
||||
[Description("Minimaler Log-Level für die Datei-Logs (Debug, Info, Warn, Error).")]
|
||||
[JsonPropertyName("minimumLogLevel")]
|
||||
public string MinimumLogLevel { get; set; } = "Info";
|
||||
|
||||
[Category("UI")]
|
||||
[DisplayName("Max. Log-Zeilen in UI")]
|
||||
[Description("Maximale Anzahl Zeilen in der Log-RichTextBox bevor bereinigt wird.")]
|
||||
[JsonPropertyName("maxLogLinesInUi")]
|
||||
public int MaxLogLinesInUi { get; set; } = 2000;
|
||||
|
||||
[Category("UI")]
|
||||
[DisplayName("Log-Aktualisierungsintervall (ms)")]
|
||||
[Description("Intervall in Millisekunden, in dem die Log-Anzeige aktualisiert wird.")]
|
||||
[JsonPropertyName("logRefreshIntervalMs")]
|
||||
public int LogRefreshIntervalMs { get; set; } = 500;
|
||||
|
||||
[Category("API")]
|
||||
[DisplayName("Status-Check-Intervall (Sek)")]
|
||||
[Description("Intervall in Sekunden für den OpenRouter-API-Status-Check.")]
|
||||
[JsonPropertyName("statusCheckIntervalSeconds")]
|
||||
public int StatusCheckIntervalSeconds { get; set; } = 60;
|
||||
|
||||
[Category("API")]
|
||||
[DisplayName("OpenRouter Base-URL")]
|
||||
[Description("Basis-URL der OpenRouter-API.")]
|
||||
[JsonPropertyName("openRouterBaseUrl")]
|
||||
public string OpenRouterBaseUrl { get; set; } = "https://openrouter.ai/api/v1/";
|
||||
|
||||
public override string ToString() => "Anwendungseinstellungen";
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Zusammenfassung einer Instanz für die Anzeige im InstanceManager.
|
||||
/// </summary>
|
||||
public sealed class InstanceInfo
|
||||
{
|
||||
public string InstanceName { get; set; } = "";
|
||||
public string FolderName { get; set; } = "";
|
||||
public string FolderPath { get; set; } = "";
|
||||
public int AgentCount { get; set; }
|
||||
public string ApiKeyStatus { get; set; } = "—";
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System.ComponentModel;
|
||||
using ClawdDotNet.Core.Config;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyGrid-freundlicher Wrapper um InstanceConfig.
|
||||
/// Änderungen werden direkt im zugrunde liegenden InstanceConfig-Objekt gespeichert.
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public sealed class InstanceSettingsViewModel
|
||||
{
|
||||
private readonly InstanceConfig _config;
|
||||
|
||||
public InstanceSettingsViewModel(InstanceConfig config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
[Category("Instanz")]
|
||||
[DisplayName("Instanz-ID")]
|
||||
[Description("Eindeutige ID dieser laufenden Instanz.")]
|
||||
public string InstanceId
|
||||
{
|
||||
get => _config.InstanceId;
|
||||
set => _config.InstanceId = value;
|
||||
}
|
||||
|
||||
[Category("Instanz")]
|
||||
[DisplayName("Instanzname")]
|
||||
[Description("Anzeigename dieser Instanz (z.B. 'Aktien-Team').")]
|
||||
public string InstanceName
|
||||
{
|
||||
get => _config.InstanceName;
|
||||
set => _config.InstanceName = value;
|
||||
}
|
||||
|
||||
[Category("API")]
|
||||
[DisplayName("OpenRouter API-Key")]
|
||||
[Description("API-Schlüssel für OpenRouter. Wird für alle Agenten dieser Instanz verwendet.")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string OpenRouterApiKey
|
||||
{
|
||||
get => _config.OpenRouterApiKey;
|
||||
set => _config.OpenRouterApiKey = value;
|
||||
}
|
||||
|
||||
[Category("Verzeichnisse")]
|
||||
[DisplayName("Arbeitsverzeichnis")]
|
||||
[Description("Basis-Arbeitsverzeichnis für diese Instanz.")]
|
||||
public string WorkingDirectory
|
||||
{
|
||||
get => _config.WorkingDirectory;
|
||||
set => _config.WorkingDirectory = value;
|
||||
}
|
||||
|
||||
[Category("Verzeichnisse")]
|
||||
[DisplayName("Log-Verzeichnis")]
|
||||
[Description("Verzeichnis für Log-Dateien dieser Instanz.")]
|
||||
public string LogDirectory
|
||||
{
|
||||
get => _config.LogDirectory;
|
||||
set => _config.LogDirectory = value;
|
||||
}
|
||||
|
||||
[Category("Netzwerk")]
|
||||
[DisplayName("Webserver-Port")]
|
||||
[Description("Port für den integrierten Webserver (0 = deaktiviert).")]
|
||||
public int WebServerPort
|
||||
{
|
||||
get => _config.WebServerPort;
|
||||
set => _config.WebServerPort = value;
|
||||
}
|
||||
|
||||
[Category("Agenten")]
|
||||
[DisplayName("Anzahl Agenten")]
|
||||
[Description("Anzahl der konfigurierten Agenten in dieser Instanz.")]
|
||||
[ReadOnly(true)]
|
||||
public int AgentCount => _config.Agents.Count;
|
||||
|
||||
[Browsable(false)]
|
||||
public InstanceConfig UnderlyingConfig => _config;
|
||||
|
||||
public override string ToString() => _config.InstanceName;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
public sealed class JobDisplayEntry
|
||||
{
|
||||
public string JobType { get; set; } = "Agent Wakeup";
|
||||
public string AgentId { get; set; } = "";
|
||||
public string AgentName { get; set; } = "";
|
||||
public string ToolName { get; set; } = "";
|
||||
public string CronExpression { get; set; } = "";
|
||||
public string TaskMessage { get; set; } = "";
|
||||
public string NextRun { get; set; } = "—";
|
||||
public string LastRun { get; set; } = "—";
|
||||
public string LastStatus { get; set; } = "—";
|
||||
public bool RunOnStart { get; set; }
|
||||
public string Status { get; set; } = "Aktiv";
|
||||
public string JobId { get; set; } = "";
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
public sealed class JobHistoryEntry
|
||||
{
|
||||
[JsonPropertyName("jobName")]
|
||||
public string JobName { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("agent")]
|
||||
public string Agent { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("time")]
|
||||
public DateTime Time { get; set; } = DateTime.Now;
|
||||
|
||||
[JsonPropertyName("jobDescription")]
|
||||
public string JobDescription { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("info")]
|
||||
public string Info { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public string Status { get; set; } = "Success"; // Success, Error, Manual
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.ComponentModel;
|
||||
using ClawdDotNet.Core.Api;
|
||||
using ClawdDotNet.Core.Api.Models;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
/// <summary>
|
||||
/// TypeConverter der im PropertyGrid eine Dropdown-Liste
|
||||
/// mit verfügbaren OpenRouter-Modellen anzeigt.
|
||||
/// Die Modelle werden einmalig per API abgerufen und gecached.
|
||||
/// Freitext-Eingabe bleibt weiterhin möglich (CanConvertFrom = true).
|
||||
/// </summary>
|
||||
public sealed class ModelTypeConverter : StringConverter
|
||||
{
|
||||
private static List<ModelInfo>? _cachedModels;
|
||||
private static bool _fetchInProgress;
|
||||
private static readonly Lock _lock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Wird von außen gesetzt (beim Start der Anwendung), damit
|
||||
/// der Converter Zugriff auf den OpenRouterClient hat.
|
||||
/// </summary>
|
||||
public static OpenRouterClient? Client { get; set; }
|
||||
|
||||
public override bool GetStandardValuesSupported(ITypeDescriptorContext? context) => true;
|
||||
|
||||
/// <summary>false = Dropdown ist editierbar (Freitext erlaubt)</summary>
|
||||
public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context) => false;
|
||||
|
||||
public override StandardValuesCollection? GetStandardValues(ITypeDescriptorContext? context)
|
||||
{
|
||||
EnsureModelsLoaded();
|
||||
|
||||
if (_cachedModels is null || _cachedModels.Count == 0)
|
||||
{
|
||||
// Fallback: Einige gängige Modelle
|
||||
return new StandardValuesCollection(new[]
|
||||
{
|
||||
"anthropic/claude-sonnet-4-5",
|
||||
"anthropic/claude-haiku-4",
|
||||
"openai/gpt-4.1",
|
||||
"openai/gpt-4.1-mini",
|
||||
"google/gemini-2.5-pro-preview",
|
||||
"google/gemini-2.5-flash-preview",
|
||||
"deepseek/deepseek-chat-v3-0324",
|
||||
"meta-llama/llama-4-maverick"
|
||||
});
|
||||
}
|
||||
|
||||
var ids = _cachedModels.Select(m => m.Id).ToArray();
|
||||
return new StandardValuesCollection(ids);
|
||||
}
|
||||
|
||||
private static void EnsureModelsLoaded()
|
||||
{
|
||||
if (_cachedModels is not null || Client is null)
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cachedModels is not null || _fetchInProgress)
|
||||
return;
|
||||
|
||||
_fetchInProgress = true;
|
||||
}
|
||||
|
||||
// Asynchronen Abruf im Hintergrund starten
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var models = await Client.GetAvailableModelsAsync();
|
||||
_cachedModels = models;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_cachedModels = []; // Fehler → Fallback wird verwendet
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (_lock) { _fetchInProgress = false; }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kann von außen aufgerufen werden um den Cache zu leeren
|
||||
/// (z.B. wenn sich der API-Key ändert).
|
||||
/// </summary>
|
||||
public static void InvalidateCache()
|
||||
{
|
||||
lock (_lock) { _cachedModels = null; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
public sealed class ServiceDisplayEntry
|
||||
{
|
||||
public string ServiceId { get; set; } = "";
|
||||
public string Name { get; set; } = "";
|
||||
public string Type { get; set; } = "";
|
||||
public int Port { get; set; }
|
||||
public string Status { get; set; } = "Gestoppt";
|
||||
public string StartedAt { get; set; } = "—";
|
||||
public string Description { get; set; } = "";
|
||||
public bool BuiltIn { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
public sealed class TokenUsageRecord
|
||||
{
|
||||
[JsonPropertyName("timestamp")]
|
||||
public DateTime Timestamp { get; set; } = DateTime.Now;
|
||||
|
||||
[JsonPropertyName("agentId")]
|
||||
public string AgentId { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("agentName")]
|
||||
public string AgentName { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("model")]
|
||||
public string Model { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("promptTokens")]
|
||||
public int PromptTokens { get; set; }
|
||||
|
||||
[JsonPropertyName("completionTokens")]
|
||||
public int CompletionTokens { get; set; }
|
||||
|
||||
[JsonPropertyName("totalTokens")]
|
||||
public int TotalTokens { get; set; }
|
||||
|
||||
[JsonPropertyName("costUsd")]
|
||||
public double CostUsd { get; set; }
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public string Status { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("stepCount")]
|
||||
public int StepCount { get; set; }
|
||||
|
||||
[JsonPropertyName("durationMs")]
|
||||
public long DurationMs { get; set; }
|
||||
}
|
||||
|
||||
public sealed class TokenUsageFile
|
||||
{
|
||||
[JsonPropertyName("instanceId")]
|
||||
public string InstanceId { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("instanceName")]
|
||||
public string InstanceName { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("records")]
|
||||
public List<TokenUsageRecord> Records { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,566 @@
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
static class ConfigHelper
|
||||
{
|
||||
public static string GetString(Dictionary<string, object?> config, string key, string fallback = "")
|
||||
{
|
||||
var val = config.GetValueOrDefault(key);
|
||||
return val switch
|
||||
{
|
||||
JsonElement je when je.ValueKind == JsonValueKind.String => je.GetString() ?? fallback,
|
||||
JsonElement je => je.ToString(),
|
||||
string s => s,
|
||||
null => fallback,
|
||||
_ => val.ToString() ?? fallback
|
||||
};
|
||||
}
|
||||
|
||||
public static int GetInt(Dictionary<string, object?> config, string key, int fallback = 0)
|
||||
{
|
||||
var val = config.GetValueOrDefault(key);
|
||||
return val switch
|
||||
{
|
||||
JsonElement je when je.ValueKind == JsonValueKind.Number => je.GetInt32(),
|
||||
JsonElement je => int.TryParse(je.ToString(), out var r) ? r : fallback,
|
||||
int i => i,
|
||||
_ => int.TryParse(val?.ToString(), out var r) ? r : fallback
|
||||
};
|
||||
}
|
||||
|
||||
public static bool GetBool(Dictionary<string, object?> config, string key, bool fallback = false)
|
||||
{
|
||||
var val = config.GetValueOrDefault(key);
|
||||
return val switch
|
||||
{
|
||||
JsonElement je when je.ValueKind is JsonValueKind.True => true,
|
||||
JsonElement je when je.ValueKind is JsonValueKind.False => false,
|
||||
JsonElement je => bool.TryParse(je.ToString(), out var r) ? r : fallback,
|
||||
bool b => b,
|
||||
_ => bool.TryParse(val?.ToString(), out var r) ? r : fallback
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetStringArray(Dictionary<string, object?> config, string key)
|
||||
{
|
||||
var val = config.GetValueOrDefault(key);
|
||||
return val switch
|
||||
{
|
||||
JsonElement je when je.ValueKind == JsonValueKind.Array =>
|
||||
string.Join(",", je.EnumerateArray().Select(e => e.GetString())),
|
||||
object[] arr => string.Join(",", arr),
|
||||
string s => s,
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum FileRWAccessLevel
|
||||
{
|
||||
Denied,
|
||||
Read,
|
||||
ReadWrite,
|
||||
Admin
|
||||
}
|
||||
|
||||
public sealed class FileRWToolSettings
|
||||
{
|
||||
[Category("Persönlicher Workspace")]
|
||||
[DisplayName("Erlaubte Endungen")]
|
||||
[Description("Dateiendungen für den eigenen Agenten-Workspace (z.B. .txt,.json,.md)")]
|
||||
public string PersonalAllowedExtensions { get; set; } = ".txt,.json,.md,.html,.js,.css";
|
||||
|
||||
[Category("Shared Workspace")]
|
||||
[DisplayName("Zugriffslevel")]
|
||||
[Description("Legt fest, welche Operationen im SharedWorkspace erlaubt sind")]
|
||||
public FileRWAccessLevel SharedAccessLevel { get; set; } = FileRWAccessLevel.Denied;
|
||||
|
||||
[Category("Shared Workspace")]
|
||||
[DisplayName("Erlaubte Endungen")]
|
||||
[Description("Dateiendungen für den geteilten Workspace")]
|
||||
public string SharedAllowedExtensions { get; set; } = ".txt,.json,.md";
|
||||
|
||||
[Category("Shared Workspace – Schutz")]
|
||||
[DisplayName("Geschützte Pfade")]
|
||||
[Description("Komma-getrennte Pfade im SharedWorkspace die append-only sind (z.B. stocks/,archives/). Dateien dort können nur erstellt, nicht überschrieben oder gelöscht werden. Admin-Level umgeht den Schutz.")]
|
||||
public string ProtectedPaths { get; set; } = "stocks/";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["personalAllowedExtensions"] = PersonalAllowedExtensions.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries),
|
||||
["sharedAccessLevel"] = SharedAccessLevel.ToString(),
|
||||
["sharedAllowedExtensions"] = SharedAllowedExtensions.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries),
|
||||
["protectedPaths"] = ProtectedPaths.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
};
|
||||
|
||||
public static FileRWToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
PersonalAllowedExtensions = ConfigHelper.GetStringArray(config, "personalAllowedExtensions") is { Length: > 0 } s1
|
||||
? s1 : (ConfigHelper.GetStringArray(config, "allowedExtensions") is { Length: > 0 } sOld ? sOld : ".txt,.json,.md,.html,.js,.css"),
|
||||
|
||||
SharedAccessLevel = Enum.TryParse<FileRWAccessLevel>(ConfigHelper.GetString(config, "sharedAccessLevel"), true, out var level)
|
||||
? level : FileRWAccessLevel.Denied,
|
||||
|
||||
SharedAllowedExtensions = ConfigHelper.GetStringArray(config, "sharedAllowedExtensions") is { Length: > 0 } s2
|
||||
? s2 : ".txt,.json,.md",
|
||||
|
||||
ProtectedPaths = ConfigHelper.GetStringArray(config, "protectedPaths") is { Length: > 0 } s3
|
||||
? s3 : "stocks/"
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class MailToolSettings
|
||||
{
|
||||
[Category("Mail - Konto")]
|
||||
[DisplayName("Benutzername")]
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
[Category("Mail - Konto")]
|
||||
[DisplayName("Passwort")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string Password { get; set; } = "";
|
||||
|
||||
[Category("Mail - IMAP")]
|
||||
[DisplayName("IMAP-Host")]
|
||||
public string ImapHost { get; set; } = "";
|
||||
|
||||
[Category("Mail - IMAP")]
|
||||
[DisplayName("IMAP-Port")]
|
||||
public int ImapPort { get; set; } = 993;
|
||||
|
||||
[Category("Mail - SMTP")]
|
||||
[DisplayName("SMTP-Host")]
|
||||
public string SmtpHost { get; set; } = "";
|
||||
|
||||
[Category("Mail - SMTP")]
|
||||
[DisplayName("SMTP-Port")]
|
||||
public int SmtpPort { get; set; } = 587;
|
||||
|
||||
[Category("Mail - Sicherheit")]
|
||||
[DisplayName("Erlaubte Empfänger")]
|
||||
[Description("Komma-getrennte Liste erlaubter E-Mail-Adressen")]
|
||||
public string AllowedRecipients { get; set; } = "";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["username"] = Username,
|
||||
["password"] = Password,
|
||||
["imapHost"] = ImapHost,
|
||||
["imapPort"] = ImapPort,
|
||||
["smtpHost"] = SmtpHost,
|
||||
["smtpPort"] = SmtpPort,
|
||||
["allowedRecipients"] = AllowedRecipients.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
};
|
||||
|
||||
public static MailToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
Username = ConfigHelper.GetString(config, "username"),
|
||||
Password = ConfigHelper.GetString(config, "password"),
|
||||
ImapHost = ConfigHelper.GetString(config, "imapHost"),
|
||||
ImapPort = ConfigHelper.GetInt(config, "imapPort", 993),
|
||||
SmtpHost = ConfigHelper.GetString(config, "smtpHost"),
|
||||
SmtpPort = ConfigHelper.GetInt(config, "smtpPort", 587),
|
||||
AllowedRecipients = ConfigHelper.GetStringArray(config, "allowedRecipients")
|
||||
};
|
||||
}
|
||||
|
||||
public enum DatabaseType
|
||||
{
|
||||
MySql,
|
||||
Postgres,
|
||||
MsSql,
|
||||
MongoDb
|
||||
}
|
||||
|
||||
public enum DatabaseAccessLevel
|
||||
{
|
||||
[Description("Nur Lesen (SELECT/find)")]
|
||||
ReadOnly,
|
||||
[Description("Lesen und Schreiben (INSERT/UPDATE/DELETE)")]
|
||||
ReadWrite,
|
||||
[Description("Vollzugriff (Admin/Schema-Änderungen)")]
|
||||
Admin
|
||||
}
|
||||
|
||||
public sealed class DatabaseToolSettings
|
||||
{
|
||||
[Category("Datenbank")]
|
||||
[DisplayName("Typ")]
|
||||
[Description("Der zu verwendende Datenbanktyp")]
|
||||
public DatabaseType Type { get; set; } = DatabaseType.MySql;
|
||||
|
||||
[Category("Datenbank")]
|
||||
[DisplayName("Connection-String")]
|
||||
public string ConnectionString { get; set; } = "";
|
||||
|
||||
[Category("Datenbank")]
|
||||
[DisplayName("Zugriffsebene")]
|
||||
[Description("Legt fest, welche Operationen der Agent ausführen darf")]
|
||||
public DatabaseAccessLevel AccessLevel { get; set; } = DatabaseAccessLevel.ReadOnly;
|
||||
|
||||
[Category("Datenbank - Sicherheit")]
|
||||
[DisplayName("Erlaubte Tabellen")]
|
||||
[Description("Komma-getrennte Liste erlaubter Tabellen/Collections")]
|
||||
public string AllowedTables { get; set; } = "";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["type"] = Type.ToString().ToLowerInvariant(),
|
||||
["connectionString"] = ConnectionString,
|
||||
["accessLevel"] = AccessLevel.ToString(),
|
||||
["allowedTables"] = AllowedTables.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
};
|
||||
|
||||
public static DatabaseToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
Type = Enum.TryParse<DatabaseType>(config.GetValueOrDefault("type")?.ToString(), true, out var result) ? result : DatabaseType.MySql,
|
||||
ConnectionString = config.GetValueOrDefault("connectionString")?.ToString() ?? "",
|
||||
AccessLevel = Enum.TryParse<DatabaseAccessLevel>(config.GetValueOrDefault("accessLevel")?.ToString() ?? config.GetValueOrDefault("allowWrite")?.ToString(), true, out var level)
|
||||
? level
|
||||
: (config.GetValueOrDefault("allowWrite") is true or "True" or "true" ? DatabaseAccessLevel.ReadWrite : DatabaseAccessLevel.ReadOnly),
|
||||
AllowedTables = config.GetValueOrDefault("allowedTables") is object[] arr
|
||||
? string.Join(",", arr)
|
||||
: config.GetValueOrDefault("allowedTables")?.ToString() ?? ""
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class FTPToolSettings
|
||||
{
|
||||
[Category("FTP Server")]
|
||||
[DisplayName("Host")]
|
||||
public string Host { get; set; } = "";
|
||||
|
||||
[Category("FTP Server")]
|
||||
[DisplayName("Port")]
|
||||
public int Port { get; set; } = 21;
|
||||
|
||||
[Category("FTP Server")]
|
||||
[DisplayName("Benutzername")]
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
[Category("FTP Server")]
|
||||
[DisplayName("Passwort")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string Password { get; set; } = "";
|
||||
|
||||
[Category("FTP Lokal")]
|
||||
[DisplayName("Root-Pfad")]
|
||||
[Description("Basisverzeichnis für Dateiübertragungen")]
|
||||
public string RootPath { get; set; } = "./data/";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["host"] = Host,
|
||||
["port"] = Port,
|
||||
["username"] = Username,
|
||||
["password"] = Password,
|
||||
["rootPath"] = RootPath
|
||||
};
|
||||
|
||||
public static FTPToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
Host = ConfigHelper.GetString(config, "host"),
|
||||
Port = ConfigHelper.GetInt(config, "port", 21),
|
||||
Username = ConfigHelper.GetString(config, "username"),
|
||||
Password = ConfigHelper.GetString(config, "password"),
|
||||
RootPath = ConfigHelper.GetString(config, "rootPath", "./data/")
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class TelegramToolSettings
|
||||
{
|
||||
[Category("Telegram")]
|
||||
[DisplayName("Bot-Token")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string BotToken { get; set; } = "";
|
||||
|
||||
[Category("Telegram")]
|
||||
[DisplayName("Standard Chat-ID")]
|
||||
[Description("Die Standard-ID, an die Nachrichten gesendet werden, wenn keine andere ID angegeben ist.")]
|
||||
public string DefaultChatId { get; set; } = "";
|
||||
|
||||
[Category("Telegram - Sicherheit")]
|
||||
[DisplayName("Erlaubte Chat-IDs")]
|
||||
[Description("Komma-getrennte Liste erlaubter Chat-IDs")]
|
||||
public string AllowedChatIds { get; set; } = "";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["botToken"] = BotToken,
|
||||
["defaultChatId"] = DefaultChatId,
|
||||
["allowedChatIds"] = AllowedChatIds.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
};
|
||||
|
||||
public static TelegramToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
BotToken = ConfigHelper.GetString(config, "botToken"),
|
||||
DefaultChatId = ConfigHelper.GetString(config, "defaultChatId"),
|
||||
AllowedChatIds = ConfigHelper.GetStringArray(config, "allowedChatIds")
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class DirectAPIToolSettings
|
||||
{
|
||||
[Category("DirectAPI")]
|
||||
[DisplayName("Standard-Provider")]
|
||||
public string DefaultProvider { get; set; } = "twelvedata";
|
||||
|
||||
[Category("DirectAPI")]
|
||||
[DisplayName("Cache TTL (Sekunden)")]
|
||||
public int CacheTtlSeconds { get; set; } = 60;
|
||||
|
||||
[Category("DirectAPI - API Keys")]
|
||||
[DisplayName("Twelve Data Key")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string TwelveDataKey { get; set; } = "";
|
||||
|
||||
[Category("DirectAPI - API Keys")]
|
||||
[DisplayName("Alpha Vantage Key")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string AlphaVantageKey { get; set; } = "";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["defaultProvider"] = DefaultProvider,
|
||||
["cacheTtlSeconds"] = CacheTtlSeconds,
|
||||
["providers"] = new Dictionary<string, object?>
|
||||
{
|
||||
["twelvedata"] = new { apiKey = TwelveDataKey },
|
||||
["alphavantage"] = new { apiKey = AlphaVantageKey }
|
||||
}
|
||||
};
|
||||
|
||||
public static DirectAPIToolSettings FromConfig(Dictionary<string, object?> config)
|
||||
{
|
||||
var settings = new DirectAPIToolSettings
|
||||
{
|
||||
DefaultProvider = ConfigHelper.GetString(config, "defaultProvider", "twelvedata"),
|
||||
CacheTtlSeconds = ConfigHelper.GetInt(config, "cacheTtlSeconds", 60)
|
||||
};
|
||||
|
||||
if (config.GetValueOrDefault("providers") is JsonElement providersJe)
|
||||
{
|
||||
var providers = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(providersJe.GetRawText());
|
||||
if (providers != null)
|
||||
{
|
||||
if (providers.TryGetValue("twelvedata", out var td) && td.TryGetProperty("apiKey", out var tdk))
|
||||
settings.TwelveDataKey = tdk.GetString() ?? "";
|
||||
if (providers.TryGetValue("alphavantage", out var av) && av.TryGetProperty("apiKey", out var avk))
|
||||
settings.AlphaVantageKey = avk.GetString() ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WebFetchToolSettings
|
||||
{
|
||||
[Category("WebFetch")]
|
||||
[DisplayName("Erlaubte Domains")]
|
||||
[Description("Komma-getrennte Liste (z.B. reuters.com,bloomberg.com)")]
|
||||
public string AllowedDomains { get; set; } = "";
|
||||
|
||||
[Category("WebFetch")]
|
||||
[DisplayName("Max Response KB")]
|
||||
public int MaxResponseKb { get; set; } = 512;
|
||||
|
||||
[Category("WebFetch")]
|
||||
[DisplayName("User Agent")]
|
||||
public string UserAgent { get; set; } = "ClawdDotNet-Agent/1.0";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["allowedDomains"] = AllowedDomains.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries),
|
||||
["maxResponseKb"] = MaxResponseKb,
|
||||
["userAgent"] = UserAgent
|
||||
};
|
||||
|
||||
public static WebFetchToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
AllowedDomains = ConfigHelper.GetStringArray(config, "allowedDomains"),
|
||||
MaxResponseKb = ConfigHelper.GetInt(config, "maxResponseKb", 512),
|
||||
UserAgent = ConfigHelper.GetString(config, "userAgent", "ClawdDotNet-Agent/1.0")
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class WebMonitorToolSettings
|
||||
{
|
||||
[Category("WebMonitor")]
|
||||
[DisplayName("Monitore (JSON)")]
|
||||
[Description("JSON-Konfiguration der Monitore")]
|
||||
public string MonitorsJson { get; set; } = "{}";
|
||||
|
||||
public Dictionary<string, object?> ToConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Dictionary<string, object?>
|
||||
{
|
||||
["monitors"] = JsonSerializer.Deserialize<Dictionary<string, object?>>(MonitorsJson) ?? new()
|
||||
};
|
||||
}
|
||||
catch { return new Dictionary<string, object?> { ["monitors"] = new Dictionary<string, object?>() }; }
|
||||
}
|
||||
|
||||
public static WebMonitorToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
MonitorsJson = config.GetValueOrDefault("monitors") is JsonElement je ? je.GetRawText() : "{}"
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class AgentCommToolSettings
|
||||
{
|
||||
[Category("AgentComm")]
|
||||
[DisplayName("Info")]
|
||||
[Description("Dieses Tool benötigt keine Konfiguration. Es ermöglicht Agenten, mit anderen Agenten in der gleichen Instanz zu kommunizieren.")]
|
||||
[ReadOnly(true)]
|
||||
public string Status { get; set; } = "Aktiv";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new();
|
||||
|
||||
public static AgentCommToolSettings FromConfig(Dictionary<string, object?> config) => new();
|
||||
}
|
||||
|
||||
public sealed class SocialMediaManagerToolSettings
|
||||
{
|
||||
// ─── X (Twitter) ───
|
||||
|
||||
[Category("1. X (Twitter) - API")]
|
||||
[DisplayName("Bearer Token")]
|
||||
[Description("X API v2 Bearer Token für die Authentifizierung")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string XApiKey { get; set; } = "";
|
||||
|
||||
[Category("1. X (Twitter) - Monitoring")]
|
||||
[DisplayName("Überwachte Accounts")]
|
||||
[Description("Komma-getrennte Liste von X-Accounts die überwacht werden sollen (ohne @). Beispiel: elonmusk,unusual_whales,DeItaone")]
|
||||
public string XWatchAccounts { get; set; } = "";
|
||||
|
||||
// ─── Reddit ───
|
||||
|
||||
[Category("2. Reddit - Monitoring")]
|
||||
[DisplayName("Überwachte Subreddits")]
|
||||
[Description("Komma-getrennte Liste von Subreddits die überwacht werden sollen (ohne r/). Beispiel: wallstreetbets,stocks,options")]
|
||||
public string RedditWatchSubreddits { get; set; } = "";
|
||||
|
||||
[Category("2. Reddit - Monitoring")]
|
||||
[DisplayName("Posts pro Subreddit")]
|
||||
[Description("Maximale Anzahl Posts die pro Subreddit bei jedem Check abgerufen werden (Standard: 15)")]
|
||||
public int RedditPostLimit { get; set; } = 15;
|
||||
|
||||
// ─── YouTube / STT ───
|
||||
|
||||
[Category("3. YouTube / STT")]
|
||||
[DisplayName("OpenRouter API Key")]
|
||||
[Description("API Key für Speech-to-Text Transkription über OpenRouter")]
|
||||
[PasswordPropertyText(true)]
|
||||
public string OpenRouterApiKey { get; set; } = "";
|
||||
|
||||
[Category("3. YouTube / STT")]
|
||||
[DisplayName("STT Modell")]
|
||||
[Description("OpenRouter Modell-ID für die Transkription")]
|
||||
public string STTModel { get; set; } = "openai/whisper-1";
|
||||
|
||||
[Category("3. YouTube / STT")]
|
||||
[DisplayName("YouTube Kanäle")]
|
||||
[Description("Komma-getrennte Liste von YouTube Kanal-URLs für automatische Überwachung")]
|
||||
public string YoutubeChannels { get; set; } = "";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new()
|
||||
{
|
||||
["xApiKey"] = XApiKey,
|
||||
["xWatchAccounts"] = SplitToArray(XWatchAccounts),
|
||||
["redditWatchSubreddits"] = SplitToArray(RedditWatchSubreddits),
|
||||
["redditPostLimit"] = RedditPostLimit,
|
||||
["openRouterApiKey"] = OpenRouterApiKey,
|
||||
["sttModel"] = STTModel,
|
||||
["youtubeChannels"] = SplitToArray(YoutubeChannels)
|
||||
};
|
||||
|
||||
public static SocialMediaManagerToolSettings FromConfig(Dictionary<string, object?> config) => new()
|
||||
{
|
||||
XApiKey = ConfigHelper.GetString(config, "xApiKey"),
|
||||
XWatchAccounts = ConfigHelper.GetStringArray(config, "xWatchAccounts"),
|
||||
RedditWatchSubreddits = ConfigHelper.GetStringArray(config, "redditWatchSubreddits"),
|
||||
RedditPostLimit = ConfigHelper.GetInt(config, "redditPostLimit", 15),
|
||||
OpenRouterApiKey = ConfigHelper.GetString(config, "openRouterApiKey"),
|
||||
STTModel = ConfigHelper.GetString(config, "sttModel", "openai/whisper-1"),
|
||||
YoutubeChannels = ConfigHelper.GetStringArray(config, "youtubeChannels")
|
||||
};
|
||||
|
||||
private static string[] SplitToArray(string csv)
|
||||
=> csv.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
}
|
||||
|
||||
public sealed class AgentEditorToolSettings
|
||||
{
|
||||
[Category("AgentEditor")]
|
||||
[DisplayName("Info")]
|
||||
[Description("Erlaubt dem Agenten, Identity und Soul anderer Agenten zu lesen, zu bearbeiten und neue Agenten zu erstellen. Keine weitere Konfiguration nötig.")]
|
||||
[ReadOnly(true)]
|
||||
public string Status { get; set; } = "Aktiv";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new();
|
||||
|
||||
public static AgentEditorToolSettings FromConfig(Dictionary<string, object?> config) => new();
|
||||
}
|
||||
|
||||
public sealed class AgentSpawnToolSettings
|
||||
{
|
||||
[Category("AgentSpawn")]
|
||||
[DisplayName("Info")]
|
||||
[Description("Dieses Tool benötigt keine Konfiguration. Es ermöglicht Agenten, andere Agenten zu starten und ihnen Aufgaben zuzuweisen.")]
|
||||
[ReadOnly(true)]
|
||||
public string Status { get; set; } = "Aktiv";
|
||||
|
||||
public Dictionary<string, object?> ToConfig() => new();
|
||||
|
||||
public static AgentSpawnToolSettings FromConfig(Dictionary<string, object?> config) => new();
|
||||
}
|
||||
|
||||
public static class ToolSettingsFactory
|
||||
{
|
||||
public static object? CreateViewModel(string toolName, Dictionary<string, object?>? config)
|
||||
{
|
||||
config ??= new();
|
||||
return toolName switch
|
||||
{
|
||||
"FileRW" => FileRWToolSettings.FromConfig(config),
|
||||
"Mail" => MailToolSettings.FromConfig(config),
|
||||
"Database" => DatabaseToolSettings.FromConfig(config),
|
||||
"Telegram" => TelegramToolSettings.FromConfig(config),
|
||||
"FTP" => FTPToolSettings.FromConfig(config),
|
||||
"DirectAPI" => DirectAPIToolSettings.FromConfig(config),
|
||||
"WebFetch" => WebFetchToolSettings.FromConfig(config),
|
||||
"WebMonitor" => WebMonitorToolSettings.FromConfig(config),
|
||||
"AgentComm" => AgentCommToolSettings.FromConfig(config),
|
||||
"SocialMediaManager" => SocialMediaManagerToolSettings.FromConfig(config),
|
||||
"AgentSpawn" => AgentSpawnToolSettings.FromConfig(config),
|
||||
"AgentEditor" => AgentEditorToolSettings.FromConfig(config),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
public static Dictionary<string, object?>? ToConfig(string toolName, object? viewModel)
|
||||
{
|
||||
return viewModel switch
|
||||
{
|
||||
FileRWToolSettings f => f.ToConfig(),
|
||||
MailToolSettings m => m.ToConfig(),
|
||||
DatabaseToolSettings d => d.ToConfig(),
|
||||
TelegramToolSettings t => t.ToConfig(),
|
||||
FTPToolSettings ftp => ftp.ToConfig(),
|
||||
DirectAPIToolSettings dapi => dapi.ToConfig(),
|
||||
WebFetchToolSettings wf => wf.ToConfig(),
|
||||
WebMonitorToolSettings wm => wm.ToConfig(),
|
||||
AgentCommToolSettings ac => ac.ToConfig(),
|
||||
SocialMediaManagerToolSettings smm => smm.ToConfig(),
|
||||
AgentSpawnToolSettings asp => asp.ToConfig(),
|
||||
AgentEditorToolSettings ae => ae.ToConfig(),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user