diff --git a/Spice/Spice.csproj b/Spice/Spice.csproj index 7b366ef..59ee5b2 100644 --- a/Spice/Spice.csproj +++ b/Spice/Spice.csproj @@ -2,7 +2,7 @@ SpiceAI - 0.3.0 + 0.4.0 netstandard2.0;net8.0;net9.0;net10.0 diff --git a/docs/release_notes/v0.4.0.md b/docs/release_notes/v0.4.0.md new file mode 100644 index 0000000..1bea1b0 --- /dev/null +++ b/docs/release_notes/v0.4.0.md @@ -0,0 +1,101 @@ +# Spice.ai .NET SDK v0.4.0 Release Notes + +## New Features + +### Health and Readiness Checks + +New `SpiceClient.IsSpiceHealthyAsync` and `SpiceClient.IsSpiceReadyAsync` methods wrap the runtime's `/health` and `/v1/ready` endpoints, reusing the endpoint, credentials, TLS/mTLS and user agent already configured on the builder. + +```csharp +using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); +if (!await client.IsSpiceHealthyAsync(cts.Token)) +{ + // runtime unreachable or unhealthy +} + +bool ready = await client.IsSpiceReadyAsync(); +``` + +An unreachable or unhealthy runtime is reported as `false` rather than thrown as an exception; caller-requested cancellation still propagates. + +### Vector, Keyword, and Hybrid Search + +New `SpiceClient.SearchAsync(SearchRequest, CancellationToken)` wraps `POST /v1/search` for datasets with an embedding column and a loaded embedding model. + +```csharp +using Spice.Search; + +var response = await client.SearchAsync(new SearchRequest("cozy mountain cabin") +{ + Datasets = new[] { "listings" }, + Limit = 10, + Where = "city = 'Tahoe'", + AdditionalColumns = new[] { "price" }, +}); + +foreach (var match in response.Results) +{ + Console.WriteLine($"{match.Dataset}: {match.Score}"); +} +``` + +Setting `Keywords` pre-filters the embedding column with a lexical search before the vector search runs, making the search hybrid. + +### Natural Language to SQL (Nsql) + +New `SpiceClient.NsqlAsync(NsqlRequest, CancellationToken)` translates a natural-language question into SQL via the runtime's configured LLM and runs it, returning the rows alongside the generated SQL. `NsqlGenerateSqlAsync` generates the SQL without running it. + +```csharp +using Spice.Nsql; + +var response = await client.NsqlAsync(new NsqlRequest("how many taxi trips were there yesterday?")); +Console.WriteLine(response.SQL); // the SQL the model generated +Console.WriteLine(response.Data); // the rows it returned, decoded from JSON + +// Inspect or edit the generated SQL without running it: +string sql = await client.NsqlGenerateSqlAsync(new NsqlRequest("how many taxi trips were there yesterday?")); +``` + +Requires an LLM model configured in the Spicepod. + +### On-Demand Dataset Refresh Options + +`RefreshDatasetAsync` accepts an optional `RefreshOptions` to override the dataset's configured refresh behavior for a single on-demand refresh. + +```csharp +await client.RefreshDatasetAsync("taxi_trips", new RefreshOptions() + .WithRefreshSql("SELECT * FROM taxi_trips WHERE tip_amount > 10.0") + .WithRefreshMode(RefreshMode.Append) + .WithMaxJitter(TimeSpan.FromSeconds(10))); +``` + +Any option left unset falls back to the dataset's configured value. Applies to datasets accelerated with `full` or `append` refresh mode; datasets using `changes` mode are kept up to date by change data capture and are unaffected. + +### Mutual TLS (mTLS) Client Certificate Support + +`SpiceClientBuilder` now accepts a PEM-encoded client certificate and key for mTLS, in addition to the existing server-side TLS options. + +```csharp +using var client = new SpiceClientBuilder() + .WithAddress("https://localhost:50051") + .WithTlsClientCertificate("client.pem", "client.key") + .WithTlsRootCertificate("ca.pem") + .Build(); +``` + +`WithTlsClientCertificate` implies `WithTls(true)`. Applies to both the Flight (gRPC) and HTTP clients. + +## Bug Fixes + +- Fixed `AuthenticateAsync` throwing `System.InvalidOperationException: Can't get the call trailers because the call has not completed successfully` on a failed handshake, which masked the actual gRPC authentication error. The auth token is now read from response headers first, falling back to trailers only when headers carry none. +- Fixed mTLS client certificate handshakes failing on Windows. +- `PooledConnectionLifetime` is now set on the gRPC channel's `SocketsHttpHandler` so long-lived connections are periodically recycled and DNS is re-resolved. Previously, clients connecting through load-balanced endpoints (e.g. AWS ALBs) could get stuck on a stale backend IP after a rebalance. + +## Dependencies + +Added: +- `System.Text.Json` 9.0.9 (netstandard2.0 target only) + +## Breaking Changes + +None.