Skip to content

Hooks

The AI Context module implements several hooks and provides two alter hooks for third-party modules.

Alter hooks

hook_ai_context_scope_info_alter()

Allows modules to add, modify, or remove scope plugin definitions before they are used for discovery, settings tabs, and matching. Called from AiContextScopeManager via alterInfo('ai_context_scope_info').

Use this to hide or replace scope plugins based on site configuration or optional module availability.

function hook_ai_context_scope_info_alter(array &$definitions): void {
  if (!\Drupal::moduleHandler()->moduleExists('my_optional_module')) {
    unset($definitions['my_scope']);
  }

  $definitions['department']['icon_class'] = 'ai-icon--scope-department';
}

Parameters:

  • $definitions -- scope plugin definitions keyed by plugin ID (by reference)

API group: @ingroup ai_context_scope_api

hook_ai_context_scope_values_alter()

Allows modules to add, modify, or remove values from any scope plugin. Called when scope values are retrieved for display in forms, labels, filters, and other display paths via AiContextScopeInterface::getAlteredValues(). Matching uses stored value IDs directly and does not invoke this hook.

function hook_ai_context_scope_values_alter(
  array &$values,
  string $scope_id,
  ?\Drupal\Core\Cache\CacheableMetadata $cache = NULL,
): void {
  if ($scope_id === 'use_case') {
    $values['custom_workflow'] = t('Custom Workflow');
  }

  if ($scope_id === 'language') {
    unset($values['und']);
  }

  if ($cache) {
    $cache->addCacheTags(['config:my_module.settings']);
  }
}

Parameters:

  • $values -- associative array of value_id => label pairs (by reference)
  • $scope_id -- plugin ID of the scope (e.g., use_case, language)
  • $cache -- optional CacheableMetadata when labels are collected for a cached display. Add tags or contexts for sources the altered labels depend on. Existing two-argument implementations remain valid.

API group: @ingroup ai_context_scope_api

No consumer-type definition alter

There is no hook_ai_context_consumer_type_info_alter(). Consumer type discovery is not alterable. Use the enabled key on ai_context.consumer_type_settings.{type} to turn automatic push off for every instance of that type. A disabled type still appears in listings; pull-based tools keep working. See Consumer type API.

Implemented hooks

hook_ENTITY_TYPE_insert() for ai_context_item

When a context item is inserted, adds its scope values to the denormalized scope index table via ai_context.scope_index.

Implemented in ai_context_ai_context_item_insert() in ai_context.module.

hook_ENTITY_TYPE_update() for ai_context_item

When a context item is updated, refreshes its scope index rows. If the item is a parent and its scope values changed, reindexes inheriting children so their indexed scope mirrors the parent.

Implemented in ai_context_ai_context_item_update() in ai_context.module.

hook_ENTITY_TYPE_delete() for ai_context_item

When a parent context item is deleted, clears the parent and subcontext_type fields from all children to prevent orphaned references. Also removes the item's rows from the scope index.

Implemented in ai_context_ai_context_item_delete() in ai_context.module.

hook_entity_delete()

When a non-context-item entity is deleted, asks opted-in scope plugins whether to scrub stored values (AiContextScopeStoredValueInterface::shouldScrubAfterEntityDelete()), then clears entity item references from context items that pointed at the deleted entity. Deleting a host entity also removes its matching row from ai_context.consumers when a consumer type maps that entity (Agent: ai_agent → agent:{id}, Automator: ai_automator → automator:{id}). Disabled and unavailable types are still asked. A type that fails to instantiate or map is skipped and logged so one broken plugin cannot abort the delete.

The consumer row is kept when the module that provided the deleted entity's type is being uninstalled. Those deletes are the type going away, not an admin removing one consumer, so the saved override survives and the consumers listing shows it as Off (type unavailable). Availability cannot decide this: core clears core.extension only after the config entities are gone, so the type still reports as installed while the deletes run. See hook_module_preuninstall().

Implemented in ai_context_entity_delete() in ai_context.module.

hook_module_preuninstall()

Records the module core is about to uninstall so ai_context_entity_delete() can tell a module teardown apart from a single host-entity delete. Core fires this before it deletes the module's configuration, which is when the host entities disappear. Config sync is not special-cased: the host entities are deleted the same way, so their overrides must survive either path.

