Context
Data Machine currently bundles vendor/chubes4/ai-http-client (v2.0.13) — a filter-based AI provider abstraction layer. WordPress 7.0 core now ships wp-ai-client with equivalent functionality via a fluent OOP API (wp_ai_client_prompt()). The bundled library should be removed and all AI requests routed through core's client directly.
Key constraints:
- Core's AI client does not support multisite (network-wide API key/model cascading). Data-machine must own that.
- Core requires separate provider plugins (e.g.,
ai-provider-for-openai) to register actual provider implementations. Data-machine follows the same model.
- No backwards compatibility layer — all
chubes_ai_* filter hooks are eliminated; consuming code is rewritten.
- No custom provider implementations — data-machine does not ship or register providers. That's a separate concern.
- No adapter class —
RequestBuilder calls wp_ai_client_prompt() directly and normalizes the response inline.
API Comparison
| Aspect |
ai-http-client (old) |
wp-ai-client (new) |
| Request |
Array via apply_filters('chubes_ai_request', ...) |
Fluent builder: wp_ai_client_prompt()->with_history()->using_model()->generate_text_result() |
| Response |
['success'=>bool, 'data'=>['content','usage','tool_calls'], 'error'=>string] |
GenerativeAiResult|WP_Error with ->toText(), ->getTokenUsage(), candidates with MessagePart::getFunctionCall() |
| Tool calls in |
Array in $request['tools'] |
FunctionDeclaration objects via using_function_declarations() |
| Tool calls out |
$response['data']['tool_calls'] = [['name'=>..., 'parameters'=>...]] |
$candidate->getMessage()->getParts() → $part->getFunctionCall() → FunctionCall::getName(), ::getArgs(), ::getId() |
| API keys |
get_site_option('chubes_ai_http_shared_api_keys') (one array) |
Connectors system: individual get_option('connectors_ai_{id}_api_key') per provider |
| Multisite |
Built into key storage via get_site_option |
None — DM must own this |
| Streaming |
Supported (unused by DM) |
Not supported |
Implementation Plan
Step 1: Create DataMachineAPIKeys — multisite key resolver
New file: inc/Engine/AI/DataMachineAPIKeys.php
Resolution order:
- Per-site:
get_option('connectors_ai_{provider}_api_key')
- Network:
NetworkSettings::get('api_keys')[$provider]
- Environment variable:
{PROVIDER_ID}_API_KEY
- Empty string
Modify: inc/Core/NetworkSettings.php — add 'api_keys' to NETWORK_KEYS
Step 2: Rewrite RequestBuilder::build()
Modify: inc/Engine/AI/RequestBuilder.php
Replace lines 93-105 (apply_filters('chubes_ai_request', ...)) with direct wp_ai_client_prompt() calls inline:
- Resolve API key via
DataMachineAPIKeys::get($provider)
- Set auth on registry:
$registry->setProviderRequestAuthentication($provider, new ApiKeyRequestAuthentication($key))
- Extract system messages from
$request['messages'] → using_system_instruction()
- Convert remaining messages to
Message objects → with_history()
- Convert tools to
FunctionDeclaration objects → using_function_declarations()
- Set provider/model →
using_provider() + using_model(registry->getProviderModel())
- Apply config →
using_temperature(), using_max_tokens() if set
- Call
generate_text_result()
- Normalize
GenerativeAiResult → DM's expected response array inline:
$result->toText() → ['data']['content']
$result->getTokenUsage() → ['data']['usage']
- Tool calls from message parts →
['data']['tool_calls'] as [['name'=>..., 'parameters'=>...]]
WP_Error → ['success'=>false, 'error'=>...]
Step 3: Migrate API key storage
Modify: inc/Engine/Filters/DataMachineFilters.php
- Remove the
chubes_ai_provider_api_keys filter hook
- Add one-time migration: read
get_site_option('chubes_ai_http_shared_api_keys') → write each key into update_option('connectors_ai_{provider}_api_key', $key)
Step 4: Rewrite Providers::handle_get_providers()
Modify: inc/Api/Providers.php
Replace chubes_ai_providers, chubes_ai_provider_api_keys, chubes_ai_models filter calls with:
$registry = AiClient::defaultRegistry();
$provider_ids = $registry->getRegisteredProviderIds();
// For each: wp_get_connector($id) for metadata
// $registry->findProviderModelsMetadataForSupport() for models
Step 5: Rewrite API key management in SettingsAbilities
Modify: inc/Abilities/SettingsAbilities.php
getAiProviderSettings() (line 340): Replace apply_filters('chubes_ai_provider_api_keys', null) with reading from Connectors + NetworkSettings
executeUpdateSettings() (line 498-513): Write to update_option('connectors_ai_{provider}_api_key', ...) for per-site, NetworkSettings::update(['api_keys' => ...]) for network
Step 6: Update Chat.php provider validation
Modify: inc/Api/Chat/Chat.php (line 77) — replace apply_filters('chubes_ai_providers', array()) with AiClient::defaultRegistry()->getRegisteredProviderIds() or wp_get_connectors()
Step 7: Remove ai-http-client dependency
- Remove from
composer.json: "chubes4/ai-http-client": "^2.0.13"
- Delete
vendor/chubes4/ai-http-client/
- Remove autoload references
Files to Modify
| File |
Change |
inc/Engine/AI/DataMachineAPIKeys.php |
NEW — multisite API key resolution |
inc/Engine/AI/RequestBuilder.php |
Replace chubes_ai_request filter with direct wp_ai_client_prompt() calls |
inc/Api/Providers.php |
Replace all chubes_ai_* filters with ProviderRegistry calls |
inc/Abilities/SettingsAbilities.php |
Replace chubes_ai_provider_api_keys with Connectors + NetworkSettings |
inc/Engine/Filters/DataMachineFilters.php |
Remove chubes_ai_provider_api_keys filter; add one-time key migration |
inc/Api/Chat/Chat.php |
Replace chubes_ai_providers filter with registry check |
inc/Core/NetworkSettings.php |
Add api_keys to NETWORK_KEYS |
composer.json |
Remove chubes4/ai-http-client dependency |
vendor/chubes4/ |
DELETE entire directory |
What does NOT change
AIConversationLoop.php — consumes RequestBuilder::build() return value which keeps the same array shape
ConversationManager.php — builds DM's internal message format; RequestBuilder handles the translation
ToolExecutor.php, ToolPolicyResolver.php, ToolServiceProvider.php — tool execution unchanged
PromptBuilder.php (DM's directive system) — unchanged, still builds the $request array
- All directive classes — unchanged
AIStep.php, ChatOrchestrator.php — unchanged (call AIConversationLoop which calls RequestBuilder)
Logger.php, DirectoryManager.php — unchanged multisite code
Key SDK Classes (for reference)
| Class |
Full Namespace |
| Message |
WordPress\AiClient\Messages\DTO\Message |
| MessagePart |
WordPress\AiClient\Messages\DTO\MessagePart |
| MessageRoleEnum |
WordPress\AiClient\Messages\Enums\MessageRoleEnum |
| FunctionDeclaration |
WordPress\AiClient\Tools\DTO\FunctionDeclaration |
| FunctionCall |
WordPress\AiClient\Tools\DTO\FunctionCall |
| FunctionResponse |
WordPress\AiClient\Tools\DTO\FunctionResponse |
| AiClient |
WordPress\AiClient\AiClient |
| ProviderRegistry |
WordPress\AiClient\Providers\ProviderRegistry |
| GenerativeAiResult |
WordPress\AiClient\Results\DTO\GenerativeAiResult |
| ApiKeyRequestAuthentication |
WordPress\AiClient\Providers\Http\DTO\ApiKeyRequestAuthentication |
| WP_AI_Client_Prompt_Builder |
(WordPress wrapper class) |
Verification Checklist
Context
Data Machine currently bundles
vendor/chubes4/ai-http-client(v2.0.13) — a filter-based AI provider abstraction layer. WordPress 7.0 core now shipswp-ai-clientwith equivalent functionality via a fluent OOP API (wp_ai_client_prompt()). The bundled library should be removed and all AI requests routed through core's client directly.Key constraints:
ai-provider-for-openai) to register actual provider implementations. Data-machine follows the same model.chubes_ai_*filter hooks are eliminated; consuming code is rewritten.RequestBuildercallswp_ai_client_prompt()directly and normalizes the response inline.API Comparison
apply_filters('chubes_ai_request', ...)wp_ai_client_prompt()->with_history()->using_model()->generate_text_result()['success'=>bool, 'data'=>['content','usage','tool_calls'], 'error'=>string]GenerativeAiResult|WP_Errorwith->toText(),->getTokenUsage(), candidates withMessagePart::getFunctionCall()$request['tools']FunctionDeclarationobjects viausing_function_declarations()$response['data']['tool_calls']=[['name'=>..., 'parameters'=>...]]$candidate->getMessage()->getParts()→$part->getFunctionCall()→FunctionCall::getName(),::getArgs(),::getId()get_site_option('chubes_ai_http_shared_api_keys')(one array)get_option('connectors_ai_{id}_api_key')per providerget_site_optionImplementation Plan
Step 1: Create
DataMachineAPIKeys— multisite key resolverNew file:
inc/Engine/AI/DataMachineAPIKeys.phpResolution order:
get_option('connectors_ai_{provider}_api_key')NetworkSettings::get('api_keys')[$provider]{PROVIDER_ID}_API_KEYModify:
inc/Core/NetworkSettings.php— add'api_keys'toNETWORK_KEYSStep 2: Rewrite
RequestBuilder::build()Modify:
inc/Engine/AI/RequestBuilder.phpReplace lines 93-105 (
apply_filters('chubes_ai_request', ...)) with directwp_ai_client_prompt()calls inline:DataMachineAPIKeys::get($provider)$registry->setProviderRequestAuthentication($provider, new ApiKeyRequestAuthentication($key))$request['messages']→using_system_instruction()Messageobjects →with_history()FunctionDeclarationobjects →using_function_declarations()using_provider()+using_model(registry->getProviderModel())using_temperature(),using_max_tokens()if setgenerate_text_result()GenerativeAiResult→ DM's expected response array inline:$result->toText()→['data']['content']$result->getTokenUsage()→['data']['usage']['data']['tool_calls']as[['name'=>..., 'parameters'=>...]]WP_Error→['success'=>false, 'error'=>...]Step 3: Migrate API key storage
Modify:
inc/Engine/Filters/DataMachineFilters.phpchubes_ai_provider_api_keysfilter hookget_site_option('chubes_ai_http_shared_api_keys')→ write each key intoupdate_option('connectors_ai_{provider}_api_key', $key)Step 4: Rewrite
Providers::handle_get_providers()Modify:
inc/Api/Providers.phpReplace
chubes_ai_providers,chubes_ai_provider_api_keys,chubes_ai_modelsfilter calls with:Step 5: Rewrite API key management in SettingsAbilities
Modify:
inc/Abilities/SettingsAbilities.phpgetAiProviderSettings()(line 340): Replaceapply_filters('chubes_ai_provider_api_keys', null)with reading from Connectors + NetworkSettingsexecuteUpdateSettings()(line 498-513): Write toupdate_option('connectors_ai_{provider}_api_key', ...)for per-site,NetworkSettings::update(['api_keys' => ...])for networkStep 6: Update Chat.php provider validation
Modify:
inc/Api/Chat/Chat.php(line 77) — replaceapply_filters('chubes_ai_providers', array())withAiClient::defaultRegistry()->getRegisteredProviderIds()orwp_get_connectors()Step 7: Remove ai-http-client dependency
composer.json:"chubes4/ai-http-client": "^2.0.13"vendor/chubes4/ai-http-client/Files to Modify
inc/Engine/AI/DataMachineAPIKeys.phpinc/Engine/AI/RequestBuilder.phpchubes_ai_requestfilter with directwp_ai_client_prompt()callsinc/Api/Providers.phpchubes_ai_*filters with ProviderRegistry callsinc/Abilities/SettingsAbilities.phpchubes_ai_provider_api_keyswith Connectors + NetworkSettingsinc/Engine/Filters/DataMachineFilters.phpchubes_ai_provider_api_keysfilter; add one-time key migrationinc/Api/Chat/Chat.phpchubes_ai_providersfilter with registry checkinc/Core/NetworkSettings.phpapi_keysto NETWORK_KEYScomposer.jsonchubes4/ai-http-clientdependencyvendor/chubes4/What does NOT change
AIConversationLoop.php— consumesRequestBuilder::build()return value which keeps the same array shapeConversationManager.php— builds DM's internal message format; RequestBuilder handles the translationToolExecutor.php,ToolPolicyResolver.php,ToolServiceProvider.php— tool execution unchangedPromptBuilder.php(DM's directive system) — unchanged, still builds the$requestarrayAIStep.php,ChatOrchestrator.php— unchanged (call AIConversationLoop which calls RequestBuilder)Logger.php,DirectoryManager.php— unchanged multisite codeKey SDK Classes (for reference)
WordPress\AiClient\Messages\DTO\MessageWordPress\AiClient\Messages\DTO\MessagePartWordPress\AiClient\Messages\Enums\MessageRoleEnumWordPress\AiClient\Tools\DTO\FunctionDeclarationWordPress\AiClient\Tools\DTO\FunctionCallWordPress\AiClient\Tools\DTO\FunctionResponseWordPress\AiClient\AiClientWordPress\AiClient\Providers\ProviderRegistryWordPress\AiClient\Results\DTO\GenerativeAiResultWordPress\AiClient\Providers\Http\DTO\ApiKeyRequestAuthenticationVerification Checklist
RequestBuilder::build()correctly translates DM arrays → wp-ai-client calls and normalizes response backchubes_ai_http_shared_api_keys→ individualconnectors_ai_*optionsGET /datamachine/v1/providersreturns correct data from registrygrep -r 'chubes_ai_' inc/returns zero results