Repository navigation
refactor(core)!: type provider options and provider metadata as namespace to JSON object - #217
Draft
cunninghamcard-bit wants to merge 9 commits into
Draft
cunninghamcard-bit wants to merge 9 commits into
cunninghamcard-bit wants to merge 9 commits into
Conversation
…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 <[email protected]>
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 <[email protected]>
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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…ntract fixtures Why: carry up the stack the source union, the removal of the separate thought-signature field, the deletion of the self-generated contract fixtures and the changes below this branch. This branch's code is converted to them. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…tions as upstream schemas do; restore ported tests What: Bedrock reads the amazonBedrock namespace first and falls back to bedrock. Vendor option parsing follows each upstream schema: nullish fields accept null, optional ones do not, wrong types are errors, unknown keys are dropped before the request body (OpenAI, Groq, DeepSeek, Anthropic, xAI, and partly Cohere, Google, Mistral). Restores the ported tracker metadata cases, Google files option cases and the Bedrock message-conversion tests deleted earlier. Why: review found options passed through unvalidated where upstream rejects or strips them, and ported tests deleted instead of adapted. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
Why: carry up the stack the fixes made after the third independent review on the branches below; this branch's code is converted to them. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
…stral; stop unknown keys leaking What: the Cohere, Google and Mistral option readers return errors for null where upstream's schema rejects it (thinking, structuredOutputs, safePrompt) and Cohere accepts a numeric token budget; the converters return Result and the model, Vertex and Azure paths propagate it. OpenAI Responses nested fields and the Google and Vertex image options no longer pass unknown keys into the request body. Why: completes the option-validation alignment started in the previous commit; upstream strips unknown keys and fails on these nulls. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS
This branch has not been deployed
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
This pull request replaces arbitrary JSON provider options and metadata with namespace maps whose values are JSON objects, matching
SharedV4ProviderOptionsandSharedV4ProviderMetadata. It also corrects the reviewed vendor option readers so invalid known fields produce errors and unknown schema fields are discarded rather than leaking into requests. It is based onrfc-0036/output-content-typesand precedesrfc-0036/provider-prompt-typesin the protocol and provider-factory stack.Before and after
Option<Value>on parts and messages; maps of arbitrary JSON values elsewhereSharedProviderOptions = HashMap<String, JsonObject>, followingprovider/src/shared/v4/shared-v4-provider-options.tsValueand direct JSON result fieldsSharedProviderMetadata = HashMap<String, JsonObject>;types::ProviderMetadataaliases it, followingSharedV4ProviderMetadataandai/src/types/provider-metadata.tsprovider_namespacebuilds a namespace map and rejects a non-object input; valid JSON object payloads retain their representationtokenBudgetvalues are preserved, followingcohereLanguageModelChatOptionsbedrockwas readamazonBedrocktakes precedence, withbedrockas fallback, followingamazon-bedrock-chat-language-model.tsThe namespace value must now be an object: scalars, arrays and null cannot deserialize as namespace values. This is distinct from a declared field inside that object being explicitly null, which is accepted or rejected according to its upstream schema.
Upstream
JSONObjectalso permits an inner property value ofundefinedin TypeScript. Rust keeps JSONValue, and generated Node types do not express that additional value: the type generator cannot represent it and JSON has noundefinedvalue. The upstream object type itself does not add runtime validation; the vendor schemas do.Tests
Hand-written conversion and option tests are deleted rather than used to define behavior that conflicts with upstream. Retained upstream ports are migrated to typed namespace maps. The streaming tool-call tracker metadata cases, Google files valid and unknown option cases, and Bedrock message-conversion tests removed during the initial migration are restored and adapted to the new types. Cassette replay coverage is kept;
aimux-providers/tests/cassettesandfixtures/have no changes in this branch diff.Not in this pull request
Optionvalues serialized as null, and generated Node fields that are required and nullable. Changing the namespace value type does not settle the binding wire format.ModelMessagetool-result shape remains a maintainer decision; this pull request changes its provider option and metadata types, not that result representation.SharedV4ProviderOptions.Not verified
No cargo commands or runtime tests were run for this documentation rewrite. Node
npm testand Pythonpytestwere not run. Restored mock HTTP tests require local port binding and are not runnable here. The schema comparison is a source review, not a runtime gate result.Verification
Gate on the final commit
3ccf7dd1:cargo fmt --check,cargo clippy --workspace --all-targets -D warnings,cargo doc, tests of core, provider-utils, providers, ffi, web, replay and cli: 2,627 passed, 0 failed; Node and Python bindingscargo check; provider boundary script;gen_ts_types.py --check,gen_providers_doc.py --check. Cassettes andfixtures/aisdkunchanged relative to the base. 150 files, +1571 / −7714.🤖 Generated with Claude Code
https://claude.ai/code/session_01WGwanvo9WLU9HWD7sRR8TS