diff --git a/templates/index.html b/templates/index.html
index e50e204..6f532a7 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -795,6 +795,75 @@
+
+
Orquestrador AI (Planner + Executor)
+
+
+
Status: Carregando...
+
+
+
+
+
+
+
+
+ Planner (Planejador)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Executor (Executor)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Terminal & Insights da IA
@@ -897,6 +966,10 @@
function initDashboard() {
fetchStats();
loadConfig();
+ loadOrchestratorStatus();
+ loadLLMModels().then(function() {
+ loadLLMConfig();
+ });
}
// Theme management
@@ -1111,6 +1184,156 @@
}
}
+ // ================== ORCHESTRATOR LLM CONFIG ==================
+
+ let availableModels = {};
+
+ async function loadOrchestratorStatus() {
+ try {
+ const res = await apiFetch('/api/orchestrator-status');
+ const data = await res.json();
+
+ const statusEl = document.getElementById('orchestrator-status');
+ if (statusEl) {
+ statusEl.innerHTML = 'Planner: ' + data.planner.name + ' | Executor: ' + data.executor.name + ' | Ferramentas: ' + data.available_tools;
+ }
+ } catch (e) {
+ const statusEl = document.getElementById('orchestrator-status');
+ if (statusEl) statusEl.textContent = 'Erro ao carregar';
+ }
+ }
+
+ async function loadLLMModels() {
+ try {
+ const res = await apiFetch('/api/llm-models');
+ availableModels = await res.json();
+ } catch (e) {
+ console.error('Erro ao carregar modelos:', e);
+ }
+ }
+
+ async function loadLLMConfig() {
+ try {
+ const res = await apiFetch('/api/llm-config');
+ const data = await res.json();
+
+ // Planner
+ const plannerProvider = document.getElementById('planner_provider');
+ const plannerModel = document.getElementById('planner_model');
+ if (plannerProvider) plannerProvider.value = data.planner.provider;
+ await loadPlannerModels();
+ if (plannerModel && data.planner.model) {
+ plannerModel.value = data.planner.model;
+ }
+
+ // Executor
+ const executorProvider = document.getElementById('executor_provider');
+ const executorModel = document.getElementById('executor_model');
+ if (executorProvider) executorProvider.value = data.executor.provider;
+ await loadExecutorModels();
+ if (executorModel && data.executor.model) {
+ executorModel.value = data.executor.model;
+ }
+ } catch (e) {
+ console.error('Erro ao carregar config LLM:', e);
+ }
+ }
+
+ function populateModelSelect(selectEl, models) {
+ if (!selectEl) return;
+ selectEl.innerHTML = '';
+
+ if (!models || models.length === 0) {
+ selectEl.innerHTML = '';
+ return;
+ }
+
+ models.forEach(function(model) {
+ const opt = document.createElement('option');
+ opt.value = model;
+ opt.textContent = model;
+ selectEl.appendChild(opt);
+ });
+ }
+
+ async function loadPlannerModels() {
+ const provider = document.getElementById('planner_provider')?.value;
+ const modelSelect = document.getElementById('planner_model');
+ if (!modelSelect) return;
+
+ modelSelect.innerHTML = '';
+
+ if (provider === 'ollama') {
+ const models = availableModels.models?.find(function(p) { return p.provider === 'ollama'; })?.models || [];
+ populateModelSelect(modelSelect, models.length > 0 ? models : ['qwen2.5-coder:1.5b', 'llama3.1:8b', 'codellama:13b']);
+ } else {
+ const fixedModels = {
+ gemini: ['gemini-2.5-flash', 'gemini-2.0-pro', 'gemini-1.5-flash'],
+ openai: ['gpt-4o', 'gpt-4-turbo', 'gpt-3.5-turbo'],
+ anthropic: ['claude-3-5-sonnet-20241022', 'claude-3-5-haiku-20241022', 'claude-3-opus-20240229']
+ };
+ populateModelSelect(modelSelect, fixedModels[provider] || []);
+ }
+ }
+
+ async function loadExecutorModels() {
+ const provider = document.getElementById('executor_provider')?.value;
+ const modelSelect = document.getElementById('executor_model');
+ if (!modelSelect) return;
+
+ modelSelect.innerHTML = '';
+
+ if (provider === 'ollama') {
+ const models = availableModels.models?.find(function(p) { return p.provider === 'ollama'; })?.models || [];
+ populateModelSelect(modelSelect, models.length > 0 ? models : ['qwen2.5-coder:1.5b', 'llama3.1:8b', 'codellama:13b']);
+ } else if (provider === 'gemini') {
+ populateModelSelect(modelSelect, ['gemini-2.5-flash', 'gemini-2.0-pro']);
+ } else {
+ populateModelSelect(modelSelect, []);
+ }
+ }
+
+ async function saveLLMConfig() {
+ const plannerProvider = document.getElementById('planner_provider')?.value;
+ const plannerModel = document.getElementById('planner_model')?.value;
+ const executorProvider = document.getElementById('executor_provider')?.value;
+ const executorModel = document.getElementById('executor_model')?.value;
+
+ try {
+ const res = await apiFetch('/api/llm-config', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ planner_provider: plannerProvider,
+ planner_model: plannerModel,
+ executor_provider: executorProvider,
+ executor_model: executorModel
+ })
+ });
+
+ if (res.ok) {
+ showToast('Config LLM salva! Planner: ' + plannerProvider + ', Executor: ' + executorProvider);
+ loadOrchestratorStatus();
+ } else {
+ throw new Error();
+ }
+ } catch (e) {
+ showToast('Erro ao salvar config LLM.', true);
+ }
+ }
+
+ async function syncCredentials() {
+ try {
+ const res = await apiFetch('/api/sync-credentials', {
+ method: 'POST'
+ });
+ const data = await res.json();
+ showToast('Credenciais sincronizadas! Services: ' + Object.keys(data.services || {}).length);
+ } catch (e) {
+ showToast('Erro ao sincronizar.', true);
+ }
+ }
+
async function testLLMSpeed() {
const btn = document.getElementById('btn-test-llm');
const originalContent = btn.innerHTML;