Add Anthropic platform: wire-served metadata via listing dialect (provider 2)
The 5th registry row: id "anthropic", ANTHROPIC_API_KEY > auth.json "anthropic" scope, api.anthropic.com/v1 with KIGI_ANTHROPIC_BASE_URL override, Messages dialect. Two new spec dimensions most future rows reuse: ListingDialect (Anthropic's /v1/models wants x-api-key + anthropic-version headers, ?limit=1000, and its own response shape) and PlatformKeyHeader (Bearer vs x-api-key across listing/validation/ inference, with auth_scheme stamped onto entries). The 2026 Anthropic listing serves real metadata: the adapter maps max_input_tokens, per-level effort capabilities (low..max as the menu, xhigh/max distinct), thinking/image flags — and enrichment fills only genuine wire gaps (e2e pins wire-1M beating enrichment, and a zero context filled to 200k). Two review-confirmed defects fixed red-green: - Output caps were dropped at three layers, so every sub-128K-output model (64k Haiku, legacy models) would 400 on EVERY request against the sampler's 128K max_tokens default. Wire max_tokens and enrichment limit.output now flow to entry.max_completion_tokens. - An explicit wire effort-decline was indistinguishable from wire silence, letting enrichment inject effort menus pre-4.6 models reject (adaptive thinking 400). The adapter now emits a decline sentinel (support:false) that enrichment respects — proven end to end. Also: the Messages client now sends anthropic-version (previously never sent — real api.anthropic.com rejects such requests; pinned across all three scheme/backend quadrants), key validation builds per-key-header requests, missing listing data fails fast, empty-id ghosts drop with a warning, kimi-import recognizes api.anthropic.com as built-in automatically.
This commit is contained in:
@@ -371,6 +371,14 @@ impl SamplingClient {
|
||||
)
|
||||
})?;
|
||||
headers.insert(HeaderName::from_static("x-api-key"), header_value);
|
||||
if config.api_backend == kigi_sampling_types::ApiBackend::Messages {
|
||||
// The real Anthropic Messages wire rejects requests
|
||||
// without this; compatible endpoints ignore it.
|
||||
headers.insert(
|
||||
HeaderName::from_static("anthropic-version"),
|
||||
HeaderValue::from_static(kigi_sampling_types::ANTHROPIC_VERSION),
|
||||
);
|
||||
}
|
||||
}
|
||||
AuthScheme::Bearer => {
|
||||
let bearer = format!("Bearer {}", api_key);
|
||||
@@ -1890,6 +1898,41 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// The real Anthropic Messages wire rejects requests without
|
||||
/// `anthropic-version`; the XApiKey+Messages client must carry it in its
|
||||
/// default headers, and Bearer/ChatCompletions clients must NOT.
|
||||
#[test]
|
||||
fn x_api_key_messages_client_sends_anthropic_version() {
|
||||
let mut config = minimal_config();
|
||||
config.auth_scheme = AuthScheme::XApiKey;
|
||||
config.api_backend = ApiBackend::Messages;
|
||||
let client = SamplingClient::new(config).expect("client builds");
|
||||
assert_eq!(
|
||||
client
|
||||
.default_headers
|
||||
.get("anthropic-version")
|
||||
.and_then(|v| v.to_str().ok()),
|
||||
Some(kigi_sampling_types::ANTHROPIC_VERSION)
|
||||
);
|
||||
assert!(client.default_headers.get("x-api-key").is_some());
|
||||
|
||||
let bearer = SamplingClient::new(minimal_config()).expect("client builds");
|
||||
assert!(
|
||||
bearer.default_headers.get("anthropic-version").is_none(),
|
||||
"non-anthropic clients must not grow the header"
|
||||
);
|
||||
let mut x_api_chat = minimal_config();
|
||||
x_api_chat.auth_scheme = AuthScheme::XApiKey;
|
||||
let x_api_chat = SamplingClient::new(x_api_chat).expect("client builds");
|
||||
assert!(
|
||||
x_api_chat
|
||||
.default_headers
|
||||
.get("anthropic-version")
|
||||
.is_none(),
|
||||
"XApiKey without the Messages backend must not grow the header"
|
||||
);
|
||||
}
|
||||
|
||||
/// Verify the serialized shape of StreamingChatRequest matches the
|
||||
/// expected wire format: all ChatCompletionRequest fields flattened at
|
||||
/// top level, plus `stream: true` and `stream_options.include_usage: true`.
|
||||
|
||||
Reference in New Issue
Block a user