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:
2026-07-21 06:12:53 -04:00
parent 23e94939c0
commit b86722f508
7 changed files with 579 additions and 27 deletions
+10 -3
View File
@@ -6894,7 +6894,7 @@ pub(crate) mod tests {
#[test]
fn pending_menu_items_lists_interactive_methods_plus_quit() {
let items = pending_menu_items(&fresh_user_auth_methods(), None);
assert_eq!(items.len(), 5, "4 login rows + Quit, got {items:?}");
assert_eq!(items.len(), 6, "5 login rows + Quit, got {items:?}");
assert!(
matches!(&items[0], PendingMenuItem::Login { label } if label == "Kimi Code (OAuth)"),
"row 0 must be the OAuth login, got {:?}",
@@ -6922,7 +6922,14 @@ pub(crate) mod tests {
},
"new registry rows must appear in the picker with zero TUI changes"
);
assert_eq!(items[4], PendingMenuItem::Quit);
assert_eq!(
items[4],
PendingMenuItem::ApiKey {
target: PlatformLogin(kigi_shell::models::PlatformId::Anthropic),
label: "Anthropic (API key)".into(),
}
);
assert_eq!(items[5], PendingMenuItem::Quit);
// The non-interactive methods must never appear as rows.
let byok = kigi_shell::agent::auth_method::build_auth_methods(
kigi_shell::agent::auth_method::AuthMethodsBuildInputs {
@@ -6933,7 +6940,7 @@ pub(crate) mod tests {
);
assert_eq!(
pending_menu_items(&byok.methods, None).len(),
5,
6,
"xai.api_key / cached_token must not add rows"
);
}