- _build_cached_system_message() marks the static block with
cache_control: ephemeral when the resolved provider supports it
- providers._CONTENT_CACHING_PROVIDERS set declares which providers
support content-block caching (anthropic by default)
- register_content_caching_provider() lets consuming apps opt-in new
providers without touching service.py
- resolve_provider() reads AIModel.provider from DB so the correct
provider is always used
- Mirrors the silverstripe-ai / DataObjectAgent pattern exactly
- BuildCachedSystemMessageTest: 7 unit tests verify structure directly
without LLM calls — would have caught this regression immediately