From 3d3db677e2c40f193970799c8cd185209b1a4878 Mon Sep 17 00:00:00 2001
From: eric8810
Date: Mon, 17 Aug 2026 10:58:17 +0800
Subject: [PATCH 1/4] docs(changelog): comprehensive 0.3.0 release notes (merge
Unreleased)
---
CHANGELOG.md | 193 +++++++++++++++++++++++++++++++++++----------------
1 file changed, 133 insertions(+), 60 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b310b9f6..7d361061 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,79 +5,152 @@ 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** — `RouterModel` (RFC-0021) and `MoaModel`
+ mixture-of-agents (RFC-0022).
+- **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.
+- **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
From 449434a8ec5236eaa70d4b6bf1bc6d0ae40c3211 Mon Sep 17 00:00:00 2001
From: eric8810
Date: Mon, 17 Aug 2026 11:10:49 +0800
Subject: [PATCH 2/4] docs(readme): 0.3.0 features, counts, RFC table;
changelog composite-models detail
---
CHANGELOG.md | 11 ++++-
README.md | 130 +++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 125 insertions(+), 16 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d361061..856f5ef6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -75,8 +75,15 @@ bindings, a browser console, and a large provider-correctness sweep.
`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** — `RouterModel` (RFC-0021) and `MoaModel`
- mixture-of-agents (RFC-0022).
+- **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,
diff --git a/README.md b/README.md
index f1197064..595cea8d 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,12 @@
-> **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.**
[](https://github.com/arcships/aimux/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.rust-lang.org/)
-[](docs/api/providers.md)
+[](docs/api/providers.md)
[](bindings/)
[](https://crates.io/crates/aimux-core)
[](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
From 81ad189edd4476ba7f7bd2e1b6fe9cf9bfb5d94f Mon Sep 17 00:00:00 2001
From: eric8810
Date: Mon, 17 Aug 2026 11:11:01 +0800
Subject: [PATCH 3/4] docs(swift): bump SPM example to 0.3.0
---
docs/api/swift.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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"])
```
From 98b449999df9480fcf0a3d21ef7481762fb4384b Mon Sep 17 00:00:00 2001
From: eric8810
Date: Mon, 17 Aug 2026 12:15:27 +0800
Subject: [PATCH 4/4] docs(changelog): in-page key settings bullet
---
CHANGELOG.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 856f5ef6..8e1d6100 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -94,6 +94,11 @@ bindings, a browser console, and a large provider-correctness sweep.
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