Issue #3590963: Bump SDK constraint and drop method_exists defensive check

Phase 2 of the Anthropic provider native-SDK work (#3590963): prompt caching admin UI + PDF document input. Builds on Phase 1 (#3572402, merged in d1e078a1). Targets 1.3.x; fast-forward mergeable.

What this delivers

Prompt caching

  • Admin UI: "Enable prompt caching" toggle and TTL selector (5m / 1h), #states-gated in the provider settings form.
  • System prompt sent as a typed TextBlockParam with cache_control when caching is on (caching a bare string is a no-op; the breakpoint must sit on a content block).
  • 1h TTL is GA and works without any beta header (verified live).
  • cache_creation_input_tokens surfaced through ChatOutput::getMetadata()['cache_creation_tokens'].

PDF input

  • buildMessageContent() detects application/pdf files on a ChatMessage and emits a typed DocumentBlockParam + Base64PDFSource.
  • getConfiguredModels() gains a ChatWithPdf capability filter (using the AiModelCapability::ChatWithPdf enum case shipped in drupal/ai 1.4).

SDK + infrastructure

  • anthropic-ai/sdk constraint ^0.16^0.29 (running and live-tested on v0.29.1). Cross-version audit of v0.24–v0.29.1 against every typed symbol we touch surfaced exactly one breaking change in our zone (v0.25 added a required outputTokensDetails param to Usage::with() / MessageDeltaUsage::with()); production code is unaffected (only reads usage), and the two mock-usage builders in the unit tests pass NULL for the new param. The floor sits at ^0.29 rather than the strict minimum (^0.25) because that is the version end-to-end verified live (1h TTL, 5m TTL, PDF round-trip), and a lower floor would assert behavior on intermediate releases (v0.25–v0.28) that have not been exercised.
  • drupal/ai bumped to ^1.4.0 to use the native AiModelCapability::ChatWithPdf enum case.
  • Module-local phpunit.xml.dist with scoped <source> coverage.

Verification

  • PHPCS (Drupal + DrupalPractice) on src/ and tests/: clean.
  • PHPStan level 8: clean.
  • PHPUnit: drupalci pipeline on this MR is the authoritative gate (not re-run locally for this iteration).
  • Live end-to-end on a real key (DDEV): cache write/hit on Sonnet 4.5, 1h TTL accepted, PDF round-trip on Sonnet 4.5 / Opus 4.7 / Haiku 4.5. Details in the issue comments.

Not in scope

  • PDF upload UI. Phase 2 ships provider plumbing; an end-user upload path is an upstream ai_api_explorer / ai_chatbot change.
  • Per-block cache breakpoints. Needs an upstream ChatMessage marking mechanism.
  • Compaction, token counting, citations. A later phase.
  • Mid-conversation system blocks (v0.25 SDK feature). Looks like a candidate to replace the hand-built single-block system caching; tracking as a Phase 3 follow-up.

AI-Generated: Yes (Claude Code with Claude Opus 4.7 and 4.8 used for architecture, implementation, and test scaffolding across Phases 1 and 2. Live E2E validation and code review performed against each iteration; final review by maintainer.)

Closes #3590963

Edited by Carlos Ospina

Merge request reports

Loading