< Summary

Information
Class: Intentum.AI.SystemOne.SystemOneClient
Assembly: Intentum.AI.SystemOne
File(s): /home/runner/work/Intentum/Intentum/src/Intentum.AI.SystemOne/SystemOneClient.cs
Line coverage
100%
Covered lines: 42
Uncovered lines: 0
Coverable lines: 42
Total lines: 79
Line coverage: 100%
Branch coverage
60%
Covered branches: 6
Total branches: 10
Branch coverage: 60%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%11100%
.ctor(...)50%44100%
Decide(...)100%11100%
DecideAsync()75%44100%
BuildRequestUri()50%22100%
.ctor(...)100%11100%

File(s)

/home/runner/work/Intentum/Intentum/src/Intentum.AI.SystemOne/SystemOneClient.cs

#LineLine coverage
 1using System.Net.Http.Json;
 2using System.Text.Json;
 3using System.Text.Json.Serialization;
 4
 5namespace Intentum.AI.SystemOne;
 6
 7/// <summary>HTTP client for a System One compatible <c>POST /v1/systemone</c> endpoint.</summary>
 8public sealed class SystemOneClient
 9{
 110    private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
 11
 12    private readonly SystemOneOptions _options;
 13    private readonly HttpClient _httpClient;
 14
 15    /// <summary>Creates a client for the given engine options.</summary>
 416    public SystemOneClient(SystemOneOptions options, HttpClient httpClient)
 417    {
 418        _options = options ?? throw new ArgumentNullException(nameof(options));
 419        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
 420    }
 21
 22    /// <summary>Sends the state and typed questions and returns the answers synchronously.</summary>
 23    /// <param name="state">State to evaluate (string or object).</param>
 24    /// <param name="questions">Typed questions keyed by your own id.</param>
 25    public SystemOneResponse Decide(object state, IReadOnlyDictionary<string, SystemOneQuestion> questions) =>
 426        DecideAsync(state, questions).GetAwaiter().GetResult();
 27
 28    /// <summary>Sends the state and typed questions and returns the answers.</summary>
 29    /// <param name="state">State to evaluate (string or object).</param>
 30    /// <param name="questions">Typed questions keyed by your own id.</param>
 31    /// <param name="cancellationToken">Cancellation token.</param>
 32    public async Task<SystemOneResponse> DecideAsync(
 33        object state,
 34        IReadOnlyDictionary<string, SystemOneQuestion> questions,
 35        CancellationToken cancellationToken = default)
 436    {
 437        _options.Validate();
 438        ArgumentNullException.ThrowIfNull(state);
 439        ArgumentNullException.ThrowIfNull(questions);
 40
 441        var request = new SystemOneRequest(state, questions, _options.Model);
 442        var json = JsonSerializer.SerializeToUtf8Bytes(request, JsonOptions);
 443        using var message = new HttpRequestMessage(HttpMethod.Post, BuildRequestUri())
 444        {
 445            Content = new ByteArrayContent(json)
 446            {
 447                Headers = { ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json") { CharSet
 448            }
 449        };
 50
 451        if (_options.ApiKey is not null)
 152            message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _options.Api
 53
 454        var response = await _httpClient
 455            .SendAsync(message, cancellationToken)
 456            .ConfigureAwait(false);
 457        response.EnsureSuccessStatusCode();
 58
 459        var payload = await response.Content
 460            .ReadFromJsonAsync<SystemOneResponse>(JsonOptions, cancellationToken)
 461            .ConfigureAwait(false);
 62
 463        return payload ?? throw new InvalidOperationException("System One engine returned an empty response.");
 464    }
 65
 66    private Uri BuildRequestUri()
 467    {
 468        var baseUrl = _options.BaseUrl.TrimEnd('/');
 469        var path = _options.EndpointPath.StartsWith('/') ? _options.EndpointPath : "/" + _options.EndpointPath;
 470        return new Uri(baseUrl + path);
 471    }
 72
 473    private sealed record SystemOneRequest(
 474        [property: JsonPropertyName("state")] object State,
 475        [property: JsonPropertyName("questions")] IReadOnlyDictionary<string, SystemOneQuestion> Questions,
 476        [property: JsonPropertyName("model")]
 477        [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
 878        string? Model);
 79}