Files
nexus/backend/Integrations/OpenClawRuntime.cs
T
iris a79d8282dc
CI - Build & Test / Backend (.NET) (push) Successful in 54s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 19s
CI - Build & Test / Security Check (push) Successful in 2s
refactor: Clean Architecture mit Repository Pattern, Controllern und DTOs
- 15 Controller-Klassen ersetzen Minimal APIs in Program.cs
- Repository Pattern mit Interfaces + Implementierungen (Project, Task, Activity, User)
- AuthService verwendet jetzt IUserRepository statt direktem DbContext-Zugriff
- SecurityHeadersMiddleware als eigenständige Middleware-Klasse
- PathSecurityHelper als gemeinsamer Helper für Pfadvalidierung
- DTOs in eigenem Namespace Nexus.Api.DTOs
- EF-Entities in Nexus.Api.Data (vorher Nexus.Api.Domain)
- Program.cs auf DI-Registrierung + Middleware reduziert
- Alle 43 Endpoints unverändert erhalten
- Build + 3/3 Tests erfolgreich
2026-06-09 19:52:58 +02:00

76 lines
2.8 KiB
C#

using System.Diagnostics;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Nexus.Api.Data;
namespace Nexus.Api.Integrations;
public sealed class OpenClawRuntime(HttpClient client, IConfiguration configuration) : IAgentRuntime
{
public string Name => "OpenClaw";
public async Task<AgentRuntimeStatus> GetStatusAsync(CancellationToken cancellationToken)
{
var stopwatch = Stopwatch.StartNew();
try
{
using var request = new HttpRequestMessage(HttpMethod.Get, "/");
ApplyAuthorization(request);
using var response = await client.SendAsync(request, cancellationToken);
stopwatch.Stop();
var status = response.IsSuccessStatusCode
? OperationalStatus.Online
: OperationalStatus.Degraded;
return new(Name, status, stopwatch.Elapsed, $"HTTP {(int)response.StatusCode}");
}
catch (Exception exception)
{
stopwatch.Stop();
return new(Name, OperationalStatus.Offline, stopwatch.Elapsed, exception.Message);
}
}
public async Task<AgentChatResult> ChatAsync(
string message,
string conversationId,
string agentId,
CancellationToken cancellationToken)
{
using var request = new HttpRequestMessage(HttpMethod.Post, "/v1/chat/completions");
ApplyAuthorization(request);
request.Content = JsonContent.Create(new
{
model = $"openclaw/{agentId}",
messages = new[] { new { role = "user", content = message } },
user = conversationId,
stream = false
});
using var response = await client.SendAsync(request, cancellationToken);
var body = await response.Content.ReadAsStringAsync(cancellationToken);
if (!response.IsSuccessStatusCode)
throw new HttpRequestException($"OpenClaw chat returned HTTP {(int)response.StatusCode}: {body}");
using var document = JsonDocument.Parse(body);
var content = document.RootElement
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString();
if (string.IsNullOrWhiteSpace(content))
throw new InvalidOperationException("OpenClaw returned an empty assistant response.");
return new(Name, agentId, conversationId, content);
}
private void ApplyAuthorization(HttpRequestMessage request)
{
var credential = configuration["Integrations:OpenClaw:Password"]
?? configuration["Integrations:OpenClaw:Token"];
if (!string.IsNullOrWhiteSpace(credential))
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", credential);
}
}