feat: ship agent-first mission control v0.2.57
This commit is contained in:
@@ -1,86 +1,42 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using Nexus.Api.DTOs;
|
||||
|
||||
namespace Nexus.Api.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Compatibility adapter for the existing calendar API. Its data now comes
|
||||
/// exclusively from the real OpenClaw cron control plane; disconnected or
|
||||
/// unsupported Gateways return an empty list instead of fabricated jobs.
|
||||
/// </summary>
|
||||
public sealed class CalendarService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IConfiguration configuration,
|
||||
ILogger<CalendarService> logger) : ICalendarService
|
||||
IOpenClawControlService openClaw) : ICalendarService
|
||||
{
|
||||
public async Task<IReadOnlyList<CronJobEntry>> GetCronJobsAsync(CancellationToken ct = default)
|
||||
public async Task<IReadOnlyList<CronJobEntry>> GetCronJobsAsync(
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = CreateGatewayClient();
|
||||
var response = await client.GetAsync("/api/cron", ct);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var data = await response.Content.ReadFromJsonAsync<List<CronJobEntry>>(ct);
|
||||
return data ?? new List<CronJobEntry>();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogDebug(ex, "Gateway cron endpoint not reachable, using fallback data");
|
||||
}
|
||||
|
||||
return BuildFallbackCronJobs();
|
||||
var response = await openClaw.GetCronJobsAsync(200, ct);
|
||||
return response.Items
|
||||
.Select(job => new CronJobEntry(
|
||||
job.Id,
|
||||
job.Name,
|
||||
job.Schedule,
|
||||
job.LastRunAt?.ToString("O") ?? string.Empty,
|
||||
job.NextRunAt?.ToString("O") ?? string.Empty,
|
||||
job.Status))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<UpcomingCronEntry>> GetUpcomingCronJobsAsync(CancellationToken ct = default)
|
||||
public async Task<IReadOnlyList<UpcomingCronEntry>> GetUpcomingCronJobsAsync(
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = CreateGatewayClient();
|
||||
var response = await client.GetAsync("/api/cron/upcoming", ct);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var data = await response.Content.ReadFromJsonAsync<List<UpcomingCronEntry>>(ct);
|
||||
return data ?? new List<UpcomingCronEntry>();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogDebug(ex, "Gateway upcoming cron endpoint not reachable, using fallback data");
|
||||
}
|
||||
|
||||
return BuildFallbackUpcomingJobs();
|
||||
}
|
||||
|
||||
private HttpClient CreateGatewayClient()
|
||||
{
|
||||
var client = httpClientFactory.CreateClient("gateway");
|
||||
var token = configuration["Integrations:OpenClaw:Token"];
|
||||
if (!string.IsNullOrWhiteSpace(token))
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
return client;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<CronJobEntry> BuildFallbackCronJobs()
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
return
|
||||
[
|
||||
new("health-check", "Health Check", "*/5 * * * *", now.AddMinutes(-3).ToString("O"), now.AddMinutes(2).ToString("O"), "completed"),
|
||||
new("memory-sync", "Memory Sync", "0 */6 * * *", now.AddHours(-2).ToString("O"), now.AddHours(4).ToString("O"), "completed"),
|
||||
new("task-cleanup", "Task Cleanup", "0 3 * * *", now.AddDays(-1).ToString("O"), now.AddDays(1).AddHours(3).ToString("O"), "completed"),
|
||||
new("backup", "Database Backup", "0 4 * * *", now.AddDays(-1).AddHours(-1).ToString("O"), now.AddDays(1).AddHours(4).ToString("O"), "completed"),
|
||||
new("model-routing-refresh", "Model Routing Refresh", "*/30 * * * *", now.AddMinutes(-12).ToString("O"), now.AddMinutes(18).ToString("O"), "running")
|
||||
];
|
||||
}
|
||||
|
||||
private static IReadOnlyList<UpcomingCronEntry> BuildFallbackUpcomingJobs()
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
return
|
||||
[
|
||||
new("health-check", "Health Check", now.AddMinutes(2).ToString("O"), "*/5 * * * *"),
|
||||
new("model-routing-refresh", "Model Routing Refresh", now.AddMinutes(18).ToString("O"), "*/30 * * * *"),
|
||||
new("memory-sync", "Memory Sync", now.AddHours(4).ToString("O"), "0 */6 * * *"),
|
||||
new("task-cleanup", "Task Cleanup", now.AddDays(1).AddHours(3).ToString("O"), "0 3 * * *"),
|
||||
new("backup", "Database Backup", now.AddDays(1).AddHours(4).ToString("O"), "0 4 * * *")
|
||||
];
|
||||
var response = await openClaw.GetCronJobsAsync(200, ct);
|
||||
return response.Items
|
||||
.Where(job => job.Enabled && job.NextRunAt is not null)
|
||||
.OrderBy(job => job.NextRunAt)
|
||||
.Select(job => new UpcomingCronEntry(
|
||||
job.Id,
|
||||
job.Name,
|
||||
job.NextRunAt!.Value.ToString("O"),
|
||||
job.Schedule))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user