feat: ship agent-first mission control v0.2.57
This commit is contained in:
@@ -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."));
|
||||
}
|
||||
Reference in New Issue
Block a user