Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
287 commits
Select commit Hold shift + click to select a range
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
1d8398b
Merge [5/8] into [6/8]: specification_version and the pinned AI SDK s…
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
e8d6544
fix(openai): map the legacy function_call finish reason to tool-calls
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
e0c3430
fix(openai): native chat cacheRead reads only the nested cached_tokens
claude Oct 13, 2026
c910ccc
fix(providers): user-agent versions come from the pinned AI SDK packages
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
7e88215
fix(providers): AWS user-agents and SigV4 signing follow the AI SDK s…
claude Oct 13, 2026
272cbf8
fix(azure): no bearer token on a cross-origin redirect hop
claude Oct 13, 2026
8201981
refactor(provider-utils)!: give each transport its own proxy, drop in…
claude Oct 13, 2026
909b4a7
test(vertex): an executable credential needs the opt-in and spawns no…
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
dba352b
feat(openai-compatible): supportsMultiPartToolContent setting
claude Oct 13, 2026
76d66b6
test(openai): restore the realtime transcription WebSocket tests
claude Oct 13, 2026
82b48f4
test(openai): pin the chat stream tool-call type validation to if-pre…
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
97e131d
fix(openai): stream error statuses follow the upstream packages
claude Oct 13, 2026
6a52e8b
fix(anthropic): map in-stream error types as upstream does
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
279a195
fix(core): read OpenAI-output logprobs under the calling provider's key
claude Oct 13, 2026
a6f73db
test(presets): restore the registry base URL regression guard
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
4d9d3a1
fix(anthropic-aws): region, workspace id and default auth follow upst…
claude Oct 13, 2026
b1daee7
docs(alignment): legacy namespace keys are read and written back as u…
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
764b5b4
feat(vertex): MaaS and xAI sub-providers
claude Oct 13, 2026
97037c9
fix(core): stream_text drops empty text deltas without provider metadata
claude Oct 13, 2026
1e8e85f
fix(vertex): the Anthropic sub-provider sends no google-vertex user-a…
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
cdc01fa
feat(openai,azure): provider tools on the provider instance
claude Oct 13, 2026
3630471
test(openai): pin raw chunks on the Responses stream
claude Oct 13, 2026
a437aee
docs(api): list the Vertex MaaS and xAI factories
claude Oct 13, 2026
f5ce5a2
fix(core): redact the Prodia and Azure subscription key headers
claude Oct 13, 2026
406f8aa
chore(types): regenerate the ApiCallError status_code doc
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
7384b47
fix(providers): each package names its own provider-utils in the user…
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
f7c9177
fix(openai-compatible): chat stream errors carry no inferred status
claude Oct 13, 2026
75865e3
test(core): restore RFC-0031's stream timeout and pipeline tests (#23…
claude Oct 13, 2026
e131a55
fix(vertex): partner provider headers win over per-call headers
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
96e96fa
fix(anthropic): stream error data is the frame's data or the error
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
f745459
fix(core): OpenAI output logprobs in the Chat Completions wire shape
claude Oct 13, 2026
90945bb
docs(alignment): register Bedrock Mantle and AWS GET signing as known…
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
3386ec5
fix(open-responses): send the ai-sdk-open-responses user-agent part
claude Oct 13, 2026
96a6a4f
fix(openai): chat logprobs metadata drops bytes as upstream
claude Oct 13, 2026
4c00266
Merge [3/8] into [4/8]: core ContentPart steps, prompt and tool-choic…
claude Oct 13, 2026
ee18247
fix(vertex): a partner provider user-agent header replaces the whole one
claude Oct 13, 2026
8520201
docs: the alignment document follows ai 7.0.127 for results, jobs and…
claude Oct 13, 2026
dcaf474
fix(provider-utils): URL downloads send no user-agent, as downloadBlob
claude Oct 13, 2026
fb416f9
fix(openai): image edits download URL files through the download guard
claude Oct 13, 2026
a87b9ca
fix(google): files upload sends no provider-utils user-agent part
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
d2c82df
Merge [5/8] into [6/8]: providers are AI SDK factories
claude Oct 13, 2026
8b23a16
fix(providers): layer 6 provider code takes layer 5's types
claude Oct 13, 2026
f4c5fe0
fix(providers): the layer 6 transcription models refuse URL audio
claude Oct 13, 2026
c3846ba
test(anthropic): an unparsable stream chunk is an error part
claude Oct 13, 2026
ac0d061
fix(providers): Cohere, Open Responses and xAI Responses declare thei…
claude Oct 13, 2026
317ebcd
test: restore the hand-written unit tests 48a92aaf deleted that still…
claude Oct 13, 2026
d062be3
fix(codex): Codex models declare the OpenAI Responses supported URLs
claude Oct 13, 2026
3f389ba
fix(huggingface): pin @ai-sdk/huggingface 2.0.62 and declare its supp…
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
8bef2c9
Merge [5/8] into [6/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
a382242
Merge [5/8] into [6/8]: recording schema 2, master recordings load
claude Oct 13, 2026
370f077
docs(changelog): legacy vertex and bedrock keys are still read and wr…
claude Oct 13, 2026
4cb1e53
Merge [5/8] into [6/8]: CHANGELOG wording for legacy namespace keys
claude Oct 13, 2026
87e652c
docs: fix two rustdoc links that fail cargo doc -D warnings
claude Oct 13, 2026
58572b3
Merge [5/8] into [6/8]: rustdoc link fixes
claude Oct 13, 2026
03b43b7
ci: speed up test builds, deduplicate caches, and use prebuilt cargo-ndk
cunninghamcard-bit 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
777e358
Merge [5/8] into [6/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
dd13b04
Merge [5/8] into [6/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
636b4ca
Merge [5/8] into [6/8]: master (#205-#212, #248, #263), #262's CI fol…
claude Oct 16, 2026
a693548
test(mistral): model_length is a length finish
claude Oct 15, 2026
bd2d041
test(providers): non-object input of a past tool call
claude Oct 15, 2026
007ad30
fix(anthropic): toolset member calls go back as upstream sends them
claude Oct 16, 2026
ed69b7e
test(preset): the registry checks run on any input
claude Oct 16, 2026
a9a97fd
fix(anthropic): provider tool args are checked as upstream checks them
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
46e974a
Merge [5/8] into [6/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
2eef03b
Merge [5/8] into [6/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
4ba56b0
Merge [5/8] into [6/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
7da96b4
Merge [5/8] into [6/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
bed5ca7
Merge [5/8] into [6/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
f88bd61
Merge [5/8] into [6/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
7be67e6
Merge [5/8] into [6/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
dbf852f
Merge [5/8] into [6/8]: #262, #246 and #247 as eric merged them
claude Oct 17, 2026
6a061b4
Merge master into [6/8]: keep this layer versions
eric8810 Oct 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 112 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,79 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`available_providers`. Node and Python OpenAI constructors use Responses
by default.

- Vendor packages follow their upstream counterparts more closely. Visible
changes: Bedrock percent-encodes the model id in request URLs and writes
provider metadata under both `amazonBedrock` and `bedrock`; OpenAI embeddings
request `encoding_format: "float"` and no longer decode base64 vectors; the
Google provider result no longer carries a model id unless the API returns
one; an Anthropic mid-stream `error` event is forwarded as an error part
without a synthetic finish; each package sends its own `user-agent` suffix;
Mistral has no `transform_request_body` setting; the deprecated
`text_embedding` and `text_embedding_model` provider methods are removed.

- `SigV4Fetch::new` takes a required `SigV4Signing`. `Aws4Fetch` signs like
aws4fetch 1.0.20, the signer of the AI SDK's AWS packages: `user-agent`,
`content-type` and its other `UNSIGNABLE_HEADERS` are sent but not signed,
and no `x-amz-content-sha256` is sent. `AllHeaders` is the previous rule.
Bedrock and Anthropic-AWS sign with `Aws4Fetch`, Polly with `AllHeaders`.
Bedrock, Bedrock Mantle and Anthropic-AWS send the user-agents of
`@ai-sdk/amazon-bedrock` 5.0.100 and `@ai-sdk/anthropic-aws` 2.0.63 (the
package part is appended again by the transport).

- The `ai-sdk-provider-utils/<v>` part of a pinned package's user-agent names
the provider-utils that the package's upstream `package.json` depends on, as
the AI SDK sends it. That is 5.0.51 for Azure, Bedrock, Cohere, DeepSeek,
Groq, Mistral, xAI and Google Vertex, and 5.0.53 for OpenAI,
OpenAI-compatible, Open Responses, Anthropic, Anthropic-AWS and Google. A
per-call `user-agent` keeps the package's part. The Vertex MaaS and xAI
sub-providers send `ai-sdk-openai-compatible/3.0.59`, the version
google-vertex depends on. Hugging Face sends `ai-sdk-provider-utils/5.0.53`
and no package part, as `@ai-sdk/huggingface` 2.0.62 does (now pinned in
`VERSIONS.json`). Other packages send `ai-sdk-provider-utils/5.0.53`.

- `to_chat_completion` reads `choices[].logprobs` from the calling
provider's metadata namespace (Azure's `azure`, DeepSeek's `deepseek`)
and returns it in the Chat Completions wire shape, `{ "content": [...],
"refusal": null }`. It used to return the provider's raw token list. A
Responses result's per-part lists become one list, and a token without
`bytes` gets `"bytes": null`.

- Security: OpenAI image edits download URL files (`files` and `mask`) with
`download_blob`, as `@ai-sdk/openai` does with `downloadBlob`. The download
goes through the download guard, so a private-network, loopback or
link-local URL is refused before any request, and it sends no headers. A
failed download is a status-code error rather than a parsed OpenAI error.

- OpenAI chat `providerMetadata.openai.logprobs` holds the entries as the AI
SDK's chat schema parses them, `{token, logprob, top_logprobs: [{token,
logprob}]}`: `bytes` is dropped, so `to_chat_completion` returns it as
`null`. A `null` `content` sets no `logprobs`.

- Anthropic-AWS follows `@ai-sdk/anthropic-aws` 2.0.63 settings: the region
comes from the setting or `AWS_REGION` with no `us-east-1` default; the
workspace id is required, from the setting or `ANTHROPIC_AWS_WORKSPACE_ID`;
with no `auth`, a request uses `ANTHROPIC_AWS_API_KEY` when it is set and
otherwise SigV4 with `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and
`AWS_SESSION_TOKEN`. All of them are read when a request is made.

- Anthropic gains the computer toolset of `@ai-sdk/anthropic` 4.0.71
(`anthropic.computer_toolset_20260801`). A member call in a response (for
example `left_click`) comes back as one call of the caller's toolset tool,
with the member name as `action` in its input and
`providerMetadata.anthropic.toolsetName`. Sent back as history, the call
keeps its input as it is, `action` included; a call without a string
`action` is still sent, named after the toolset, with a warning; the
toolset name is read from the call's tools or from
`providerOptions.anthropic.toolsetName` only.

- Anthropic checks the args of the provider-defined tools that
`@ai-sdk/anthropic` 4.0.71 `prepareTools` validates (computer toolset,
advisor, `text_editor_20250728`, the three `web_fetch` and three
`web_search` versions): args that do not match fail the call with
`InvalidArgument` before any request, on Anthropic, Vertex and Bedrock
alike. `anthropic::prepare_tools::{prepare_tools,
prepare_tools_with_provider}` return a `Result`.

- Public surface (`aimux-core`, `aimux-provider-utils`): removed
`recording::init_recording_from_env`; made private the retry preparation
helpers and default constants, `composite::{add_usage,
Expand Down Expand Up @@ -68,8 +141,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
before the call and download each prompt file URL it does not cover (user
`FileUrl` parts and `file` items of tool outputs; not `data:` URLs), which
then reaches the provider as inline data; they used to pass every URL
through. `GenerateTextOptions::download` takes a `DownloadFunction` (the AI
SDK's `experimental_download`) instead. `AudioInput::Url` is new:
through. The Cohere chat, Open Responses and xAI Responses models declare
the URLs their packages declare (HTTP(S) images; for xAI also PDF and
text), so those still reach the API as URLs. Codex models declare the
OpenAI Responses model's URLs (HTTP(S) images and PDFs) on both channels,
and the Hugging Face Responses model declares HTTP(S) images, as
`@ai-sdk/huggingface` does.
`GenerateTextOptions::download` takes a `DownloadFunction` (the AI SDK's
`experimental_download`) instead. `AudioInput::Url` is new:
`transcribe` downloads it with `TranscriptionCallOptions::download`, and a
transcription model given one returns `AudioInput::url_error()`.
`generate_video` downloads every video returned as a URL with
Expand Down Expand Up @@ -476,6 +555,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
of an empty string; a new call without a function name ends the stream with
`InvalidResponseData` (previously it started a call with an empty name).
`DeltaToolCall.index` is now `Option<usize>`.
- Once compatible servers moved to `openai_compatible`, the OpenAI (and
Azure) chat stream drives the tracker with `@ai-sdk/openai`'s options:
`type` is validated when present, ids missing from the wire come from the
provider's `generate_id`, and `DeltaToolCall.index` is required again, so a
chunk without it fails to parse.

**Rust (provider factory, RFC-0036)**

Expand Down Expand Up @@ -760,6 +844,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Vertex AI MaaS and xAI sub-providers, as `@ai-sdk/google-vertex` 5.0.98's
`/maas` and `/xai` paths: `create_google_vertex_maas` / `google_vertex_maas`
(an OpenAI-compatible provider named `vertex.maas`) and
`create_google_vertex_xai` / `google_vertex_xai` (Grok chat models named
`googleVertex.xai`), over the project/location `endpoints/openapi` URL with
a Google OAuth token. As in the Node wrappers, the provider headers and the
token go over the per-call headers, and a provider `user-agent` header is
sent as the whole user-agent.
- Open Responses requests carry `ai-sdk-open-responses/2.0.58`, the package
part of `@ai-sdk/open-responses` (now pinned in `VERSIONS.json`).
`OpenResponsesProviderSettings::user_agent_suffix` replaces it, as the AI
SDK's `userAgentSuffix` does.
- `aimux_provider_utils::download_blob`, the AI SDK's `downloadBlob`: a GET
of an untrusted URL through the download guard with no headers, so no
`user-agent`. OpenAI-compatible image edits download URL files with it, as
upstream does, and no longer send `ai-sdk-provider-utils/5.0.53` there.
- `HttpRequest::omit_provider_utils_user_agent` (`aimux-provider-utils`):
sends the `user-agent` as given, without the `ai-sdk-provider-utils/<v>`
part, for an exchange the AI SDK makes with a plain `fetch`. A struct
literal of `HttpRequest` must now set it or use `..Default::default()`.
The Google Files upload uses it: the init request sends the provider
headers (`ai-sdk-google/4.0.87`) and the byte upload sends no
`user-agent`, as `@ai-sdk/google`'s `fetch` calls do.
- `OpenAIProvider::tools` and `AzureOpenAIProvider::tools`: the provider tools
on the provider instance, as the AI SDK's `openai.tools` and `azure.tools`
(`openai().tools.web_search(…)`). Azure's holds its upstream subset.
- `aimux_core::wrap_provider`, the AI SDK's `wrapProvider`: wraps every
language model of a provider with language-model middleware and, when
given, every image model with image-model middleware; all other members
Expand Down
20 changes: 13 additions & 7 deletions aimux-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ pub struct ApiCallError {
/// Sanitized request values used to create the API request.
pub request_body_values: serde_json::Value,
/// HTTP status of the response, when it came from one
/// (`APICallError.statusCode`). Always the *observed* status: the HTTP
/// layer fills it for every response-derived error; errors built without
/// an HTTP exchange leave it `None`.
/// (`APICallError.statusCode`). The HTTP layer fills the observed status
/// for every response-derived error. An error frame inside a stream
/// carries the status its provider maps it to, as upstream's provider
/// stream errors do (OpenAI infers one from the frame's `code`/`type`,
/// Anthropic from its error type); errors built without an HTTP exchange
/// leave it `None`.
#[serde(default)]
pub status_code: Option<u16>,
/// Provider's machine-readable code (OpenAI's `code`/`type`,
Expand Down Expand Up @@ -488,10 +491,13 @@ impl AiMuxError {

/// Returns the HTTP status code carried by this error, if any.
///
/// This is the *observed* status only — the field the selected response
/// handler filled when a response actually arrived. An error built without an HTTP exchange (a
/// missing API key, a bare constructor, a transport failure) reports
/// `None`: no status was seen, so none is invented.
/// This is the status the selected response handler filled when a
/// response actually arrived, or, for an error frame inside a stream, the
/// status the provider maps that frame to as upstream does (OpenAI's
/// `createOpenAIProviderStreamError` infers it from `code`/`type`). An
/// error built without an HTTP exchange (a missing API key, a bare
/// constructor, a transport failure) reports `None`: no status was seen,
/// so none is invented.
///
/// `TokenExpired` reports `Some(401)` by definition, not by fabrication:
/// its only producer is the codex subscription channel's observed-401
Expand Down
6 changes: 3 additions & 3 deletions aimux-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ pub mod prelude {
init_session_store, list_sessions, session_calls,
};
pub use crate::shared::{
AspectRatio, FileBytes, FileData, GeneratedFileData, JsonObject, SharedHeaders,
SharedProviderMetadata, SharedProviderOptions, SharedProviderReference, Size,
provider_namespace,
AspectRatio, FileBytes, FileData, GeneratedFileData, JsonObject, ResponseInfo,
SharedHeaders, SharedProviderMetadata, SharedProviderOptions, SharedProviderReference,
Size, StreamResponseInfo, provider_namespace,
};
pub use crate::skills_model::{SkillFile, Skills, UploadSkillCallOptions, UploadSkillResult};
pub use crate::speech_model::{SpeechCallOptions, SpeechModel, SpeechResult, generate_speech};
Expand Down
66 changes: 62 additions & 4 deletions aimux-core/src/openai_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ pub struct ChatCompletionChoice {
pub index: u32,
pub message: ChatCompletionMessage,
pub finish_reason: Option<String>,
/// The Chat Completions logprobs object, `{ "content": [...], "refusal":
/// null }`, each entry `{ token, logprob, bytes, top_logprobs }`, when
/// the calling provider returned logprobs.
#[serde(skip_serializing_if = "Option::is_none")]
pub logprobs: Option<Value>,
}
Expand Down Expand Up @@ -464,11 +467,19 @@ fn build_chat_completion<'a>(
},
};

// logprobs from provider_metadata
// logprobs from the calling provider's metadata namespace. Upstream
// writes them under the provider's own key, not a fixed `openai`: the
// Responses model under `providerOptionsName` (`azure` for Azure,
// @ai-sdk/openai 4.0.83 src/responses/openai-responses-language-model.ts:324,
// :1080), DeepSeek under `deepseek`. One model call carries one
// provider's namespace, so the namespace holding `logprobs` is the
// caller's.
let logprobs = provider_metadata
.and_then(|pm| pm.get("openai"))
.and_then(|o| o.get("logprobs"))
.cloned();
.and_then(|pm| {
pm.values()
.find_map(|namespace| namespace.get("logprobs").filter(|value| !value.is_null()))
})
.and_then(chat_logprobs);

ChatCompletion {
id: id.unwrap_or_else(|| format!("chatcmpl-{}", random_id())),
Expand Down Expand Up @@ -1095,6 +1106,53 @@ pub const DONE_FRAME: &str = "data: [DONE]\n\n";
// Internal helpers
// ─────────────────────────────────────────────────────────────────────────────

/// A provider's `logprobs` metadata in the Chat Completions wire shape:
/// `{ "content": [...], "refusal": null }`.
///
/// The OpenAI chat model stores the token list `choice.logprobs.content`
/// (@ai-sdk/openai 4.0.83 src/chat/openai-chat-language-model.ts:459-461), and
/// the Responses model one token list per text part
/// (src/responses/openai-responses-language-model.ts:1062-1080), which
/// becomes one list in output order. A provider that stores the whole
/// logprobs object (DeepSeek's `{ content, reasoning_content }`,
/// @ai-sdk/deepseek 3.0.56 src/chat/deepseek-chat-language-model.ts:497) is
/// passed on as it is. An entry without `bytes` gets `null`, which the wire
/// format allows for a token with no byte representation.
fn chat_logprobs(logprobs: &Value) -> Option<Value> {
fn token(entry: &Value) -> Value {
let mut entry = entry.clone();
if let Some(object) = entry.as_object_mut() {
object.entry("bytes").or_insert(Value::Null);
let top = object
.entry("top_logprobs")
.or_insert_with(|| Value::Array(Vec::new()));
for alternative in top.as_array_mut().into_iter().flatten() {
if let Some(alternative) = alternative.as_object_mut() {
alternative.entry("bytes").or_insert(Value::Null);
}
}
}
entry
}
match logprobs {
Value::Object(_) => Some(logprobs.clone()),
Value::Array(items) => {
let content: Vec<Value> = if items.iter().all(Value::is_array) {
items
.iter()
.filter_map(Value::as_array)
.flatten()
.map(token)
.collect()
} else {
items.iter().map(token).collect()
};
Some(serde_json::json!({ "content": content, "refusal": null }))
}
_ => None,
}
}

/// Map a finish reason to an OpenAI `finish_reason` string.
fn finish_reason_to_openai(unified: FinishReasonUnified, raw: Option<&str>) -> Option<String> {
match unified {
Expand Down
1 change: 1 addition & 0 deletions aimux-core/src/replay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,7 @@ pub struct ReplayOverrides {
/// - `recording.input.options` 中的 headers/provider_options 已脱敏,
/// 重发会用脱敏后的 `[REDACTED]` 值——需要真实头时用 `overrides` 或
/// 重建 provider 时补充。
/// - 逐消息和逐内容部分的 `provider_options` 原样保留。
///
/// # Errors
///
Expand Down
4 changes: 3 additions & 1 deletion aimux-core/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use std::pin::Pin;
use ts_rs::TS;

use crate::error::AiMuxError;
use crate::shared::{GeneratedFileData, RequestInfo, ResponseInfo, StreamResponseInfo};
pub use crate::shared::GeneratedFileData;
use crate::shared::{RequestInfo, ResponseInfo, StreamResponseInfo};

use crate::stream_part::StreamPart;
use crate::tool::{RawToolCall, ToolResult};
use crate::types::{FinishReason, NamespacedKind, ProviderMetadata, Usage, Warning};
Expand Down
13 changes: 13 additions & 0 deletions aimux-provider-utils/src/aisdk_pins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! The `ai-sdk-provider-utils/<v>` part the request helpers append to every
//! request's user-agent, as the AI SDK's `postToApi` / `getFromApi` do.
//!
//! Upstream, `<v>` is the provider-utils that the calling package depends on,
//! so it differs between packages (5.0.51 for `@ai-sdk/groq@4.0.52`, 5.0.53
//! for `@ai-sdk/openai@4.0.83`, ...). The pinned packages in `aimux-providers`
//! name their own version through their transport (`shared::aisdk_pins` and
//! `shared::package_fetch` there); this value is what a request of any other
//! package carries. It is deliberately not the `@ai-sdk/provider-utils` pin of
//! `fixtures/aisdk/VERSIONS.json`, which is the version this crate's port
//! follows and may move without changing any user-agent.

pub(crate) const PROVIDER_UTILS: &str = "5.0.53";
Loading
Loading