PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 3.6.0
AI Engine – The Chatbot, AI Framework & MCP for WordPress v3.6.0
3.6.0 3.5.9 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / labs / wpai-gateway.php
ai-engine / labs Last commit date
mcp-core.php 11 hours ago mcp-oauth.php 1 month ago mcp-rest.php 3 weeks ago mcp.conf 1 year ago mcp.js 8 months ago mcp.md 8 months ago mcp.php 1 week ago wpai-connectors.php 2 months ago wpai-gateway-availability.php 2 months ago wpai-gateway-directory.php 2 months ago wpai-gateway-image-model.php 2 months ago wpai-gateway-model.php 2 months ago wpai-gateway-providers.php 2 months ago wpai-gateway.php 2 months ago
wpai-gateway.php
178 lines
1 <?php
2 /**
3 * WP AI Client Gateway — replaces the native provider classes in WP's
4 * `AiClient::defaultRegistry()` with AI Engine-backed adapters, so every
5 * `wp_ai_client_prompt()->using_provider(...)` call dispatches through
6 * `Meow_MWAI_Core::run_query()` and lands in AI Engine's Insights.
7 *
8 * @package MeowApps
9 */
10
11 class Meow_MWAI_Labs_WPAI_Gateway {
12
13 /** Shared reference to AI Engine core (read-only for the model classes). */
14 public static $core = null;
15
16 public function __construct( $core ) {
17 self::$core = $core;
18
19 if ( ! class_exists( '\\WordPress\\AiClient\\AiClient' ) ) {
20 return;
21 }
22
23 // Register after the native providers (init 20) and after WP's
24 // `_wp_connectors_pass_default_keys_to_ai_client`, so our replacements
25 // land last and stick.
26 add_action( 'init', [ $this, 'register' ], 25 );
27
28 // Tiny test endpoint for developers to verify end-to-end dispatch without
29 // wiring up ChatKit. Hit `admin-ajax.php?action=mwai_wpai_gateway_test`.
30 add_action( 'wp_ajax_mwai_wpai_gateway_test', [ $this, 'ajax_test' ] );
31 }
32
33 public function ajax_test(): void {
34 if ( ! current_user_can( 'manage_options' ) ) {
35 wp_send_json_error( [ 'message' => 'forbidden' ], 403 );
36 }
37 $message = isset( $_REQUEST['message'] ) ? wp_unslash( $_REQUEST['message'] ) : 'Say hi in one word.';
38 $model = isset( $_REQUEST['model'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['model'] ) ) : '';
39 try {
40 $registry = \WordPress\AiClient\AiClient::defaultRegistry();
41 $provider_id = isset( $_REQUEST['provider'] ) ? sanitize_key( wp_unslash( $_REQUEST['provider'] ) ) : '';
42 if ( ! $provider_id ) {
43 foreach ( self::ADAPTERS as $id => $_cls ) {
44 if ( $registry->hasProvider( $id ) && $registry->isProviderConfigured( $id ) ) {
45 $provider_id = $id;
46 break;
47 }
48 }
49 }
50 if ( ! $provider_id ) {
51 wp_send_json_error( [ 'message' => 'no configured AI Engine adapter found; enable the Connectors takeover' ], 500 );
52 }
53 $provider = $registry->getProviderClassName( $provider_id );
54 if ( ! $model ) {
55 $models = $provider::modelMetadataDirectory()->listModelMetadata();
56 if ( empty( $models ) ) {
57 wp_send_json_error( [ 'message' => 'no models exposed by ' . $provider_id ], 500 );
58 }
59 $model = $models[0]->getId();
60 }
61 $modelInstance = $provider::model( $model );
62 $user = new \WordPress\AiClient\Messages\DTO\UserMessage( [
63 new \WordPress\AiClient\Messages\DTO\MessagePart( $message ),
64 ] );
65 $result = $modelInstance->generateTextResult( [ $user ] );
66 $text = '';
67 foreach ( $result->getCandidates() as $c ) {
68 foreach ( $c->getMessage()->getParts() as $p ) {
69 if ( $p->getType()->isText() ) {
70 $text .= $p->getText();
71 }
72 }
73 }
74 wp_send_json_success( [
75 'model' => $model,
76 'reply' => $text,
77 'tokens' => [
78 'prompt' => $result->getTokenUsage()->getPromptTokens(),
79 'completion' => $result->getTokenUsage()->getCompletionTokens(),
80 'total' => $result->getTokenUsage()->getTotalTokens(),
81 ],
82 ] );
83 }
84 catch ( \Throwable $e ) {
85 wp_send_json_error( [
86 'message' => $e->getMessage(),
87 'file' => $e->getFile() . ':' . $e->getLine(),
88 ], 500 );
89 }
90 }
91
92 /** Mapping from AiClient provider id → AI Engine adapter class. */
93 const ADAPTERS = [
94 'anthropic' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Anthropic::class,
95 'openai' => Meow_MWAI_Labs_WPAI_Gateway_Provider_OpenAI::class,
96 'google' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Google::class,
97 'mistral' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Mistral::class,
98 'openrouter' => Meow_MWAI_Labs_WPAI_Gateway_Provider_OpenRouter::class,
99 'perplexity' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Perplexity::class,
100 'replicate' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Replicate::class,
101 'ollama' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Ollama::class,
102 'azure' => Meow_MWAI_Labs_WPAI_Gateway_Provider_Azure::class,
103 ];
104
105 public function register(): void {
106 try {
107 require_once __DIR__ . '/wpai-gateway-availability.php';
108 require_once __DIR__ . '/wpai-gateway-directory.php';
109 require_once __DIR__ . '/wpai-gateway-model.php';
110 require_once __DIR__ . '/wpai-gateway-image-model.php';
111 require_once __DIR__ . '/wpai-gateway-providers.php';
112
113 $registry = \WordPress\AiClient\AiClient::defaultRegistry();
114
115 // Only fully take over when the Connectors takeover is in managed mode.
116 // Otherwise, native provider plugins keep handling their own calls.
117 $managed = get_option( Meow_MWAI_Labs_WPAI_Connectors::OPTION_MODE, 'observe' ) === 'managed';
118 if ( ! $managed ) {
119 return;
120 }
121
122 foreach ( self::ADAPTERS as $id => $adapter_class ) {
123 $this->force_replace_provider( $registry, $id, $adapter_class );
124 }
125 }
126 catch ( \Throwable $e ) {
127 error_log( '[MWAI_WPAI_GATEWAY] registration failed: ' . $e->getMessage() . ' @ ' . $e->getFile() . ':' . $e->getLine() );
128 }
129 }
130
131 /**
132 * Replace a provider registration in AiClient, even if the id is already
133 * taken by a native plugin. AiClient exposes no unregister method, so we
134 * reach into the private registry state via reflection.
135 */
136 private function force_replace_provider( $registry, string $id, string $adapter_class ): void {
137 try {
138 $ref = new \ReflectionObject( $registry );
139
140 // Scrub existing registration for this id (if any).
141 if ( $registry->hasProvider( $id ) ) {
142 foreach ( [ 'registeredIdsToClassNames', 'registeredClassNamesToIds', 'providerAuthenticationInstances' ] as $prop_name ) {
143 if ( ! $ref->hasProperty( $prop_name ) ) {
144 continue;
145 }
146 $prop = $ref->getProperty( $prop_name );
147 $prop->setAccessible( true );
148 $value = $prop->getValue( $registry );
149 if ( $prop_name === 'registeredIdsToClassNames' ) {
150 $old_class = $value[ $id ] ?? null;
151 unset( $value[ $id ] );
152 $prop->setValue( $registry, $value );
153 if ( $old_class ) {
154 // Also drop reverse map entries for the old class.
155 foreach ( [ 'registeredClassNamesToIds', 'providerAuthenticationInstances' ] as $rev ) {
156 if ( ! $ref->hasProperty( $rev ) ) {
157 continue;
158 }
159 $rp = $ref->getProperty( $rev );
160 $rp->setAccessible( true );
161 $rv = $rp->getValue( $registry );
162 unset( $rv[ $old_class ] );
163 $rp->setValue( $registry, $rv );
164 }
165 }
166 break;
167 }
168 }
169 }
170
171 $registry->registerProvider( $adapter_class );
172 }
173 catch ( \Throwable $e ) {
174 error_log( "[MWAI_WPAI_GATEWAY] replace $id failed: " . $e->getMessage() );
175 }
176 }
177 }
178