diff --git a/CHANGELOG.md b/CHANGELOG.md index b310b9f6..8e1d6100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,79 +5,164 @@ All notable changes to aimux are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.3.0] — pending (planned 2026-08-17) -### Changed - -- **Breaking (python / node bindings)**: streaming-transcription sessions - now surface in-stream errors by raising (`next_part`) / rejecting - (`nextPart`) the typed error hierarchy instead of returning a serialized - `{"Err": ...}` part through the data channel, and part payloads are no - longer wrapped in a `{"Ok": ...}` envelope — both now match the C-ABI - session shape and the other six bindings (#145). Code that parsed the - envelope manually must catch the exception instead. - -## [0.3.0] - 2026-08-10 - -**Breaking release.** Reworks the error model across the C ABI and every -binding, and adds observability primitives (request recording/replay, sessions, -tracing). See [Breaking](#breaking) and [Removed](#removed) for migration. +**Breaking release.** 196 commits since 0.2.1: observability primitives +(recording / replay / sessions / tracing), composite models, streaming +transcription, a reworked error model across the C ABI and all eight +bindings, a browser console, and a large provider-correctness sweep. ### Breaking -- **`AiMuxError::RateLimited` gained a `message: String` field** (aimux-core). - The variant is now `RateLimited { retry_after_ms, message }` so callers can - distinguish "quota exceeded" from "too many requests". `#[serde(default)]` - keeps deserializing pre-0.3.0 error payloads, but the generated TypeScript - binding marks `message` required — update any exhaustive destructuring or - manual serialization. -- **`GenerateTextOptions` / `CallOptions` / `StreamTextResult` gained public - fields** (e.g. `session_id`, recording/trace controls, stream-result - metadata). Exhaustive struct initializers must add the new fields; prefer - struct-update (`..Default::default()`) to avoid breakage. -- **C ABI error transport switched to an `AimuxError` out-parameter.** FFI - functions now take `err: *mut AimuxError` and return a failure sentinel - instead of a JSON envelope string. The old JSON error envelope and the - streaming `on_error` callback have been removed — C-ABI consumers must read - the out-param rather than parsing a JSON error. -- **`aimux_last_error()` removed** from the C ABI. Error detail is now returned - via the `AimuxError` out-param on the call that failed; drop any - `aimux_last_error` declarations and handles. -- **Error model restructured in Kotlin, Java, Go, Swift, and Flutter** to mirror - the new `AimuxError` (typed code + HTTP status + retry hint + message). - Binding consumers should migrate from the old string/JSON error shape to the - typed error struct. +**Rust (aimux-core / aimux-provider-utils)** + +- `AiMuxError::RateLimited` gained `message: String` (now + `RateLimited { retry_after_ms, message }`); `#[serde(default)]` keeps + old payloads deserializable, but the generated TypeScript marks + `message` required — update exhaustive destructuring. +- `GenerateTextOptions` / `CallOptions` / `StreamTextResult` gained public + fields (`session_id`, recording/trace controls, stream-result metadata). + Use struct-update (`..Default::default()`) instead of exhaustive + initializers. +- `shared_client()` / `shared_streaming_client()` (aimux-provider-utils) + now return `Result<&'static Client, AiMuxError>`: client-build failures + (TLS backend, resource exhaustion) surface as a sticky, non-retryable + `ApiCall` instead of aborting the host process (#147). +- Panicking convert wrappers are deprecated in favor of fallible variants. + +**C ABI & the six FFI bindings (Kotlin / Java / Swift / Go / Flutter / C)** + +- Error transport switched to an `AimuxError` out-parameter with typed + code + HTTP status + retry hint; the JSON error envelope, the streaming + `on_error` callback, and `aimux_last_error()` are removed. +- All six bindings restructured to the typed error model. +- **Kotlin**: `topK` is now `Double` (was `Long` — 40.5 truncated + silently); published artifacts require **JDK 17** (`jvmToolchain(17)`). +- **Java**: `topK` likewise typed as double-valued (#106). +- `init_recording_ring(0)` now throws instead of a silent no-op + (consistent across all seven languages). + +**Python / Node (native bindings)** + +- Streaming-transcription sessions surface in-stream errors by raising + (`next_part`) / rejecting (`nextPart`) the typed hierarchy, and part + payloads are no longer wrapped in a `{"Ok": ...}` envelope — both now + match the C-ABI session shape and the other six bindings (#145/#150). + Code that parsed the envelope manually must catch the exception. ### Added -- **Request recording & replay** (RFC-0023 / RFC-0024) — `recording.rs` / - `replay.rs` capture provider config plus request/response streams to JSONL - and replay them offline for regression and CI; `config_snapshot()` records - the minimal provider/model identity. -- **Session grouping** — `session_id` on `GenerateTextOptions` groups related - calls for observability (RFC-0024; orthogonal to RFC-0019 session-affinity - headers). -- **Request tracing store** — `aimux-core::trace` records call spans for - debugging and audit (RFC-0015). -- **OpenAI Responses / output API** — the Azure Responses path - (`azure/responses.rs`) and the Codex subscription channel expose the - Responses API output flow. -- **`list_models` / `get_model_specs`** — `Provider::list_models` enumerates a - provider's models; `get_model_specs` returns reasoning/capability metadata - (RFC-0027 host-side merge). -- **Typed error model** across Rust and all eight bindings — machine-readable - `error_type`, HTTP status code, retry hint, and message. +- **Request recording & replay** (RFC-0023) — `Recorder` / + `JsonlRecorder` plus a bounded in-memory `RingRecorder` with drop + counting; layer-B HTTP choke-point recording (per-attempt, streaming, + credential redaction); mock & request replay with matchers and the + `aimux-replay` CLI; cross-binding exposure via C ABI, Python, Node, Go, + Swift, Kotlin, Java, Flutter; `config_snapshot()` captures the minimal + provider/model identity. `aimux_recording_try_flush` FFI export reports + write failures (sticky first error) across the ABI (#133/#137). +- **Session grouping** (RFC-0024) — `session_id` groups related calls; + `SessionStore` + `SessionInferer` with query APIs in all bindings; + session-cache trajectory export. +- **Cache-hit tracing** (RFC-0015) — `TraceLayer`, verdict engine, and + `RingTraceStore` detect prompt-cache hits from provider headers + (vLLM / SGLang / LMCache behaviours), with cluster/route-aware gating; + exposed in every binding. +- **`aimux-cli` cache-probe client** (RFC-0025) — offline / session / + provider probing over the trace store. +- **OpenAI-compatible output** (RFC-0026) — `generateOpenAIOutput` + across all eight bindings. +- **Model catalogue & listing** (RFC-0027) — `Provider::list_models` and + `get_model_specs` with reasoning/capability metadata. +- **External provider config overlay** (RFC-0020) — register or override + OpenAI-compatible providers from JSON at runtime. +- **Composite models** — drop-in `LanguageModel` wrappers, usable from every + binding with zero call-site changes: + - `RouterModel` (RFC-0021) routes each call to one child model through a + pluggable `Router` strategy (built-ins: `RuleRouter`, `WeightedRouter`) + with automatic fallback to the remaining children on failure. + - `MoaModel` (RFC-0022) implements mixture-of-agents in a single call: + reference models run in parallel, their outputs are spliced into an + aggregator prompt, and the aggregated answer is returned — no agent + loop involved. +- **Core API growth** — `streamText` aggregation, `generateObject`, + top-level result aggregation (reasoning / sources / files / + responseMessages), proxy configuration, `rawFinishReason`, logprobs, + `usage.raw`, streaming warnings, `includeRawChunks`, + `ResponseMetadata.timestamp`. +- **Streaming transcription** (RFC-0028) — realtime WebSocket sessions + with push-audio / next-part / abort / first-chunk and idle timeouts, + an FFI session API, and first-class support in all eight bindings. +- **`aimux-web` console** (RFC-0029) — browser-based model-call testing + and trace visualization, shipped as release artifacts. +- **In-page API key settings for the console** (RFC-0029 revision) — + set provider keys in the browser (Settings page): in-memory by default, + opt-in disk persistence at `0600`, masked hints only, and plaintext + entry is loopback-gated (non-loopback binds fall back to `env:VAR` + references). +- **FFI/binding ergonomics** — default-capacity ring init, cancellable Go + streams, `ProviderWithConfig` (Go), full `ProviderOptions` for + `provider()` (Python), optional recording-ring capacity in every + language. ### Fixed -- Audit rounds 1–4 fixes: Python binding exports (recording / mock-replay entry - points, `get_model_specs`), FFI error-transport correctness, and CI drift - (regenerated Node `index.js` / `index.d.ts`). +**Provider correctness** + +- Gemini: `functionResponse.name` now uses the tool name instead of the + opaque call id (multi-turn tool calls no longer 400) (#127). +- Anthropic: in-stream errors now emit the terminal `Finish` part + (contract parity with OpenAI/Google) (#128); assistant reasoning — + including its signature — is echoed back when thinking is enabled + (#131/#138). +- Bedrock & Anthropic: streaming no longer drops reasoning signatures; + extended-thinking multi-turn keeps its context (#131). +- Vertex: grounding / url-context / code-execution / server-tool results + are no longer silently dropped from streams; finish metadata restored + (#141/#143). +- AWS SigV4 signs the host header with non-default ports; local gateways + and proxied environments no longer fail (#125/#129). +- Six providers (openai/bedrock/cohere/mistral/huggingface/anthropic) + stop discarding response fields they had already parsed (#101/#139). +- Recording: writer I/O failures (e.g. ENOSPC) surface through + `try_flush` instead of a silent Ok, and the completion barrier requires + the input record before finalizing (#110/#133). +- Structured `ApiCall`/`NoSuchProvider` fields with unified retry + classification (#94); retry config honored for vertex/anthropic-aws; + credential-source accuracy for xai/open-responses; real provider + identity surfaced on the OpenAI chat path. +- Kotlin: the documented retryable timeout sentinel for `nextPart` is + actually reachable (#116/#144); close-race read/write locks for handle + types in Kotlin/Java/Flutter; Python exposes recording / mock-replay / + `get_model_specs` with typed exceptions. + +**Tests & fixtures** + +- Cassette bodies are no longer blanked for every streaming response — + 157 recovered recordings across 640 files (#102). +- Contract fixtures now type-check (field *values*, not just names) + across Rust and all eight bindings; the `top_k` drift that hid for + months is regression-locked (#106). + +### Engineering + +- Quality gates: workspace fmt, clippy baseline plus a permanent + 5-lint subset (1,521 fixes, incl. 146 hand-written `# Errors` docs), + `rustdoc -D warnings` in CI, ts-rs type-drift check, ProviderName + generator-drift check. +- Coverage infrastructure (cargo-llvm-cov) with a 78.5% workspace + baseline; unified e2e suite extended to six protocols; a 96-export FFI + smoke harness; RFC-0028 error-path coverage in Rust, Python and Node. +- Round 4 quality audit: 16 verified findings, full reports under + `docs/quality-audit/round4/`; unused-dependency sweep; rustdoc errors + 47 → 0. +- Release pipeline hardened from the 0.2.1 post-mortem (JVM Central + Portal routing, napi rebuild before publish, Flutter xcframework + embedding) plus a troubleshooting handbook. ### Removed -- `aimux_last_error()` C ABI function (replaced by the `AimuxError` out-param). -- C ABI JSON error envelope and the streaming `on_error` callback. +- `aimux_last_error()` (C ABI) — replaced by the `AimuxError` out-param. +- The C ABI JSON error envelope and the streaming `on_error` callback. ## [0.2.1] - 2026-08-04 diff --git a/README.md b/README.md index f1197064..595cea8d 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ aimux banner

