Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 732c7ad393 |
@@ -88,6 +88,14 @@ class SitiWebUpdater {
|
||||
|
||||
$this->get_repository_info(); // Get the repo info
|
||||
|
||||
if ( empty( $this->github_response ) || empty( $this->github_response['tag_name'] ) ) {
|
||||
return $transient;
|
||||
}
|
||||
|
||||
if ( empty( $checked[ $this->basename ] ) ) {
|
||||
return $transient;
|
||||
}
|
||||
|
||||
$out_of_date = version_compare( $this->github_response['tag_name'], $checked[ $this->basename ], 'gt' ); // Check if we're out of date
|
||||
|
||||
if( $out_of_date ) {
|
||||
@@ -114,11 +122,15 @@ class SitiWebUpdater {
|
||||
public function plugin_popup( $result, $action, $args ) {
|
||||
|
||||
if( ! empty( $args->slug ) ) { // If there is a slug
|
||||
|
||||
|
||||
if( $args->slug == current( explode( '/' , $this->basename ) ) ) { // And it's our slug
|
||||
|
||||
$this->get_repository_info(); // Get our repo info
|
||||
|
||||
if ( empty( $this->github_response ) || empty( $this->github_response['tag_name'] ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Set it to an array
|
||||
$plugin = array(
|
||||
'name' => $this->plugin["Name"],
|
||||
@@ -175,4 +187,4 @@ class SitiWebUpdater {
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
const modelSelect = document.getElementById('groq-ai-model-select');
|
||||
const refreshButton = document.getElementById('groq-ai-refresh-models');
|
||||
const refreshStatus = document.getElementById('groq-ai-refresh-models-status');
|
||||
const excludedModels = data.excludedModels || {};
|
||||
let currentModelValue = (modelSelect && modelSelect.dataset.currentModel) || data.currentModel || '';
|
||||
|
||||
function toggleProviderRows() {
|
||||
@@ -42,6 +43,32 @@
|
||||
});
|
||||
}
|
||||
|
||||
function isModelAllowed(model, providerOverride) {
|
||||
if (!model) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const provider = providerOverride || (providerSelect ? providerSelect.value : data.currentProvider);
|
||||
if (!provider || !excludedModels[provider]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return excludedModels[provider].indexOf(model) === -1;
|
||||
}
|
||||
|
||||
function ensureCurrentModelAllowed(providerOverride) {
|
||||
if (!currentModelValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isModelAllowed(currentModelValue, providerOverride)) {
|
||||
currentModelValue = '';
|
||||
if (modelSelect) {
|
||||
modelSelect.dataset.currentModel = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildModelOptions() {
|
||||
if (!modelSelect || !data.providers) {
|
||||
return;
|
||||
@@ -53,6 +80,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
ensureCurrentModelAllowed(provider);
|
||||
|
||||
const models = Array.isArray(providerData.models) ? providerData.models : [];
|
||||
const frag = document.createDocumentFragment();
|
||||
const placeholder = document.createElement('option');
|
||||
@@ -63,6 +92,9 @@
|
||||
|
||||
let hasCurrent = false;
|
||||
models.forEach(function (model) {
|
||||
if (!isModelAllowed(model, provider)) {
|
||||
return;
|
||||
}
|
||||
const option = document.createElement('option');
|
||||
option.value = model;
|
||||
option.textContent = model;
|
||||
@@ -72,7 +104,7 @@
|
||||
frag.appendChild(option);
|
||||
});
|
||||
|
||||
if (currentModelValue && !hasCurrent) {
|
||||
if (currentModelValue && !hasCurrent && isModelAllowed(currentModelValue, provider)) {
|
||||
const extraOption = document.createElement('option');
|
||||
extraOption.value = currentModelValue;
|
||||
extraOption.textContent = currentModelValue;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* Plugin Name: SitiAI Product Teksten
|
||||
* Description: Genereer productteksten met diverse AI-aanbieders rechtstreeks vanuit WooCommerce.
|
||||
* Version: 1.1.1
|
||||
* Version: 1.2.0
|
||||
* Author: SitiAI
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@ if ( ! defined( 'GROQ_AI_DEBUG_TRACE_ADDED' ) && defined( 'WP_DEBUG' ) && WP_DEB
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/includes/Core/class-groq-ai-service-container.php';
|
||||
require_once __DIR__ . '/includes/Core/class-groq-ai-model-exclusions.php';
|
||||
require_once __DIR__ . '/includes/Core/class-groq-ai-ajax-controller.php';
|
||||
require_once __DIR__ . '/includes/Contracts/interface-groq-ai-provider.php';
|
||||
require_once __DIR__ . '/includes/Providers/class-groq-ai-abstract-openai-provider.php';
|
||||
@@ -60,6 +61,7 @@ $updater->initialize();
|
||||
final class Groq_AI_Product_Text_Plugin {
|
||||
const OPTION_KEY = 'groq_ai_product_text_settings';
|
||||
const CONVERSATION_OPTION_KEY = 'groq_ai_product_text_conversations';
|
||||
const MODELS_CACHE_OPTION_KEY = 'groq_ai_product_text_models';
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
@@ -260,6 +262,10 @@ final class Groq_AI_Product_Text_Plugin {
|
||||
return $this->get_settings_manager()->is_response_format_compat_enabled( $settings );
|
||||
}
|
||||
|
||||
public function get_image_context_mode( $settings = null ) {
|
||||
return $this->get_settings_manager()->get_image_context_mode( $settings );
|
||||
}
|
||||
|
||||
public function should_use_response_format( Groq_AI_Provider_Interface $provider, $settings ) {
|
||||
return ! $this->is_response_format_compat_enabled( $settings ) && $provider->supports_response_format();
|
||||
}
|
||||
@@ -289,7 +295,78 @@ final class Groq_AI_Product_Text_Plugin {
|
||||
}
|
||||
|
||||
public function get_selected_model( Groq_AI_Provider_Interface $provider, $settings ) {
|
||||
return ! empty( $settings['model'] ) ? $settings['model'] : $provider->get_default_model();
|
||||
$provider_key = $provider->get_key();
|
||||
$model = ! empty( $settings['model'] ) ? $settings['model'] : '';
|
||||
$model = Groq_AI_Model_Exclusions::ensure_allowed( $provider_key, $model );
|
||||
|
||||
if ( '' === $model ) {
|
||||
$default = Groq_AI_Model_Exclusions::ensure_allowed( $provider_key, $provider->get_default_model() );
|
||||
if ( '' !== $default ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$available = Groq_AI_Model_Exclusions::filter_models( $provider_key, $provider->get_available_models() );
|
||||
if ( ! empty( $available ) ) {
|
||||
return $available[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function get_cached_models_for_provider( $provider ) {
|
||||
$provider = sanitize_key( (string) $provider );
|
||||
$cache = $this->get_models_cache();
|
||||
|
||||
return isset( $cache[ $provider ] ) ? $cache[ $provider ] : [];
|
||||
}
|
||||
|
||||
public function update_cached_models_for_provider( $provider, $models ) {
|
||||
$provider = sanitize_key( (string) $provider );
|
||||
$models = $this->sanitize_models_list( $models );
|
||||
|
||||
$cache = $this->get_models_cache();
|
||||
$cache[ $provider ] = $models;
|
||||
|
||||
update_option( self::MODELS_CACHE_OPTION_KEY, $cache );
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
private function get_models_cache() {
|
||||
$cache = get_option( self::MODELS_CACHE_OPTION_KEY, [] );
|
||||
|
||||
if ( ! is_array( $cache ) ) {
|
||||
$cache = [];
|
||||
}
|
||||
|
||||
foreach ( $cache as $provider => $models ) {
|
||||
$cache[ $provider ] = $this->sanitize_models_list( $models );
|
||||
}
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
private function sanitize_models_list( $models ) {
|
||||
if ( ! is_array( $models ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$models = array_map( 'sanitize_text_field', $models );
|
||||
$models = array_filter(
|
||||
$models,
|
||||
function ( $model ) {
|
||||
return '' !== $model;
|
||||
}
|
||||
);
|
||||
|
||||
$models = array_values( array_unique( $models ) );
|
||||
|
||||
if ( ! empty( $models ) ) {
|
||||
sort( $models, SORT_NATURAL | SORT_FLAG_CASE );
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
public function log_debug( $message, $context = [] ) {
|
||||
|
||||
@@ -136,6 +136,7 @@ class Groq_AI_Logs_Table extends WP_List_Table {
|
||||
|
||||
protected function column_created_at( $item ) {
|
||||
$date = esc_html( mysql2date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $item['created_at'] ) );
|
||||
$usage = $this->get_usage_meta( $item );
|
||||
$payload = [
|
||||
'created_at' => $item['created_at'],
|
||||
'user' => $this->column_default( $item, 'user_id' ),
|
||||
@@ -149,6 +150,7 @@ class Groq_AI_Logs_Table extends WP_List_Table {
|
||||
'prompt' => $item['prompt'],
|
||||
'response' => $item['response'],
|
||||
'error_message' => $item['error_message'],
|
||||
'image_context' => isset( $usage['image_context'] ) ? $usage['image_context'] : null,
|
||||
];
|
||||
$encoded = esc_attr( wp_json_encode( $payload ) );
|
||||
return sprintf(
|
||||
@@ -157,4 +159,14 @@ class Groq_AI_Logs_Table extends WP_List_Table {
|
||||
$date
|
||||
);
|
||||
}
|
||||
|
||||
private function get_usage_meta( $item ) {
|
||||
if ( empty( $item['usage_json'] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = json_decode( $item['usage_json'], true );
|
||||
|
||||
return is_array( $data ) ? $data : [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,15 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
[ $this, 'render_logs_page' ]
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
'options-general.php',
|
||||
__( 'Siti AI Prompt instellingen', 'groq-ai-product-text' ),
|
||||
__( 'Siti AI Prompt instellingen', 'groq-ai-product-text' ),
|
||||
'manage_options',
|
||||
'groq-ai-product-text-prompts',
|
||||
[ $this, 'render_prompt_settings_page' ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function hide_menu_links() {
|
||||
@@ -50,7 +59,8 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
?>
|
||||
<style>
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-modules"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-logs"] {
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-logs"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-prompts"] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
@@ -96,36 +106,51 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
);
|
||||
}
|
||||
|
||||
add_settings_section(
|
||||
'groq_ai_product_text_prompts',
|
||||
__( 'Prompt instellingen', 'groq-ai-product-text' ),
|
||||
'__return_false',
|
||||
'groq-ai-product-text-prompts'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'groq_ai_store_context',
|
||||
__( 'Winkelcontext', 'groq-ai-product-text' ),
|
||||
[ $this, 'render_store_context_field' ],
|
||||
'groq-ai-product-text',
|
||||
'groq_ai_product_text_general'
|
||||
'groq-ai-product-text-prompts',
|
||||
'groq_ai_product_text_prompts'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'groq_ai_default_prompt',
|
||||
__( 'Standaard prompt', 'groq-ai-product-text' ),
|
||||
[ $this, 'render_default_prompt_field' ],
|
||||
'groq-ai-product-text',
|
||||
'groq_ai_product_text_general'
|
||||
'groq-ai-product-text-prompts',
|
||||
'groq_ai_product_text_prompts'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'groq_ai_context_fields',
|
||||
__( 'Standaard productcontext', 'groq-ai-product-text' ),
|
||||
[ $this, 'render_context_fields_field' ],
|
||||
'groq-ai-product-text',
|
||||
'groq_ai_product_text_general'
|
||||
'groq-ai-product-text-prompts',
|
||||
'groq_ai_product_text_prompts'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'groq_ai_response_format_compat',
|
||||
__( 'Response-format compatibiliteit', 'groq-ai-product-text' ),
|
||||
[ $this, 'render_response_format_compat_field' ],
|
||||
'groq-ai-product-text',
|
||||
'groq_ai_product_text_general'
|
||||
'groq-ai-product-text-prompts',
|
||||
'groq_ai_product_text_prompts'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'groq_ai_image_context_mode',
|
||||
__( 'Afbeeldingen toevoegen', 'groq-ai-product-text' ),
|
||||
[ $this, 'render_image_context_mode_field' ],
|
||||
'groq-ai-product-text-prompts',
|
||||
'groq_ai_product_text_prompts'
|
||||
);
|
||||
|
||||
add_settings_section(
|
||||
@@ -144,6 +169,26 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
);
|
||||
}
|
||||
|
||||
public function render_image_context_mode_field() {
|
||||
$settings = $this->plugin->get_settings();
|
||||
$mode = isset( $settings['image_context_mode'] ) ? $settings['image_context_mode'] : 'url';
|
||||
$options = [
|
||||
'none' => __( 'Nee, geen afbeeldingen', 'groq-ai-product-text' ),
|
||||
'url' => __( 'Ja, voeg afbeeldings-URL’s toe aan de prompt', 'groq-ai-product-text' ),
|
||||
'base64' => __( 'Ja, verstuur afbeeldingen als Base64 (indien ondersteund)', 'groq-ai-product-text' ),
|
||||
];
|
||||
?>
|
||||
<select name="<?php echo esc_attr( $this->plugin->get_option_key() ); ?>[image_context_mode]">
|
||||
<?php foreach ( $options as $value => $label ) : ?>
|
||||
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $mode, $value ); ?>><?php echo esc_html( $label ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Bepaal hoe productafbeeldingen worden meegestuurd: helemaal niet, als URL’s in de prompt of als Base64-bijlagen voor modellen die beeldcontext ondersteunen.', 'groq-ai-product-text' ); ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function render_settings_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
@@ -154,6 +199,9 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Siti AI Productteksten', 'groq-ai-product-text' ); ?></h1>
|
||||
<p style="margin-bottom:16px;">
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=groq-ai-product-text-prompts' ) ); ?>" class="button button-primary">
|
||||
<?php esc_html_e( 'Prompt instellingen', 'groq-ai-product-text' ); ?>
|
||||
</a>
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=groq-ai-product-text-modules' ) ); ?>" class="button button-secondary">
|
||||
<?php esc_html_e( 'Ga naar modules', 'groq-ai-product-text' ); ?>
|
||||
</a>
|
||||
@@ -161,19 +209,14 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
<?php esc_html_e( 'Bekijk AI-logboek', 'groq-ai-product-text' ); ?>
|
||||
</a>
|
||||
</p>
|
||||
<p><?php esc_html_e( 'Kies je AI-aanbieder, stel de juiste API-sleutel en het gewenste model in en beheer optionele winkelcontext of standaard prompt.', 'groq-ai-product-text' ); ?></p>
|
||||
<p><?php esc_html_e( 'Kies je AI-aanbieder, stel de juiste API-sleutel en het gewenste model in.', 'groq-ai-product-text' ); ?></p>
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
settings_fields( 'groq_ai_product_text_group' );
|
||||
do_settings_sections( 'groq-ai-product-text' );
|
||||
submit_button();
|
||||
?>
|
||||
?>
|
||||
</form>
|
||||
<div class="groq-ai-prompt-helper">
|
||||
<h2><?php esc_html_e( 'Prompt generator', 'groq-ai-product-text' ); ?></h2>
|
||||
<p><?php esc_html_e( 'Gebruik deze velden om belangrijke informatie voor de AI bij te houden (bijvoorbeeld tone of voice, USP’s of doelgroepen). Voeg ze toe aan je prompt met kopiëren en plakken.', 'groq-ai-product-text' ); ?></p>
|
||||
<textarea class="large-text" rows="6" readonly><?php echo esc_textarea( $this->plugin->build_prompt_template_preview( $settings ) ); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
@@ -198,6 +241,37 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
<?php
|
||||
}
|
||||
|
||||
public function render_prompt_settings_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = $this->plugin->get_settings();
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Prompt instellingen', 'groq-ai-product-text' ); ?></h1>
|
||||
<p style="margin-bottom:16px;">
|
||||
<a href="<?php echo esc_url( admin_url( 'options-general.php?page=groq-ai-product-text' ) ); ?>" class="button button-secondary">
|
||||
<?php esc_html_e( 'Terug naar algemene instellingen', 'groq-ai-product-text' ); ?>
|
||||
</a>
|
||||
</p>
|
||||
<p><?php esc_html_e( 'Beheer hier de winkelcontext, standaardprompt, productcontext en response-format instellingen. Deze keuzes bepalen hoe elke prompt richting de AI wordt opgebouwd.', 'groq-ai-product-text' ); ?></p>
|
||||
<form action="options.php" method="post">
|
||||
<?php
|
||||
settings_fields( 'groq_ai_product_text_group' );
|
||||
do_settings_sections( 'groq-ai-product-text-prompts' );
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
<div class="groq-ai-prompt-helper">
|
||||
<h2><?php esc_html_e( 'Prompt generator', 'groq-ai-product-text' ); ?></h2>
|
||||
<p><?php esc_html_e( 'Gebruik deze velden om belangrijke informatie voor de AI bij te houden (bijvoorbeeld tone of voice, USP’s of doelgroepen). Voeg ze toe aan je prompt met kopiëren en plakken.', 'groq-ai-product-text' ); ?></p>
|
||||
<textarea class="large-text" rows="6" readonly><?php echo esc_textarea( $this->plugin->build_prompt_template_preview( $settings ) ); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function render_logs_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
@@ -244,6 +318,20 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
<span id="groq-ai-log-tokens-total">—</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="groq-ai-log-images">
|
||||
<div>
|
||||
<strong><?php esc_html_e( 'Afbeeldingsmodus', 'groq-ai-product-text' ); ?></strong>
|
||||
<span id="groq-ai-log-images-mode">—</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong><?php esc_html_e( 'Beschikbare afbeeldingen', 'groq-ai-product-text' ); ?></strong>
|
||||
<span id="groq-ai-log-images-available">—</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong><?php esc_html_e( 'Base64 meegestuurd', 'groq-ai-product-text' ); ?></strong>
|
||||
<span id="groq-ai-log-images-base64">—</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -256,6 +344,7 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
.groq-ai-log-fields label{display:block;margin-bottom:15px;}
|
||||
.groq-ai-log-fields textarea{width:100%;}
|
||||
.groq-ai-log-tokens{display:flex;gap:20px;margin-top:10px;}
|
||||
.groq-ai-log-images{display:flex;gap:20px;margin-top:10px;}
|
||||
.groq-ai-log-row{display:inline-block;}
|
||||
</style>
|
||||
<script>
|
||||
@@ -268,6 +357,9 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
const tokensPrompt=document.getElementById('groq-ai-log-tokens-prompt');
|
||||
const tokensCompletion=document.getElementById('groq-ai-log-tokens-completion');
|
||||
const tokensTotal=document.getElementById('groq-ai-log-tokens-total');
|
||||
const imagesMode=document.getElementById('groq-ai-log-images-mode');
|
||||
const imagesAvailable=document.getElementById('groq-ai-log-images-available');
|
||||
const imagesBase64=document.getElementById('groq-ai-log-images-base64');
|
||||
const meta=document.querySelector('.groq-ai-log-meta');
|
||||
function openModal(data){
|
||||
if(!data){return;}
|
||||
@@ -276,6 +368,22 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
if(tokensPrompt){tokensPrompt.textContent=Number.isFinite(data.tokens_prompt)?data.tokens_prompt:'—';}
|
||||
if(tokensCompletion){tokensCompletion.textContent=Number.isFinite(data.tokens_completion)?data.tokens_completion:'—';}
|
||||
if(tokensTotal){tokensTotal.textContent=Number.isFinite(data.tokens_total)?data.tokens_total:'—';}
|
||||
const imageContext=data.image_context||null;
|
||||
if(imagesMode){
|
||||
let mode='—';
|
||||
if(imageContext){
|
||||
mode=imageContext.effective_mode||imageContext.requested_mode||'—';
|
||||
}
|
||||
imagesMode.textContent=mode||'—';
|
||||
}
|
||||
if(imagesAvailable){
|
||||
const available=imageContext&&Number.isFinite(imageContext.available)?imageContext.available:'—';
|
||||
imagesAvailable.textContent=available;
|
||||
}
|
||||
if(imagesBase64){
|
||||
const base64=imageContext&&Number.isFinite(imageContext.base64_sent)?imageContext.base64_sent:'—';
|
||||
imagesBase64.textContent=base64;
|
||||
}
|
||||
if(meta){
|
||||
meta.textContent=(data.provider||'')+' • '+(data.model||'')+' • '+(data.post_title||'')+' • '+(data.status||'');
|
||||
}
|
||||
@@ -515,7 +623,7 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
}
|
||||
|
||||
public function enqueue_settings_assets( $hook ) {
|
||||
if ( ! in_array( $hook, [ 'settings_page_groq-ai-product-text', 'settings_page_groq-ai-product-text-modules' ], true ) ) {
|
||||
if ( ! in_array( $hook, [ 'settings_page_groq-ai-product-text', 'settings_page_groq-ai-product-text-modules', 'settings_page_groq-ai-product-text-prompts' ], true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -550,15 +658,19 @@ class Groq_AI_Product_Text_Settings_Page {
|
||||
'providerRows' => [],
|
||||
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
||||
'refreshNonce' => wp_create_nonce( 'groq_ai_refresh_models' ),
|
||||
'excludedModels' => Groq_AI_Model_Exclusions::get_all(),
|
||||
'placeholders' => [
|
||||
'selectModel' => __( 'Selecteer een model via "Live modellen ophalen"', 'groq-ai-product-text' ),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ( $this->provider_manager->get_providers() as $provider ) {
|
||||
$provider_key = $provider->get_key();
|
||||
$cached_models = $this->plugin->get_cached_models_for_provider( $provider_key );
|
||||
$cached_models = Groq_AI_Model_Exclusions::filter_models( $provider_key, $cached_models );
|
||||
$data['providers'][ $provider->get_key() ] = [
|
||||
'default_label' => sprintf( __( 'Gebruik standaardmodel (%s)', 'groq-ai-product-text' ), $provider->get_default_model() ),
|
||||
'models' => [],
|
||||
'models' => $cached_models,
|
||||
'supports_live' => $provider->supports_live_models(),
|
||||
];
|
||||
$data['providerRows'][ $provider->get_key() ] = 'groq_ai_api_key_' . $provider->get_key();
|
||||
|
||||
@@ -18,4 +18,6 @@ interface Groq_AI_Provider_Interface {
|
||||
public function fetch_live_models( $api_key );
|
||||
|
||||
public function supports_response_format();
|
||||
|
||||
public function supports_image_context();
|
||||
}
|
||||
|
||||
@@ -36,9 +36,43 @@ class Groq_AI_Ajax_Controller {
|
||||
$system_prompt = $prompt_builder->build_system_prompt( $settings, $conversation_id );
|
||||
$model = $this->plugin->get_selected_model( $provider, $settings );
|
||||
$context_fields = $prompt_builder->parse_context_fields_from_request( isset( $_POST['context_fields'] ) ? $_POST['context_fields'] : '', $settings );
|
||||
$product_context_text = $prompt_builder->build_product_context_block( $post_id, $context_fields );
|
||||
$image_context_mode = $this->plugin->get_image_context_mode( $settings );
|
||||
|
||||
if ( 'none' === $image_context_mode ) {
|
||||
$context_fields['images'] = false;
|
||||
}
|
||||
|
||||
$image_context_enabled = ! empty( $context_fields['images'] );
|
||||
$use_base64_payloads = $image_context_enabled && 'base64' === $image_context_mode && $provider->supports_image_context();
|
||||
$image_context_count = $image_context_enabled ? $prompt_builder->get_product_image_count( $post_id ) : 0;
|
||||
|
||||
$prompt_image_mode = 'none';
|
||||
if ( $image_context_enabled ) {
|
||||
if ( $use_base64_payloads ) {
|
||||
$prompt_image_mode = 'base64';
|
||||
} else {
|
||||
$prompt_image_mode = 'url';
|
||||
}
|
||||
|
||||
if ( 'base64' === $image_context_mode && ! $provider->supports_image_context() ) {
|
||||
$prompt_image_mode = 'url';
|
||||
}
|
||||
}
|
||||
|
||||
$product_context_text = $prompt_builder->build_product_context_block( $post_id, $context_fields, $prompt_image_mode );
|
||||
$image_context_payloads = [];
|
||||
if ( $use_base64_payloads ) {
|
||||
$image_context_payloads = $prompt_builder->get_product_image_payloads( $post_id );
|
||||
}
|
||||
$prompt_with_context = $prompt_builder->prepend_context_to_prompt( $prompt, $product_context_text );
|
||||
|
||||
$image_context_meta = [
|
||||
'requested_mode' => $image_context_mode,
|
||||
'effective_mode' => $prompt_image_mode,
|
||||
'available' => $image_context_count,
|
||||
'base64_sent' => $use_base64_payloads ? count( $image_context_payloads ) : 0,
|
||||
];
|
||||
|
||||
$response_format = null;
|
||||
$use_response_format = $this->plugin->should_use_response_format( $provider, $settings );
|
||||
if ( $use_response_format ) {
|
||||
@@ -57,6 +91,7 @@ class Groq_AI_Ajax_Controller {
|
||||
'temperature' => 0.7,
|
||||
'conversation_id' => $conversation_id,
|
||||
'response_format' => $response_format,
|
||||
'image_context' => $image_context_payloads,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -67,7 +102,9 @@ class Groq_AI_Ajax_Controller {
|
||||
'model' => $model,
|
||||
'prompt' => $final_prompt,
|
||||
'response' => '',
|
||||
'usage' => [],
|
||||
'usage' => [
|
||||
'image_context' => $image_context_meta,
|
||||
],
|
||||
'post_id' => $post_id,
|
||||
'status' => 'error',
|
||||
'error_message' => $result->get_error_message(),
|
||||
@@ -78,6 +115,10 @@ class Groq_AI_Ajax_Controller {
|
||||
|
||||
$response_text = $this->extract_content_text( $result );
|
||||
$response_usage = is_array( $result ) && isset( $result['usage'] ) ? $result['usage'] : [];
|
||||
if ( ! is_array( $response_usage ) ) {
|
||||
$response_usage = [];
|
||||
}
|
||||
$response_usage['image_context'] = $image_context_meta;
|
||||
|
||||
$response = $prompt_builder->parse_structured_response( $response_text, $settings );
|
||||
|
||||
@@ -143,7 +184,10 @@ class Groq_AI_Ajax_Controller {
|
||||
wp_send_json_error( [ 'message' => $result->get_error_message() ], 500 );
|
||||
}
|
||||
|
||||
wp_send_json_success( [ 'models' => array_values( array_unique( $result ) ) ] );
|
||||
$models = Groq_AI_Model_Exclusions::filter_models( $provider_key, array_values( array_unique( $result ) ) );
|
||||
$models = $this->plugin->update_cached_models_for_provider( $provider_key, $models );
|
||||
|
||||
wp_send_json_success( [ 'models' => $models ] );
|
||||
}
|
||||
|
||||
private function extract_content_text( $result ) {
|
||||
|
||||
155
includes/Core/class-groq-ai-model-exclusions.php
Normal file
155
includes/Core/class-groq-ai-model-exclusions.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
final class Groq_AI_Model_Exclusions {
|
||||
private const DEFAULT_EXCLUSIONS = [
|
||||
'groq' => [
|
||||
'playai-tts-arabic',
|
||||
'moonshotai/kimi-k2-instruct',
|
||||
'meta-llama/llama-prompt-guard-2-22m',
|
||||
'groq/compound-mini',
|
||||
'meta-llama/llama-guard-4-12b',
|
||||
'openai/gpt-oss-20b',
|
||||
'groq/compound',
|
||||
'openai/gpt-oss-safeguard-20b',
|
||||
'whisper-large-v3-turbo',
|
||||
'meta-llama/llama-4-scout-17b-16e-instruct',
|
||||
'allam-2-7b',
|
||||
'playai-tts',
|
||||
'moonshotai/kimi-k2-instruct-0905',
|
||||
'whisper-large-v3',
|
||||
'meta-llama/llama-prompt-guard-2-86m',
|
||||
],
|
||||
'openai' => [],
|
||||
'google' => [
|
||||
'embedding-gecko-001',
|
||||
'embedding-001',
|
||||
'text-embedding-004',
|
||||
'gemini-embedding-exp-03-07',
|
||||
'gemini-embedding-exp',
|
||||
'gemini-embedding-001',
|
||||
'gemini-2.5-flash-image-preview',
|
||||
'gemini-2.5-flash-image',
|
||||
'gemini-2.5-flash-preview-tts',
|
||||
'gemini-2.5-pro-preview-tts',
|
||||
'gemini-2.5-flash-native-audio-latest',
|
||||
'gemini-2.5-flash-native-audio-preview-09-2025',
|
||||
'gemini-2.5-computer-use-preview-10-2025',
|
||||
'gemini-3-pro-image-preview',
|
||||
'nano-banana-pro-preview',
|
||||
'gemini-robotics-er-1.5-preview',
|
||||
'deep-research-pro-preview-12-2025',
|
||||
'aqa',
|
||||
'imagen-4.0-generate-preview-06-06',
|
||||
'imagen-4.0-ultra-generate-preview-06-06',
|
||||
'imagen-4.0-generate-001',
|
||||
'imagen-4.0-ultra-generate-001',
|
||||
'imagen-4.0-fast-generate-001',
|
||||
'veo-2.0-generate-001',
|
||||
'veo-3.0-generate-001',
|
||||
'veo-3.0-fast-generate-001',
|
||||
'veo-3.1-generate-preview',
|
||||
'veo-3.1-fast-generate-preview',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Geeft de volledige lijst met uitgesloten modellen terug, gegroepeerd per aanbieder.
|
||||
*
|
||||
* @return array<string, string[]>
|
||||
*/
|
||||
public static function get_all() {
|
||||
$list = apply_filters( 'groq_ai_model_exclusions', self::DEFAULT_EXCLUSIONS );
|
||||
|
||||
if ( ! is_array( $list ) ) {
|
||||
$list = [];
|
||||
}
|
||||
|
||||
$normalized = [];
|
||||
foreach ( $list as $provider => $models ) {
|
||||
$normalized[ self::normalize_provider( $provider ) ] = self::normalize_models_list( $models );
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $provider
|
||||
* @return string[]
|
||||
*/
|
||||
public static function get_for_provider( $provider ) {
|
||||
$provider = self::normalize_provider( $provider );
|
||||
$list = self::get_all();
|
||||
|
||||
return isset( $list[ $provider ] ) ? $list[ $provider ] : [];
|
||||
}
|
||||
|
||||
public static function is_excluded( $provider, $model ) {
|
||||
if ( '' === $model ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$model = sanitize_text_field( $model );
|
||||
$provider = self::normalize_provider( $provider );
|
||||
$list = self::get_for_provider( $provider );
|
||||
|
||||
return in_array( $model, $list, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $provider
|
||||
* @param string $model
|
||||
* @return string
|
||||
*/
|
||||
public static function ensure_allowed( $provider, $model ) {
|
||||
if ( self::is_excluded( $provider, $model ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $provider
|
||||
* @param array $models
|
||||
* @return array
|
||||
*/
|
||||
public static function filter_models( $provider, $models ) {
|
||||
if ( ! is_array( $models ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$provider = self::normalize_provider( $provider );
|
||||
|
||||
return array_values(
|
||||
array_filter(
|
||||
array_map(
|
||||
'sanitize_text_field',
|
||||
$models
|
||||
),
|
||||
function ( $model ) use ( $provider ) {
|
||||
return ! self::is_excluded( $provider, $model );
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static function normalize_provider( $provider ) {
|
||||
return sanitize_key( (string) $provider );
|
||||
}
|
||||
|
||||
private static function normalize_models_list( $models ) {
|
||||
if ( ! is_array( $models ) ) {
|
||||
$models = [];
|
||||
}
|
||||
|
||||
$models = array_map( 'sanitize_text_field', $models );
|
||||
$models = array_filter(
|
||||
$models,
|
||||
function ( $model ) {
|
||||
return '' !== $model;
|
||||
}
|
||||
);
|
||||
|
||||
return array_values( array_unique( $models ) );
|
||||
}
|
||||
}
|
||||
@@ -138,4 +138,8 @@ abstract class Groq_AI_Abstract_OpenAI_Provider implements Groq_AI_Provider_Inte
|
||||
$field = $this->get_option_key();
|
||||
return isset( $settings[ $field ] ) ? $settings[ $field ] : '';
|
||||
}
|
||||
|
||||
public function supports_image_context() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ class Groq_AI_Provider_Google implements Groq_AI_Provider_Interface {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function supports_image_context() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function fetch_live_models( $api_key ) {
|
||||
$endpoint = add_query_arg(
|
||||
[ 'key' => $api_key, 'pageSize' => 100 ],
|
||||
@@ -92,15 +96,59 @@ class Groq_AI_Provider_Google implements Groq_AI_Provider_Interface {
|
||||
sprintf( 'https://generativelanguage.googleapis.com/v1beta/models/%s:generateContent', rawurlencode( $model ) )
|
||||
);
|
||||
|
||||
$image_context = isset( $args['image_context'] ) && is_array( $args['image_context'] ) ? $args['image_context'] : [];
|
||||
|
||||
$parts = [];
|
||||
|
||||
if ( '' !== trim( (string) $system_prompt ) ) {
|
||||
$parts[] = [
|
||||
'text' => $system_prompt,
|
||||
];
|
||||
}
|
||||
|
||||
if ( '' !== trim( (string) $prompt ) ) {
|
||||
$parts[] = [
|
||||
'text' => $prompt,
|
||||
];
|
||||
}
|
||||
|
||||
if ( ! empty( $image_context ) ) {
|
||||
foreach ( $image_context as $image ) {
|
||||
if ( empty( $image['data'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$label = isset( $image['label'] ) ? trim( (string) $image['label'] ) : '';
|
||||
if ( '' !== $label ) {
|
||||
$parts[] = [
|
||||
'text' => sprintf(
|
||||
/* translators: %s: image label */
|
||||
__( 'Contextafbeelding: %s', 'groq-ai-product-text' ),
|
||||
$label
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
$parts[] = [
|
||||
'inline_data' => [
|
||||
'mime_type' => ! empty( $image['mime_type'] ) ? $image['mime_type'] : 'image/jpeg',
|
||||
'data' => $image['data'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $parts ) ) {
|
||||
$parts[] = [
|
||||
'text' => $prompt,
|
||||
];
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'contents' => [
|
||||
[
|
||||
'role' => 'user',
|
||||
'parts' => [
|
||||
[
|
||||
'text' => $system_prompt . "\n\n" . $prompt,
|
||||
],
|
||||
],
|
||||
'parts' => $parts,
|
||||
],
|
||||
],
|
||||
'generationConfig' => [
|
||||
|
||||
@@ -125,7 +125,7 @@ class Groq_AI_Prompt_Builder {
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
public function build_product_context_block( $post_id, $fields ) {
|
||||
public function build_product_context_block( $post_id, $fields, $image_mode = 'url' ) {
|
||||
$post_id = absint( $post_id );
|
||||
|
||||
if ( ! $post_id ) {
|
||||
@@ -162,6 +162,13 @@ class Groq_AI_Prompt_Builder {
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $fields['images'] ) && 'url' === $image_mode ) {
|
||||
$images = $this->get_product_images_text( $post_id );
|
||||
if ( $images ) {
|
||||
$parts[] = sprintf( __( 'Afbeeldingen: %s', 'groq-ai-product-text' ), $images );
|
||||
}
|
||||
}
|
||||
|
||||
return implode( "\n\n", array_filter( $parts ) );
|
||||
}
|
||||
|
||||
@@ -350,4 +357,144 @@ class Groq_AI_Prompt_Builder {
|
||||
|
||||
return implode( '; ', $lines );
|
||||
}
|
||||
|
||||
private function get_product_images_text( $post_id ) {
|
||||
$image_ids = $this->get_product_image_ids( $post_id );
|
||||
|
||||
if ( empty( $image_ids ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$entries = [];
|
||||
|
||||
foreach ( $image_ids as $index => $attachment_id ) {
|
||||
$descriptor = $this->describe_product_image( $attachment_id, $index + 1 );
|
||||
if ( ! $descriptor ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entries[] = sprintf( '%s - %s', $descriptor['label'], $descriptor['url'] );
|
||||
}
|
||||
|
||||
return implode( '; ', array_filter( $entries ) );
|
||||
}
|
||||
|
||||
public function get_product_image_payloads( $post_id, $limit = 3, $max_filesize = 1572864 ) {
|
||||
$image_ids = array_slice( $this->get_product_image_ids( $post_id ), 0, max( 1, (int) $limit ) );
|
||||
|
||||
if ( empty( $image_ids ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$payloads = [];
|
||||
|
||||
foreach ( $image_ids as $index => $attachment_id ) {
|
||||
$descriptor = $this->describe_product_image( $attachment_id, $index + 1 );
|
||||
if ( ! $descriptor || empty( $descriptor['path'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $descriptor['path'];
|
||||
|
||||
if ( ! file_exists( $path ) || ! is_readable( $path ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filesize = filesize( $path );
|
||||
if ( false !== $filesize && $filesize > $max_filesize ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = @file_get_contents( $path );
|
||||
if ( false === $data ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$payloads[] = [
|
||||
'attachment_id' => $attachment_id,
|
||||
'label' => $descriptor['label'],
|
||||
'mime_type' => $descriptor['mime_type'],
|
||||
'data' => base64_encode( $data ),
|
||||
'url' => $descriptor['url'],
|
||||
];
|
||||
}
|
||||
|
||||
return $payloads;
|
||||
}
|
||||
|
||||
public function get_product_image_count( $post_id ) {
|
||||
return count( $this->get_product_image_ids( $post_id ) );
|
||||
}
|
||||
|
||||
private function get_product_image_ids( $post_id ) {
|
||||
$post_id = absint( $post_id );
|
||||
|
||||
if ( ! $post_id ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$image_ids = [];
|
||||
|
||||
$featured_id = get_post_thumbnail_id( $post_id );
|
||||
if ( $featured_id ) {
|
||||
$image_ids[] = $featured_id;
|
||||
}
|
||||
|
||||
$gallery_ids = [];
|
||||
if ( function_exists( 'wc_get_product' ) ) {
|
||||
$product = wc_get_product( $post_id );
|
||||
if ( $product ) {
|
||||
$gallery_ids = (array) $product->get_gallery_image_ids();
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $gallery_ids ) ) {
|
||||
$raw_gallery = get_post_meta( $post_id, '_product_image_gallery', true );
|
||||
if ( is_string( $raw_gallery ) && '' !== trim( $raw_gallery ) ) {
|
||||
$gallery_ids = array_filter( array_map( 'absint', explode( ',', $raw_gallery ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $gallery_ids ) ) {
|
||||
$image_ids = array_merge( $image_ids, $gallery_ids );
|
||||
}
|
||||
|
||||
return array_values( array_unique( array_filter( array_map( 'absint', $image_ids ) ) ) );
|
||||
}
|
||||
|
||||
private function describe_product_image( $attachment_id, $position ) {
|
||||
$url = wp_get_attachment_url( $attachment_id );
|
||||
|
||||
if ( ! $url ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$label = trim( (string) get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) );
|
||||
if ( '' === $label ) {
|
||||
$label = get_the_title( $attachment_id );
|
||||
}
|
||||
$label = trim( wp_strip_all_tags( (string) $label ) );
|
||||
|
||||
if ( '' === $label ) {
|
||||
$label = sprintf( __( 'Afbeelding %d', 'groq-ai-product-text' ), $position );
|
||||
}
|
||||
|
||||
$path = get_attached_file( $attachment_id );
|
||||
$mime = get_post_mime_type( $attachment_id );
|
||||
if ( ! $mime && $path ) {
|
||||
$mime = wp_get_image_mime( $path );
|
||||
}
|
||||
|
||||
if ( $mime && 0 !== strpos( $mime, 'image/' ) ) {
|
||||
$mime = '';
|
||||
}
|
||||
|
||||
return [
|
||||
'attachment_id' => $attachment_id,
|
||||
'label' => $label,
|
||||
'url' => esc_url_raw( $url ),
|
||||
'path' => $path,
|
||||
'mime_type' => $mime ? $mime : 'image/jpeg',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class Groq_AI_Settings_Manager {
|
||||
'google_api_key' => '',
|
||||
'context_fields' => $this->get_default_context_fields(),
|
||||
'modules' => $this->get_default_modules_settings(),
|
||||
'image_context_mode' => 'url',
|
||||
'response_format_compat' => false,
|
||||
];
|
||||
|
||||
@@ -44,6 +45,19 @@ class Groq_AI_Settings_Manager {
|
||||
$settings = wp_parse_args( (array) $settings, $defaults );
|
||||
$settings['context_fields'] = $this->normalize_context_fields( isset( $settings['context_fields'] ) ? $settings['context_fields'] : [] );
|
||||
$settings['modules'] = $this->sanitize_modules_settings( isset( $settings['modules'] ) ? $settings['modules'] : [] );
|
||||
$settings['model'] = Groq_AI_Model_Exclusions::ensure_allowed( $settings['provider'], isset( $settings['model'] ) ? $settings['model'] : '' );
|
||||
|
||||
$image_mode = isset( $settings['image_context_mode'] ) ? sanitize_text_field( $settings['image_context_mode'] ) : 'url';
|
||||
if ( 'none' === $image_mode ) {
|
||||
$settings['context_fields']['images'] = false;
|
||||
$settings['image_context_mode'] = 'none';
|
||||
} elseif ( in_array( $image_mode, [ 'url', 'base64' ], true ) ) {
|
||||
$settings['context_fields']['images'] = true;
|
||||
$settings['image_context_mode'] = $image_mode;
|
||||
} else {
|
||||
$settings['context_fields']['images'] = true;
|
||||
$settings['image_context_mode'] = 'url';
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
@@ -65,6 +79,7 @@ class Groq_AI_Settings_Manager {
|
||||
'google_api_key' => '',
|
||||
'context_fields' => $this->get_default_context_fields(),
|
||||
'modules' => $this->get_default_modules_settings(),
|
||||
'image_context_mode' => 'url',
|
||||
'response_format_compat' => false,
|
||||
];
|
||||
|
||||
@@ -80,16 +95,34 @@ class Groq_AI_Settings_Manager {
|
||||
$provider = 'groq';
|
||||
}
|
||||
|
||||
$model = sanitize_text_field( $input['model'] );
|
||||
$model = Groq_AI_Model_Exclusions::ensure_allowed( $provider, $model );
|
||||
|
||||
$image_mode = isset( $input['image_context_mode'] ) ? sanitize_text_field( $input['image_context_mode'] ) : $defaults['image_context_mode'];
|
||||
$allowed_modes = [ 'none', 'base64', 'url' ];
|
||||
if ( ! in_array( $image_mode, $allowed_modes, true ) ) {
|
||||
$image_mode = 'url';
|
||||
}
|
||||
|
||||
$context_fields = $this->normalize_context_fields( $context_posted ? $raw_input['context_fields'] : $defaults['context_fields'] );
|
||||
|
||||
if ( 'none' === $image_mode ) {
|
||||
$context_fields['images'] = false;
|
||||
} else {
|
||||
$context_fields['images'] = true;
|
||||
}
|
||||
|
||||
return [
|
||||
'provider' => $provider,
|
||||
'model' => sanitize_text_field( $input['model'] ),
|
||||
'model' => $model,
|
||||
'store_context' => sanitize_textarea_field( $input['store_context'] ),
|
||||
'default_prompt' => sanitize_textarea_field( $input['default_prompt'] ),
|
||||
'groq_api_key' => sanitize_text_field( $input['groq_api_key'] ),
|
||||
'openai_api_key' => sanitize_text_field( $input['openai_api_key'] ),
|
||||
'google_api_key' => sanitize_text_field( $input['google_api_key'] ),
|
||||
'response_format_compat' => ! empty( $raw_input['response_format_compat'] ),
|
||||
'context_fields' => $this->normalize_context_fields( $context_posted ? $raw_input['context_fields'] : $defaults['context_fields'] ),
|
||||
'image_context_mode' => $image_mode,
|
||||
'context_fields' => $context_fields,
|
||||
'modules' => $this->sanitize_modules_settings(
|
||||
$modules_posted ? $raw_input['modules'] : [],
|
||||
$defaults['modules'],
|
||||
@@ -122,6 +155,11 @@ class Groq_AI_Settings_Manager {
|
||||
'description' => __( 'Voeg gestructureerde productattributen toe (zoals kleur, maat, materiaal).', 'groq-ai-product-text' ),
|
||||
'default' => false,
|
||||
],
|
||||
'images' => [
|
||||
'label' => __( 'Afbeeldingen', 'groq-ai-product-text' ),
|
||||
'description' => __( 'Voeg een korte lijst toe met productafbeeldingen (beschrijving + URL).', 'groq-ai-product-text' ),
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -219,6 +257,17 @@ class Groq_AI_Settings_Manager {
|
||||
return max( 200, min( 2000, $value ) );
|
||||
}
|
||||
|
||||
public function get_image_context_mode( $settings = null ) {
|
||||
if ( null === $settings ) {
|
||||
$settings = $this->all();
|
||||
}
|
||||
|
||||
$mode = isset( $settings['image_context_mode'] ) ? sanitize_text_field( $settings['image_context_mode'] ) : 'url';
|
||||
$allowed_modes = [ 'none', 'base64', 'url' ];
|
||||
|
||||
return in_array( $mode, $allowed_modes, true ) ? $mode : 'url';
|
||||
}
|
||||
|
||||
public function is_response_format_compat_enabled( $settings = null ) {
|
||||
if ( null === $settings ) {
|
||||
$settings = $this->all();
|
||||
|
||||
Reference in New Issue
Block a user