Skip to content

Latest commit

 

History

History
538 lines (404 loc) · 28.1 KB

API.md

File metadata and controls

538 lines (404 loc) · 28.1 KB

aimux API Documentation

Unified LLM service access layer — one API to access every provider (providers.md carries the count)

Table of Contents

Language Guides

Legacy (0.5 API). The language guides below still describe the 0.5 binding API, which V4 removed; each binding's README.md under bindings/ describes the current API. V4 errors are the shared ErrorEnvelope {kind, code, message, error} with no retry hint: read a retry delay from error.responseHeaders (retry-after-ms, then retry-after), as with the AI SDK. The rewrite is tracked in #277.

Each language has its own guide with that language's examples:

Language Guide Coverage
Node.js api/node.md Full multimodal surface (native path)
Python api/python.md Full multimodal surface (native path)
Rust api/rust.md Full multimodal surface (core)
Go api/go.md Full multimodal surface (C ABI path, typed wrappers)
C/C++ api/c.md Full multimodal surface (C ABI)
Swift api/swift.md Full multimodal surface (C ABI path)
Kotlin api/kotlin.md Full multimodal surface (C ABI path)
Flutter/Dart api/flutter.md Full multimodal surface (C ABI path)
Java api/java.md Full multimodal surface (C ABI path)

Quick Start

All bindings share the same API shape — only the syntax differs. Pick your language guide and follow its Quick Start:

Node.js · Python · Rust · Go · C/C++ · Swift · Kotlin · Flutter/Dart

Providers

Native protocols

OpenAI, Anthropic, Google, Bedrock, Vertex, Azure, Cohere, Mistral, xAI, Anthropic-AWS — one constructor per provider: openai(apiKey, model, baseUrl?) / anthropic(apiKey, model, baseUrl?) (Node, Python), NewOpenAI(apiKey, model) (Go), Model.openai(apiKey, modelId) (Java, Kotlin, Flutter), Aimux.openai(apiKey:modelId:) (Swift), create_openai(..) (Rust). Multimodal, local-inference and search providers have their own constructors too — full list: reference.md.

OpenAI-compatible (registry-backed)

Rust uses aimux_providers::create_provider(name, PresetSettings) for vendor packages and all 282 presets, then Provider::language_model(model_id). default_providers() supplies a map for aimux_core::provider_registry::create_provider_registry(providers, options), whose model ids default to provider:model. provider_names() lists accepted names; Provider::discovery() exposes runtime model listing.

The language bindings retain:

provider(name, api_key?, model_id, config?)   // language bindings
  name     — vendor package or registry preset name as a string
  api_key  — optional; omitted/None reads the provider's env var
  config   — optional overrides (base_url / headers / organization / project / params)
             `maxRetries` (a per-call option) and `bodyOverrides` (removed) are
             rejected with InvalidArgument, not ignored
  • Full list (name / env var / base URL): providers.md
  • Custom endpoint: registry name + base_url override, or the OpenAI constructor with a base URL

Features

Text Generation

Non-streaming text generation; returns the complete result.

Examples: Node.js · Python · Rust · Go · Swift · Kotlin · Flutter · C ABI

Parameters

Parameter Type Description
prompt string / Message[] Prompt or message array
max_output_tokens number? Maximum number of generated tokens
temperature number? Sampling temperature
top_p number? Nucleus sampling
stop_sequences string[]? Stop sequences
tools Tool[]? List of available tools
tool_choice ToolChoice? Tool selection strategy
instructions string? System instructions
reasoning ReasoningEffort? Reasoning effort
max_retries number? Per-call retry override; 0 disables retries (None = 2)
timeout TimeoutConfiguration? Per-call timeouts (total / step / first-chunk / chunk idle) — see Timeouts
provider_options object? Per-provider options keyed by namespace; for OpenAI-compatible providers, unknown fields of the provider's own namespace go to the request body as given
headers object? Extra HTTP headers

Node.js additionally accepts an AbortSignal as the 4th argument of generateText / streamText (see Request Cancellation).

Return Value

The result is a structured object with these fields (the exact type declaration differs per language — see each language guide for its own declaration):

