Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
224 commits
Select commit Hold shift + click to select a range
103d23a
refactor(providers): remove generated provider name types
Sep 29, 2026
837aaaf
docs(changelog): record removal of generated ProviderName as breaking
Sep 29, 2026
9523030
fix(providers): drop the redundant #[must_use] on provider_names()
claude Oct 11, 2026
94c48ab
chore: drop stale provider_name references left after the ProviderNam…
cunninghamcard-bit Oct 1, 2026
1434ae1
docs(roadmap): Node drops the ProviderName string-literal union too
claude Oct 3, 2026
06db6c7
ci: run checks on every pull request and cancel superseded PR runs
claude Oct 12, 2026
7e9b5c2
test: delete self-generated contract fixtures and hand-written tests …
claude Oct 11, 2026
94630bf
refactor(web): consume generated core types directly
Sep 29, 2026
2f66709
refactor(web): generate wire types with ts-rs and import core types v…
Sep 29, 2026
25e678c
refactor(stream)!: remove unused StreamingToolCallTracker
claude Sep 29, 2026
22904a2
feat(stream)!: align StreamingToolCallTracker with the current AI SDK
claude Sep 29, 2026
028759b
feat(provider-utils)!: move the tool-call tracker next to its users a…
cunninghamcard-bit Oct 1, 2026
1922427
test(provider-utils): note the None/undefined mapping in the argument…
claude Oct 3, 2026
057e0bc
docs(changelog): record the tracker move to aimux-provider-utils
claude Oct 3, 2026
9f6bd17
refactor(provider-utils)!: rewrite the tool-call tracker in idiomatic…
Oct 9, 2026
7ffa66a
chore(stream): drop the tool-call tracker from the crate's dependenci…
claude Oct 11, 2026
043f88f
fix: address review findings on provider_names and wire export
Sep 29, 2026
cc5446f
refactor(core)!: messages, content, provider options and prompts foll…
claude Oct 12, 2026
25d28fb
refactor(core)!: provider results carry request and response informat…
claude Oct 12, 2026
ca115bc
refactor(core)!: tool types follow the AI SDK V4 tool types
claude Oct 12, 2026
c7fd832
Merge branch 'refactor/remove-generated-provider-name-types' into v4/…
claude Oct 12, 2026
6b2ca73
refactor!: providers are AI SDK V4 factories built on the AI SDK requ…
claude Oct 12, 2026
bbf4484
fix(provider-utils): drop the redundant #[must_use] on bytes_stream
claude Oct 12, 2026
27fc212
test(go): pass the prompt reasoning signature in provider_options
claude Oct 12, 2026
4140c69
fix(flutter): accept content in the StreamTextResultAggregated constr…
claude Oct 12, 2026
c81e221
test(flutter): drop the typed-call helper options no test passes any …
claude Oct 12, 2026
7646d84
Merge branch 'v4/3-messages-and-content-follow-the-ai-sdk' into v4/4-…
claude Oct 12, 2026
ae9ec6e
test(bindings): code 18 is NoOutputGenerated, 19 is the first unassig…
claude Oct 12, 2026
a9f7c7d
fix(swift): decode the FinishStep stream part
claude Oct 12, 2026
c0bc99d
fix: synchronize provider stack ABI and binding tests
Oct 12, 2026
39c162f
chore: record the integrated web wire type generation dependency
Oct 12, 2026
d4b1c62
test(bindings): serve the Chat Completions mocks to the deepseek preset
claude Oct 12, 2026
979f7bd
chore: remove the MIGRATION-NS.md scratch recipe
claude Oct 13, 2026
87c1b37
chore(fixtures): pin the AI SDK packages with sha512 integrity
claude Oct 13, 2026
7978920
chore(scripts): fetch the pinned AI SDK sources into target/aisdk
claude Oct 13, 2026
53b3dbe
chore(scripts): fetch all-or-nothing and keep the pinned integrity
claude Oct 13, 2026
6cc76f7
fix(provider-utils): keep parallel tool calls apart as provider-utils…
claude Oct 13, 2026
9687619
fix(core)!: keep specification_version on Provider and model traits
claude Oct 13, 2026
6195009
refactor(provider-utils)!: export only the tracker, keep its modules …
claude Oct 13, 2026
44e9820
test(provider-utils): differential tracker test against the pinned AI…
claude Oct 13, 2026
a3cb71b
fix(core): back-fill invalid tool input with the prototype-safe parse
claude Oct 13, 2026
3c3faa3
docs(core): say what TimeoutConfiguration mirrors
claude Oct 13, 2026
6f97d4b
docs: merge the migration into master layer by layer
claude Oct 13, 2026
ca19e38
docs: drop never-built aimux-only designs, move size gates to ROADMAP
claude Oct 13, 2026
a6c4fd5
test(core): restore the AiMuxError variant-set test
claude Oct 13, 2026
d053629
test(core): restore the RouterModel unit tests
claude Oct 13, 2026
d4caa28
fix(core)!: a repaired call that fails validation is not wrapped
claude Oct 13, 2026
90217da
test(core): tool-argument vectors checked against the AI SDK parse
claude Oct 13, 2026
606b9ee
fix(core)!: RetryError names the last error by its message
claude Oct 13, 2026
94501ec
docs(core): retry-count comments name the AI SDK default
claude Oct 13, 2026
4197573
refactor(core)!: provider namespace maps keep insertion order
claude Oct 13, 2026
c5200fd
refactor(core)!: video polling follows generateVideo's poll option
claude Oct 13, 2026
d41ffff
fix(core): ignore non-finite Retry-After values in retry_after_hint
claude Oct 13, 2026
0046bb9
refactor(core)!: model calls carry the V4 tool choice object union
claude Oct 13, 2026
ab3ad11
refactor(core)!: drop the reasoning part's top-level signature
claude Oct 13, 2026
d2c5e99
fix(core)!: a provider tool id must be namespaced
claude Oct 13, 2026
76eac2c
fix(core)!: a V4 tool result is never null
claude Oct 13, 2026
c2c7e68
docs: core tool results follow the AI SDK tool result family
claude Oct 13, 2026
77fb595
test(core): restore the MoA unit tests
claude Oct 13, 2026
e7e2291
test(core): restore the RFC-0026 OpenAI output converter tests
claude Oct 13, 2026
cb9eabe
fix(providers)!: hold the preset table without leaking memory
claude Oct 13, 2026
496ef24
Merge [1/8] into [2/8]: pinned AI SDK sources and the layer-by-layer …
claude Oct 13, 2026
cbb031a
fix(providers): report an invalid env base URL per call, not by panic…
claude Oct 13, 2026
b4c1970
docs(provider-utils): describe the redirect rule the code follows
claude Oct 13, 2026
f160c98
refactor(core)!: user messages are a union by role with per-role content
claude Oct 13, 2026
4ab3381
Merge [1/8] into [5/8]: pinned AI SDK sources and the layer-by-layer …
claude Oct 13, 2026
6036b57
fix(providers): keep AWS secret keys and Codex tokens out of Debug ou…
claude Oct 13, 2026
c4c8781
fix(provider-utils): strip URL userinfo from logs, errors and recordings
claude Oct 13, 2026
c6fd816
refactor!: remove ModelId, the download_guard re-export and deprecate…
claude Oct 13, 2026
f0e5bcf
refactor(provider-utils)!: move the shared OpenAI-shaped error handle…
claude Oct 13, 2026
e34d4b4
Merge [2/8] into [3/8]: tool choice union, namespaced kinds, tracker …
claude Oct 13, 2026
f82be3e
fix(anthropic): emit raw chunks when include_raw_chunks is set
claude Oct 13, 2026
f52c050
fix(openai): merge Responses reasoning parts by item id
claude Oct 13, 2026
067dc36
chore(node): regenerate call-option types for the retry-count comments
claude Oct 13, 2026
a3ab0a1
refactor(core)!: make supported_urls and its middleware override async
claude Oct 13, 2026
8e331d3
feat(core): add wrap_provider, the AI SDK's wrapProvider
claude Oct 13, 2026
db927e9
feat(core)!: accept the AI SDK's deprecated tool output items (#229 C37)
claude Oct 13, 2026
8201981
refactor(provider-utils)!: give each transport its own proxy, drop in…
claude Oct 13, 2026
c523dbe
test(openai): compare chat stream parts with the fixture, assert erro…
claude Oct 13, 2026
d3fd820
refactor(core)!: results and streams follow the AI SDK's steps, usage…
claude Oct 13, 2026
fe5e03f
test(openai-compatible): assert the request body key order on the sen…
claude Oct 13, 2026
76d66b6
test(openai): restore the realtime transcription WebSocket tests
claude Oct 13, 2026
252371b
feat(core)!: standardize the prompt and check tool results and tool c…
claude Oct 13, 2026
dd6ec60
docs: register header and transport differences, add RFC revision lines
claude Oct 13, 2026
8c8d25e
style: satisfy clippy map_entry and cloned_ref_to_slice_refs
claude Oct 13, 2026
ddfa3ff
chore(bindings): regenerate CallOptions.ts for the include_raw_chunks…
claude Oct 13, 2026
7b2599c
docs(changelog): rewrap the preset table bullet
claude Oct 13, 2026
8de583f
docs(bindings): describe init_proxy as replacing the default transport
claude Oct 13, 2026
767e80c
refactor(core)!: text results carry the AI SDK's core ContentPart (#2…
claude Oct 13, 2026
eec0a67
Merge [1/8] into [5/8]: the pinned AI SDK sources and the merge plan
claude Oct 13, 2026
7069574
fix(core)!: a custom content kind must be namespaced (#229 NP2-2)
claude Oct 13, 2026
45d6107
fix(bindings)!: bindings read the AI SDK-shaped results and stream parts
claude Oct 13, 2026
462af75
docs: API guides describe the step-based results and the full stream
claude Oct 13, 2026
97037c9
fix(core): stream_text drops empty text deltas without provider metadata
claude Oct 13, 2026
004f2a7
refactor(core)!: call options carry no call id or step helper (#230 C…
claude Oct 13, 2026
ed0e436
docs: scope note for part 2 and the speech and transcription tracing …
claude Oct 13, 2026
f5ce5a2
fix(core): redact the Prodia and Azure subscription key headers
claude Oct 13, 2026
2e8b3e4
fix(flutter): give the NativeFinalizer a pointer-sized drop entry point
claude Oct 13, 2026
fe9136c
fix(python): release the GIL around every blocking native call
claude Oct 13, 2026
0b85e7e
fix(core): an approval request replays input_schema_input only when i…
claude Oct 13, 2026
20d7458
fix(core)!: a provider tool result without its call is an error unles…
claude Oct 13, 2026
9a94b17
fix(web): accept env:VAR only for the provider's registered key variable
claude Oct 13, 2026
9111473
refactor(core)!: stream tool results are the AI SDK's typed tool resu…
claude Oct 13, 2026
e01a6c6
feat(core): an invalid tool call in the stream is followed by a tool …
claude Oct 13, 2026
1a9c60a
feat(core): the stream's part set includes tool-output-denied and too…
claude Oct 13, 2026
124dd49
fix(web): send no stored or env key to a caller-supplied base_url
claude Oct 13, 2026
75865e3
test(core): restore RFC-0031's stream timeout and pipeline tests (#23…
claude Oct 13, 2026
f9a31f4
test(core): acceptance tests for the stream part set, stream state an…
claude Oct 13, 2026
9505486
fix(core): never mark a recording complete after a lost or inconsiste…
claude Oct 13, 2026
ced1a9b
fix(replay): replay decision recordings of any provider live
claude Oct 13, 2026
c4b089f
docs: RFC-0031 states where the AI SDK request pipeline differs (U2, …
claude Oct 13, 2026
555630b
fix(web): give each custom endpoint its own trace scope
claude Oct 13, 2026
21f1457
docs(rfc): add the RFC-0023 revision line for the V4 recording layer
claude Oct 13, 2026
4c00266
Merge [3/8] into [4/8]: core ContentPart steps, prompt and tool-choic…
claude Oct 13, 2026
8520201
docs: the alignment document follows ai 7.0.127 for results, jobs and…
claude Oct 13, 2026
822def8
refactor(core)!: the retry count, timeout and session id are operatio…
claude Oct 13, 2026
e6f88ba
Merge [4/8] into [5/8]: AI SDK steps, stream parts and operation sett…
claude Oct 13, 2026
92e86a9
fix(core): tests and comments follow the merged retry and error sets
claude Oct 13, 2026
4b662a5
fix(providers): layer 5 provider code takes layers 2 to 4 types
claude Oct 13, 2026
9bfa1e9
chore(fixtures): the recorder pins provider-utils 5.0.55 as VERSIONS.…
claude Oct 13, 2026
ed192ea
docs: video polling, retry comments and generated types after the merge
claude Oct 13, 2026
06bb478
feat(core)!: the operations take an injectable download, as the AI SD…
claude Oct 13, 2026
35711cb
test(node): the reasoning replay test gives its tool call a result
claude Oct 13, 2026
dcc11f8
Merge [3/8] into [4/8]: the reasoning replay test gives its tool call…
claude Oct 13, 2026
18e3e0e
test(bindings): the DeepSeek usage.raw tests read the step usage
claude Oct 13, 2026
4ce9aa0
docs(node): regenerate index.d.ts for applyToolCallRepair's doc
claude Oct 13, 2026
cfe290a
Merge [4/8] into [5/8]: binding tests follow layers 3 and 4
claude Oct 13, 2026
38770b5
fix(core): keep recording schema 2 and read the recordings master writes
claude Oct 13, 2026
9d01eb5
chore(core): keep the removed key-source field name out of code
claude Oct 13, 2026
370f077
docs(changelog): legacy vertex and bedrock keys are still read and wr…
claude Oct 13, 2026
87e652c
docs: fix two rustdoc links that fail cargo doc -D warnings
claude Oct 13, 2026
03b43b7
ci: speed up test builds, deduplicate caches, and use prebuilt cargo-ndk
Oct 14, 2026
9ab9dff
ci: keep uploaded artifacts unchanged and stop PR runs from evicting …
claude Oct 14, 2026
c9ade5f
ci: fewer jobs per run so pull requests stop queueing for runners
claude Oct 14, 2026
2e746cd
docs(alignment): the first-chunk timer start is a registered difference
claude Oct 14, 2026
df7a67c
Merge the CI speed-up (#262) into [1/8]
claude Oct 14, 2026
4e0bfe2
Merge [1/8] into [2/8]: the CI speed-up (#262)
claude Oct 14, 2026
0fe1a89
Merge [2/8] into [3/8]: the CI speed-up (#262)
claude Oct 14, 2026
2af8255
Merge [3/8] into [4/8]: the CI speed-up (#262)
claude Oct 14, 2026
8ecea4e
Merge [4/8] into [5/8]: the CI speed-up (#262)
claude Oct 14, 2026
8ab9abb
ci: restore the Flutter SDK cache everywhere, save it from master only
claude Oct 14, 2026
753b61b
ci: build test-only FFI libraries at opt-level 1, not 0
claude Oct 14, 2026
19b9e9f
Merge the CI fix (#262) into [1/8]: test libraries at opt-level 1
claude Oct 14, 2026
824f948
Merge [1/8] into [2/8]: the CI fix (#262)
claude Oct 14, 2026
515fb3d
Merge [2/8] into [3/8]: the CI fix (#262)
claude Oct 14, 2026
75e96c2
Merge [3/8] into [4/8]: the CI fix (#262)
claude Oct 14, 2026
5aadb1c
Merge [4/8] into [5/8]: the CI fix (#262)
claude Oct 14, 2026
8ccd560
Merge branch 'master' into ci/optimize-ci-speed-and-cache
claude Oct 15, 2026
ca886c1
ci: pin cargo-ndk and keep pull requests from saving two more caches
claude Oct 15, 2026
7c5ded7
Merge branch 'master' into ci/optimize-ci-speed-and-cache
claude Oct 15, 2026
3fcf1da
Merge master into the ProviderName removal: Bedrock SigV4 and secret …
claude Oct 15, 2026
ec7ab7c
chore: delete the web console's generated ProviderName copy
claude Oct 15, 2026
ea0384a
Merge master into the web wire types: tiered CI (#263), Bedrock SigV4…
claude Oct 15, 2026
1bd6a55
ci: type-check the web console against the generated types
claude Oct 15, 2026
d1005cf
Merge the CI speed-up branch (with master) into [1/8]: tiered CI (#26…
claude Oct 15, 2026
d482975
docs: size and performance gates follow RFC-0043
claude Oct 15, 2026
c1d10b5
docs: the alignment doc links back to RFC-0036 §12.2 and names the me…
claude Oct 15, 2026
b32dc0a
ci: run the AI SDK pin script tests
claude Oct 15, 2026
710fcd7
docs: note the retired contract fixtures in the RFCs and the changelog
claude Oct 15, 2026
be87f81
docs(web): note that cargo test rewrites the tracked node types
claude Oct 15, 2026
d30833d
Merge [1/8] into [2/8]: master (#205-#212, #248, #263), the RFC-0043 …
claude Oct 15, 2026
d005871
test(openai): tool calls are flushed after an error frame
claude Oct 15, 2026
f0ee302
refactor(provider-utils): bound the tracker's id suffix search
claude Oct 15, 2026
fb2f23f
Merge [2/8] into [3/8]: master (#205-#212, #248, #263), the RFC-0043 …
claude Oct 15, 2026
7a726e3
test(core): restore the OpenAI output tool-argument tests
claude Oct 15, 2026
88ce267
test(core): part metadata replays whole into providerOptions
claude Oct 15, 2026
750f9a0
test(ffi): restore the composite, frame-error and session-input tests
claude Oct 15, 2026
4b21206
fix(core): a stream that ends with Finish is traced as completed
claude Oct 15, 2026
bfd9fdd
test(core): restore the TraceLayer suite
claude Oct 15, 2026
6faea33
test(core): a traced call keeps the id of its recording
claude Oct 15, 2026
62e2967
test(google): restore the inlineData-to-file tests
claude Oct 15, 2026
9fd8905
test(core): restore the replay_with_model tests
claude Oct 15, 2026
95d9a3a
Merge [3/8] into [4/8]: master (#205-#212, #248, #263), the RFC-0043 …
claude Oct 15, 2026
a7efac0
test(core): pin an abort after a finished step and repeated tool-call…
claude Oct 15, 2026
d989330
docs(alignment): register recording_context and deferred provider res…
claude Oct 15, 2026
1aead53
refactor(stream_text): the chunk loop has no arm that cannot run
claude Oct 16, 2026
73626fe
Merge [4/8] into [5/8]: master (#205-#212, #248, #263), #262's CI fol…
claude Oct 16, 2026
5fa4045
test(provider-utils): the default-transport test keeps 127.0.0.1 off …
claude Oct 15, 2026
e03b5f1
docs(web): a blank key at a custom base_url goes out as an empty key
claude Oct 15, 2026
20a0ee5
test(provider-utils): pin the redirect cap and re-signing on a same-o…
claude Oct 15, 2026
b7f1b7f
docs(rfc): RFC-0040 §3.2 follows the implemented redirect rule
claude Oct 15, 2026
a2ba419
test(providers): a preset's base-URL and optional-key variables
claude Oct 15, 2026
ed69b7e
test(preset): the registry checks run on any input
claude Oct 16, 2026
8f90ad6
feat(core): the recording context has an operation scope
claude Oct 16, 2026
13131b8
refactor(core)!: the recording context is an operation value, not a c…
claude Oct 16, 2026
2c86792
Merge the ProviderName removal (#246) into the web wire types
claude Oct 16, 2026
c749bf5
fix(core)!: a deferred tool result needs a provider tool that support…
claude Oct 16, 2026
9432c71
docs(core): the replay key and input record no longer name a recordin…
claude Oct 16, 2026
36b91bc
Merge [4/8] into [5/8]: deferred tool results and the recording scope
claude Oct 16, 2026
0b78344
build(core): ts-rs exports run only from the generator
claude Oct 16, 2026
e4104aa
fix(provider-utils): the tool call tracker generates ids as upstream
claude Oct 16, 2026
2f51e47
feat(bindings): typed provider tools carry supportsDeferredResults
claude Oct 16, 2026
79ea814
chore(node): regenerate InputRecord.ts for the corrected options comment
claude Oct 16, 2026
af67cb8
Merge [2/8] into [3/8]: the tracker generates ids as upstream
claude Oct 16, 2026
1e0a04d
Merge [3/8] into [4/8]: the tracker generates ids as upstream
claude Oct 16, 2026
85e65d8
Merge [4/8] into [5/8]: tracker ids, binding provider tools, InputRec…
claude Oct 16, 2026
c525525
Merge #247 into [1/8]: gated ts-rs exports and the ProviderName removal
claude Oct 16, 2026
020688d
Merge [1/8] into [2/8]: gated ts-rs exports and the ProviderName removal
claude Oct 16, 2026
21a4b2f
Merge [2/8] into [3/8]: gated ts-rs exports and the ProviderName removal
claude Oct 16, 2026
36a9e5c
Merge [3/8] into [4/8]: gated ts-rs exports and the ProviderName removal
claude Oct 16, 2026
2c477ce
Merge [4/8] into [5/8]: gated ts-rs exports and the ProviderName removal
claude Oct 16, 2026
b0dc009
docs(changelog): the deferred tool result rule is generate_text's
claude Oct 16, 2026
6422a37
Merge [4/8] into [5/8]: the deferred tool result rule is generate_text's
claude Oct 16, 2026
7a4b023
Merge master into #246: the #266 docs wording
claude Oct 16, 2026
453f611
Merge #246 into #247: master's #266 docs wording
claude Oct 16, 2026
796bd99
Merge #247 into [1/8]: master's #266 docs wording
claude Oct 16, 2026
36c8823
Merge [1/8] into [2/8]: master's #266 docs wording
claude Oct 16, 2026
59d9005
Merge [2/8] into [3/8]: master's #266 docs wording
claude Oct 16, 2026
2997346
Merge [3/8] into [4/8]: master's #266 docs wording
claude Oct 16, 2026
857b29d
Merge [4/8] into [5/8]: master's #266 docs wording
claude Oct 16, 2026
6ca248e
test(scripts): give the pin fetch test its own user and global npmrc
claude Oct 16, 2026
e572504
Merge [3/8] into [4/8]: the pin fetch test fix
claude Oct 16, 2026
7790a2b
Merge [1/8] into [2/8]: the pin fetch test fix
claude Oct 16, 2026
be39004
Merge [2/8] into [3/8]: the pin fetch test fix
claude Oct 16, 2026
9a9056c
Merge [4/8] into [5/8]: the pin fetch test fix
claude Oct 16, 2026
38b6cde
docs(rfc): the retry count, timeout and session id are operation sett…
claude Oct 16, 2026
f039e50
Merge [4/8] into [5/8]: RFC text for the operation settings
claude Oct 16, 2026
2a0b02b
Merge master into [1/8]: keep this layer ci.yml/CHANGELOG/local-ci
eric8810 Oct 17, 2026
057453e
Merge [1/8] into [2/8]: #262, #246 and #247 as eric merged them
claude Oct 17, 2026
bdeebad
Merge [2/8] into [3/8]: #262, #246 and #247 as eric merged them
claude Oct 17, 2026
6fec783
Merge [3/8] into [4/8]: #262, #246 and #247 as eric merged them
claude Oct 17, 2026
79c2efc
Merge [4/8] into [5/8]: #262, #246 and #247 as eric merged them
claude Oct 17, 2026
c0e6ec4
Merge master into [5/8]: keep this layer versions
eric8810 Oct 17, 2026
c435a38
fix(tests): restore this layer's openrouter and elevenlabs tests afte…
cunninghamcard-bit Oct 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,8 @@ jobs:
- uses: actions/checkout@v4
- name: Providers doc generator drift (docs/api/providers.md must match generator output)
run: python3 scripts/gen_providers_doc.py --check
- name: Provider boundaries (no call-level reads or provider-name branches in providers, removed names stay removed)
run: bash scripts/check_provider_boundaries.sh
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ quirks-corpus/
# Generated audit artifacts — keep conclusions in Markdown, not raw output.
/docs/quality-audit/**/lcov.info
/docs/quality-audit/**/*.log

# AI SDK protocol fixture recorder (scripts/aisdk-fixtures) — npm install output
scripts/aisdk-fixtures/node_modules/
418 changes: 406 additions & 12 deletions CHANGELOG.md

Large diffs are not rendered by default.

29 changes: 23 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ to set up a development environment, run the tests, and submit changes.
aimux/
├── aimux-core/ # Core abstractions: LanguageModel / Provider / Message / StreamPart
├── aimux-providers/ # provider implementations + cassettes (counts: docs/api/providers.md)
├── aimux-stream/ # SSE parsing
├── aimux-provider-utils/ # HTTP utilities: retry, backoff, error parsing, API-key loading, streamed tool-call tracking
├── aimux-stream/ # SSE decoding
├── aimux-provider-utils/ # HTTP utilities: Fetch transport, Resolvable settings, error parsing, API-key loading, streamed tool-call tracking
├── aimux-ffi/ # C ABI (opaque handle + JSON + push callback) for non-native bindings
├── bindings/ # Node, Python, Swift, Kotlin, Flutter, Go, C — share one Rust core
├── rfc/ # Design docs (RFCs)
Expand Down Expand Up @@ -38,6 +38,20 @@ cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
```

Provider changes also run the generator and boundary checks CI runs in the
`contract-tests` job:

```bash
python3 scripts/gen_providers_doc.py --check # docs/api/providers.md
python3 scripts/gen_ts_types.py --check # ts-rs types for the Node binding
bash scripts/check_provider_boundaries.sh # factory-shape rules for provider packages
```

The Node and Python bindings are separate workspaces: run `cargo fmt` and
`cargo clippy -- -D warnings` inside each, then `npm ci && npm run build &&
npm test` (Node) or `maturin build --release`, `pip install` the wheel and
`python -m pytest tests/` (Python).

## Testing

Tests run entirely on **cassette playback** — no network access and no API keys
Expand All @@ -62,10 +76,13 @@ aimux distinguishes three kinds of providers:
1. **Native protocol** — providers with their own request/response model
(OpenAI, Anthropic, Google, Bedrock, …). Implement the full `convert`/model
path and handle provider-specific differences.
2. **OpenAI-compatible thin wrapper** — the majority. Describe differences via
`OpenAICompatProfile` (top_k, tools, response_format, streaming usage,
request-body post-processing) so the thin wrapper does not erase
provider-specific behavior.
2. **OpenAI-compatible preset** — the majority. One row of
`aimux-providers/src/provider_registry.json` (base URL, key variable or
`auth: none`, optional URL variable and template parameters) that
is embedded and parsed once into a runtime table. Create presets by name
through `provider(name, ...)`. Vendors with behavior of their own get a package on
the shared compatible chat model (`groq/`, `deepseek/`) instead of a
branch on their name.
3. **Modality-specific** — speech, image, video, transcription, etc.

Step-by-step checklists (with the generator and CI rules) live in
Expand Down
79 changes: 39 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<img src="assets/aimux-banner.png" alt="aimux banner" width="100%">
</p>

> **A unified LLM access layer written in Rust. One API for [327 AI providers](docs/api/providers.md).**
> **A unified LLM access layer written in Rust. One API for [327 provider names](docs/api/providers.md).**

[![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)
Expand Down Expand Up @@ -32,13 +32,10 @@ For planned milestones and their current status, see the [roadmap](ROADMAP.md).

## Why aimux

- **327 providers** (as of 2026-09-24) — 251 registry-backed OpenAI-compatible
(unified `provider(name, ...)` entry) + 76 typed providers (native protocol
implementations such as OpenAI/Anthropic/Google/Bedrock/Vertex, local
engines like Ollama/vLLM, and speech/image/video/search modality providers).
Counts by category and the full list live in
[docs/api/providers.md](docs/api/providers.md) — generated, and the single
source of truth for provider counts (only the badge above repeats the total).
- **327 provider names** — 282 registry-backed OpenAI-compatible presets
+ 45 vendor packages, covering text and other modalities. Local engines
such as Ollama/vLLM are presets. `provider_names()` lists the Rust names;
the generated catalogue lives in [docs/api/providers.md](docs/api/providers.md).
- **Unified, object-safe interface** — the `LanguageModel` trait supports
`Box<dyn>` so providers are interchangeable without changing call sites.
- **Full multimodal** — text, streaming, tool calling, embeddings, image,
Expand All @@ -51,10 +48,12 @@ For planned milestones and their current status, see the [roadmap](ROADMAP.md).
- **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 registry-backed OpenAI-compatible provider (base URL, env var, profile
quirks: top_k, tools, response_format, streaming usage, max_tokens key);
one unified `provider(name, ...)` entry in every binding.
- **Config-driven provider registry** — `provider_registry.json` describes
each registry-backed OpenAI-compatible provider (base URL, env var, auth
mode, template parameters); the embedded JSON is parsed once into a runtime
descriptor table. Rust uses `create_provider(name, PresetSettings)` for
presets and vendor packages; bindings retain `provider(name, ...)`.
Packages follow the AI SDK shape: `XxxProviderSettings` + `create_xxx()` + a default `xxx()`.
- **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,
Expand Down Expand Up @@ -150,14 +149,12 @@ console.log(result.text)

```rust
use aimux_core::prelude::*;
use aimux_providers::{OpenAIConfig, OpenAIProvider};
use aimux_providers::openai::openai;

#[tokio::main]
async fn main() -> Result<(), AiMuxError> {
let provider = OpenAIProvider::new(
OpenAIConfig::new(std::env::var("OPENAI_API_KEY")?)
);
let model = provider.model("gpt-4o");
// The default provider loads OPENAI_API_KEY when a request is made.
let model = openai().chat("gpt-4o");

let result = generate_text(
&model,
Expand Down Expand Up @@ -222,9 +219,10 @@ 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 provider = aimux_providers::openai::openai();
let children: Vec<ChildModel> = vec![
Arc::new(provider.model("gpt-4o")) as ChildModel,
Arc::new(provider.model("gpt-4o-mini")) as ChildModel,
Arc::new(provider.chat("primary-model-id")) as ChildModel,
Arc::new(provider.chat("secondary-model-id")) as ChildModel,
];
let routed = RouterModel::new(
children.clone(),
Expand All @@ -236,7 +234,7 @@ let routed = RouterModel::new(
// MoA: fan out to references, aggregate their answers (RFC-0022).
let moa = MoaModel::new(
children,
Arc::new(provider.model("gpt-4o")) as ChildModel,
Arc::new(provider.chat("primary-model-id")) as ChildModel,
MoaConfig::default(),
);

Expand Down Expand Up @@ -275,35 +273,36 @@ session.close()
## Switch providers

```rust
// OpenAI → DeepSeek: only the provider name changes (registry-backed;
// key read from the provider's env var)
use aimux_providers::{provider, provider_from_env};
use aimux_core::provider_registry::create_provider_registry;
use aimux_providers::{create_provider, default_providers, provider_names, PresetSettings};

let model = provider("deepseek", None, "deepseek-chat", None)?;
let model = provider_from_env("deepseek", "deepseek-chat", None)?;
// Keys are loaded when a request is made.
let provider = create_provider("deepseek", PresetSettings::default())?;
let model = provider.language_model("deepseek-chat")?;

// Or assemble the built-in providers and resolve a provider:model id.
let registry = create_provider_registry(default_providers(), Default::default());
let model = registry.language_model("deepseek:deepseek-chat")?;
let names = provider_names();
// model usage is identical — it's all dyn LanguageModel
```

All registry-backed OpenAI-compatible providers share one entry:
`provider(name, ...)` in every binding. Provider names are runtime strings;
the generated provider list is the discovery surface.
The retired per-provider shell types (`XxxConfig`/`XxxProvider`) are gone —
see [docs/API.md](docs/API.md#providers).

> **Scope:** OpenAI-compatible → `provider(name, ...)`; others (Anthropic,
> multimodal, local…) → their constructors. List:
> [docs/api/providers.md](docs/api/providers.md).
Rust by-name creation covers vendor packages and all 282 presets. Each vendor
also has `create_xxx(XxxProviderSettings {..})` and a default instance `xxx()`.
Bindings keep their own `provider(name, ...)` API. Runtime model listing uses
`Provider::discovery()` and then `ProviderDiscovery::list_models()` — see
[docs/api/rust.md](docs/api/rust.md#providers).

## Provider coverage

Counts by category live in
[docs/api/providers.md](docs/api/providers.md#totals) — generated from the
registry and `lib.rs`, and the single source of truth. The rough shape of
The generated catalogue is [docs/api/providers.md](docs/api/providers.md).
The accepted Rust names come from `provider_names()`. The rough shape of
the roster:

- **Native protocol** — OpenAI, Anthropic, Google, Bedrock, Vertex, Azure, Cohere, Mistral, xAI, Anthropic-AWS, Voyage, Codex, OpenRouter
- **OpenAI-compatible (registry-backed)** — Groq, Fireworks, Together, Perplexity, Ollama Cloud, DeepSeek, Alibaba Tongyi, Zhipu, Baidu, Tencent, Moonshot, SiliconFlow…
- **OpenAI-compatible (standalone + Vertex-hosted)** — Hugging Face, Ollama, vLLM, SGLang, Llama.cpp, LiteLLM Proxy, Vertex-hosted DeepSeek/Qwen/Llama…
- **Native protocol** — OpenAI, Anthropic, Google, Bedrock, Vertex, Azure, Cohere, Mistral, Groq, DeepSeek, xAI, Anthropic-AWS, Voyage
- **OpenAI-compatible (registry-backed)** — Fireworks, Together, Perplexity, OpenRouter, Ollama Cloud, Alibaba Tongyi, Zhipu, Baidu, Tencent, Moonshot, SiliconFlow…
- **Local and Vertex-hosted presets** — Ollama, vLLM, SGLang, Llama.cpp, LiteLLM Proxy, Vertex-hosted DeepSeek/Qwen/Llama…
- **Responses API for text** — xAI and Hugging Face (no chat-completions entry)
- **Speech / transcription** — ElevenLabs, Deepgram, AssemblyAI, AWS Polly, Cartesia, Hume, Gladia, RevAI, LMNT, Fal
- **Image / video** — Black Forest Labs, Replicate, Luma, Prodia, KlingAI, Recraft, Stability, RunwayML
- **Embeddings / rerank / search** — Voyage, Jina, Tavily, Exa, Firecrawl, Serper, SearXNG, You.com…
Expand Down
12 changes: 6 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ aimux 是 **provider 接入与治理的运行时**:
│ ├─→ #174 Auth L1 ──→ #175 Auth L2 ← 依赖 B1
│ └─→ #167 transport-level replay ──→ #179 replay 子命令 ← 依赖 B1
├─ C 轨 FFI(现 123 个 extern "C",#166 基线 109)→ ops 协议(C1 升级为传输无关协议:op 表 / 二进制帧 / 版本协商)
│ └─ C2 构造器转发 shim 是 B4/B5 前置
│ └─ C2 构造器转发 shim 取消:B4/B5 的直接构造调用点随 provider 工厂切换一次迁移(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系))
├─ D 轨 8 种绑定重写为 ops 薄封装(依赖 C1)+ D8 类型镜像生成
├─ E 轨 内部清理(#164 已合入,改为 master 上独立 PR)+ 文档三层重组
│
Expand Down Expand Up @@ -75,12 +75,12 @@ aimux 是 **provider 接入与治理的运行时**:
| 项 | 内容 |
|---|---|
| B2–B8 | 17 个 LanguageModel 实现 → ~7 个协议;33 个 wrapper 退役;responses 家族合并(遵循 #166 修正 3/6) |
| #174 / #175 | registry `auth` schema + `apply_auth()`;Credential 解析序 + CredentialStore + TokenRefresher |
| #174 / #175 | registry `auth` 列作为 preset descriptor 数据,鉴权在各厂商包内以 headers 闭包 / fetch 装饰器实现;CredentialStore + TokenRefresher 随宿主回调后置(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系)) |
| L2 补齐 | `StreamPart::Raw` / `provider_metadata` 在各协议接线——投影不下的不得静默丢弃 |
| **S3** | `cargo-bloat` 审计 0.5.0 增重(Android `.so` 13.4 → 21 MB);feature gating 仅作可选小体积路径,默认全量 |
| ~~调研 RFC~~ | ~~L2 数据模型选型(AI SDK 形态 / Open Responses items / 自有),指标见 RFC-0036 §3~~ 撤销:选型已定为 AI SDK V4 形态(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系)) |

版本语义:Rust API 大 breaking(33 wrapper 退役);C ABI 经 C2 转发不受影响。
版本语义:Rust API、binding wire 与 C ABI 在全链路对齐切换时一次性 breaking(33 wrapper 退役、构造器替换),不经 C2 转发(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系))。

### 0.8.0 ——「ops 协议落地」(~4-5 周)

Expand All @@ -92,13 +92,13 @@ aimux 是 **provider 接入与治理的运行时**:
| D8 | 类型镜像生成:serde → JSON Schema → 各语言,`--check` 门禁扩到全部输出 |
| P | stdio 入口往返开销纳入性能门禁 |

版本语义:新 ABI 加入,旧导出并存(#166 要求共存至少一个 minor 版本);绑定按各自节奏迁移。“共存至少一个 minor”不再作为承诺:全链路对齐切换本身没有共存期,之后 ops ABI 引入时的旧符号也按切换门一次替换;C2 转发 shim 与 C4 旧导出清理随之取消(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系))。
版本语义:新 ABI 按切换门一次替换旧符号,不提供共存期(#166 原要求的“共存至少一个 minor”撤销);全链路对齐切换本身同样没有共存期,C2 转发 shim 与 C4 旧导出清理随之取消(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系))。

### 0.9.0 ——「治理」(~3-4 周)

| 项 | 内容 |
|---|---|
| #167 | transport-level replay:mock 挂 HTTP 层跑真协议代码,覆盖全协议 / 全模态;`ProviderRecord` = registry 行 + protocol |
| #167 | transport-level replay:mock 挂 HTTP 层跑真协议代码,覆盖全协议 / 全模态;录制只存身份,不保存可重建的 `ProviderRecord`(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系)) |
| 漂移检测 | #170 扩展:定期重录,与 cassette 字节级 diff |
| 能力矩阵 | provider × 能力,每格由探测或录制支撑;后置到全链路对齐迁移之后(见 §6.1) |
| CLI | `aimux probe / replay / diff`(#179 replay 子命令并入);#181 debug CLI 并入 |
Expand All @@ -107,7 +107,7 @@ aimux 是 **provider 接入与治理的运行时**:

| 项 | 内容 |
|---|---|
| C4 | 8 种绑定全部迁移后删除旧导出、旧头文件、旧 FFI 测试 |
| ~~C4~~ | ~~8 种绑定全部迁移后删除旧导出、旧头文件、旧 FFI 测试~~ 取消:旧导出在切换时随绑定一起删除,1.0 不再补删(调整:见 [docs/aisdk-architecture-alignment.md §0.7](docs/aisdk-architecture-alignment.md#07-与-roadmap--rfc-0036-既有承诺的关系)) |
| 冻结范围 | ops 协议与 L0 / L1 契约。**L2 独立版本化,不随 1.0 冻结** |
| 发布判据 | #166 ledger 全勾(B9 / #171 后半除外);错误模型 #95 与请求管线 #164 稳定一个周期;各门禁(S2 / P)连续绿 |

Expand Down
1 change: 1 addition & 0 deletions aimux-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ httpdate = { workspace = true }
rand = { workspace = true }
base64 = "0.22"
jsonschema = { workspace = true }
regex = "1"

[dev-dependencies]
tokio = { workspace = true, features = ["macros", "rt", "test-util"] }
Expand Down
15 changes: 8 additions & 7 deletions aimux-core/src/composite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
//! - [`ChildModel`] — the child-handle shape (`Arc<dyn LanguageModel>`).
//! - `step_context` — the recording context of one child step.
//! - `child_max_retries` — the operation's retry count for a child call.
//! - [`add_usage`] — per-field `Usage` accumulation.
//! - [`extract_text`] — pull text out of a `GenerateContent` list.
//! - [`build_aggregator_prompt`] — assemble the MoA aggregator prompt.
//! - `add_usage` — per-field `Usage` accumulation.
//! - `extract_text` — pull text out of a `GenerateContent` list.
//! - `build_aggregator_prompt` — assemble the MoA aggregator prompt.
//!
//! See [`crate::trace::layer::TraceLayer`] for the established decorator pattern
//! (`inner: Arc<dyn LanguageModel>` implementing `LanguageModel`); composite
Expand Down Expand Up @@ -43,7 +43,8 @@ pub(crate) fn step_context(step: impl Into<String>) -> Option<RecordingContext>

/// The retry count of a child call: the `max_retries` of the operation the
/// composite runs in ([`OperationSettings::current`]). `None` outside an
/// operation, or when the operation sets none, leaves the child's default.
/// operation, or when the operation sets none, retries twice, the AI SDK
/// default.
pub(crate) fn child_max_retries() -> Option<u32> {
OperationSettings::current().and_then(|settings| settings.max_retries)
}
Expand All @@ -54,7 +55,7 @@ pub(crate) fn child_max_retries() -> Option<u32> {
/// Each usage detail field is `Option<u32>`; `None` is treated as zero so a
/// child that doesn't report a breakdown doesn't erase the other child's data.
#[must_use]
pub fn add_usage(a: Usage, b: &Usage) -> Usage {
pub(crate) fn add_usage(a: Usage, b: &Usage) -> Usage {
Usage {
input_tokens: InputTokenUsage {
total: opt_add(a.input_tokens.total, b.input_tokens.total),
Expand Down Expand Up @@ -84,7 +85,7 @@ fn opt_add(a: Option<u32>, b: Option<u32>) -> Option<u32> {
/// are kept; `Reasoning` / `ToolCall` / `Source` / `File` are dropped (MoA
/// thin version — references contribute analysis text, not tool calls).
#[must_use]
pub fn extract_text(content: &[GenerateContent]) -> String {
pub(crate) fn extract_text(content: &[GenerateContent]) -> String {
let mut out = String::new();
for c in content {
if let GenerateContent::Text { text, .. } = c {
Expand All @@ -103,7 +104,7 @@ pub fn extract_text(content: &[GenerateContent]) -> String {
/// The reference list may be empty — in that case the aggregator just runs the
/// original prompt (degenerates to a single-model call).
#[must_use]
pub fn build_aggregator_prompt(
pub(crate) fn build_aggregator_prompt(
prompt: &LanguageModelPrompt,
instructions: Option<&str>,
references: &[(String, String)],
Expand Down
Loading
Loading