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:
+165
@@ -0,0 +1,165 @@
|
||||
using ClawdDotNet.Core.Config;
|
||||
using ClawdDotNet.Core.Engine;
|
||||
using ClawdDotNet.UI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
|
||||
namespace ClawdDotNet;
|
||||
|
||||
public partial class frm_chat : Form
|
||||
{
|
||||
private readonly AgentConfig _agentConfig;
|
||||
private readonly AgentEngine _engine;
|
||||
private readonly string _instanceId;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private WebViewBridge? _bridge;
|
||||
|
||||
public frm_chat(AgentConfig agentConfig, AgentEngine engine,
|
||||
string instanceId, ILoggerFactory loggerFactory)
|
||||
{
|
||||
_agentConfig = agentConfig;
|
||||
_engine = engine;
|
||||
_instanceId = instanceId;
|
||||
_logger = loggerFactory.CreateLogger($"ClawdDotNet.UI.Chat.{agentConfig.AgentId}");
|
||||
|
||||
InitializeComponent();
|
||||
Text = $"Chat – {agentConfig.DisplayName}";
|
||||
Load += async (_, _) => await InitWebViewAsync();
|
||||
}
|
||||
|
||||
public frm_chat()
|
||||
{
|
||||
_agentConfig = new AgentConfig();
|
||||
_engine = null!;
|
||||
_instanceId = "";
|
||||
_logger = LoggerFactory.Create(_ => { }).CreateLogger("Design");
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async Task InitWebViewAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await webView_chat2.EnsureCoreWebView2Async();
|
||||
|
||||
var uiPath = EmbeddedUiManager.GetExtractedPath();
|
||||
webView_chat2.CoreWebView2.SetVirtualHostNameToFolderMapping(
|
||||
"ui.clwd.internal", uiPath,
|
||||
CoreWebView2HostResourceAccessKind.DenyCors);
|
||||
|
||||
_bridge = new WebViewBridge(webView_chat2, _logger);
|
||||
_bridge.MessageReceived += OnBridgeMessage;
|
||||
|
||||
webView_chat2.CoreWebView2.Navigate(
|
||||
$"https://ui.clwd.internal/chat.html?agent={_agentConfig.AgentId}");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
await _bridge.SendAsync(new BridgeMessage(
|
||||
Type: BridgeTypes.AgentListUpdate,
|
||||
AgentId: _agentConfig.AgentId,
|
||||
Extra: new
|
||||
{
|
||||
agents = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
agentId = _agentConfig.AgentId,
|
||||
displayName = _agentConfig.DisplayName,
|
||||
model = _agentConfig.Model
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
await LoadChatHistoryAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "frm_chat WebView2 init failed");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnBridgeMessage(BridgeMessage msg)
|
||||
{
|
||||
if (InvokeRequired) { Invoke(() => OnBridgeMessage(msg)); return; }
|
||||
|
||||
switch (msg.Type)
|
||||
{
|
||||
case BridgeTypes.UserMessage:
|
||||
if (msg.Content is not null)
|
||||
await HandleUserMessageAsync(msg.Content);
|
||||
break;
|
||||
|
||||
case BridgeTypes.RunNow:
|
||||
await HandleUserMessageAsync("Führe deine zugewiesenen Aufgaben aus.");
|
||||
break;
|
||||
|
||||
case BridgeTypes.AbortRun:
|
||||
_engine.AbortChat(_agentConfig.AgentId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleUserMessageAsync(string text)
|
||||
{
|
||||
if (_bridge is null) return;
|
||||
|
||||
await _bridge.SendAsync(new BridgeMessage(
|
||||
Type: BridgeTypes.ChatMessage,
|
||||
AgentId: _agentConfig.AgentId,
|
||||
Content: text,
|
||||
Extra: new { role = "user", timestamp = DateTime.Now }));
|
||||
|
||||
await _bridge.SendAsync(new BridgeMessage(
|
||||
Type: BridgeTypes.ChatTyping,
|
||||
AgentId: _agentConfig.AgentId));
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _engine.ChatAsync(
|
||||
_agentConfig, text, _instanceId, CancellationToken.None,
|
||||
source: ChatSource.WebView);
|
||||
|
||||
await _bridge.SendAsync(new BridgeMessage(
|
||||
Type: BridgeTypes.ChatMessage,
|
||||
AgentId: _agentConfig.AgentId,
|
||||
Content: result.FinalMessage ?? "[Keine Antwort]",
|
||||
Extra: new { role = "assistant", timestamp = DateTime.Now }));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Chat failed");
|
||||
await _bridge!.SendAsync(new BridgeMessage(
|
||||
Type: BridgeTypes.ChatMessage,
|
||||
AgentId: _agentConfig.AgentId,
|
||||
Content: $"[Fehler: {ex.Message}]",
|
||||
Extra: new { role = "assistant", timestamp = DateTime.Now }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task LoadChatHistoryAsync()
|
||||
{
|
||||
if (_bridge is null) return;
|
||||
|
||||
var history = _engine.GetChatHistory(_agentConfig.AgentId);
|
||||
await _bridge.SendAsync(new BridgeMessage(
|
||||
Type: BridgeTypes.ChatHistory,
|
||||
AgentId: _agentConfig.AgentId,
|
||||
Extra: history.Select(e => new
|
||||
{
|
||||
role = e.Role,
|
||||
content = e.Content,
|
||||
timestamp = e.Timestamp
|
||||
}).ToArray()));
|
||||
}
|
||||
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
_bridge?.Dispose();
|
||||
base.OnFormClosed(e);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user