drupal/thunder_ai

Thunder AI base recipe with provider installer.

Maintainers

Package info

git.drupalcode.org/project/thunder_ai.git

Type:drupal-recipe

pkg:composer/drupal/thunder_ai

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

1.0.0-beta1 2026-05-17 18:35 UTC

This package is auto-updated.

Last update: 2026-05-17 17:07:43 UTC


README

A Drupal recipe for Thunder that installs and configures AI providers.

What this recipe installs

ModuleDescription
drupal/aiCore AI integration layer
drupal/ai_provider_azureAzure OpenAI provider integration
drupal/ai_provider_openaiOpenAI provider integration
drupal/gemini_providerGoogle Gemini provider integration
drupal/ai_provider_anthropicAnthropic provider integration

Requirements

  • Thunder distribution
  • Composer

Installation

Apply the recipe using Drupal's recipe system:

drush recipe ../recipes/thunder_ai

The recipe asks the following questions:

  1. Default AI providerazure, openai, gemini, or anthropic
  2. Key storage methodconfig (value stored in Drupal config) or env (value read from an environment variable)
  3. Azure API key value or env var name — press Enter to skip if not using Azure
  4. Azure endpoint URL — the full deployment endpoint from Azure AI Studio
  5. OpenAI: API key value or env var name — press Enter to skip if not using OpenAI
  6. Google Gemini: API key value or env var name — press Enter to skip if not using Gemini
  7. Anthropic: API key value or env var name — press Enter to skip if not using Anthropic
  8. Default model ID — model to use for chat; defaults to thunder_ai_azure (the Azure model registered by this recipe). Override when using a different provider (e.g. gpt-4o, claude-opus-4-5, gemini-2.0-flash)

For questions 3, 5, 6, and 7: enter the raw API key when using config storage, or the environment variable name (e.g. OPENAI_API_KEY) when using env storage.

Note: Drupal recipe inputs cannot be made conditional, so all questions are always shown. Only fill in credentials and a model for the provider you selected; press Enter to skip the rest.

To skip the prompts entirely, pass all values as flags:

drush recipe ../recipes/thunder_ai \
  --input="thunder_ai.default_provider=azure" \
  --input="thunder_ai.default_model=thunder_ai_azure" \
  --input="thunder_ai.key_provider=env" \
  --input="thunder_ai.azure_api_key=AZURE_API_KEY" \
  --input="thunder_ai.azure_endpoint=https://my-resource.openai.azure.com/openai/deployments/my-deployment/chat" \
  --input="thunder_ai.openai_api_key=" \
  --input="thunder_ai.gemini_api_key=" \
  --input="thunder_ai.anthropic_api_key="

All three provider modules are installed regardless of the selection. The chosen provider is set as the site default for chat operations.

What the recipe configures

For each provider whose credentials are supplied, the recipe:

  1. Creates a Key module entity (thunder_ai_{provider}_key) using the chosen key provider (config or env)
  2. Wires the Key entity to the provider's settings
  3. For Azure: registers a chat model (using the supplied azure_model ID) in ai.settings.models with the given endpoint
  4. Sets the chosen provider and its model as the site default for chat in ai.settings

Post-installation

Non-Azure modelai.settings.default_providers.chat.model_id is set from the azure_model input. If you selected OpenAI, Gemini, or Anthropic, visit Administration > Configuration > AI to update the default model.

Production key storage — credentials are stored in Drupal config via the Key module's config provider. For production environments, switch to an environment-variable-based key provider at Administration > Configuration > System > Keys.

FAQ

Why are all four AI providers installed when I only selected one?

Drupal recipes have no conditional logic — it is not possible to install a module only when a specific input value is chosen. All four provider modules are always installed regardless of the selection. The chosen provider is set as the site default; the others are installed but unconfigured. See Removing unneeded providers for how to clean them up.

Why does the default model default to thunder_ai_azure when I selected a different provider?

Azure OpenAI requires an explicit model registration in ai.settings.models that includes the deployment endpoint URL. The recipe registers one such model (thunder_ai_azure) using the endpoint supplied as input. Other providers discover available models dynamically and need no registration entry. Because the recipe always creates the Azure model entry, the default_model input defaults to thunder_ai_azure. When using a different provider, override the default_model input during recipe application or update the default model afterwards at Administration > Configuration > AI.

Why is setupAiProvider not used to configure the providers?

The drupal/ai module provides a setupAiProvider config action that creates a Key entity and wires it to a provider in one step. It was not used for two reasons:

  1. The Azure provider does not implement getSetupData() — it returns an empty array — which causes the action to fail for Azure.
  2. setupAiProvider hardcodes the Key module's config storage backend. There is no way to have it create a Key entity that reads from an environment variable instead.

The recipe uses createIfNotExists and simpleConfigUpdate directly, which avoids both limitations and works uniformly for all four providers.

Removing unneeded providers

The recipe installs all four AI provider modules. Once you have decided which provider to use, you can unpack the recipe and remove the providers you do not need.

Unpacking inlines the recipe's Composer dependencies into your project's composer.json and removes the recipe package itself, giving you full control over each dependency.

1. Install the unpack plugin

composer require drupal/core-recipe-unpack

2. Unpack the recipe

composer drupal:recipe-unpack drupal/thunder_ai

This moves all packages from drupal/thunder_ai's require into your root composer.json and removes the recipe package.

3. Uninstall the unused Drupal modules

Drupal modules must be uninstalled before their packages are removed from Composer. Removing the package first leaves Drupal with a reference to a missing module, which causes pm:uninstall to fail.

drush pm:uninstall ai_provider_azure     # not using Azure OpenAI
drush pm:uninstall ai_provider_openai    # not using OpenAI
drush pm:uninstall gemini_provider       # not using Google Gemini
drush pm:uninstall ai_provider_anthropic # not using Anthropic

4. Delete the unused Key config entries

drush config:delete key.key.thunder_ai_azure_key
drush config:delete key.key.thunder_ai_openai_key
drush config:delete key.key.thunder_ai_gemini_key
drush config:delete key.key.thunder_ai_anthropic_key

5. Export the updated configuration

drush config:export

6. Remove the unused provider packages

Now that the modules are uninstalled, remove their Composer packages:

composer remove drupal/ai_provider_azure
composer remove drupal/ai_provider_openai
composer remove drupal/gemini_provider
composer remove drupal/ai_provider_anthropic