feat: add Google Gemini provider option to bot-config AI tab
- Add Gemini option to ai_provider select (alongside OpenAI/Mock) - Show/hide OpenAI vs Gemini fields dynamically via aiProviderChange() - Add gemini_api_key and gemini_model fields to the form - Add openai_api_key field in bot-config (per-company override) - Save handler now persists gemini_api_key, gemini_model, openai_api_key Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
845dd08a3a
commit
4c93c20482
@@ -2513,8 +2513,20 @@ HTML;
|
||||
$commands = $config['commands'] ?? [];
|
||||
$menus = $config['menus'] ?? [];
|
||||
$flows = $config['flows'] ?? [];
|
||||
$aiProviderOpenai = $aiProviderVal === 'openai' ? ' selected' : '';
|
||||
$aiProviderMock = $aiProviderVal === 'mock' ? ' selected' : '';
|
||||
$aiProviderOpenai = $aiProviderVal === 'openai' ? ' selected' : '';
|
||||
$aiProviderGemini = $aiProviderVal === 'gemini' ? ' selected' : '';
|
||||
$aiProviderMock = $aiProviderVal === 'mock' ? ' selected' : '';
|
||||
$openaiApiKeyVal = self::h($config['openai_api_key'] ?? '');
|
||||
$geminiApiKeyVal = self::h($config['gemini_api_key'] ?? '');
|
||||
$geminiModelVal = $config['gemini_model'] ?? 'gemini-2.0-flash';
|
||||
$geminiModelF20 = $geminiModelVal === 'gemini-2.0-flash' ? ' selected' : '';
|
||||
$geminiModelF15 = $geminiModelVal === 'gemini-1.5-flash' ? ' selected' : '';
|
||||
$geminiModelP15 = $geminiModelVal === 'gemini-1.5-pro' ? ' selected' : '';
|
||||
// Determine which provider panel to show initially
|
||||
$showOpenai = ($aiProviderVal === 'openai' || $aiProviderVal === '')
|
||||
? 'display:flex;flex-direction:column;gap:10px' : 'display:none';
|
||||
$showGemini = $aiProviderVal === 'gemini'
|
||||
? 'display:flex;flex-direction:column;gap:10px' : 'display:none';
|
||||
|
||||
// Per-category config HTML
|
||||
$perTypeConfig = $config['per_type'] ?? [];
|
||||
@@ -2892,23 +2904,53 @@ HTML;
|
||||
<div class="tab-content" id="tab-ai">
|
||||
<div class="card-h">🤖 Inteligencia Artificial</div>
|
||||
<div class="form-group">
|
||||
<label>Proveedor (sobrescribe el global)</label>
|
||||
<select name="ai_provider">
|
||||
<label>Proveedor</label>
|
||||
<select name="ai_provider" onchange="aiProviderChange(this.value)">
|
||||
<option value="">Usar configuración global</option>
|
||||
<option value="openai"{$aiProviderOpenai}>OpenAI</option>
|
||||
<option value="openai"{$aiProviderOpenai}>OpenAI (GPT)</option>
|
||||
<option value="gemini"{$aiProviderGemini}>Google Gemini</option>
|
||||
<option value="mock"{$aiProviderMock}>Mock (simulado)</option>
|
||||
</select>
|
||||
<div style="font-size:11px;color:#7a8291;margin-top:3px">Si no se selecciona, usa el proveedor de Configuración General</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>Modelo</label>
|
||||
<select name="ai_model">
|
||||
<option value="gpt-4o-mini"{$aiModelMini}>GPT-4o Mini</option>
|
||||
<option value="gpt-4o"{$aiModel4o}>GPT-4o</option>
|
||||
<option value="gpt-3.5-turbo"{$aiModel35}>GPT-3.5 Turbo</option>
|
||||
</select>
|
||||
|
||||
<!-- OpenAI fields -->
|
||||
<div id="ai-openai-fields" style="{$showOpenai}">
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>API Key OpenAI</label>
|
||||
<input type="password" name="openai_api_key" value="{$openaiApiKeyVal}" placeholder="sk-...">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Modelo</label>
|
||||
<select name="ai_model">
|
||||
<option value="gpt-4o-mini"{$aiModelMini}>GPT-4o Mini</option>
|
||||
<option value="gpt-4o"{$aiModel4o}>GPT-4o</option>
|
||||
<option value="gpt-3.5-turbo"{$aiModel35}>GPT-3.5 Turbo</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gemini fields -->
|
||||
<div id="ai-gemini-fields" style="{$showGemini}">
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>API Key Google Gemini</label>
|
||||
<input type="password" name="gemini_api_key" value="{$geminiApiKeyVal}" placeholder="AIza...">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Modelo Gemini</label>
|
||||
<select name="gemini_model">
|
||||
<option value="gemini-2.0-flash"{$geminiModelF20}>Gemini 2.0 Flash</option>
|
||||
<option value="gemini-1.5-flash"{$geminiModelF15}>Gemini 1.5 Flash</option>
|
||||
<option value="gemini-1.5-pro"{$geminiModelP15}>Gemini 1.5 Pro</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row" style="margin-top:4px">
|
||||
<div class="form-group">
|
||||
<label>Temperatura ({$aiTempVal})</label>
|
||||
<input type="range" name="ai_temperature" min="0" max="1" step="0.1" value="{$aiTempVal}" oninput="this.previousElementSibling.textContent='Temperatura ('+this.value+')'">
|
||||
@@ -3214,6 +3256,17 @@ function addFlowCard() {
|
||||
container.lastElementChild.scrollIntoView({behavior:'smooth'});
|
||||
}
|
||||
|
||||
function aiProviderChange(v) {
|
||||
const oai = document.getElementById('ai-openai-fields');
|
||||
const gem = document.getElementById('ai-gemini-fields');
|
||||
if (oai) oai.style.display = (v === 'openai' || v === '') ? 'flex' : 'none';
|
||||
if (oai) oai.style.flexDirection = 'column';
|
||||
if (oai) oai.style.gap = '10px';
|
||||
if (gem) gem.style.display = v === 'gemini' ? 'flex' : 'none';
|
||||
if (gem) gem.style.flexDirection = 'column';
|
||||
if (gem) gem.style.gap = '10px';
|
||||
}
|
||||
|
||||
function updatePreview() {
|
||||
const g = document.getElementById('prevGreeting')?.value || '';
|
||||
const f = document.getElementById('prevFallback')?.value || '';
|
||||
|
||||
+7
-1
@@ -474,8 +474,14 @@ $routes = [
|
||||
$aiTemp = trim($_POST['ai_temperature'] ?? '');
|
||||
if ($aiTemp !== '') $config['ai_temperature'] = (float)$aiTemp;
|
||||
$aiProvider = trim($_POST['ai_provider'] ?? '');
|
||||
if ($aiProvider !== '') $config['ai_provider'] = $aiProvider;
|
||||
if ($aiProvider !== '') $config['ai_provider'] = $aiProvider; else unset($config['ai_provider']);
|
||||
$config['ai_for_media'] = isset($_POST['ai_for_media']);
|
||||
$openaiKey = trim($_POST['openai_api_key'] ?? '');
|
||||
if ($openaiKey !== '') $config['openai_api_key'] = $openaiKey;
|
||||
$geminiKey = trim($_POST['gemini_api_key'] ?? '');
|
||||
if ($geminiKey !== '') $config['gemini_api_key'] = $geminiKey;
|
||||
$geminiModel = trim($_POST['gemini_model'] ?? '');
|
||||
if ($geminiModel !== '') $config['gemini_model'] = $geminiModel;
|
||||
|
||||
// Per-category menus — merge sobre la config existente para no perder flows/commands por categoría
|
||||
$perTypeMenus = $_POST['per_type_menu'] ?? [];
|
||||
|
||||
Reference in New Issue
Block a user