feat: #3631526 Add an AI Media settings page

Part of #3631526.

Depends on no open MR. !4 (closed), !5 (merged) and !7 (merged) are merged. !7 (merged) landed with an earlier version of this settings page, so 1.0.x was merged into this branch (a merge commit, no force-push); the diff against 1.0.x is only the second round below. Commits to review: 557add3 (generators table, formats, name/title/alt, config actions), d65dd2c (AI Context), a1c2bdb (the merge, with docs and E2E updates), a9daf87 (AI Context version message), 0e290fb (editor options).

What is new in this round

Tab Setting (key) Where it takes effect
Generators A draggable table: enabled, order, label, what it makes (generators.<id>.enabled, .weight) AiMediaGeneratorBase::isOffered() / weight(); AiMediaHooks::preprocessMediaLibraryMenu() orders the AI tabs by it
Formats per generator as table rows: enabled, default (radio), order (generators.<id>.formats.<ext>, .default_format). Image png/jpg/webp, SVG svg, video mp4, document pdf/docx/md/txt formats() / defaultFormat(); the generate form offers only formats that are enabled and accepted by the media type field. An "Accepted by" column names the media types and links to the field when one refuses a format
Format check before the call AiMediaGenerateForm::checkFormat() refuses a format the field does not accept before any provider request (the SVG and Markdown refusal after a paid call is gone)
Image quality and JPEG/WebP compression (quality, output_compression) Image::doGenerate() through providerFor(), only when the model has the option
Name, title and alternative text For the media name, image alt and image title (when the field has titles on): from the description, ask AI after generating, the AI Image Alt Text button (alt only, when that module is on), or leave empty; prompt and maximum length each (metadata.<target>.*) AiMediaMetadata::values(). Ask AI is one more request: images go to the chat with image vision provider with the generated image, SVGs and documents to the chat provider with the request and the start of the result. Without a provider it falls back to the description, and the form says so. Credit cost stated on the form
AI Image Alt Text That module already adds its "Generate with AI" button to every image widget, the Media Library review step included. AI Media now keeps it when this option is chosen (and removes it otherwise), leaving the alt empty. Its own controller, JS, settings and provider do the work; nothing is copied or forked
Providers New: chat with image vision (providers.chat_with_image_vision) Used by Ask AI for images
AI Context Shown when ai_context is enabled: on/off, which generators, which of name/alt/title, token limit (ai_context.*); otherwise one line saying it is available when enabled AiMediaContext, through the public ai_context.selection_factory service (optional service, no dependency). Scopes: the "AI Media generation" use case (added with hook_ai_context_scope_values_alter()), "Working with media", the page language, the host entity_type:bundle from the Media Library opener, and the host entity when it is saved. The text goes into the generation prompt and the Ask AI requests. Editors see "Uses site context: N items", never the items
AI Context Version check AI Context before 1.0.0-rc1 has no selection service: with such a release enabled, the tab says "AI Media needs AI Context 1.0.0-rc1 or later" and generation runs without context. No composer conflict, so a site still on beta4 (as Varbase can be) is not blocked from requiring AI Media
Editor options (new tab) Per generator, show or hide: provider and model (editor_options.<id>.models: show, allowed "provider__model" pairs from the AI module's getSimpleProviderModelOptions(), the same source as the Providers tab; none ticked allows all), size (.size: show, allowed, default), quality (editor_options.image.quality.show) and format (.format.show). All hidden by default AiMediaGenerateForm::editorElements() and formatElement() add the shown ones under Options as core selects and radios, the Providers tab choice and the default size preselected. AiMediaGeneratorBase::resolveOptions() checks every submitted model, size, quality and format against these lists before any provider call and fills hidden ones with the site defaults; providerFor() uses the picked model. With everything hidden the image, SVG and video forms are just the description and Generate (documents keep their own Length). The description always names the provider
Shape folded into size The old Shape option and default_shape are replaced by the size option: square, landscape or portrait, matched by sizeFor() to the closest size the chosen model lists (for example 1792x1024 for landscape on OpenAI), so there is one control
Files Lifetimes are now 15 minutes, 1 hour and 6 hours only Core removes temporary files after 6 hours anyway
All Help texts cut to one or two sentences

Config actions for recipes, on ai_media.settings: enableAiMediaGenerator, disableAiMediaGenerator, orderAiMediaGenerators, setAiMediaFormats (formats in order, the first by default, the rest off). Everything else uses core's simpleConfigUpdate, for example metadata.alt.source: ai. Documented in the README and docs/info/settings.md.

No update functions (the module is still being initialized). Comments are one short line where that says why.

Usage of context items is not recorded: ai_context's usage tracker takes a consumer ID of a registered consumer type, and registering an AI Media consumer type is a larger integration. Left as a follow-up.

Testing

aimtheme1: Drupal 11.4.10, AI 1.5.1 with the Echo test provider, AI Image Alt Text 1.0.3, AI Context 1.0.0-rc1 with AI Agents 1.3.5. Firefox headless, wide screens only, in Claro, Gin and Default Admin at 1440 and 1920:

  • Settings form: every tab saves and reloads (23 checks per run, 6 runs). Validation errors render: pass.
  • New behavior (25 checks per run, 6 runs): tabledrag order changes the AI tab order; a generator off hides its tab; formats off and default change the editor's choices; format and quality reach a model that has them (OpenAI gpt-image-1 configuration, no call); a disallowed format is caught before any provider call (no file is created, pre-call message); the Generators tab flags and links a field that refuses a format; Ask AI for name and alt makes the second request and its answer lands (Echo echoes); title from the description on a field with titles; Leave empty; Ask AI falls back without a vision provider and the form says so; the AI Image Alt Text button is kept when chosen, fills the alt through its own controller, and is removed otherwise; AI Context shows "Uses site context: 2 items", both items (one global, one "AI Media generation" use case) reach the generation prompt and the Ask AI alt request, and nothing is added when it is off or the generator is not listed; Files offers 15 min / 1 hour / 6 hours: all pass.
  • Earlier settings (30 checks per theme): all pass.
  • AI Context uninstalled: the tab shows the one-line note, no context line, generation works.
  • Editor options, on aimctx1 with Echo and AI logging, Claro, Gin and Default Admin at 1440 and 1920 (17 checks per run): all hidden gives no Options on the image form and the disclosure still names the provider; the tab saves; the document model select lists the allowed models with the site default preselected; the picked model reaches the request (the AI log records echoai/gpt-awesome); image sizes show only the allowed ones with the default preselected, quality shown, model hidden; a forged model and a forged size in the form are refused before any request: all pass. Direct calls, without the form: a model, size or quality sent while hidden, a model or size outside the allowed list, and an unknown format are all refused; allowed values and no values generate.
  • The earlier checks rerun on aimctx1 after this change (formsave, behavior, behavior2, axe on every tab and form): all pass.
  • AI Context version, on a fresh plain Drupal 11.4.10 site (aimctx1), Claro, Gin and Default Admin at 1440 and 1920: with 1.0.0-beta4 the tab names the version needed, there is no context line and a document generates without context; after updating to 1.0.0-rc1 the tab has its settings, "Uses site context: 2 items" shows and both items reach the prompt; axe 0 violations in each state: all pass.
  • axe-core 4.10.2 (WCAG 2.0/2.1/2.2 A and AA): 0 violations on all seven settings tabs, after save and with errors, on the image, SVG and document forms, the review step with the alt text button, and the form with the context line, in all three themes at both widths.
  • Varbase E2E free lane, Firefox: 35 scenarios passed. CI pipeline 1008554: all jobs green, including functional-testing (Drupal core) (35 scenarios, 646 steps). The fixtures recipe shows the document format so the suite can pick one.
  • phpcs (Drupal, DrupalPractice): 0 errors. phpstan level 0: clean apart from new static(), which the template ignores. eslint: 0 errors. cspell: 0 issues.

NOT TESTED

  • The size actually sent to a real image model: Echo has no size option, so the mapping was checked against OpenAI's model settings without a call, and a real image request was not made.
  • AI Context releases other than 1.0.0-beta4 and 1.0.0-rc1, and the Varbase site itself (beta4 there; the beta4 path was reproduced on a separate site).
  • Real vision or chat answers for Ask AI (Echo only echoes; the request and the landing value are tested).
  • Paid generation with real providers (@ai-credits not run).
  • Dictation in a browser with real Web Speech.
  • Mobile widths (out of scope).

AI-Generated: Yes. Written with Claude Code (Claude Opus 5.5) under the Drupal AI policy; tested and reviewed by the author before submission.

Checkpoints:

  • File an issue
  • Addition/Change/Update/Fix
  • Testing to ensure no regression
  • Automated unit testing coverage
  • Automated functional testing coverage
  • UX/UI designer responsibilities
  • Readability
  • Accessibility
  • Performance
  • Security
  • Developer Documentation
  • User Guide Documentation
  • Reviewed by human
  • Code review by maintainers
  • Full testing and approval
  • Credit contributors
  • Review with the product owner
  • Release notes snippet
  • Release
Edited by Rajab Natshah

Merge request reports

Loading
Loading