PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 3.6.4
AI Engine – The Chatbot, AI Framework & MCP for WordPress v3.6.4
3.6.4 3.6.5 3.6.3 3.6.2 3.6.1 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 / model-audit.php
ai-engine / labs Last commit date
mcp-core.php 2 days ago mcp-oauth.php 23 hours ago mcp-rest.php 1 month ago mcp.conf 1 year ago mcp.js 9 months ago mcp.md 9 months ago mcp.php 23 hours ago model-audit.php 2 days ago workspace-mock.html 2 days ago wpai-connectors.php 2 months ago wpai-gateway-availability.php 3 months ago wpai-gateway-directory.php 3 months ago wpai-gateway-image-model.php 3 months ago wpai-gateway-model.php 3 months ago wpai-gateway-providers.php 3 months ago wpai-gateway.php 3 months ago
model-audit.php
144 lines
1 <?php
2 /**
3 * Model coverage audit for the dynamic-model engines (Google, OpenRouter, …).
4 *
5 * Those engines build their model list at "Refresh Models" time from the provider's own
6 * API, then guess each model's nice name, features, tags and tools with a pile of
7 * regexes. When a provider ships a new naming shape those regexes quietly miss, and the
8 * model either vanishes from the dropdown or shows up without the capabilities it has.
9 * That is invisible until a user complains, so this audits it.
10 *
11 * Run it from the WordPress root:
12 * wp eval-file labs/model-audit.php # every dynamic engine
13 * wp eval-file labs/model-audit.php google # one engine type
14 *
15 * Findings are heuristics, not verdicts. Read them, then check the provider's docs
16 * before touching the regexes in classes/engines/<engine>.php.
17 */
18
19 global $mwai;
20 $core = $mwai->core;
21 $only = $args[0] ?? null;
22
23 // Engines whose models come from the provider API rather than constants/models.php.
24 $dynamic_types = [ 'google', 'openrouter' ];
25 $issues_total = 0;
26
27 foreach ( (array) $core->get_option( 'ai_envs' ) as $env ) {
28 $type = $env['type'] ?? '';
29 if ( !in_array( $type, $dynamic_types, true ) ) {
30 continue;
31 }
32 if ( $only && $type !== $only ) {
33 continue;
34 }
35 if ( empty( $env['apikey'] ) ) {
36 echo "SKIP {$type} ({$env['name']}): no API key\n";
37 continue;
38 }
39
40 echo "\n=== {$type} / {$env['name']} ===\n";
41
42 try {
43 $engine = Meow_MWAI_Engines_Factory::get( $core, $env['id'] );
44 $models = $engine->retrieve_models();
45 }
46 catch ( Exception $e ) {
47 echo " ERROR: " . $e->getMessage() . "\n";
48 continue;
49 }
50
51 echo " models classified: " . count( $models ) . "\n";
52 $issues = [];
53
54 // 1. Duplicate display names. Google ships preview and GA variants of the same model
55 // and the name formatter strips the suffix from both, which makes the dropdown
56 // ambiguous. Anything still colliding here needs disambiguating.
57 $by_name = [];
58 foreach ( $models as $m ) {
59 $by_name[$m['name']][] = $m['model'];
60 }
61 foreach ( $by_name as $name => $ids ) {
62 if ( count( $ids ) > 1 ) {
63 $issues[] = "duplicate name \"{$name}\" for: " . implode( ', ', $ids );
64 }
65 }
66
67 // 2. Names that clearly fell through the formatter: still carrying a raw id, or a
68 // lowercased fragment that should have become a proper word.
69 foreach ( $models as $m ) {
70 if ( $m['name'] === $m['model'] ) {
71 $issues[] = "unformatted name for {$m['model']} (name === id)";
72 }
73 else if ( preg_match( '/(preview|latest|exp|[0-9]{4}-[0-9]{2}|customtools|nano-banana)/i', $m['name'] )
74 && !preg_match( '/\(/', $m['name'] ) ) {
75 $issues[] = "raw id fragment left in name \"{$m['name']}\" ({$m['model']})";
76 }
77 }
78
79 // 3. Capability mismatches: the id advertises something the features do not.
80 // These are the exact shapes that were silently wrong before 2026-07-26.
81 $expectations = [
82 // id pattern => feature that must be present
83 '/-image(-preview)?$|nano-banana/' => 'image-generation',
84 '/embedding/' => 'embedding',
85 '/(native-audio|-live-)/' => 'realtime',
86 '/(veo|video)/' => 'video-generation',
87 ];
88 foreach ( $models as $m ) {
89 $features = (array) ( $m['features'] ?? [] );
90 foreach ( $expectations as $pattern => $needed ) {
91 if ( preg_match( $pattern, $m['model'] ) && !in_array( $needed, $features, true ) ) {
92 $issues[] = "{$m['model']} looks like '{$needed}' but features are: "
93 . ( implode( ',', $features ) ?: '(none)' );
94 }
95 }
96 }
97
98 // 4. Models with no usable feature at all: they will render in the dropdown and then
99 // fail at query time.
100 foreach ( $models as $m ) {
101 if ( empty( $m['features'] ) ) {
102 $issues[] = "{$m['model']} has no features";
103 }
104 }
105
106 // 5. Anything the provider exposes that never made it into the list. Only the engine
107 // knows the raw payload, so this compares against the provider call where possible.
108 if ( $type === 'google' ) {
109 $res = wp_remote_get(
110 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=200&key=' . $env['apikey'],
111 [ 'timeout' => 30 ]
112 );
113 if ( !is_wp_error( $res ) ) {
114 $body = json_decode( wp_remote_retrieve_body( $res ), true );
115 $classified = array_column( $models, 'model' );
116 foreach ( (array) ( $body['models'] ?? [] ) as $raw ) {
117 $id = str_replace( 'models/', '', $raw['name'] );
118 $methods = (array) ( $raw['supportedGenerationMethods'] ?? [] );
119 // Only care about ids we would plausibly want to offer.
120 $wanted = preg_match( '/^(gemini|nano-banana|imagen|veo)/', $id )
121 && ( in_array( 'generateContent', $methods, true ) || in_array( 'embedContent', $methods, true ) );
122 // Deliberate exclusions: dated snapshots, TTS, robotics.
123 $excluded = preg_match( '/-(tts|robotics)|(preview|exp)-\d{2}-\d{2,4}$|-\d{8}$/', $id );
124 if ( $wanted && !$excluded && !in_array( $id, $classified, true ) ) {
125 $issues[] = "provider exposes {$id} (" . implode( ',', $methods ) . ") but it was dropped";
126 }
127 }
128 }
129 }
130
131 if ( empty( $issues ) ) {
132 echo " no issues found\n";
133 }
134 else {
135 $issues = array_values( array_unique( $issues ) );
136 $issues_total += count( $issues );
137 foreach ( $issues as $i ) {
138 echo " ISSUE: {$i}\n";
139 }
140 }
141 }
142
143 echo "\nTOTAL ISSUES: {$issues_total}\n";
144