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:
@@ -379,8 +379,9 @@ pub fn missing_platform_key_error(platform: kigi_models::PlatformId) -> String {
|
||||
/// missing-key message. A present key is validated with
|
||||
/// `GET {platform_base}/models` (the same endpoint the catalog fetch uses):
|
||||
/// 401 → "invalid API key"; any other non-success status or network error
|
||||
/// surfaces as-is. SECURITY: the key is only ever sent as the bearer header —
|
||||
/// it must never appear in errors or logs.
|
||||
/// surfaces as-is. SECURITY: the key is only ever sent as the platform's
|
||||
/// key header (Bearer or x-api-key) — it must never appear in errors or
|
||||
/// logs.
|
||||
pub(crate) async fn authenticate_platform_api_key(
|
||||
platform: kigi_models::PlatformId,
|
||||
key: Option<&str>,
|
||||
@@ -394,9 +395,16 @@ pub(crate) async fn authenticate_platform_api_key(
|
||||
return Err(auth_err(missing_platform_key_error(platform)));
|
||||
};
|
||||
let url = format!("{}/models", platform.base_url().trim_end_matches('/'));
|
||||
let response = crate::http::shared_client()
|
||||
.get(&url)
|
||||
.header("Authorization", format!("Bearer {key}"))
|
||||
let request = match platform.key_header() {
|
||||
kigi_models::PlatformKeyHeader::Bearer => crate::http::shared_client()
|
||||
.get(&url)
|
||||
.header("Authorization", format!("Bearer {key}")),
|
||||
kigi_models::PlatformKeyHeader::XApiKey => crate::http::shared_client()
|
||||
.get(&url)
|
||||
.header("x-api-key", key)
|
||||
.header("anthropic-version", kigi_sampling_types::ANTHROPIC_VERSION),
|
||||
};
|
||||
let response = request
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| auth_err(format!("Couldn't reach {}: {e}", platform.as_str())))?;
|
||||
@@ -584,7 +592,8 @@ mod tests {
|
||||
KIMI_CODE_METHOD_ID,
|
||||
MOONSHOT_CN_METHOD_ID,
|
||||
MOONSHOT_AI_METHOD_ID,
|
||||
"openai"
|
||||
"openai",
|
||||
"anthropic"
|
||||
]
|
||||
);
|
||||
assert_eq!(default_id(&built), Some(XAI_API_KEY_METHOD_ID));
|
||||
@@ -611,7 +620,8 @@ mod tests {
|
||||
KIMI_CODE_METHOD_ID,
|
||||
MOONSHOT_CN_METHOD_ID,
|
||||
MOONSHOT_AI_METHOD_ID,
|
||||
"openai"
|
||||
"openai",
|
||||
"anthropic"
|
||||
]
|
||||
);
|
||||
assert_eq!(default_id(&built), Some(CACHED_TOKEN_AUTH_METHOD_ID));
|
||||
@@ -631,7 +641,8 @@ mod tests {
|
||||
KIMI_CODE_METHOD_ID,
|
||||
MOONSHOT_CN_METHOD_ID,
|
||||
MOONSHOT_AI_METHOD_ID,
|
||||
"openai"
|
||||
"openai",
|
||||
"anthropic"
|
||||
]
|
||||
);
|
||||
assert_eq!(default_id(&built), Some(CACHED_TOKEN_AUTH_METHOD_ID));
|
||||
@@ -654,7 +665,8 @@ mod tests {
|
||||
KIMI_CODE_METHOD_ID,
|
||||
MOONSHOT_CN_METHOD_ID,
|
||||
MOONSHOT_AI_METHOD_ID,
|
||||
"openai"
|
||||
"openai",
|
||||
"anthropic"
|
||||
]
|
||||
);
|
||||
assert_eq!(default_id(&built), None);
|
||||
|
||||
Reference in New Issue
Block a user