A native OpenAI API client library for Vala and the wider GObject ecosystem, built on libsoup 3 and json-glib.
- Chat completions — one-shot and streamed (SSE), with tool calling,
JSON-mode
response_format, seed, penalties,stream_optionsand the other request knobs, plus both blocking andasyncentry points. - Embeddings —
POST /embeddings,floatandbase64encodings. - Images —
POST /images/generations, URL andb64_jsonoutput, size/quality/style controls. - Models —
GET /modelsandGET /models/{id}. - Robust errors — every failure lands in
Openai.Error, mapped from HTTP status (401 →AUTHENTICATION, 429 →RATE_LIMIT, 5xx →SERVER, ...); structured API error bodies are exposed throughClient.last_error. - Retries — 429/5xx and transient transport failures are retried with
exponential backoff honoring
Retry-After, bounded bymax_retries. - Typed models — request/response types with
to_json/from_json, nullable members only emitted when set.
- valac ≥ 0.56
- GLib/GIO ≥ 2.66
- libsoup-3.0
- json-glib-1.0
- Meson ≥ 0.56 + Ninja
Debian/Ubuntu: sudo apt install valac meson ninja-build libglib2.0-dev libsoup-3.0-dev libjson-glib-dev
meson setup build
ninja -C buildRun the test suite (unit tests plus end-to-end client tests against an in-process loopback HTTP server):
meson test -C buildInstall:
sudo ninja -C build installThis installs libopenai-1.0, the openai-1.0.vapi VAPI (with a .deps
file), the openai-1.0.h C header and a openai-1.0 pkg-config file, so the
library is consumable from Vala, C, and any GObject-introspection-friendly
toolchain.
var client = new Openai.Client("sk-...");
// or: var client = Openai.Client.from_environment();
var request = new Openai.ChatCompletionRequest("gpt-4o");
request.add_system("You are terse.");
request.add_user("Say hi in three words.");
request.temperature = 0.7;
try {
Openai.ChatCompletion reply = client.chat_completion(request);
print("%s\n", reply.text);
print("usage: %lld tokens\n", reply.usage.total_tokens);
} catch (Openai.Error e) {
warning("%s", e.message);
}Streaming:
var stream = client.chat_completion_stream(request);
Openai.ChatCompletionChunk? chunk;
while ((chunk = stream.next()) != null) {
var delta = chunk.text_delta;
if (delta != null)
print(delta);
}Async — every method has an _async twin:
var reply = yield client.chat_completion_async(request);Compiling against the installed library:
valac --pkg openai-1.0 app.vala -o app
# or via pkg-config from C/meson projects: dependency('openai-1.0')All public API carries valadoc comments. To render HTML docs:
meson setup build -Ddocs=true
ninja -C build docs # output in build/docs/html/| Class | Purpose |
|---|---|
Openai.Client |
Transport, auth, retries; sync + async methods |
Openai.ChatCompletionRequest |
Chat request builder |
Openai.ChatMessage, ChatRole |
Conversation messages |
Openai.ChatCompletion, ChatChoice, CompletionUsage |
Response types |
Openai.ChatCompletionStream, ChatCompletionChunk, ChatDelta |
SSE streaming |
Openai.Tool, FunctionDefinition, ToolCall, FunctionCall |
Tool calling |
Openai.EmbeddingRequest, EmbeddingResponse, Embedding |
Embeddings |
Openai.ImageGenerationRequest, ImageGenerationResponse, GeneratedImage, ImageFormat |
Image generation |
Openai.ModelList, ModelInfo |
Model catalog |
Openai.Error, ApiError |
Error reporting |
- Message
contentis handled as plain text; multipart content arrays (images, audio) are not yet modeled. - Base64 embedding responses are decoded to
float[]automatically (little-endian float32, per the API contract). - Not covered yet: audio, files, fine-tuning, batch, assistants
endpoints. The
Openai.Clientplumbing (extra_headers,with_session) is designed to make those incremental additions easy.
MIT — see LICENSE.