-> **A unified LLM access layer written in Rust. One API for 325 AI providers.** +> **A unified LLM access layer written in Rust. One API for 329 AI providers.** [![CI](https://github.com/arcships/aimux/actions/workflows/ci.yml/badge.svg)](https://github.com/arcships/aimux/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Rust](https://img.shields.io/badge/rust-stable-orange.svg)](https://www.rust-lang.org/) -[![Providers](https://img.shields.io/badge/providers-325-green.svg)](docs/api/providers.md) +[![Providers](https://img.shields.io/badge/providers-329-green.svg)](docs/api/providers.md) [![Bindings](https://img.shields.io/badge/bindings-8-9cf.svg)](bindings/) [![crates.io](https://img.shields.io/crates/v/aimux-core)](https://crates.io/crates/aimux-core) [![npm](https://img.shields.io/npm/v/@arcships/aimux)](https://www.npmjs.com/package/@arcships/aimux) @@ -30,16 +30,24 @@ difference: aimux is an access layer, those are orchestration layers. ## Why aimux -- **325 provider modules** — 250 registry-backed OpenAI-compatible +- **329 provider modules** — 251 registry-backed OpenAI-compatible (unified `provider(name, ...)` entry) + 10 native protocol implementations (OpenAI, Anthropic, Google, Bedrock, Vertex, Azure, Cohere, - Mistral, xAI, Anthropic-AWS) + 65 standalone/modality/local/search providers + Mistral, xAI, Anthropic-AWS) + 68 standalone/modality/local/search providers (OpenRouter, DeepSeek, Ollama, vLLM, ElevenLabs, KlingAI, Tavily, …). Full list: [docs/api/providers.md](docs/api/providers.md). - **Unified, object-safe interface** — the `LanguageModel` trait supports `Box` so providers are interchangeable without changing call sites. - **Full multimodal** — text, streaming, tool calling, embeddings, image, - speech, transcription, video, reranking, files. + speech, transcription, video, reranking, files — plus **realtime + transcription sessions** (RFC-0028: push audio, pull transcript parts, + retryable timeouts). +- **Observability built in** (new in 0.3.0) — record every request/response + pair to JSONL and replay it offline (RFC-0023), group calls into sessions + (RFC-0024), and detect provider prompt-cache hits (RFC-0015). +- **Composite models** (new in 0.3.0) — `RouterModel` routes each call with + fallback (RFC-0021); `MoaModel` aggregates parallel reference models + mixture-of-agents style (RFC-0022). Both are plain `LanguageModel`s. - **Config-driven provider registry** — `provider-registry.json` describes each of the 250 OpenAI-compatible providers (base URL, env var, profile quirks: top_k, tools, response_format, streaming usage, max_tokens key); @@ -47,8 +55,9 @@ difference: aimux is an access layer, those are orchestration layers. - **Fast and small** — Rust core, release profile tuned for binary size (`lto`, `codegen-units=1`, `panic="abort"`, `strip`, `opt-level="z"`). - **8 language bindings** from one core: Node, Python, Swift, Kotlin, Flutter, - Go, Java, C. -- **Hermetic tests** — 2,650+ cassettes replay real API responses; no network + Go, Java, C — plus `aimux-web`, a browser console for model-call testing + and trace visualization (RFC-0029). +- **Hermetic tests** — 2,800+ cassettes replay real API responses; no network or API keys required. ## Performance @@ -90,7 +99,8 @@ aimux/ ├── aimux-providers # 290+ provider implementations (250 registry-backed + native) ├── aimux-stream # SSE / NDJSON stream parsing ├── aimux-provider-utils # HTTP utilities: retry, backoff, error parsing, API-key loading -└── aimux-ffi # C ABI (handles + JSON results + AimuxError out-param) for non-native bindings +├── aimux-ffi # C ABI (handles + JSON results + AimuxError out-param) for non-native bindings +└── tools/ # aimux-cli (cache probe) · aimux-replay · aimux-web (console) ``` ``` @@ -178,6 +188,87 @@ while let Some(part) = stream.next().await { } ``` +## Record & replay (new in 0.3.0) + +Every request/response pair can be captured to JSONL and replayed offline — +regression tests, incident forensics, and CI without network or keys +([RFC-0023](rfc/0023-runtime-request-recording.md)): + +```rust +use aimux_core::recording::{init_recording, JsonlRecorder}; +use std::sync::Arc; + +// One line turns on recording for the process (every binding has the same +// switch; secrets are redacted before hitting disk). +init_recording(Some(Arc::new(JsonlRecorder::new("./recordings")))); + +let result = generate_text(&model, "Explain Rust ownership.", Default::default()).await?; +// → ./recordings/recordings.jsonl now holds the full request + response, +// replayable offline with the `aimux-replay` CLI. +``` + +Related: sessions group calls with `session_id` ([RFC-0024](rfc/0024-session-aggregation.md)), +and cache-hit tracing detects prompt-cache reuse from provider headers +([RFC-0015](rfc/0015-cache-trace-audit.md), surfaced by `aimux-cli`). + +## Composite models: router & MoA (new in 0.3.0) + +```rust +use aimux_core::composite::ChildModel; +use aimux_core::moa::{MoaConfig, MoaModel}; +use aimux_core::router::{FallbackPolicy, RouterConfig, RouterModel, RuleRouter}; + +// Router: pick one model per call, fall back on failure (RFC-0021). +let children: Vec = vec![ + Arc::new(provider.model("gpt-4o")) as ChildModel, + Arc::new(provider.model("gpt-4o-mini")) as ChildModel, +]; +let routed = RouterModel::new( + children.clone(), + Box::new(RuleRouter), + FallbackPolicy::OnError, + RouterConfig::default(), +); + +// MoA: fan out to references, aggregate their answers (RFC-0022). +let moa = MoaModel::new( + children, + Arc::new(provider.model("gpt-4o")) as ChildModel, + MoaConfig::default(), +); + +// Both are plain LanguageModel — every API and binding works unchanged. +let result = generate_text(&routed, "…", Default::default()).await?; +``` + +## Realtime transcription sessions (new in 0.3.0) + +WebSocket-based streaming transcription with push-audio / next-part / +retryable timeouts, in every binding ([RFC-0028](rfc/0028-transcription-streaming.md)). +TypeScript: + +```typescript +import { openaiTranscription, startTranscriptionSession } from '@arcships/aimux' + +const model = await openaiTranscription(process.env.OPENAI_API_KEY!, 'gpt-realtime-whisper') +const session = await startTranscriptionSession(model, null) + +session.pushAudio(pcmChunk) // push audio as it arrives + +for (;;) { + try { + const raw = await session.nextPart(500) + if (raw === null) break // stream ended + const part = JSON.parse(raw) + if ('TranscriptDelta' in part) process.stdout.write(part.TranscriptDelta.delta) + } catch (e: any) { + if (e.retryable === false && e.message.includes('timeout')) continue + throw e // real failure — typed error + } +} +session.close() +``` + ## Switch providers ```rust @@ -192,7 +283,7 @@ let model = provider_from_env("deepseek", "deepseek-chat", None)?; // model usage is identical — it's all dyn LanguageModel ``` -All 250 OpenAI-compatible providers are registry-backed: `provider(name, ...)` +All 251 OpenAI-compatible providers are registry-backed: `provider(name, ...)` in every binding, with typed `ProviderName` (enum/union/consts per language). The retired per-provider shell types (`XxxConfig`/`XxxProvider`) are gone — see [docs/API.md](docs/API.md#providers). @@ -206,8 +297,8 @@ see [docs/API.md](docs/API.md#providers). | Type | Count | Examples | |------|:-----:|----------| | Native protocol | 10 | OpenAI, Anthropic, Google, Bedrock, Vertex, Azure, Cohere, Mistral, xAI, Anthropic-AWS | -| OpenAI-compatible (registry) | 250 | Groq, Fireworks, Together, Perplexity, Ollama Cloud, DeepSeek, Alibaba Tongyi, Zhipu, Baidu, Tencent, Moonshot, SiliconFlow… | -| OpenAI-compatible (standalone + Vertex-hosted) | 32 | OpenRouter, Hugging Face, Ollama, vLLM, SGLang, Llama.cpp, LiteLLM Proxy, Vertex-hosted DeepSeek/Qwen/Llama… | +| OpenAI-compatible (registry) | 251 | Groq, Fireworks, Together, Perplexity, Ollama Cloud, DeepSeek, Alibaba Tongyi, Zhipu, Baidu, Tencent, Moonshot, SiliconFlow… | +| OpenAI-compatible (standalone + Vertex-hosted) | 35 | OpenRouter, Hugging Face, Ollama, vLLM, SGLang, Llama.cpp, LiteLLM Proxy, Vertex-hosted DeepSeek/Qwen/Llama… | | Speech / transcription | 10 | ElevenLabs, Deepgram, AssemblyAI, AWS Polly, Cartesia, Hume, Gladia, RevAI, LMNT, Fal | | Image / video | 8 | Black Forest Labs, Replicate, Luma, Prodia, KlingAI, Recraft, Stability, RunwayML | | Embeddings / rerank / search | 13 | Voyage, Jina, Tavily, Exa, Firecrawl, Serper, SearXNG, You.com… | @@ -224,9 +315,9 @@ aimux ships 8 bindings that share the same Rust core: | **Node.js** | native | napi-rs v3 | `npm install @arcships/aimux` — [npm](https://www.npmjs.com/package/@arcships/aimux) | bundled in the package, nothing to do | | **Python** | native | PyO3 + maturin | `pip install arcships-aimux` — [PyPI](https://pypi.org/project/arcships-aimux/) | bundled in the wheel, nothing to do | | **Go** | C ABI | cgo (static link) | `go get github.com/arcships/aimux/bindings/go` then `go generate` | auto-downloaded `.a` from [GitHub Releases](https://github.com/arcships/aimux/releases) | -| **Swift** | C ABI | SPM | SPM: `https://github.com/arcships/aimux` (`from: "0.2.1"`) | `libaimux_ffi.dylib` — see [guide](docs/api/swift.md#install) | -| **Kotlin** | C ABI | JNA | `ai.arcships:aimux-kotlin` — Maven Central (publishing) | `libaimux_ffi.so/.dylib` or `aimux_ffi.dll` on the JNA search path — see [guide](docs/api/kotlin.md#install) | -| **Java** | C ABI | JNA | `ai.arcships:aimux-java` — Maven Central (publishing) | same as Kotlin — see [guide](docs/api/java.md#install) | +| **Swift** | C ABI | SPM | SPM: `https://github.com/arcships/aimux` (`from: "0.3.0"`) | `libaimux_ffi.dylib` — see [guide](docs/api/swift.md#install) | +| **Kotlin** | C ABI | JNA | `ai.arcships:aimux-kotlin` — Maven Central · **requires JDK 17+** (0.3.0) | `libaimux_ffi.so/.dylib` or `aimux_ffi.dll` on the JNA search path — see [guide](docs/api/kotlin.md#install) | +| **Java** | C ABI | JNA | `ai.arcships:aimux-java` — Maven Central | same as Kotlin — see [guide](docs/api/java.md#install) | | **Flutter** | C ABI | dart:ffi | `aimux` on pub.dev — Flutter plugin, native core embedded (publisher `arcships.ai`) | iOS/Android 开箱即用,桌面端开发/测试 — see [guide](docs/api/flutter.md#install) | | **C / C++** | C ABI | direct link | `.so`/`.dylib`/`.dll` + `aimux-ffi.h` from [GitHub Releases](https://github.com/arcships/aimux/releases) | link against it — see [guide](docs/api/c.md#install) | @@ -275,7 +366,18 @@ Tests run on cassette playback — no network and no keys. See | [0017](rfc/0017-provider-config-dx.md) | Unified provider config & request body overrides (DX) | | [0018](rfc/0018-codex-subscription.md) | Codex subscription channel provider (evaluation) | | [0019](rfc/0019-session-affinity.md) | Session affinity lightweight support | +| [0014](rfc/0014-logging.md) | Logging (`AIMUX_LOG` controls) | +| [0015](rfc/0015-cache-trace-audit.md) | Cache-hit tracing & audit (TraceLayer / verdict engine) | | [0020](rfc/0020-pi-agent-integration.md) | Pi Agent integration — aimux as a Pi package (provider registry → Pi models) | +| [0021](rfc/0021-composite-model-routing.md) | RouterModel — composite model routing with fallback | +| [0022](rfc/0022-moa-single-fanout.md) | MoaModel — single-fanout mixture-of-agents | +| [0023](rfc/0023-runtime-request-recording.md) | Request recording & replay (JSONL, ring, redaction) | +| [0024](rfc/0024-session-aggregation.md) | Session grouping & query APIs | +| [0025](rfc/0025-aimux-cli-cache-probe.md) | `aimux-cli` cache-probe client | +| [0026](rfc/0026-openai-compatible-output.md) | OpenAI-compatible output format | +| [0027](rfc/0027-model-catalogue-and-list-api.md) | Model catalogue & `list_models` | +| [0028](rfc/0028-transcription-streaming.md) | Realtime transcription streaming (WS sessions) | +| [0029](rfc/0029-web-console.md) | `aimux-web` browser console | ## Contributing diff --git a/docs/api/swift.md b/docs/api/swift.md index f86345fd..35ccf8a4 100644 --- a/docs/api/swift.md +++ b/docs/api/swift.md @@ -10,7 +10,7 @@ with ARC-managed model handles. Add the package via SPM (the git tag is the version): ```swift -.package(url: "https://github.com/arcships/aimux", from: "0.2.1"), +.package(url: "https://github.com/arcships/aimux", from: "0.3.0"), .target(name: "Aimux", dependencies: ["Aimux"]) ```