Repository navigation
refactor(core)!: align public core types with the AI SDK V4 shapes - #219
Closed
cunninghamcard-bit wants to merge 67 commits into
Closed
cunninghamcard-bit wants to merge 67 commits into
cunninghamcard-bit wants to merge 67 commits into
Conversation
aimux-core defined "tool call" five times and "tool result" four times, with `input` meaning raw text in some and parsed JSON in others, so `raw_tool_input` had to guess which. Mirror the AI SDK: one type per layer. - Provider output: `tool::RawToolCall` (moved from parse_tool_call), input is always the raw argument string. `GenerateContent::ToolCall(RawToolCall)`. - Core output: `tool::ToolCall`, input always parsed. Unchanged. - `tool::ToolResult` is now the union of the old variant fields and is the payload of both `GenerateContent::ToolResult` and `StreamPart::ToolResult`. - `StreamPart<C = RawToolCall>` is generic over the tool-call payload; `TextStreamPart = StreamPart<ToolCall>` is what `stream_text` produces and later stages consume. `map_tool_call` re-emits the parsed call. - ts-rs exports the generic with `concrete(C = ToolCall)`, so the TS shape of the stream part is unchanged; bindings regenerated. - Deleted `raw_tool_input`, `deserialize_tool_call_input` (and its legacy-shape test) and every Value::String round trip of tool input. Wire format is unchanged except that a provider-layer `StreamPart::ToolCall` input is now always a JSON string. aimux-providers, aimux-ffi, bindings and tools are intentionally not updated here. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Rebuilding the raw call from an invalid `ToolCall` whose error did not
record the argument text used `input.to_string()`, which turns the stored
text `{broken` into the JSON string literal "{broken" and makes malformed
arguments look valid on the next parse. `invalid_tool_call` stores
unparsable text as a JSON string by definition, so that string is returned
as is; a structured input is serialized. The AI SDK keeps the original
`toolCall.input` here (parse-tool-call.ts).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…types Follows the core change: a provider emits `RawToolCall` (raw argument text) in `GenerateContent::ToolCall` and `StreamPart::ToolCall`, and `tool::ToolResult` for provider-executed results. Streams after `stream_text` are `TextStreamPart`. - Vendor packages: variants built with the shared structs; the places that wrapped the argument text in `Value::String` pass the text itself. - Tests: provider-layer inputs are compared as strings; tests reading a `stream_text` stream match the parsed `ToolCall`. - FFI, Node, Python: the forwarded stream is typed `TextStreamPart`. Exported symbols and JSON output are unchanged. - Generated TypeScript types regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
With one struct per layer, the remaining places that passed or rebuilt a tool call or result field by field take the struct: - `response_messages::tool_result` takes a `ToolResult` instead of seven parameters; the two callers in generate.rs no longer destructure one to pass the same fields on. - parse_tool_call.rs: the three places that copied every field between `RawToolCall` and `ToolCall` share one private conversion each way. - replay.rs passes the recorded `RawToolCall` through. No behavior or public API change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…shape note - CHANGELOG (Unreleased, Breaking): the new types, where each is used, and the three wire-format changes. - docs/api/gaps.md §9 said a pre-refactor `GenerateResult` with a parsed `input` keeps loading through a compatibility deserializer. That deserializer is removed; the section now says so and describes the provider stream and `TextStreamPart`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
aimux-core defined a source, a generated file and a reasoning segment twice
each: inline in `GenerateContent`/`StreamPart` and again as the lossy
`SourcePart`/`FilePart`/`ReasoningPart` of the text results, which dropped
`provider_metadata` (so the reasoning signature never reached the top level).
`StreamPart::ResponseMetadata` repeated the fields of `types::ResponseMetadata`.
Mirror the AI SDK: one type, reused in content, stream parts and the result
projections.
- `result::Source`, `result::GeneratedFile`, `result::ReasoningOutput` are the
payloads of `GenerateContent::{Source,File,Reasoning}` and
`StreamPart::{Source,File}`, and the elements of `sources`, `files` and
`reasoning` on `GenerateTextResult` and `StreamTextResultAggregated`.
- `StreamPart::ResponseMetadata` wraps `types::ResponseMetadata`.
- Deleted `SourcePart`, `FilePart`, `ReasoningPart`.
- `ResponseMessageBuilder::reasoning` takes the `ReasoningOutput`.
Variant JSON is unchanged; the top-level `sources`/`files`/`reasoning` arrays
now carry the full element (additive `provider_metadata`, and `url`/`title`
serialize as null when absent). aimux-providers, aimux-ffi, bindings and tools
are intentionally not updated here.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…ent types Follow-up to the aimux-core change: providers and their tests build `Source`, `GeneratedFile`, `ReasoningOutput` and `ResponseMetadata` payloads in the newtype variants instead of repeating the field lists. TypeScript types are regenerated (`SourcePart`/`FilePart`/`ReasoningPart` become `Source`, `GeneratedFile`, `ReasoningOutput`; `StreamPart` and `GenerateContent` reference them), the Node API doc names the new types, and the changelog records the change as breaking. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…adata
The AI SDK types both as Record<string, JSONObject> (namespace -> object).
aimux-core carried four looser representations: ProviderMetadata was an
arbitrary serde_json::Value, SharedProvider{Options,Metadata} mapped a
namespace to any Value, and per-part / per-message options were Option<Value>.
Now JsonObject is serde_json::Map, SharedProviderOptions and
SharedProviderMetadata are HashMap<String, JsonObject>, and types::ProviderMetadata
aliases SharedProviderMetadata. Every provider_options field (parts, messages,
call/generate options, tools) is Option<SharedProviderOptions> and every
provider_metadata field (content, stream parts, results, tool types) is
Option<ProviderMetadata>. Valid {"ns": {...}} JSON serializes as before; shapes
whose namespace value is not an object are now rejected on deserialization.
shared::provider_namespace(namespace, object) builds a one-namespace map from a
json! literal, replacing the several hundred json!({"ns": {...}}) sites in the
vendor packages. Core and provider-utils tests are converted; generated
TypeScript bindings are regenerated for aimux-core. aimux-providers, ffi and
the aimux-web target do not compile until they are migrated.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…tions and metadata
Follows the core change: provider options and provider metadata are
`HashMap<String, JsonObject>` (namespace -> JSON object), the AI SDK's
`Record<string, JSONObject>`. Every vendor package now builds its metadata
with `provider_namespace(ns, json!({..}))` or by inserting an object under
its namespace, and reads options with `options.get(ns)`, which yields the
object directly. The emitted JSON is unchanged: same namespaces, same keys.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…nd metadata - Provider tests build options with `provider_namespace` or from a JSON literal and compare metadata by namespace; assertions are unchanged. - FFI, Node and Python: the streaming-transcription session options carry `SharedProviderOptions`, so a non-object namespace value is rejected when the options JSON is parsed instead of reaching the provider. - CHANGELOG: the typed shape and what it rejects. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…vider prompts by hand What: deletes 34 test files under aimux-providers/tests. Each one builds provider prompts from the old message struct and asserts request JSON or parsed output that a hand-written mock server returns. Why: the next commit replaces the provider prompt type. These files pin Rust's own earlier behaviour rather than a recording or an upstream sample, so they are removed instead of being rewritten. The same files are removed on the provider factory branch. Recorded-cassette tests, upstream-sample tests and the remaining suites stay and are converted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: `LanguageModelPrompt` is now `Vec<LanguageModelMessage>`, an enum by role: a system message holds a string; user, assistant and tool messages hold their own part unions (`UserPart`, `AssistantPart`, `ToolPart`). The part structs (`TextPart`, `FilePart`, `ReasoningPart`, `ToolCallPart`, `ToolResultPart`) are each defined once. A provider sees exactly one file part, whose `data` is the existing `FileData` union. `convert_to_language_model_prompt` is the single conversion from user messages: it folds the five user-facing file variants into `FilePart` and rejects a part its role does not allow, or a system message that is not plain text, with `InvalidPrompt`. `LanguageModelPromptMessage` is removed. Why: this is the shape of upstream's `LanguageModelV4Message`. Before, every provider received the user-facing part union for every role, so each converter repeated five file arms and handled role and part combinations that cannot occur. The user-facing `ModelMessage` and `ContentPart` and their JSON are unchanged; the tool result fields and the two signature fields keep their current form and are listed as remaining differences. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…and tests What: the vendor converters (OpenAI chat and Responses, Open Responses, Anthropic, Bedrock, Google, Cohere, Mistral, xAI, Hugging Face), the replay helpers, the web and replay tools and the remaining tests match on `LanguageModelMessage` and the per-role parts. The five file arms in each converter become one arm that matches `FilePart.data`; arms for role and part combinations the types rule out are deleted. TypeScript types are regenerated. Why: follow-up to the core change. Request JSON for a given prompt is unchanged; the recorded-cassette and upstream-sample tests pass without any change to cassettes or fixtures. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
… upstream does What: `GenerateResult` has `request: Option<RequestInfo>` and `response: Option<ResponseInfo>`; `ResponseInfo` holds the response id, timestamp and model id next to headers and body. `StreamResult` has `request` and `response: Option<StreamResponseInfo>` (headers only). The flat `request_body` and `response_headers` fields are removed, and `response` is no longer required. Vendors, tools, FFI and tests build and read the new fields. The call layer fills a missing response id, timestamp and model id where upstream `generateText` and `streamText` do, so a provider no longer has to invent them. Why: this is the shape of upstream's `LanguageModelV4GenerateResult` and `LanguageModelV4StreamResult`. Before, a provider had to return response metadata even when the API gave none, and the response body had no place. Kept on purpose: the user-facing results and their JSON do not change. The `raw` field of `GenerateTextResult` still serializes the flat keys through a small adapter, because six language bindings parse that shape; it goes away with `raw` in the user-result pull request. No cassette or fixture changes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
The changelog is what binding authors read before upgrading; the prompt type change alters the provider trait input and the recorded prompt JSON. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…ds as breaking The provider trait output changes shape, so implementers of a custom provider need the old and new field names side by side. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: Cohere and Mistral decide image versus document by the top-level media type, so a bare "image" is an image again. Inline text file data is rejected where upstream rejects it (OpenAI Responses, Mistral, Cohere images) and Google falls back to text/plain for an incomplete media type. The provider tool-result part no longer accepts "output" as a second name for "result". Why: an independent review found that the move to one file part changed these three behaviours; the alias gave one field two spellings. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Why: carry the media-type, text-data and tool-result alias fixes up the stack so every branch above the prompt types has them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…fields What: provider content and stream parts gain custom, reasoning-file and tool-approval-request. A generated file holds data or a URL only. Input and output token details are separate types with upstream's fields, and raw usage is a JSON object. Request and response information carry body and headers, and a URL file keeps its original URL. Hand-written tests that pinned the old shapes are deleted rather than rewritten. Why: an independent field-by-field comparison with the pinned upstream content, stream-part, usage and result types found these differences. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: provider_namespace returns an error for a non-object value instead of replacing it with an empty object. Callers follow. Hand-written tests that pinned the old behaviour are deleted rather than rewritten. Why: upstream types provider options as namespace to JSON object; silently replacing a caller's value hid mistakes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…uments
What: CallOptions.tool_choice is optional and each vendor omits it when
unset, as its upstream package does. FunctionTool.input_examples is a list
of { input: object } and ProviderTool.args is a JSON object. Hand-written
tests that pinned the old shapes are deleted rather than rewritten.
Why: an independent field-by-field comparison with the pinned upstream tool
types found these three differences. The project keeps cassette replays,
upstream samples and contract fixtures as its tests; those still pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Why: carry the tool type changes up the stack. Conflicts were confined to hand-written test files both branches had trimmed; files that the prompt types branch deletes anyway are removed here, the rest keep this branch's side. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Why: carry the content and tool type changes up the stack. The newly arrived code is converted to this branch's typed provider options and provider metadata. Hand-written tests that no longer compile are deleted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: brings up the tool, content and provider-option type changes and converts this branch's code to them. In the provider prompt, a tool result has a required tool name and a structured output with upstream's six variants instead of a free JSON value plus flags. Reasoning and tool-call signatures travel in provider options under the vendor namespace. The assistant side gains reasoning-file and custom parts and the tool side gains tool-approval-response. Hand-written tests that no longer compile are deleted. Why: a field-by-field comparison with the pinned upstream prompt types found these differences. The user-level message types are unchanged; the contract fixture pins them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: removes stream_error_semantics_test.rs and tool_result_and_reasoning_fix_test.rs. Why: the project keeps cassette replays, upstream samples and contract fixtures as its tests. These two files asserted behaviour written by hand against a mock and had been rewritten rather than deleted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Why: carry the tool, content, provider-option and prompt type changes up the stack. This branch's request and response information is kept and the newly arrived code is converted to it. Hand-written tests that no longer compile are deleted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: removes 86 test functions and in-file test modules that the branch below had deleted and the last merge resolution restored. Why: the project keeps cassette replays, upstream samples and contract fixtures as its tests. The difference from the branch below is now only this branch's own work on request and response information. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
What: the type tags of provider prompt parts and tool result outputs are tool-call, tool-result, reasoning-file, tool-approval-response, execution-denied, error-text, error-json. Why: these types are new in this stack and no fixture pins them, so they take upstream's spelling instead of snake_case. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Why: carry the tag spelling fix up the stack. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
cunninghamcard-bit
changed the base branch from
rfc-0036/provider-prompt-types
to
rfc-0036/integration
October 8, 2026 03:10
This was referenced Oct 8, 2026
Closed
Contributor
Author
|
审批类型与 core 处理需要按最新职责边界收窄(核对 head 本轮确认的范围调整:aimux 不承担审批运行时,也不定义统一的审批公共类型/语义;审批相关的定义、解释和处理由上层负责。这是对 #200 §0.4 原先“保留审批 variant”范围的收窄,不是否认 AI SDK 中存在这些类型。 本 PR 已实际引入:
请移除这套统一审批公共类型、专用错误及 core 关联/重建逻辑,连同相应导出和类型参数一起调整。调整时遵守已有的数据返回契约,不破坏已承诺的 raw/metadata 等通用行为。本评论不要求为审批新增原始输入透传、Raw 事件、回放或审批往返能力,也不将这些新能力作为删除审批专用类型的前置条件。 |
This was referenced Oct 8, 2026
Amp-Thread-ID: https://ampcode.com/threads/T-01a11e83-bf7b-75bb-900b-34851e6f12ee Co-authored-by: Amp <amp@ampcode.com> # Conflicts: # aimux-provider-utils/src/streaming_tool_call_tracker.rs # aimux-provider-utils/tests/streaming_tool_call_tracker_test.rs # bindings/node/src/types/InputRecord.ts
Amp-Thread-ID: https://ampcode.com/threads/T-01a11e83-bf7b-75bb-900b-34851e6f12ee Co-authored-by: Amp <amp@ampcode.com>
What: `apply_tool_call_repair_to_result` rewrote `tool_calls` and the
`response_messages` transcript but left `content` with the unrepaired call.
After repairing `{"city":7}` to `{"city":"Tokyo"}`, `tool_calls` said Tokyo
while `content` still said 7, so one result described two different calls.
The matching `content` entry, and the call an approval request embeds, are
now replaced with the repaired call. A repair that renames the call also
renames the transcript's approval request, so it keeps pointing at the call.
`raw` still holds the provider's output unchanged.
Why: every field of a result has to describe the same tool call; a host
reading `content` acted on the arguments the repair had replaced.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QeURmKQzedTSiu2vL3yVes
This was referenced Oct 11, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Core public types in
aimux-coretake the AI SDK V4 provider andaishapes: tool calls and results, output content, provider options and metadata, the provider prompt, and provider results. Baserfc-0036/integration; first of four (A to D), precedes B. Replaces #215, #216, #217 and #218, and takes over the range previously shown by #219.Layers
rfc-0036/tool-typesrfc-0036/output-content-typesrfc-0036/provider-options-typesrfc-0036/provider-prompt-typesrfc-0036/provider-result-typesBefore and after
RawToolCallwithinput: StringinGenerateContentandStreamPart; compatibility decoder andraw_tool_inputheuristic deletedLanguageModelV4ToolCallToolCallholds parsedValue(original string if parsing fails),invalid,errorTypedToolCallToolResult: requiredtool_name, optionaldynamic,provider_metadataLanguageModelV4ToolResultCallOptions.tool_choiceoptional;generate_text,stream_textsupplyautofor a nonempty tool listprepare-tool-choice.tsFunctionTool.input_examplesis{ input: object };ProviderTool.argsis an objectLanguageModelV4FunctionTool,LanguageModelV4ProviderToolwith_signaturepathSourcePartSourceURL/document unionLanguageModelV4SourceGeneratedFilewithGeneratedFileData(data or URL; URL keepsoriginal_url)LanguageModelV4File,SharedV4FileDataUrlReasoningOutputkeeps metadata; reasoning is text orReasoningFileOutput; new content variants in provider content and streams;InputTokenUsageandOutputTokenUsagereplace one usage type, raw usage is a JSON objectLanguageModelV4ReasoningFile,LanguageModelV4CustomContent,LanguageModelV4ToolApprovalRequest,LanguageModelV4UsageOption<Value>; arbitrary JSON mapsSharedProviderOptions,SharedProviderMetadata=HashMap<String, JsonObject>;provider_namespacerejects non-objectsSharedV4ProviderOptions,SharedV4ProviderMetadatabedrockreadtokenBudgetkept;amazonBedrockfirstcohereLanguageModelChatOptions,amazon-bedrock-chat-language-model.tsContentPartfor all rolesFilePartwith taggedFileDataLanguageModelV4Message,LanguageModelV4FilePartresult, error flagstool_name;outputis text, json, execution-denied, error-text, error-json or content (text, file, custom)LanguageModelV4ToolResultOutput{}; DeepSeek resolves its references, Groq and Compatible reject them; Responses references become file IDs; Google tool content URLs becomefileData; Bedrock emits S3 image locations; Cohere, Mistral, xAI, Vertex reject unsupported inputsconvert-to-*modulesGenerateResultWireflattened request body, response headersGenerateResultserializes directly with optionalrequest: RequestInfo,response: ResponseInfo;StreamResponseInfohas optional headersLanguageModelV4GenerateResult,LanguageModelV4StreamResultrawpathGenerateTextResult.request,response(defaults for missing metadata);rawisGenerateResultwithout them; aggregation keeps request and last step's responsegenerate-text.ts,stream-text.tsTextStreamPartwas the provider unionTextStreamPart; metadata inFinishStep.response; no output givesNoOutputGeneratedstream-text.ts,NoOutputGeneratedErrorstream: trueopenai-responses-language-model.tsTypeScript-only constraints (
JSONSchema7, dotted IDs,NonNullable,URL,Date, numeric types, innerundefinedinJSONObject) are not enforced upstream at runtime; Rust keepsValue,String,u32and adds no checks.Tests
contract-tests/(self-generated JSON, runner) and the 16 tests reading it; they recorded Rust's former output. CI, scripts and docs stop using them.openai_output.rsandmoa.rs.cassette_full_test.rsmatchesTextStreamPart; stream tests expectFinishStepthenFinish; round-trip callers usegenerate_text_result_to_chat_completion. Hand-written end-to-end files remain.bedrock_remaining_test.rs,anthropic_remaining_test.rsreturn in C. Cassettes andfixtures/unchanged.Not in this pull request
ToolChoiceserializesauto,none,requiredas bare strings; upstream uses tagged objects. D does not nameToolChoice.ModelMessagetool-result shape: covered by D. D does not mention theTextStreamParttool-result payload (still the providerToolResult), a tool-error event for invalid calls, or the stream'sResulterror channel.asyncreplay: covered by C.Relation to the maintainer's design
Reference order: the pinned AI SDK source first; where it has no counterpart (C ABI, bindings, recording, code generation), the maintainer's RFCs 0039 (ops and bindings, #209), 0040 (provider construction and auth, #210), 0041 (replay governance, #211) and 0042 (V4 type boundaries, #212), which are Drafts that refine the #200 design doc
docs/aisdk-architecture-alignment.md; that design doc only where those RFCs defer to it. Where an RFC restates upstream behaviour differently from the pinned source, upstream wins and the RFC gets an amendment request. The stack targetsrfc-0036/integration; RFC-0039 §11 and RFC-0040 §7.2 require the whole closure to switch to master at once, so items marked "before master" must land on integration first. "Branch E" is the follow-up branch stacked on D, in progress.aimux-provider, userModelMessageand transport inaimux-provider-utils, factories and protocol code inaimux-providers, operations and registry inaimux, recording and replay inaimux-devtools; the docs: full-chain AI SDK alignment design and impact map #200 design doc §2.1 adds that no compatibility re-exports remain. This stack keeps all code inaimux-core(56 files, about 22,900 lines in its top two directory levels); behaviour is unaffected, and those dependency directions are not yet enforced by the compiler.SharedProviderOptionsandSharedProviderMetadatahave that shape.Verification
Gate on the head
c16749d6:cargo fmt --check,cargo clippy --workspace --all-targets -D warnings,cargo docwith-D warnings, tests of core, provider-utils, providers, ffi, web, replay and cli: 2,364 passed, 0 failed, 8 ignored; Node and Python bindingscargo check;gen_ts_types.py --check;gen_providers_doc.py --check. Cassettes andfixtures/aisdkunchanged;contract-tests/fixtures/tool-call-repair.jsonandwire-format.json(fixtures generated by aimux itself) are deleted. Diff against the base: 330 files changed, 10710 insertions(+), 67662 deletions(-). After the restack onto the currentmaster, only this head was tested; the intermediate layers were checked with fmt and clippy only.Restacked head
5342962b. Restack (2026-10-09): mergedmaster(#213, SSE) and the rewritten #204 tracker down the stack by merge, no history rewrite. This layer re-applies its V4 output change (StreamPart::ToolCall(RawToolCall { input: String, .. }),provider_namespace) to the rewritten tracker and updates theMIGRATION-NS.mdnote on tool-call metadata. Checked:cargo fmt --check,cargo clippy --workspace --all-targets -D warnings, tests of provider-utils and providers (103 test binaries, 0 failed).cargo doc, binding checks and the generator--checkscripts were not rerun.Not verified
No GitHub check runs were attached at the last refresh. Go, Java, Kotlin, Swift and Flutter were not compiled locally in that refresh; Node
npm testand Pythonpytestwere not run. Live vendor calls and unported upstream cases are outside validation.🤖 Generated with Claude Code