Problem/Motivation
The context/metadata system used usage_notes and schema_meta naming which was inconsistent and unclear. The hook_entity_blueprint_schema_meta_alter hook name didn't clearly convey its purpose, and the system lacked a declarative (non-PHP) way to provide context and managed keys — modules had to implement hooks even for purely static data.
The EntityStorageHandler lived in the entity_blueprint_ai sub-module despite being a general-purpose storage routing service, limiting reuse by other consumers of the base module.
Field handlers had no mechanism to advertise the input formats they accept, forcing AI consumers to rely on hardcoded documentation or system prompts to understand field type semantics.
There was no workspace enforcement — AI tools could persist content changes directly to the live environment without requiring an active workspace, creating risk of unreviewed changes in production.
The schema builder did not check entity access, allowing schema retrieval for bundles the current user cannot create. Layout components always required an explicit region even for single-region layouts, adding unnecessary verbosity for the most common case.
Proposed resolution
Context system refactor:
- Rename
usage_notestoguidanceandhook_entity_blueprint_schema_meta_altertohook_entity_blueprint_context_alterthroughout. - Add YAML file discovery for both context (
MODULE.entity_blueprint.context.yml) and managed keys (MODULE.entity_blueprint.managed_keys.yml), with scoped variants for entity_type/bundle-specific declarations (MODULE.entity_blueprint.context.ENTITY_TYPE.BUNDLE.yml). - Three-layer precedence: universal YAML → scoped YAML → hooks (alter always wins). Uses
array_replace_recursive()for clean scalar replacement. - Add a
field_typescontext level so modules can provide or override guidance per field type.
Field handler guidance:
- Add
getGuidance(): ?stringtoFieldHandlerInterface. All handlers implement it with concise LLM-facing descriptions of accepted input formats. - Guidance is collected by
BlueprintSchemaBuilderinto a deduplicatedfield_typessection in schema output, and also included per-field in field info.
Workspace enforcement:
- Move
EntityStorageHandlerfromentity_blueprint_aito the baseentity_blueprintmodule as a proper service (entity_blueprint.storage_handler). - Add
WorkspaceRequiredExceptionand workspace checking toEntityStorageHandler::persist(). - Add configurable
require_workspacesetting (default: TRUE) with admin form at/admin/config/content/entity-blueprint. - Add
SettingsFormTraitfor shared form elements, used by both the standaloneSettingsFormand aSettingsFormAlterhook class that embeds settings in the Plus Suite form. - Add
requireWorkspace()helper toEntityBlueprintToolBase— all AI write tools call it at the top ofexecute(). When a workspace is required, the tool returns available workspaces and instructs the AI to ask the user before choosing. - Add
SwitchWorkspaceAI tool plugin for switching to or creating workspaces.
Other improvements:
- Schema builder now checks bundle create access before returning schema.
- Single-region layouts no longer require explicit
regionon components — both the structural validator and layout deserializer auto-resolve the default region. - Add
hook_entity_blueprint_entity_persistedto the base module (fires fromEntityStorageHandlerafter every successful persist). - Rename the AI sub-module's persist hook to
hook_entity_blueprint_ai_tool_persistedfor clarity, and change its$saveparameter to$is_new. GenerateImagenow routes throughEntityStorageHandler::persist()instead of calling$media->save()directly.- Rename schema key
layout_buildertolayout_builder__layoutto match the actual field name. - Remove unused
workflow_hintfrom serializer output. - Reorder
ALWAYS_SKIP_FIELDSand addentity_workflow_contentto the skip list.
User interface changes
- New admin settings form at
/admin/config/content/entity-blueprintwith a "Require workspace for content changes" checkbox (visible only when the Workspaces module is enabled). - Module now has a "Configure" link on the Extend page pointing to this settings form.
- Entity Blueprint settings are also embedded in the Plus Suite settings form when that module is present.
API changes
- Renamed hook:
hook_entity_blueprint_schema_meta_alter→hook_entity_blueprint_context_alter. Parameter renamed from$metato$context. - Renamed key:
usage_notes→guidancein all schema output and context arrays. - Renamed schema key:
layout_builder→layout_builder__layoutin schema output. - New hook:
hook_entity_blueprint_context_altersupports afield_typeslevel for per-field-type guidance. - New hook:
hook_entity_blueprint_entity_persistedin the base module (fires afterEntityStorageHandler::persist()). - Renamed hook (AI sub-module):
hook_entity_blueprint_entity_persisted→hook_entity_blueprint_ai_tool_persistedwith$saverenamed to$is_new. - New interface method:
FieldHandlerInterface::getGuidance(): ?string. - Moved service:
entity_blueprint_ai.storage_handler→entity_blueprint.storage_handler(class moved fromDrupal\entity_blueprint_aitoDrupal\entity_blueprintnamespace). - New exception:
WorkspaceRequiredExceptionthrown byEntityStorageHandler::persist(). - New AI tool plugin:
entity_blueprint:switch_workspace(SwitchWorkspace). - YAML discovery: Modules can now declare managed keys and context via YAML files instead of hooks.
- Schema builder now requires create access for the bundle; throws
BlueprintExceptionon access denied. - Region omission: Components in single-region layouts no longer require an explicit
region.
Data model changes
New config object entity_blueprint.settings with a single require_workspace boolean property (default: TRUE).
Comments
Comment #3
tim bozeman commented