No description
|
|
||
|---|---|---|
| examples | ||
| ixt-public@eaf4205d72 | ||
| src/IxtSdk | ||
| tests/IxtSdk.Tests | ||
| .gitignore | ||
| .gitmodules | ||
| IxtSdk.sln | ||
| README.md | ||
IXT .NET SDK (ixt-sdk-csharp)
.NET SDK for building IXT process modules in C#. Communicates with the IXT host runtime via Unix domain sockets using length-prefixed Cap'n Proto messages.
Requirements
- .NET 8.0+ SDK
- Zero NuGet dependencies (uses only built-in BCL types)
Quick Start
using IxtSdk;
public class MyModule : IxtProcessModule
{
protected override Task OnInitAsync(Dictionary<string, object?> config)
{
Log("Module initialized");
return Task.CompletedTask;
}
protected override Task<ModuleResponse> OnHandleAsync(HandleMessage message, ModuleContext context)
{
var payload = System.Text.Encoding.UTF8.GetString(message.Payload);
var response = System.Text.Encoding.UTF8.GetBytes($"Processed: {payload}");
return Task.FromResult(ModuleResponse.Success(response));
}
protected override Task OnShutdownAsync()
{
Log("Shutting down");
return Task.CompletedTask;
}
}
// Entry point
await new MyModule().RunAsync();
Module Manifest (module.imdl)
[module]
name = "my-module"
version = "1.0.0"
[artifacts.process]
interpreter = "dotnet"
entry = "MyModule.dll"
Architecture
IPC Protocol
All communication uses Cap'n Proto over Unix domain sockets:
Module <-> [4-byte LE length][Cap'n Proto IpcEnvelope] <-> Host
The IpcEnvelope wraps all message types (Init, Handle, Shutdown, ServiceRequest, etc.) with routing metadata.
Service Calls
Modules can call back to the host runtime via service clients. All service payloads use Cap'n Proto encoding (no JSON):
// KV Store
await KvStore.SetAsync("key", value);
var (found, data) = await KvStore.GetAsync("key");
// MessageBus
await MessageBus.SendAsync("target-module@1.0.0/default", "topic", payload);
// EventBus
await EventBus.PublishAsync("my.event", payload);
var subId = await EventBus.SubscribeAsync("my.*");
// Logging
await Logging.LogAsync(2, "Info message"); // 0=trace..4=error
// Assets
var data = await Assets.ReadAsync("config.json");
var files = await Assets.ListAsync("templates/");
Module Lifecycle
- Host spawns the .NET process
- Module connects via
IXT_IPC_SOCKETenvironment variable - Host sends
Initwith configuration - Host sends
OnReadyafter all modules are initialized - Host sends
Handlemessages for processing - Module can send
ServiceRequestmessages at any time - Host sends
Shutdownfor graceful termination
Project Structure
src/IxtSdk/
IxtProcessModule.cs # Abstract base class (implement this)
CapnpWireFormat.cs # Manual Cap'n Proto binary serializer
IpcSerializer.cs # Envelope build/parse + IPC framing
ServicePayloads.cs # Per-service Cap'n Proto payload builders
Models.cs # Data types (HandleMessage, ModuleResponse, etc.)
MessageType.cs # IPC message type enum
Services/ # Service client interfaces + implementations
tests/IxtSdk.Tests/ # xUnit tests (47 tests)
examples/
HelloModule/ # Minimal echo module
ServicesDemo/ # Exercises all service clients
schemas/
ipc.capnp # IPC envelope schema
ipc_services.capnp # Per-service request/response schemas
Building
dotnet build src/IxtSdk/IxtSdk.csproj
dotnet test tests/IxtSdk.Tests/IxtSdk.Tests.csproj
dotnet build examples/HelloModule/HelloModule.csproj
dotnet build examples/ServicesDemo/ServicesDemo.csproj
Cap'n Proto Wire Format
The SDK includes a zero-dependency manual Cap'n Proto serializer (CapnpWireFormat.cs) that handles:
- Single-segment messages with struct root pointers
- UInt8/16/64, Bool data fields
- Text (NUL-terminated, word-aligned)
- Data (byte arrays, word-aligned)
- Nested struct pointers
List(Text)composite lists
This matches the approach used by the Node.js SDK, avoiding the need for a C# Cap'n Proto code generator.