SDK Alignment and Compatibility
SDK Alignment and Compatibility
Section titled “SDK Alignment and Compatibility”SDK alignment
Section titled “SDK alignment”The Anthropic Messages wire model is compared against the vendored official TypeScript SDK under contrib/anthropic-sdk-typescript using:
just compare-anthropic-protocolThe comparison checks type coverage, field coverage and order, serde discriminator handling, enum literals, untagged unions, structured SDK markers, and selected serde field semantics.
Required-nullable fields
Section titled “Required-nullable fields”TypeScript distinguishes these two shapes:
field?: T // optional: the field may be absentfield: T | null // required nullable: the field should be present, but may be nullRust Option<T> accepts both missing and null during deserialization, so it is stricter than neither shape. It is exact enough for SDK-optional fields, but it is intentionally wider than SDK required-nullable fields.
When an SDK required-nullable field is represented as Option<T>, mark the Rust field directly:
pub struct Usage { pub output_tokens: u32, /// @sdk(required_nullable_accepts_missing) pub server_tool_use: Option<ServerToolUsage>,}This marker means:
- SDK shape:
field: T | null - Rust shape:
Option<T> - Intentional difference: ProxAI also accepts a missing field as compatibility tolerance
Do not use this marker when the SDK field is optional (field?: T or field?: T | null). Missing is already part of the official shape there.
Do not use this marker to justify Option<T> for SDK required non-null fields (field: T). Those should remain non-optional in Rust unless there is a separate, explicitly documented protocol decision.
The compare script prints marked fields compactly in the Required-nullable fields accepting missing section. Unmarked required-nullable Option<T> fields fail the comparison.
Compatibility normalization
Section titled “Compatibility normalization”Provider compatibility normalization should repair only conservative or measured upstream deviations into the nearest official protocol shape. Current conservative repairs are SDK required-nullable response fields missing from JSON objects (missing -> null) and bare message_start events normalized into the official nested message shape. Current measured provider repairs:
- MiniMax-compatible streams may omit
signatureon a thinkingcontent_block_start, so ProxAI inserts an empty signature for that narrow case. - GLM 5.1 Anthropic-compatible streams may emit
server_tool_usewith only one counter, so ProxAI fills the absentweb_fetch_requestsorweb_search_requestscounter with0.
Do not add other provider-specific business defaults, such as missing tool callers, unless a measured upstream case and a focused fixture document the behavior.
Keep these repairs local to provider compatibility handling. They should not redefine the official wire model.