feat: #3621892 Add a Views Agent development assistant submodule
Closes #3621892
Summary
Adds a new submodule, views_agent_dev_assistant, that gives site
builders a ready-to-use chat interface for the Views Agent: an
orchestrator ai_agent (wired to the Content Type, Field, Taxonomy, and
Views sub-agents), the ai_assistant_api assistant that wraps it, and a
chatbot block placed in the Gin toolbar.
The module depends on ai_agents_views, ai_assistant_api,
ai_chatbot, gin_toolbar, and block - real module dependencies, so
enabling it cascades everything else automatically. Gin cannot be
declared the same way (a module's dependencies can only list other
modules, not themes), so it is handled the way gin_toolbar itself
already handles this: hook_requirements() checks for it and reports an
install-blocking error if missing, without ever force-installing it. A
#[Hook('themes_installed')] implementation then creates the chatbot
block retroactively if Gin is installed after this module already was.
Changes
modules/views_agent_dev_assistant/views_agent_dev_assistant.info.yml: new submodule, with the module dependencies above.modules/views_agent_dev_assistant/views_agent_dev_assistant.install:hook_requirements(), modeled ongin_toolbar_requirements().modules/views_agent_dev_assistant/src/Hook/ViewsAgentDevAssistantHooks.php:#[Hook('themes_installed')]retroactively installs this module's ownconfig/optionalonce Gin is installed.modules/views_agent_dev_assistant/config/install/ai_agents.ai_agent.drupal_assistant.ymlandconfig/install/ai_assistant_api.ai_assistant.drupal_assistant.yml: the orchestrator agent and the assistant that wraps it. Both declare an enforced dependency on this module, so uninstalling it removes them.modules/views_agent_dev_assistant/config/optional/block.block.drupal_assistant_chatbot.yml: the chatbot block. Inconfig/optional, notconfig/install, because it targets the Gin theme and needs to be skippable if Gin is not there yet; also declares the enforced dependency above.modules/views_agent_dev_assistant/tests/src/Kernel/ViewsAgentDevAssistantInstallTest.php: 5 new Kernel tests (see Test plan).modules/views_agent_dev_assistant/README.md: install instructions and the reasoning behind each of the above.phpstan.neon: two newignoreErrorsentries scoped to the new submodule'stests/andsrc/Hook/directories, for the same class of Drupal-reflection false positive already ignored elsewhere in this project (a test's$modulesproperty, and an OO hook's constructor and hook method, both invoked reflectively rather than through a traceable call).
Test plan
-
testInstallCascadesDependenciesAndCreatesConfig: installing this module alone installs every dependency and creates the agent, assistant, and block correctly when Gin is already present. -
testInstallWithoutGinSkipsTheBlock: installing without Gin still creates the agent and assistant, and skips the block instead of creating one that targets a missing theme. -
testInstallingGinAfterwardsCreatesTheBlock: installing Gin after this module creates the previously-skipped block retroactively. -
testRequirementsHook: exerciseshook_requirements()across the non-install phase, missing Gin, and Gin present. -
testUninstallRemovesShippedConfig: uninstalling removes all three shipped config objects. - Full suite for ai_agents_views plus the new submodule: 68/68 tests, 675 assertions, no failures (1 pre-existing unrelated skip).
- PHPCS (Drupal, DrupalPractice) and PHPStan (level 1) both clean on the new submodule.
Closes #3621892
AI-Generated: Yes (Used Claude Code to design and implement the
submodule, including working through several iterations on how to handle
the Gin theme prerequisite - first a custom recipe with a hard-fail
config action, then a plain hook_install() that force-installed Gin,
settling on the hook_requirements() + retroactive themes_installed
hook approach here after empirically checking how each option actually
behaves - and to write and verify the test coverage.)