feat: ship agent-first mission control v0.2.57
CI - Build & Test / Backend (.NET) (push) Successful in 42s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 2m46s
CI - Build & Test / Security Check (push) Successful in 3s
CI - Build & Test / Deploy Nexus (push) Successful in 56s

This commit is contained in:
AzuTear
2026-07-31 22:39:47 +02:00
parent 3bc7622977
commit f5552218bc
535 changed files with 95242 additions and 8791 deletions
+194
View File
@@ -0,0 +1,194 @@
using System.Text.Json.Nodes;
using Nexus.Api.Models;
using Nexus.Api.Services;
namespace Nexus.Api.Tests;
/// <summary>
/// Minimal live-RPC test double for consumers that only need the OpenClaw
/// agent/session inventory. Unsupported control-plane calls fail loudly so a
/// test cannot accidentally fall back to a fabricated legacy source.
/// </summary>
internal sealed class StubOpenClawControlService : IOpenClawControlService
{
public StubOpenClawControlService(
IReadOnlyList<OpenClawAgentDto>? agents = null,
IReadOnlyList<OpenClawSessionDto>? sessions = null,
bool connected = true)
{
Agents = agents ??
[
Agent("iris", "Iris", "openai/gpt-5.5", "/workspace/iris"),
Agent("product-owner", "Product Owner", "openai/gpt-5.5", "/workspace-po"),
Agent("programmer", "Programmer", "openai/gpt-5.4", "/workspace/programmer"),
Agent("programmer-fast", "Programmer Fast", "openai/gpt-5.3-codex-spark", "/workspace/programmer-fast"),
Agent("reviewer", "Reviewer", "openai/gpt-5.5", "/workspace/reviewer"),
Agent("architekt", "Architekt", "openai/gpt-5.5", "/workspace/architekt")
];
Sessions = sessions ?? [];
Connected = connected;
}
public IReadOnlyList<OpenClawAgentDto> Agents { get; }
public IReadOnlyList<OpenClawSessionDto> Sessions { get; }
public bool Connected { get; }
public OpenClawConnectionDto GetConnection()
=> new(
State: Connected ? "connected" : "disconnected",
Configured: true,
CredentialConfigured: true,
Connected: Connected,
Endpoint: "ws://openclaw-gateway:18789",
GatewayVersion: "2026.7.1",
RequiredVersion: "2026.7.1",
VersionPinned: true,
VersionMatches: true,
ProtocolVersion: 4,
GrantedScopes: ["operator.read"],
AdvertisedEvents: [],
LastConnectedAt: Connected ? DateTimeOffset.UtcNow : null,
LastEventAt: Connected ? DateTimeOffset.UtcNow : null,
ReconnectAttempts: 0,
Message: null,
Recovery: null,
CheckedAt: DateTimeOffset.UtcNow);
public Task<OpenClawCollectionDto<OpenClawAgentDto>> GetAgentsAsync(
CancellationToken cancellationToken = default)
=> Task.FromResult(Collection(Agents));
public Task<OpenClawCollectionDto<OpenClawSessionDto>> GetSessionsAsync(
int limit = 100,
CancellationToken cancellationToken = default)
=> Task.FromResult(Collection<OpenClawSessionDto>(
Sessions.Take(limit).ToArray()));
public IReadOnlyList<OpenClawCapabilityDto> GetCapabilities() => [];
public Task<OpenClawOverviewDto> GetOverviewAsync(CancellationToken cancellationToken = default)
=> Unsupported<OpenClawOverviewDto>();
public Task<OpenClawCollectionDto<OpenClawTaskDto>> GetTasksAsync(
int limit = 100,
string? cursor = null,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawTaskDto>>();
public Task<OpenClawCollectionDto<OpenClawCronJobDto>> GetCronJobsAsync(
int limit = 100,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawCronJobDto>>();
public Task<OpenClawCollectionDto<OpenClawCronJobDto>> GetCronJobsAsync(
bool includeDisabled,
int limit = 100,
string? cursor = null,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawCronJobDto>>();
public Task<OpenClawOperationDto<OpenClawCronJobDetailDto>> GetCronJobAsync(
string jobId,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawOperationDto<OpenClawCronJobDetailDto>>();
public Task<OpenClawCollectionDto<OpenClawCronRunDto>> GetCronRunsAsync(
string jobId,
int limit = 100,
string? cursor = null,
string? runId = null,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawCronRunDto>>();
public Task<OpenClawCollectionDto<OpenClawApprovalDto>> GetApprovalsAsync(
int limit = 100,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawApprovalDto>>();
public Task<OpenClawCollectionDto<OpenClawActivityDto>> GetActivityAsync(
int limit = 100,
string? cursor = null,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawActivityDto>>();
public Task<OpenClawCollectionDto<OpenClawModelDto>> GetModelsAsync(
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawModelDto>>();
public Task<OpenClawCollectionDto<OpenClawModelAuthProviderDto>> GetModelAuthStatusAsync(
bool refresh = false,
CancellationToken cancellationToken = default)
=> Unsupported<OpenClawCollectionDto<OpenClawModelAuthProviderDto>>();
public Task<OpenClawOperationDto<OpenClawTaskDto>> CancelTaskAsync(
string taskId,
string? reason,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<OpenClawTaskDto>>();
public Task<OpenClawOperationDto<object>> AbortSessionAsync(
string sessionKey,
string? runId,
bool clearQueued,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<object>>();
public Task<OpenClawOperationDto<object>> PatchSessionModelAsync(
string sessionKey,
string model,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<object>>();
public Task<OpenClawOperationDto<object>> RunCronJobAsync(
string jobId,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<object>>();
public Task<OpenClawOperationDto<object>> RunCronJobAsync(
string jobId,
string? expectedHash,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<object>>();
public Task<OpenClawOperationDto<OpenClawCronJobDetailDto>> CreateCronJobAsync(
CreateOpenClawCronJobRequest request,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<OpenClawCronJobDetailDto>>();
public Task<OpenClawOperationDto<OpenClawCronJobDetailDto>> PatchCronJobAsync(
string jobId,
JsonObject patch,
string? expectedHash,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<OpenClawCronJobDetailDto>>();
public Task<OpenClawOperationDto<object>> DeleteCronJobAsync(
string jobId,
string? expectedHash = null,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<object>>();
public Task<OpenClawOperationDto<OpenClawApprovalDto>> ResolveApprovalAsync(
string approvalId,
string kind,
string decision,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Unsupported<OpenClawOperationDto<OpenClawApprovalDto>>();
private static OpenClawAgentDto Agent(
string id,
string name,
string model,
string workspace)
=> new(
Id: id,
Name: name,
Description: null,
Model: model,
Provider: "openai",
Workspace: workspace,
Status: "ready");
private static OpenClawCollectionDto<T> Collection<T>(IReadOnlyList<T> items)
=> new(
State: "ready",
Items: items,
NextCursor: null,
Message: null,
Recovery: null,
CheckedAt: DateTimeOffset.UtcNow);
private static Task<T> Unsupported<T>()
=> Task.FromException<T>(new NotSupportedException(
"This test double only supports live agent and session inventory."));
}