Forge
csharp3407750f
1using AgentForge.Abstractions;
2using AgentForge.Services;
3
4namespace AgentForge.Endpoints;
5
6public static class ForgeCommandEndpoints
7{
8 public static RouteGroupBuilder MapCommandEndpoints(this RouteGroupBuilder api)
9 {
10 api.MapPost("/commands/execute", ExecuteCommand);
11 return api;
12 }
13
14 private static async Task<IResult> ExecuteCommand(
15 ForgeCommandExecuteRequest request,
16 HttpContext context,
17 ForgeCommandExecutor executor,
18 CancellationToken cancellationToken)
19 {
20 var result = await executor.ExecuteAsync(request, context, cancellationToken).ConfigureAwait(false);
21
22 if (WantsJsonResponse(context))
23 return ToJsonResult(result);
24
25 return result.Kind switch
26 {
27 "redirect" when !string.IsNullOrWhiteSpace(result.RedirectUrl) =>
28 Results.Redirect(result.RedirectUrl),
29 "json" => Results.Ok(result.Body),
30 _ => Results.BadRequest(new { error = result.Error ?? "Command failed." }),
31 };
32 }
33
34 private static bool WantsJsonResponse(HttpContext context)
35 {
36 if (context.Request.Headers.TryGetValue("X-Forge-Command-Client", out var client)
37 && client.ToString().Contains("slash", StringComparison.OrdinalIgnoreCase))
38 return true;
39
40 return context.Request.Headers.Accept.Any(value =>
41 !string.IsNullOrEmpty(value)
42 && value.Contains("application/json", StringComparison.OrdinalIgnoreCase)
43 && !value.Contains("text/html", StringComparison.OrdinalIgnoreCase));
44 }
45
46 private static IResult ToJsonResult(ForgeCommandExecuteResponse result) =>
47 result.Kind switch
48 {
49 "redirect" => Results.Ok(new { kind = result.Kind, redirectUrl = result.RedirectUrl }),
50 "json" => Results.Ok(new { kind = result.Kind, body = result.Body }),
51 _ => Results.BadRequest(new { kind = "error", error = result.Error ?? "Command failed." }),
52 };
53}
54
View only · write via MCP/CIDE