79 lines
3.3 KiB
C#
79 lines
3.3 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.RateLimiting;
|
|
using System.Diagnostics;
|
|
using System.Security.Claims;
|
|
using Nexus.Api.DTOs;
|
|
using Nexus.Api.Services;
|
|
|
|
namespace Nexus.Api.Controllers;
|
|
|
|
[Authorize(Roles = "owner")]
|
|
[ApiController]
|
|
[Route("api/v1/chat")]
|
|
public class ChatController(
|
|
IOpenClawChatService chat,
|
|
ILogger<ChatController> logger) : ControllerBase
|
|
{
|
|
[HttpPost]
|
|
[EnableRateLimiting("agents")]
|
|
public async Task<IResult> Chat([FromBody] ChatRequest request, CancellationToken ct)
|
|
{
|
|
var message = request.Message?.Trim();
|
|
if (string.IsNullOrWhiteSpace(message) || message.Length > 8000)
|
|
return Results.ValidationProblem(new Dictionary<string, string[]> { ["message"] = ["Message must contain between 1 and 8000 characters."] });
|
|
|
|
var agentId = string.IsNullOrWhiteSpace(request.AgentId) ? "iris" : request.AgentId.Trim().ToLowerInvariant();
|
|
if (agentId is not ("iris" or "main"))
|
|
return Results.ValidationProblem(new Dictionary<string, string[]> { ["agentId"] = ["Only iris and main are supported."] });
|
|
|
|
var conversationId = string.IsNullOrWhiteSpace(request.ConversationId)
|
|
? $"nexus-{Guid.NewGuid():N}"
|
|
: request.ConversationId.Trim();
|
|
if (conversationId.Length > 160)
|
|
return Results.ValidationProblem(new Dictionary<string, string[]> { ["conversationId"] = ["Conversation id is too long."] });
|
|
|
|
try
|
|
{
|
|
var contextualMessage = MissionControlContextFormatter.Format(message, request.Context);
|
|
var invocationContext = OpenClawInvocationContextFactory.Create(
|
|
User.FindFirst("sub")?.Value
|
|
?? User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
|
?? User.Identity?.Name,
|
|
Request.Headers["Idempotency-Key"].FirstOrDefault(),
|
|
Request.Headers["X-Correlation-ID"].FirstOrDefault()
|
|
?? HttpContext.TraceIdentifier,
|
|
Request.Headers["traceparent"].FirstOrDefault()
|
|
?? Activity.Current?.Id);
|
|
var invocation = new Nexus.Api.Models.OpenClawInvocationMetadata(
|
|
invocationContext.IdempotencyKey,
|
|
invocationContext.CorrelationId,
|
|
invocationContext.Actor,
|
|
invocationContext.TraceParent);
|
|
Response.Headers["X-Correlation-ID"] = invocation.CorrelationId;
|
|
return Results.Ok(await chat.SendAsync(
|
|
contextualMessage,
|
|
conversationId,
|
|
agentId,
|
|
invocation,
|
|
ct));
|
|
}
|
|
catch (ArgumentException exception)
|
|
{
|
|
return Results.ValidationProblem(new Dictionary<string, string[]>
|
|
{
|
|
["requestMetadata"] = [exception.Message]
|
|
});
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
logger.LogWarning(exception, "OpenClaw chat request failed for agent {AgentId}", agentId);
|
|
return Results.Problem(
|
|
title: "OpenClaw chat unavailable",
|
|
detail: "The trusted OpenClaw chat endpoint is not enabled or reachable.",
|
|
statusCode: StatusCodes.Status503ServiceUnavailable);
|
|
}
|
|
}
|
|
|
|
}
|