Skip to content

Shreai/sdk-dotnet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Shre AI .NET SDK

Single-file .NET SDK for the Shre AI / AROS platform. Zero external dependencies (System.* only). Targets net6.0 and net8.0.

Spec: SHARED-SDK-SPEC.md Sibling SDKs: Python, Swift, Kotlin

TL;DR

using ShreAI;

var sa = ShreClient.Initialize(new ShreConfig
{
    Endpoint = "https://apiauth.shre.ai",
    EventsEndpoint = "https://events.shre.ai",
    TenantId = "merchant_123",
    App = "rapid_pos",
    Mode = ShreMode.ReadOnly,
});

await sa.StartAsync();

ShreClient.Track("price_updated", entityType: "item", entityId: "UPC_012345678905",
    metadata: new Dictionary<string, object?> { ["old"] = 10.49, ["new"] = 10.99 });

// On shutdown:
await sa.StopAsync();

Install

NuGet (recommended)

dotnet add package ShreAI --version 2.0.0

Git submodule

git submodule add https://github.com/Shreai/sdk-dotnet third_party/shreai-dotnet

Reference the project in your .csproj:

<ProjectReference Include="..\third_party\shreai-dotnet\src\ShreAI\ShreAI.csproj" />

Single-file copy

The SDK is one file: src/ShreAI/ShreAI.cs. Copy it into your project. No csproj changes required beyond targeting net6.0+.

Initialize

Console / minimal

using ShreAI;

internal class Program
{
    static async Task Main()
    {
        await using var sa = new ShreClient(new ShreConfig
        {
            Endpoint = "https://apiauth.shre.ai",
            EventsEndpoint = "https://events.shre.ai",
            TenantId = "merchant_123",
            App = "rapid_pos",
            Mode = ShreMode.ReadOnly,
            StoreId = "store_42",
            UserId = "user_1",
            Role = "manager",
            OnError = (ex, ctx) => Console.Error.WriteLine($"[shre:{ctx}] {ex.Message}"),
            OnFlush = (ok, ko) => Console.WriteLine($"[shre] flushed ok={ok} rejected={ko}"),
        });
        await sa.StartAsync();
        sa.TrackEvent("app_started");
        // ...
        await sa.StopAsync();
    }
}

ASP.NET Core (IHostedService)

public sealed class ShreHostedService : IHostedService
{
    private readonly ShreClient _client;

    public ShreHostedService(IConfiguration cfg)
    {
        _client = ShreClient.Initialize(new ShreConfig
        {
            Endpoint = cfg["ShreAI:Endpoint"] ?? "https://apiauth.shre.ai",
            EventsEndpoint = cfg["ShreAI:EventsEndpoint"] ?? "https://events.shre.ai",
            TenantId = cfg["ShreAI:TenantId"]!,
            App = cfg["ShreAI:App"]!,
            Mode = ShreMode.ReadOnly,
        });
    }

    public Task StartAsync(CancellationToken ct) => _client.StartAsync(ct);
    public Task StopAsync(CancellationToken ct)  => _client.StopAsync(ct);
}

// Program.cs
builder.Services.AddHostedService<ShreHostedService>();

After this, anywhere in your app:

ShreClient.Track("order_placed", entityType: "order", entityId: orderId,
    metadata: new Dictionary<string, object?> { ["total"] = order.Total });

Windows Service / Worker

The same IHostedService pattern works for Worker Services. Inject the singleton and call the static ShreClient.Track(...) from your BackgroundService.

Configuration

