Thank you for your interest in contributing to the Zig AI SDK!
-
Install Zig: Ensure you have Zig 0.13.0 or later installed
# Check your Zig version zig version -
Clone the repository:
git clone https://github.com/your-org/zig-ai-sdk.git cd zig-ai-sdk -
Build the project:
zig build
-
Run tests:
zig build test
packages/provider/- Core provider interfaces and typespackages/provider-utils/- HTTP utilities, streaming helperspackages/ai/- High-level API (generateText, streamText, etc.)packages/<provider>/- Individual provider implementationsexamples/- Example codetests/- Integration tests
-
Create a new directory under
packages/<provider-name>/src/ -
Create the provider file following this pattern:
const std = @import("std"); const provider_v3 = @import("../../provider/src/provider/v3/index.zig"); pub const MyProviderSettings = struct { base_url: ?[]const u8 = null, api_key: ?[]const u8 = null, }; pub const MyProvider = struct { allocator: std.mem.Allocator, settings: MyProviderSettings, base_url: []const u8, pub const specification_version = "v3"; pub fn init(allocator: std.mem.Allocator, settings: MyProviderSettings) @This() { return .{ .allocator = allocator, .settings = settings, .base_url = settings.base_url orelse "https://api.example.com", }; } pub fn deinit(self: *@This()) void { _ = self; } pub fn getProvider(self: *const @This()) []const u8 { _ = self; return "my-provider"; } pub fn languageModel(self: *@This(), model_id: []const u8) MyLanguageModel { return MyLanguageModel.init(self.allocator, model_id, self.base_url); } };
-
Create an
index.zigthat re-exports the public API:pub const provider = @import("my-provider.zig"); pub const MyProvider = provider.MyProvider; pub const MyProviderSettings = provider.MyProviderSettings; pub const createMyProvider = provider.createMyProvider; test { @import("std").testing.refAllDecls(@This()); }
-
Add the provider to
build.zig:const my_provider_mod = b.addModule("my-provider", .{ .root_source_file = b.path("packages/my-provider/src/index.zig"), .target = target, .optimize = optimize, }); my_provider_mod.addImport("provider", provider_mod);
-
Add tests in the provider file and integration tests
- Follow Zig's standard naming conventions
- Use
snake_casefor functions and variables - Use
PascalCasefor types - Add doc comments for public APIs using
/// - Keep functions focused and small
- Use descriptive parameter names
- Use arena allocators for request-scoped data
- Document ownership in function signatures
- Avoid memory leaks by properly deinitializing resources
- Use
deferfor cleanup operations
Example:
pub fn processRequest(allocator: std.mem.Allocator) !Result {
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
const arena_allocator = arena.allocator();
// Use arena_allocator for temporary allocations
// Return result allocated with the original allocator
return Result.init(allocator);
}- Write unit tests for all public functions
- Use
std.testingfor assertions - Test error conditions as well as happy paths
- Run tests with
zig build test
Example test:
test "MyProvider basic" {
const allocator = std.testing.allocator;
var provider = createMyProvider(allocator);
defer provider.deinit();
try std.testing.expectEqualStrings("my-provider", provider.getProvider());
}- Ensure all tests pass (
zig build test) - Ensure the build succeeds (
zig build) - Update documentation if needed
- Add a clear description of your changes
- Reference any related issues
- Check if the issue already exists
- Create a new issue with:
- Clear title and description
- Steps to reproduce
- Expected vs actual behavior
- Zig version and platform
Feel free to open an issue for questions or discussions.