using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Nexus.Api.Models;
using Nexus.Api.Services;
namespace Nexus.Api.Controllers;
///
/// Authenticated, browser-safe OpenClaw control-plane facade.
/// Gateway credentials and raw protocol payloads remain inside the backend.
///
[Authorize]
[ApiController]
[Route("api/v1/openclaw")]
public sealed class OpenClawController(IOpenClawControlService openClaw) : ControllerBase
{
[HttpGet("connection")]
[ProducesResponseType(typeof(OpenClawConnectionDto), StatusCodes.Status200OK)]
public IResult GetConnection()
=> Results.Ok(openClaw.GetConnection());
[HttpGet("capabilities")]
[ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)]
public IResult GetCapabilities()
=> Results.Ok(openClaw.GetCapabilities());
[HttpGet("overview")]
[ProducesResponseType(typeof(OpenClawOverviewDto), StatusCodes.Status200OK)]
public async Task GetOverview(CancellationToken cancellationToken)
=> Results.Ok(await openClaw.GetOverviewAsync(cancellationToken));
[HttpGet("tasks")]
[ProducesResponseType(typeof(OpenClawCollectionDto), StatusCodes.Status200OK)]
public async Task GetTasks(
[FromQuery] int limit = 100,
[FromQuery] string? cursor = null,
CancellationToken cancellationToken = default)
=> Results.Ok(await openClaw.GetTasksAsync(limit, cursor, cancellationToken));
[HttpPost("tasks/{taskId}/cancel")]
[Authorize(Roles = "owner")]
[EnableRateLimiting("agents")]
[ProducesResponseType(typeof(OpenClawOperationDto), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task CancelTask(
string taskId,
[FromBody] CancelOpenClawTaskRequest request,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(taskId))
return Results.ValidationProblem(new Dictionary
{
["taskId"] = ["Task id is required."]
});
return Results.Ok(await openClaw.CancelTaskAsync(
taskId,
request.Reason,
cancellationToken));
}
[HttpGet("sessions")]
[ProducesResponseType(typeof(OpenClawCollectionDto), StatusCodes.Status200OK)]
public async Task GetSessions(
[FromQuery] int limit = 100,
CancellationToken cancellationToken = default)
=> Results.Ok(await openClaw.GetSessionsAsync(limit, cancellationToken));
[HttpPost("sessions/abort")]
[Authorize(Roles = "owner")]
[EnableRateLimiting("agents")]
[ProducesResponseType(typeof(OpenClawOperationDto