Field Default Description
Endpoint required Control plane (https://apiauth.shre.ai)
EventsEndpoint falls back to Endpoint Data plane (https://events.shre.ai)
TenantId required Merchant / tenant identifier
App required App slug; must match ^[a-z][a-z0-9_-]{0,31}$
Mode ShreMode.ReadOnly ReadOnly (analytics) or ReadWrite (workflow agent)
BootstrapKey required for ReadWrite Server-issued bootstrap key
StoreId / UserId / Role null Optional context surfaced in events
SdkVersion "dotnet/2.0.0" Sent as X-Shre-SDK-Version and User-Agent
FlushIntervalSeconds 10 Periodic flush cadence (server can override via nextFlushSeconds)
BatchSize 50 Max events per flush
MaxQueueSize 5000 Bounded queue; oldest events drop when full
TimeoutMs 8000 HTTP timeout
OnError null (Exception, string contextTag) => void
OnFlush null (int accepted, int rejected) => void

Tracking

// Minimal
ShreClient.Track("screen_viewed");

// Full
ShreClient.Track(
    name: "price_updated",
    entityType: "item",
    entityId: "UPC_012345678905",
    metadata: new Dictionary<string, object?>
    {
        ["old_price"] = 10.49,
        ["new_price"] = 10.99,
        ["changed_by"] = "user_42",
    });

// Manual flush (rare — periodic timer handles this)
var ack = await sa.FlushAsync();
Console.WriteLine($"accepted={ack.Accepted} rejected={ack.Rejected}");

// Heartbeat (optional, surfaces SDK presence + queue depth)
await sa.HeartbeatAsync(deviceId: Environment.MachineName);

Error matrix

HTTP SDK behavior
200 Batch accepted; reset retry counter; honor nextFlushSeconds if returned
401 Re-bootstrap (refresh sdkToken); requeue batch
403 Kill switch — trackingEnabled flips to false; no further posts
429 / 5xx Exponential backoff (5s → 15s → 30s → 60s → 300s); requeue batch
Network Requeue batch; backoff; events stay in memory until MaxQueueSize is hit
Timeout Same as network

OnError(Exception, string) fires for every non-recoverable error with a context tag ("flush", "bootstrap", "flush-loop", "config-loop"). OnFlush(int accepted, int rejected) fires after every flush attempt — successful or not.

.NET-specific notes

  • No Microsoft.Extensions.Logging dependency. This SDK is System.* only. Wire to ILogger via OnError / OnFlush delegates:
    OnError = (ex, ctx) => logger.LogError(ex, "ShreAI {Context}", ctx),
    OnFlush = (ok, ko) => logger.LogInformation("ShreAI flush ok={Ok} ko={Ko}", ok, ko),
  • IDisposable and IAsyncDisposable. Either works; prefer await using in async contexts to avoid blocking on StopAsync.
  • AppDomain.ProcessExit drains queued events at shutdown. ASP.NET Core's graceful shutdown also calls IHostedService.StopAsync which calls StopAsync() directly — the SDK is safe under both paths.
  • Thread safety. All public methods are safe to call from any thread. The internal queue is a ConcurrentQueue<T>; flush serialization uses a SemaphoreSlim.
  • JSON. Uses System.Text.Json with CamelCase policy. No Newtonsoft dependency.
  • Trimming / AOT. The SDK uses Dictionary<string, object?> for event metadata which relies on reflection-based serialization. For full AOT compatibility, pin metadata to typed records or set JsonSerializerIsReflectionEnabledByDefault=true in your .csproj.

Security model

  • Endpoints validated at construction; downloads.* hostnames are rejected (those are weight-distribution hosts, not data planes).
  • ReadWrite mode requires a server-issued BootstrapKey; ReadOnly does not.
  • All requests carry X-Shre-Tenant, X-Shre-App, X-Shre-SDK-Version headers and (after bootstrap) Authorization: Bearer <sdkToken>.
  • Events carry stable eventId UUIDs for server-side idempotency.
  • The control plane can disable tracking at any moment via the trackingEnabled flag; the SDK respects it on the next flush or config refresh (every 5 minutes).

Versioning

This SDK follows the <lang>/<major.minor.patch> scheme used by all Shre AI SDKs. The SdkVersion string sent on every request is dotnet/2.0.0 for this release.

License

MIT — see LICENSE.

About

Shre AI .NET SDK — single-file event tracking client for the AROS platform

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages