PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.3
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / includes / core / AI / Providers / SchemaTranslator.php

SchemaTranslator.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.3, at includes/core/AI/Providers/SchemaTranslator.php

79 lines 2.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * SchemaTranslator — adapts ability JSON Schemas per provider.
4 *
5 * Anthropic and OpenAI accept the ability schemas as-is. Gemini's
6 * functionDeclarations accept only a restricted OpenAPI-style subset, so
7 * unsupported keywords are stripped recursively.
8 *
9 * @package WPFunnels\AI
10 * @since 3.13.0
11 */
12
13 namespace WPFunnels\AI\Providers;
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Class SchemaTranslator
19 */
20 class SchemaTranslator {
21
22 /**
23 * Keys Gemini accepts inside a schema node.
24 */
25 private const GEMINI_ALLOWED = [ 'type', 'description', 'properties', 'required', 'items', 'enum', 'nullable', 'format' ];
26
27 /**
28 * Formats Gemini accepts.
29 */
30 private const GEMINI_ALLOWED_FORMATS = [ 'enum', 'date-time' ];
31
32 /**
33 * Sanitize a JSON Schema for Gemini functionDeclarations.parameters.
34 *
35 * @param array $schema Ability input schema.
36 * @return array
37 */
38 public static function forGemini( $schema ) {
39 $clean = [];
40
41 foreach ( (array) $schema as $key => $value ) {
42 if ( ! in_array( $key, self::GEMINI_ALLOWED, true ) ) {
43 continue;
44 }
45 if ( 'format' === $key && ! in_array( $value, self::GEMINI_ALLOWED_FORMATS, true ) ) {
46 continue;
47 }
48 if ( 'properties' === $key && is_array( $value ) ) {
49 $props = [];
50 foreach ( $value as $prop => $prop_schema ) {
51 $props[ $prop ] = is_array( $prop_schema ) ? self::forGemini( $prop_schema ) : $prop_schema;
52 }
53 // Gemini rejects empty properties objects on type:object nodes.
54 if ( ! empty( $props ) ) {
55 $clean['properties'] = $props;
56 }
57 continue;
58 }
59 if ( 'items' === $key && is_array( $value ) ) {
60 $clean['items'] = self::forGemini( $value );
61 continue;
62 }
63 $clean[ $key ] = $value;
64 }
65
66 // An object schema with no properties confuses Gemini — degrade gracefully.
67 if ( isset( $clean['type'] ) && 'object' === $clean['type'] && empty( $clean['properties'] ) ) {
68 $clean['properties'] = [
69 '_' => [
70 'type' => 'string',
71 'description' => 'Unused placeholder.',
72 ],
73 ];
74 }
75
76 return $clean;
77 }
78 }
79