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
+64 -2
View File
@@ -1,8 +1,10 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Nexus.Api.Controllers;
using Nexus.Api.Services;
@@ -15,10 +17,16 @@ public class GatewayConnectorTests
// ── Options / Configuration tests ──
[Fact]
public void Options_DefaultWebSocketPath_IsWs()
public void Options_DefaultWebSocketPath_IsGatewayRoot()
{
var options = new GatewayConnectorOptions();
Assert.Equal("/ws", options.WebSocketPath);
Assert.Equal("/", options.WebSocketPath);
Assert.Equal(4, options.ProtocolVersion);
Assert.Equal(["operator.read"], options.Scopes);
Assert.Equal("nexus", options.ClientId);
Assert.Equal("backend", options.ClientMode);
Assert.False(options.ExternalClientIdentitySupported);
Assert.False(options.AllowReservedInternalClientIdentity);
}
[Fact]
@@ -49,6 +57,26 @@ public class GatewayConnectorTests
Assert.False(options.FailFastOnMissingVersion);
}
[Fact]
public void Connector_DefaultsToVerifiedGatewayVersionPin()
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Integrations:OpenClaw:BaseUrl"] = "http://127.0.0.1:18789"
})
.Build();
var connector = new GatewayConnector(
configuration,
Options.Create(new GatewayConnectorOptions()),
NullLogger<GatewayConnector>.Instance);
Assert.Equal(
OpenClawGatewayProtocol.DefaultRequiredGatewayVersion,
connector.RequiredVersion);
Assert.Equal("2026.7.1", connector.RequiredVersion);
}
// ── Configuration binding tests ──
[Fact]
@@ -58,6 +86,7 @@ public class GatewayConnectorTests
.AddInMemoryCollection(new Dictionary<string, string?>
{
["GatewayConnector:WebSocketPath"] = "/events",
["GatewayConnector:ProtocolVersion"] = "4",
["GatewayConnector:ReconnectInitialDelayMs"] = "2000",
["GatewayConnector:ReconnectMaxDelayMs"] = "60000",
["GatewayConnector:FailFastOnVersionMismatch"] = "false",
@@ -73,6 +102,7 @@ public class GatewayConnectorTests
var options = sp.GetRequiredService<IOptions<GatewayConnectorOptions>>().Value;
Assert.Equal("/events", options.WebSocketPath);
Assert.Equal(4, options.ProtocolVersion);
Assert.Equal(2000, options.ReconnectInitialDelayMs);
Assert.Equal(60000, options.ReconnectMaxDelayMs);
Assert.False(options.FailFastOnVersionMismatch);
@@ -308,4 +338,36 @@ public sealed class FakeGatewayConnector : IGatewayConnector
public DateTimeOffset? LastConnectedAt => _lastConnectedAt;
public int ReconnectAttempts => _reconnectAttempts;
public string? StatusMessage => _statusMessage;
public string? DeviceId => null;
public bool DeviceTokenConfigured => false;
public bool PairingRequired => false;
public string? PairingRequestId => null;
public int? ProtocolVersion => _state == GatewayConnectionState.Connected ? 4 : null;
public IReadOnlySet<string> AdvertisedMethods { get; } = new HashSet<string>(StringComparer.Ordinal)
{
"health",
"tasks.list"
};
public IReadOnlySet<string> AdvertisedEvents { get; } = new HashSet<string>(StringComparer.Ordinal)
{
"health",
"tick"
};
public IReadOnlySet<string> GrantedScopes { get; } = new HashSet<string>(StringComparer.Ordinal)
{
"operator.read"
};
public DateTimeOffset? LastEventAt => null;
public bool Supports(string method) => AdvertisedMethods.Contains(method);
public Task<JsonNode?> InvokeAsync(
string method,
object? parameters = null,
TimeSpan? timeout = null,
CancellationToken cancellationToken = default,
OpenClawInvocationContext? invocationContext = null)
=> Task.FromResult<JsonNode?>(null);
public IReadOnlyList<GatewayEventEnvelope> GetRecentEvents(int limit = 100) => [];
}