Overview
Currently CanvasAiPageBuilderHelper::getAllComponentsKeyedBySource() does this
if ($source === SingleDirectoryComponent::SOURCE_PLUGIN_ID) {
$this->processSdc($component, $sdc_definitions, $output);
}
elseif ($source === JsComponent::SOURCE_PLUGIN_ID) {
$this->processCodeComponents($component, $output, $available_components[$component_id]);
}
else {
// Other sources: id, name, description (description = name)
$output[$source]['components'][$component_id] = [
'id' => $component_id,
'name' => $component->label(),
'description' => $component->label(),
];
}
So for blocks, only the ID, name, and description are passed as context to the agent. However, this causes issues when the agent decides to use a block with required props (e.g., the System Branding block), because AiResponseValidator::validateComponentStructure() will throw errors like:
Component validation errors: components.0.[block.system_branding_block].props.: 'label' is a required key. components.0.[block.system_branding_block].props.: 'label_display' is a required key. components.0.[block.system_branding_block].props.: 'use_site_logo' is a required key. components.0.[block.system_branding_block].props.: 'use_site_name' is a required key. components.0.[block.system_branding_block].props.: 'use_site_slogan' is a required key
Proposed resolution
Expose the props of blocks to the agent.
Currently, _addNewComponentToLayout in layoutModelSlice.ts only sets field values for components that have the propSources property . Block components do not have this property.
const buildInitialData = (component: CanvasComponent): ComponentModel => {
if (isPropSourceComponent(component)) { // Block components return false for this check.
const initialData: EvaluatedComponentModel = {
resolved: {},
source: {},
};
Object.keys(component.propSources).forEach((propName) => {
const prop = component.propSources[propName];
// These will be needed when we support client-side preview updates.
initialData.resolved[propName] = prop.default_values?.resolved || [];
// These are the values the server needs.
// @todo Reduce the verbosity of this in https://drupal.org/i/3463996
// and https://drupal.org/i/3528043 to send less data.
initialData.source[propName] = {
expression: prop.expression,
sourceType: prop.sourceType,
value: prop.default_values?.source || [],
sourceTypeSettings: prop.sourceTypeSettings || undefined,
};
});
return initialData;
}
return {
resolved: {},
};This means it is not possible to place a block component with specific configuration values. For example, when the AI agent tries to place a Site Branding block with values like:
{
"use_site_logo": true,
"use_site_name": true
}these values are ignored because block components lack propSources. As a result, block components are always placed with their default configuration, regardless of what values the AI specifies.
User interface changes
Issue fork canvas-3569120
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
akhil babuComment #4
akhil babuComment #5
akhil babuWe need tests to ensure that prop values are properly fetched and the CanvasAiComponentDescriptionSettingsForm displays fields to override the description of these props. These can be added once #3558241: Canvas AI: CanvasAiComponentDescriptionSettingsForm redirects to 'canvas.api.config.list' after submission is merged as it already adds many tests to this from
Comment #6
arianraeesi commentedComment #8
scott falconer commented- Added block component prop extraction in CanvasAiPageBuilderHelper by mapping block config schema keys to props (defaults/required/enum) so AI sees required block inputs.
- Added a kernel test that generates system_branding_block and asserts block props appear in AI context.
- UI: guard removeMediaFields() so non‑prop components (blocks) don’t attempt propSource filtering when placing components.
Notes
- test coverage from #3558241 is now in MR;
- BlockComponentFormTest failure is tracked separately in #3570699 (test fix handled there).
MR:
- https://git.drupalcode.org/project/canvas/-/merge_requests/498
Testing:
- ddev phpcs
- ddev exec drush ev 'Drupal::service("account_switcher")->switchTo(Drupal::entityTypeManager()->getStorage("user")->load(1)); print Drupal::service("canvas_ai.page_builder_helper")->getComponentContextForAi(); Drupal::service("account_switcher")->switchBack();' | rg -n "system_branding_block|use_site_logo|use_site_name|use_site_slogan"
- ddev exec bash -lc 'cd /var/www/html/web && SIMPLETEST_DB=mysql://db:db@db/db ../vendor/bin/phpunit -c core/phpunit.xml.dist modules/contrib/canvas/modules/canvas_ai/tests/src/Kernel/CanvasAiPageBuilderHelperTest.php' (passes; existing deprecations about RunTestsInSeparateProcesses, ApiContentUpdateForDemoController service id, and canvas_requirements)
- ddev exec bash -lc 'cd /var/www/html/web && SIMPLETEST_DB=mysql://db:db@db/db SIMPLETEST_BASE_URL=https://canvas-dev.ddev.site:8443 BROWSERTEST_OUTPUT_DIRECTORY=/var/www/html/web/sites/simpletest/browser_output ../vendor/bin/phpunit -c core/phpunit.xml.dist modules/contrib/canvas/tests/src/Functional/BlockComponentFormTest.php' (fails at line 46; tracked in https://www.drupal.org/project/canvas/issues/3570699)
AI disclosure:
- AI assistance used. Output reviewed and tests run manually.
Comment #9
mglaman1. Seems like having `ui/src/components/aiExtension/AiWizard.tsx` check `isPropSourceComponent` is a big fix that could avoid bugs without exposing block inputs in this issue
2. test and code style nits
Comment #10
scott falconer commented- Enum helper now always returns an array; caller checks
count($enum) > 0 before setting enum.
- Kernel test now uses User::create(['uid' => 1]) for current user
setup.
-/BlockComponent.php: getExplicitInputDefinitions() is now public.
-- Using only getExplicitInputDefinitions() dropped the label prop (because schema label keys are stripped
there), which broke CanvasAiPageBuilderHelperTest.
-- - The final implementation keeps label and other expected block props while still using source-plugin
explicit schema data.
- AiWizard.tsx isPropSourceComponent guard comment is already
present in MR code.
- ui/src/components/aiExtension/AiWizard.tsx:205
Comment #11
akhil babuThere are conflicts in the MR now
Comment #12
akhil babuComment #13
akhil babuComment #14
akhil babu