81 lines
2.8 KiB
C#
81 lines
2.8 KiB
C#
using System.Diagnostics;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace Nexus.Api.Services;
|
|
|
|
public static class OpenClawInvocationContextFactory
|
|
{
|
|
private const int MaxMetadataLength = 128;
|
|
|
|
public static OpenClawInvocationContext Create(
|
|
string? actor = null,
|
|
string? idempotencyKey = null,
|
|
string? correlationId = null,
|
|
string? traceParent = null,
|
|
bool includeIdempotencyParameter = false)
|
|
{
|
|
var normalizedIdempotencyKey = NormalizeOrGenerate(idempotencyKey, "idem");
|
|
var normalizedCorrelationId = NormalizeOrGenerate(correlationId, "corr");
|
|
var normalizedActor = NormalizeActor(actor);
|
|
var normalizedTraceParent = NormalizeTraceParent(traceParent);
|
|
|
|
return new OpenClawInvocationContext(
|
|
normalizedIdempotencyKey,
|
|
normalizedCorrelationId,
|
|
normalizedActor,
|
|
normalizedTraceParent,
|
|
includeIdempotencyParameter);
|
|
}
|
|
|
|
public static string Hash(string value)
|
|
=> Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(value)));
|
|
|
|
private static string NormalizeOrGenerate(string? value, string prefix)
|
|
{
|
|
var trimmed = value?.Trim();
|
|
if (string.IsNullOrWhiteSpace(trimmed))
|
|
return $"{prefix}_{Guid.NewGuid():N}";
|
|
if (trimmed.Length > MaxMetadataLength)
|
|
throw new ArgumentException($"{prefix} metadata must not exceed {MaxMetadataLength} characters.");
|
|
if (trimmed.Any(char.IsControl))
|
|
throw new ArgumentException($"{prefix} metadata must not contain control characters.");
|
|
return trimmed;
|
|
}
|
|
|
|
private static string NormalizeActor(string? actor)
|
|
{
|
|
var trimmed = actor?.Trim();
|
|
if (string.IsNullOrWhiteSpace(trimmed))
|
|
return "nexus-system";
|
|
if (trimmed.Length > MaxMetadataLength)
|
|
return $"sha256:{Hash(trimmed)}";
|
|
return trimmed.Any(char.IsControl)
|
|
? $"sha256:{Hash(trimmed)}"
|
|
: trimmed;
|
|
}
|
|
|
|
private static string NormalizeTraceParent(string? traceParent)
|
|
{
|
|
var candidate = traceParent?.Trim();
|
|
if (!string.IsNullOrWhiteSpace(candidate))
|
|
{
|
|
if (!OpenClawGatewayProtocol.IsValidTraceParent(candidate))
|
|
throw new ArgumentException("traceparent must be a valid W3C trace context.", nameof(traceParent));
|
|
return candidate;
|
|
}
|
|
|
|
if (Activity.Current?.Id is { } current &&
|
|
OpenClawGatewayProtocol.IsValidTraceParent(current))
|
|
{
|
|
return current;
|
|
}
|
|
|
|
using var activity = new Activity("Nexus.OpenClaw.Invocation")
|
|
.SetIdFormat(ActivityIdFormat.W3C);
|
|
activity.Start();
|
|
return activity.Id
|
|
?? throw new InvalidOperationException("Could not create a W3C traceparent.");
|
|
}
|
|
}
|