Implemented in ai_context_module_preuninstall() in ai_context.module.

hook_entity_bundle_delete()

When a bundle is deleted, asks opted-in scope plugins whether to scrub stored values (AiContextScopeStoredValueInterface::shouldScrubAfterBundleDelete()). Entity Types keeps a type-level All value (type:_all), because All still means every current and future bundle of that type.

Implemented in ai_context_entity_bundle_delete() in ai_context.module.

hook_modules_uninstalled()

Uninstalling a module that provided entity types, vocabularies, or languages does not fire the per-option delete hooks for leftover stored values. This hook asks every opted-in plugin to drop what is now stale. It does nothing when ai_context itself is being uninstalled, or during config synchronization: sync processes extension changes before config values, so a scrub then would compare stored values to a half-imported environment.

Implemented in ai_context_modules_uninstalled() in ai_context.module.

hook_entity_type_build()

Registers the AiContextItemIntegrity constraint on ai_context_item so subcontext integrity rules are enforced through entity validation and storage pre-save checks.

hook_cron()

Purges old usage records based on configured limits (usage_max_records and usage_max_age). Runs during each cron execution.

hook_theme()

Registers theme hooks:

  • ai_context_overview -- the overview dashboard page
  • ai_context_pill_list -- renders a list of labels as pill-style tags. By default the first two labels stay visible and the rest collapse into a +N pill (max_visible, default 2). max_visible 0 puts every label in +N. Long labels use an ellipsis (truncate, default TRUE). Pass truncate FALSE to keep the full label, as the consumer listing does for count pills. AiContextThemeHooks::preprocessAiContextPillList() encodes tooltip values so Price <10 stays readable and markup cannot execute after ai/ai_global.js assigns data-ai-tooltip to innerHTML. A LegacyHook bridge covers Drupal 10.
  • ai_context_item -- entity theme hook; full view uses ai-context-item--full.html.twig, default view uses ai-context-item.html.twig. Template suggestions are added in hook_theme_suggestions_ai_context_item(). Initial preprocess is registered in AiContextThemeHooks::theme() and implemented by AiContextThemeHooks::preprocessAiContextItem(), which delegates to AiContextItemViewBuilder. The hook class is autowired in ai_context.services.yml via the AiContextItemViewBuilder class alias.

hook_local_tasks_alter()

Conditionally shows or hides the Overview tab based on the show_overview_page setting.

hook_menu_local_tasks_alter()

Hides the derived per-type and per-scope tab group (including its "All" tab) on the Consumer Types and Scope overview routes, where it would otherwise merge into the Settings trail. Implemented in AiContextLocalTaskHooks, registered in ai_context.services.yml with a LegacyHook bridge for Drupal 10.

hook_module_implements_alter()

Ensures the module's hook_form_alter() runs after Scheduler's, so it can modify Scheduler form elements.

hook_form_alter()

Applies to AI Context Item entity forms and the AI Agent edit form:

  • Moves Scheduler fields to the sidebar
  • Groups moderation state with revision information
  • Hides entity_items field when no entity types are allowed
  • Adds a "Context Control Center" section to the agent form with a link to consumer context settings

hook_field_widget_single_element_form_alter()

Restricts the dynamic entity reference widget on entity_items to only show allowed entity types and enforces one entity per field row.

hook_page_attachments_alter()

Attaches the ai_context/ai_context library globally.

hook_gin_content_form_routes()

Registers context item add/edit form routes with the Gin admin theme for content-form styling.

hook_ENTITY_TYPE_view() for ai_context_item

Attaches the ai_context_item CSS/JS library on the full view mode. Canonical and revision routes render with the full view mode; layout and sidebar variables are built by AiContextItemViewBuilder via AiContextThemeHooks::preprocessAiContextItem().

hook_block_access()

Forbids page_title_block on the canonical context item route so the template H1 is the only title. Revision view keeps the route revision title from page_title_block.

hook_preprocess_html()

Adds a page-ai-context-item-view body class on canonical and revision context item view routes.

hook_entity_type_alter()

Delegates to DiffHooks for Diff module integration (adding diff field builders to entity type definitions).

hook_modules_installed()

Delegates to DiffHooks to register diff field builders when the Diff module is installed.