Field Description
text Generated text of the final step (all Text parts concatenated)
content The final step's content parts — see Structured content
tool_calls The final step's tool calls, parsed and validated
tool_results The final step's tool results (provider-executed tools)
finish_reason Unified finish reason: stop, length, content-filter, tool-calls, error or other
raw_finish_reason The provider's own finish reason
usage Token usage (LanguageModelUsage) summed over the steps
warnings Warnings of the final step
steps Every model call of the generation (StepResult: content, finish reason, usage, performance, request, response with its messages, …)
response_messages Assistant and tool messages to append to the next prompt
output The value parsed by the output option (absent when not parsed)

reasoning, reasoning_text, files, sources, request, response, provider_metadata and total_usage are also present: the final step's values (total_usage equals usage), deprecated in the AI SDK.

LanguageModelUsage is flat and camelCase, as in the AI SDK's JSON: inputTokens, inputTokenDetails { noCacheTokens, cacheReadTokens, cacheWriteTokens }, outputTokens, outputTokenDetails { textTokens, reasoningTokens }, totalTokens and the provider's raw usage object. An unknown count is absent (the AI SDK's undefined), never zero; the two detail objects are always present. steps entries are camelCase as well (stepNumber, callId, model { provider, modelId }, performance, response { id, timestamp, modelId, headers?, body?, messages }), and each toolResults entry carries type: "tool-result".

Note: text, tool_calls and the other top-level fields are read from the final step's content. Tool calls are parsed and validated per the AI SDK parseToolCall / repairToolCall contract: a tool_calls entry carries the parsed input plus provider_metadata?, invalid? (true when tool lookup, input parse, or schema validation failed) and error? (the serialized AiMuxError — NoSuchTool / InvalidToolInput / ToolCallRepair).

Type declarations are per-language. Every binding declares these types in its own syntax: TypeScript interface/type in node.md, Python pydantic models in python.md, Rust struct/enum in rust.md, Kotlin data class in kotlin.md, Dart classes in flutter.md, Swift struct in swift.md, Go struct in go.md. The tables below describe the shared JSON shape that crosses the binding boundary — the field names and variant tags are identical in every language.

Structured content (content)

content is an array of tagged parts:

Variant Fields Description
Text text, provider_metadata? Generated text
ToolCall tool_call_id, tool_name, input, provider_executed?, dynamic?, provider_metadata?, invalid?, error? Tool call requested by the model, input parsed (same shape as a tool_calls entry)
Source source_type, id, url?, title?, … Reference/source
Reasoning text, provider_metadata? Reasoning/thinking segment
File / ReasoningFile data, media_type, provider_metadata? File generated by the model (or as part of reasoning)
ToolResult tool_call_id, tool_name, result, is_error?, preliminary?, dynamic?, provider_metadata? Tool result executed by the provider
ToolApprovalRequest approval_id, tool_call, … Approval request for a provider-executed tool call
Custom kind, provider_metadata? Provider-specific content

Streaming Generation

Returns generated content as a stream, output chunk by chunk.

Examples: Node.js · Python · Rust · Go · Swift · Kotlin · Flutter · C ABI

Stream part types

streamText yields the AI SDK's full stream (TextStreamPart): Start, then for each step StartStep … FinishStep, then Finish — or Abort when the call is aborted.

Variant Description
Start Stream start
StartStep Step start (carries request and the provider's warnings)
TextStart / TextDelta / TextEnd Text segment lifecycle (TextDelta.text)
ToolInputStart / ToolInputDelta / ToolInputEnd Tool calling input stream
ToolCall Complete tool call (same shape as a tool_calls entry, incl. invalid? / error?)
ToolResult Result of a provider-executed tool: tool_call_id, tool_name, input? (the call's input; absent for a deferred result), output, provider_executed, dynamic?, provider_metadata?
ToolError tool_call_id, tool_name, input?, error, provider_executed?, dynamic?, provider_metadata?: a provider-executed tool's error result (provider_executed: true), or the error that follows an invalid client tool call (its error message, dynamic: true)
ToolApprovalRequest Approval request for a provider-executed tool call
ToolOutputDenied / ToolApprovalResponse Part of the AI SDK's set for denied tools and answered approvals; aimux's stream does not produce them yet
ReasoningStart / ReasoningDelta / ReasoningEnd Reasoning segment lifecycle (ReasoningDelta.text)
Source / File / ReasoningFile / Custom Content parts, as in content
FinishStep Step end: response (id, timestamp, model_id, headers), usage, performance, finish_reason, raw_finish_reason, provider_metadata
Finish Stream end: finish_reason, raw_finish_reason, total_usage
Abort The call was aborted (reason?)
Error Stream error
Raw Provider raw chunk (for debugging, when include_raw_chunks is set)

stream_text emits the call-layer TextStreamPart type. Provider-layer StreamPart::ResponseMetadata events are consumed internally and do not appear in this stream.

Request Cancellation (abort)

Calls can be cancelled mid-flight. Cancellation covers the whole request lifecycle — connect, response headers, non-streaming body reads, and the streaming body (including while waiting between chunks and during retry backoff). An abort is reported as AiMuxError::Aborted (not retryable; a pre-aborted signal fails fast without sending).

  • Node.js — pass an AbortSignal as the last argument; the typed wrapper bridges it internally:

    import { openai, generateText, streamText } from '@arcships/aimux'
    
    const controller = new AbortController()
    const model = await openai('sk-...', 'gpt-4o')
    
    const result = await generateText(model, 'Explain Rust.', {}, controller.signal)
    
    const gen = streamText(model, 'Write a haiku.', {}, controller.signal)
    controller.abort() // cancels the stream promptly

    Under the hood the wrapper constructs an AbortBridge (also exported, for the raw napi surface and multimodal calls). AbortBridge is one-shot: it shares the signal's cancellation state, so aborting once aborts every call that uses the same bridge, and reusing an aborted bridge fails fast.

  • Rust — set abort_signal directly on the options (a runtime handle, it never crosses the JSON boundary):

    let signal = aimux_core::AbortSignal::new();
    let opts = GenerateTextOptions { abort_signal: Some(signal.clone()), ..Default::default() };
    let task = tokio::spawn(generate_text(&model, "Explain Rust.", opts));
    signal.abort(); // cancels the call
  • C ABI — cancellation rides a separate abort handle, not the JSON boundary: aimux_abort_signal_new() / aimux_abort_signal_abort() / aimux_abort_signal_drop(), plus the *_with_abort entry points (aimux_stream_text_with_abort, aimux_stream_text_as_openai_with_abort) and aimux_transcription_session_new's abort_handle.

  • Go — idiomatic: StreamTextContext / StreamTextAsOpenAIContext take a context.Context and drive that abort handle for you (GenerateText has no context variant yet).

  • Python / Swift / Kotlin / Java / Flutter — not yet exposed for generate/stream (tracked in RFC-0016 §7.3). Python's transcription session close() aborts its driver, and the Swift / Kotlin / Java / Flutter startStream takes an abortHandle — but only the C ABI exposes a way to create one (Go builds one internally from a context.Context and exposes none, so its StartTranscriptionSessionWithAbort has no usable caller).

Timeouts

Per-call timeout limits, JSON-serializable in every binding:

Field Type Description
total_ms number? Overall deadline for the whole call — includes retries and, for streaming, the entire stream. 0 fails immediately
first_chunk_ms number? Streaming only: time allowed from request start until the first chunk
chunk_ms number? Streaming only: max idle time between chunks (sliding window, reset on every chunk)

None/absent disables the corresponding limit. On expiry the call fails with AiMuxError::Timeout (not retryable); streaming timeouts surface as a TextStreamPart::Error item ("first chunk timeout" / "chunk idle timeout" / "total timeout"). Unrepresentable values (e.g. u64::MAX ms on narrower platforms) are rejected with AiMuxError::InvalidArgument instead of panicking. When both abort and a deadline are in play, abort wins.

// Node.js — timeouts ride inside the options object
await generateText(model, 'Explain Rust.', {
  timeout: { total_ms: 30_000, first_chunk_ms: 5_000, chunk_ms: 2_000 },
})
// Rust
let opts = GenerateTextOptions {
    timeout: Some(aimux_core::options::TimeoutConfiguration {
        total_ms: Some(30_000),
        first_chunk_ms: Some(5_000),
        chunk_ms: Some(2_000),
    }),
    ..Default::default()
};

Vercel's stepMs/toolMs are intentionally absent — they serve the multi-step tool loop (H4), which aimux does not implement (RFC-0016 §7.5).

Tool Calling

Tool definitions are language-agnostic data descriptions (JSON Schema) that require no macros.

Examples: Node.js · Python · Rust

Multi-Role Messages

prompt accepts a message array to implement multi-turn conversation; roles support system / user / assistant / tool.

Examples: Node.js · Python · Rust

Vector Embedding

Converts text into a vector representation.

Examples: Node.js · Python · Rust · Go · C ABI

Supported Providers

Factory function Provider Representative model
openaiEmbedding OpenAI text-embedding-3-small/large
cohereEmbedding Cohere embed-english-v3.0
googleEmbedding Google gemini-embedding-001

Speech Synthesis (TTS)

Converts text into speech audio.

Examples: Node.js · Python · Rust · Go · C ABI

Supported Providers

Factory function Provider Representative model
openaiSpeech OpenAI tts-1, tts-1-hd

Speech to Text (STT)

Converts audio into text (non-streaming).

Examples: Node.js · Python · Rust · Go · C ABI

Image Generation

Examples: Node.js · Python · Rust · Go · C ABI

Supported Providers

Factory function Provider Representative model
openaiImage OpenAI dall-e-3
googleImage Google gemini-2.5-flash-image

Video Generation

Most video models return a URL; the video operation downloads it, as the AI SDK's generateVideo does, and returns the bytes.

Examples: Node.js · Python · Rust · Go · C ABI

Reranking

Reorders a document list by relevance.

Examples: Node.js · Python · Rust · Go · C ABI

Search

Calls a search provider to obtain results.

Examples: Node.js · Python · Rust · Go · C ABI

⚠️ The SearchModel class is exported in Node.js / Python but there is no factory function in those bindings yet — use Rust, Go, or the C ABI.

File Upload

Uploads a file to the provider and returns a file ID.

Examples: Node.js · Python · Rust · Go · C ABI

Provider Factory Functions

Text Generation

Function Provider Example modelId
openai(apiKey, modelId, baseUrl?) OpenAI gpt-4o
anthropic(apiKey, modelId, baseUrl?) Anthropic claude-3-5-sonnet-20241022
deepseek(apiKey, modelId, baseUrl?) DeepSeek deepseek-chat

Vector Embedding

Function Provider Example modelId
openaiEmbedding(apiKey, modelId, baseUrl?) OpenAI text-embedding-3-small
cohereEmbedding(apiKey, modelId, baseUrl?) Cohere embed-english-v3.0
googleEmbedding(apiKey, modelId, baseUrl?) Google gemini-embedding-001

Speech Synthesis

Function Provider Example modelId
openaiSpeech(apiKey, modelId, baseUrl?) OpenAI tts-1

Speech to Text

Function Provider Example modelId
openaiTranscription(apiKey, modelId, baseUrl?) OpenAI whisper-1

Image Generation

Function Provider Example modelId
openaiImage(apiKey, modelId, baseUrl?) OpenAI dall-e-3
googleImage(apiKey, modelId, baseUrl?) Google gemini-2.5-flash-image

Video Generation

Function Provider Example modelId
googleVideo(apiKey, modelId, baseUrl?) Google veo-3.0

Reranking

Function Provider Example modelId
cohereReranking(apiKey, modelId, baseUrl?) Cohere rerank-v3.0

File Upload

Function Provider
openaiFiles(apiKey, baseUrl?) OpenAI

The baseUrl? parameter of all factory functions is optional; by default each provider's official API address is used. When testing, pass a local mock server URL.

Per-language naming. The tables above use the Node.js (camelCase) names. Each binding has its own naming convention for the same factories: Python uses snake_case (openai_embedding, google_video), Go uses NewXxx constructors returning (T, error) (NewOpenAIEmbedding, NewGoogleVideo), and the C ABI uses aimux_<provider>_<feature>_new (aimux_openai_embedding_new). Swift/Kotlin/Flutter/Java expose the multimodal models as their own classes (EmbeddingModel.openai(...), SpeechModel.openai(...), …). See Feature Coverage for the full matrix and each language guide for examples.


Feature Coverage

Coverage verified against the current binding implementations (2026-08-01):

Feature Rust (core) Node.js Python Swift Kotlin Flutter Go C/C++ Java
Text generation ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Streaming generation ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Vector embedding ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Speech synthesis (TTS) ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Speech to text (STT) ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Image generation ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Video generation ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Reranking ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Search ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
File upload ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
  • ✅ — available. All bindings now expose the full multimodal surface.
  • Node.js / Python (native path): full multimodal surface — every factory in the Provider Factory Functions section.
  • Go (C ABI path): full multimodal surface with typed wrappers — NewOpenAIEmbedding / NewCohereEmbedding / NewGoogleEmbedding, NewOpenAISpeech, NewOpenAITranscription, NewOpenAIImage / NewGoogleImage, NewOpenAIFiles, NewCohereReranking, NewGoogleVideo, NewTavilySearch, plus DeepSeek/NewDeepSeek and the typed Generate/Stream API. All multimodal constructors support WithBase variants.
  • C/C++ (C ABI path): full multimodal surface via the C ABI function list.
  • Swift / Kotlin / Flutter / Java (C ABI path): each now wraps all 8 multimodal model types alongside text generation and streaming. See each language guide for the API surface.

How this table was derived — every cell was checked against the binding's own source (not inferred from another language). A feature counts as ✅ only when the binding exposes a public factory and an invocable method for it; ⚠️ means the class exists but no factory function was found, so it cannot be instantiated. Evidence per binding:

Binding Evidence (source of truth)
Rust aimux-core/src/ — one trait per feature: language_model.rs, embedding_model.rs, speech_model.rs, transcription_model.rs, image_model.rs, video_model.rs, reranking_model.rs, search_model.rs, files_model.rs; plus generate.rs (generate_text / stream_text)
Node.js bindings/node/index.d.ts — 9 model classes plus a factory for every model type on the ./raw entry, tavilySearch (L499) included
Python bindings/python/src/lib.rs — 8 multimodal classes registered via add_class, 11 multimodal factories via add_function, tavily_search included
Swift bindings/swift/Sources/Aimux/Aimux.swift — Model (4 constructors) + generateText / streamText / streamTextAsync / generate; Multimodal.swift — 8 multimodal classes (EmbeddingModel, SpeechModel, TranscriptionModel, ImageModel, VideoModel, RerankingModel, SearchModel, Files) with factory constructors + methods + 19 Codable types
Kotlin bindings/kotlin/src/main/kotlin/ai/arcships/aimux/Model.kt — JNA interface declares all 97 ABI functions; Multimodal.kt — 8 multimodal Closeable classes with factory methods; the DTOs come from the Java artifact's generated ai.arcships.aimux.types package
Flutter bindings/flutter/lib/aimux.dart — Model (text); multimodal.dart — 8 multimodal classes with dart:ffi lookups for all 35 C ABI multimodal symbols (incl. the five RFC-0028 session entry points)
Go bindings/go/multimodal.go — NewOpenAIEmbedding / NewOpenAISpeech / NewOpenAITranscription / NewOpenAIImage / NewGoogleVideo / NewCohereReranking / NewTavilySearch / NewOpenAIFiles + matching ParseXxxResult; embedding & image are OpenAI-only (no Cohere/Google constructors)
C/C++ aimux-ffi/src/lib.rs — 113 exported extern "C" functions; full mapping in c.md

The ❌ / ⚠️ cells are tracked as actionable work items in Binding API Gaps — each gap lists the required C ABI functions and a reference implementation.

Construction and base_url Support

Binding FFI method base_url support Construction example
Node.js napi-rs (calls Rust directly) ✅ 3rd parameter await openai(key, model, 'http://localhost:3000')
Python PyO3 (calls Rust directly) ✅ 3rd parameter openai(key, model, "http://localhost:3000")
Swift C ABI (CAimuxFFI) ✅ baseUrl: parameter try Model.openai(apiKey: key, modelId: model, baseUrl: url)
Kotlin C ABI (JNA) ✅ 3rd parameter Model.openai(key, model, baseUrl)
Flutter/Dart C ABI (dart:ffi) ✅ baseUrl: named parameter Model.openai(key, model, baseUrl: url)
Go C ABI (cgo static linking) ✅ OpenAIWithBase aimux.OpenAIWithBase(key, model, url)
C/C++ C ABI (direct linking) ✅ _with_base function aimux_openai_new_with_base(key, model, url)

The Node/Python bindings bypass the C ABI and call aimux-providers directly; Swift/Kotlin/Flutter/Go/C go through the aimux-ffi C ABI. Go uses cgo to statically link libaimux_ffi.a, producing a single binary (see RFC-0011 for details).


Design Documents

Document Content
RFC-0001 Multi-language binding design
RFC-0003 Cassette testing design
RFC-0008 Multimodal binding design

License

MIT