Let a string definition say what it contains with contentMediaType
Problem/Motivation
A string definition cannot say whether it holds plain text, HTML, or Markdown. These two advertise the same schema:
'title' => new OutputDefinition(
data_type: 'string',
label: new TranslatableMarkup('Title'),
description: new TranslatableMarkup('The image title.'),
),
'caption' => new OutputDefinition(
data_type: 'string',
label: new TranslatableMarkup('Caption'),
description: new TranslatableMarkup('The image caption, as HTML.'),
),
// Both: {"type": "string", ...}The only signal is prose in the description. A front end rendering the output
cannot tell which string to escape, and a model cannot tell which one is safe
to quote verbatim. JSON Schema has a keyword for this, contentMediaType.
Canvas already reads it from component prop schemas, for text/html strings
and image/* URLs.
Proposed resolution
Add a MediaType constraint and have ContextDefinitionNormalizer emit its
type option as contentMediaType:
'caption' => new OutputDefinition(
data_type: 'string',
label: new TranslatableMarkup('Caption'),
description: new TranslatableMarkup('The image caption.'),
constraints: ['MediaType' => ['type' => 'text/html']],
),
// {"type": "string", "contentMediaType": "text/html", ...}MediaType is an annotation. Its validator accepts every value, the same way
JSON Schema treats contentMediaType as descriptive. It is a constraint
because the constraints array is the one place a definition carries facts
beyond its type, and the normalizer already reads Email and Uuid from
there to emit format.
This came out of #3518120 (closed), where media_type: on the attribute-defined tool
attributes is built on it. It is useful to any #[Tool] plugin on its own.
Remaining tasks
- Review the MR
API changes
New MediaType validation constraint. No changes to existing definitions or
schemas.
AI disclosure: drafted with Claude Code.