feat(sdk): add .NET SDK over libmoss (closes #431) - #460
feat(sdk): add .NET SDK over libmoss (closes #431)#460Adityacrypto-del wants to merge 3 commits into
Conversation
Codex reviewThe new .NET SDK structure is coherent, but a few contract mismatches will make important first-run and custom-embedding workflows unreliable. The biggest risks are around async mutation completion semantics and model selection for precomputed embeddings. |
| { | ||
| RequireName(name); | ||
| DocumentInfo[] snapshot = SnapshotDocs(docs); | ||
| return RunAsync(() => _native.CreateIndex(name, snapshot, modelId), cancellationToken); |
There was a problem hiding this comment.
BLOCKING CreateIndexAsync, AddDocsAsync, and DeleteDocsAsync return the native mutation result directly, but the SDK contract for these mutation calls is to poll the async job until completion before returning; MutationResult is documented as the result when the mutation job completes. The README then immediately calls LoadIndexAsync, so callers can race a still-building index.
return RunAsync(() => _native.CreateIndex(name, snapshot, modelId), cancellationToken);Fix by polling GetJobStatus until completed/failed before resolving these mutation tasks, or rename/document them as enqueue-only and update the quick start to wait for the job. (pkg.go.dev)
| using var arena = new NativeArena(); | ||
| IntPtr docsPtr = BuildDocuments(arena, docs); | ||
| Check(NativeMethods.moss_client_create_index( | ||
| _handle, arena.String(name), docsPtr, (nuint)docs.Count, arena.String(modelId), out IntPtr outPtr)); |
There was a problem hiding this comment.
BLOCKING Custom-embedding index creation is not handled: documents can carry Embedding, but this path forwards a null modelId unchanged and never enforces the all-or-none embedding rule. The existing SDK behavior defaults ModelID to "custom" when documents already have embeddings and rejects mixed batches.
_handle, arena.String(name), docsPtr, (nuint)docs.Count, arena.String(modelId), out IntPtr outPtr)Fix by detecting embeddings after SnapshotDocs: if any document has an embedding, require all documents to have one and set modelId ??= "custom" before calling native. (pkg.go.dev)
| (`libmoss.so` on Linux, `libmoss.dylib` on macOS, `moss.dll` on Windows). It | ||
| must be discoverable at runtime — on the standard library search path, next to | ||
| your application, or via `NativeLibrary` resolution. Building and unit-testing | ||
| the SDK does **not** require the native library; only running queries does. |
There was a problem hiding this comment.
CONSIDER The runtime requirement is understated. MossClient calls moss_client_new in its constructor, so any valid client creation or management call requires the native library, not only queries.
Building and unit-testing the SDK does **not** require the native library; only running queries does.Fix the docs to say libmoss is required whenever an application constructs/uses MossClient, or lazy-initialize native runtime only for local query operations if management APIs are meant to work without it.
Pull Request Checklist
Description
Adds a .NET SDK for Moss under
sdks/dotnet/, following the same two-layerstructure as the existing SDKs: an idiomatic async client (
src/Moss) over aP/Invoke interop layer (
src/Moss/Interop) that binds the nativelibmossC ABI — the same surface the Go bindings use via cgo.
Covers the issue scope: index management (create/get/list/delete), document
operations (add/delete/get), local runtime (load/unload/refresh), hybrid
search (
QueryAsync), and metadata filtering. Failures surface asMossExceptioncarrying the native status code andmoss_last_errormessage.buffer packing, and ABI struct layouts — all run without the native library
Note: the compiled
libmossruntime is required only to run queries, not tobuild or unit-test the SDK.
Fixes #431
Type of Change