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 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 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); } }