diff --git a/frontend/index.html b/frontend/index.html index 749e6b1..98fff9e 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -347,13 +347,14 @@ ${!S.ociCfg.length?'

Nenhuma credencia

-`} +`} async function sOci(){const fd=new FormData();fd.append('tenancy_name',document.getElementById('otn').value);fd.append('tenancy_ocid',document.getElementById('oto').value); fd.append('user_ocid',document.getElementById('ouo').value);fd.append('fingerprint',document.getElementById('ofp').value); fd.append('region',document.getElementById('org').value);fd.append('compartment_id',document.getElementById('ocp').value); const sk=document.getElementById('osk').files[0];if(!sk)return sm('om','Selecione a chave privada','e');fd.append('private_key',sk); const pk=document.getElementById('opk').files[0];if(pk)fd.append('public_key',pk); - try{await $api('/oci/config',{method:'POST',body:fd,headers:{}});S.ociCfg=await $api('/oci/configs');sm('om','✅ Credencial salva com sucesso!','s');R()}catch(e){sm('om',e.message,'e')}} + const btn=document.getElementById('obtn');btn.disabled=true;btn.textContent='Salvando...';sm('om',' Salvando credencial...','i'); + try{await $api('/oci/config',{method:'POST',body:fd,headers:{}});S.ociCfg=await $api('/oci/configs');sm('om','✅ Credencial salva com sucesso!','s');R()}catch(e){sm('om',e.message,'e');btn.disabled=false;btn.textContent='Salvar Credencial'}} async function tOci(id){try{const d=await $api('/oci/test/'+id,{method:'POST'});alert(d.status==='success'?'✅ Conexão OK!':'❌ '+d.message)}catch(e){alert(e.message)}} async function dOci(id){if(!confirm('Excluir credencial?'))return;await $api('/oci/configs/'+id,{method:'DELETE'});S.ociCfg=await $api('/oci/configs');R()} @@ -384,8 +385,8 @@ ${S.ociCfg.map(c=>``).join('')
-`} -async function sGenai(){try{await $api('/genai/config',{method:'POST',body:{ +`} +async function sGenai(){const btn=document.getElementById('gbtn');btn.disabled=true;btn.textContent='Salvando...';sm('gm',' Salvando modelo...','i');try{await $api('/genai/config',{method:'POST',body:{ name:document.getElementById('gname').value||'default', oci_config_id:document.getElementById('goci').value,model_id:document.getElementById('gmod').value, model_ocid:document.getElementById('gocid').value||null, @@ -395,12 +396,12 @@ async function sGenai(){try{await $api('/genai/config',{method:'POST',body:{ top_p:parseFloat(document.getElementById('gtp').value),top_k:parseInt(document.getElementById('gtk').value), frequency_penalty:parseFloat(document.getElementById('gfp').value),presence_penalty:parseFloat(document.getElementById('gpp').value), is_default:S.genaiCfg.length===0}}); - S.genaiCfg=await $api('/genai/configs');sm('gm','✅ Modelo salvo com sucesso!','s');R()}catch(e){sm('gm',e.message,'e')}} + S.genaiCfg=await $api('/genai/configs');sm('gm','✅ Modelo salvo com sucesso!','s');R()}catch(e){sm('gm',e.message,'e');btn.disabled=false;btn.textContent='Salvar Modelo'}} async function tGenai(id){try{const d=await $api('/genai/test/'+id,{method:'POST'});alert(d.status==='success'?'✅ '+d.message+'\n'+d.response:'❌ '+d.message)}catch(e){alert(e.message)}} async function dGenai(id){if(!confirm('Excluir modelo?'))return;await $api('/genai/configs/'+id,{method:'DELETE'});S.genaiCfg=await $api('/genai/configs');R()} /* ── MCP Servers ── */ -function mcpTypeFields(){const t=document.getElementById('mt')?.value; +function mcpTypeFields(){const t=document.querySelector('input[name="mt"]:checked')?.value; document.querySelectorAll('.mcp-f').forEach(el=>{el.style.display='none'}); if(t==='stdio'){document.getElementById('mf-cmd').style.display='';document.getElementById('mf-args').style.display=''} if(t==='sse')document.getElementById('mf-url').style.display=''; @@ -421,12 +422,13 @@ ${m.command?`
Comando: ${m.url?`
URL: ${m.url}
`:''} ${m.module_path?`
Módulo: ${m.module_path}
`:''}
ADB: ${adb?`${adb.config_name}`:'Nenhum'}
+
- + -
`}).join('') +`}).join('') :'

Nenhum MCP server registrado.

'}
➕ Registrar Novo Server
Configure um novo servidor MCP. Os campos se ajustam ao tipo selecionado.
@@ -448,19 +450,21 @@ ${m.module_path?`
Módulo:
Opcional — o MCP server poderá usar este banco como ferramenta.
-`} -async function sMcp(){try{let args=null;const a=document.getElementById('margs')?.value;if(a)try{args=JSON.parse(a)}catch(e){} +`} +async function sMcp(){const btn=document.getElementById('mcbtn');btn.disabled=true;btn.textContent='Registrando...';sm('mcm',' Registrando servidor...','i');try{let args=null;const a=document.getElementById('margs')?.value;if(a)try{args=JSON.parse(a)}catch(e){} const mt=document.querySelector('input[name="mt"]:checked')?.value||'stdio'; await $api('/mcp/servers',{method:'POST',body:{name:document.getElementById('mn').value,description:document.getElementById('md').value, server_type:mt,command:document.getElementById('mcmd')?.value||null,url:document.getElementById('murl')?.value||null,args, linked_adb_id:document.getElementById('madb').value||null}}); - S.mcpSvr=await $api('/mcp/servers');sm('mcm','✅ Registrado!','s');R()}catch(e){sm('mcm',e.message,'e')}} + S.mcpSvr=await $api('/mcp/servers');sm('mcm','✅ Registrado!','s');R()}catch(e){sm('mcm',e.message,'e');btn.disabled=false;btn.textContent='Registrar Server'}} async function tgMcp(id){await $api('/mcp/servers/'+id+'/toggle',{method:'PUT'});S.mcpSvr=await $api('/mcp/servers');R()} async function dMcp(id){if(!confirm('Excluir server?'))return;await $api('/mcp/servers/'+id,{method:'DELETE'});S.mcpSvr=await $api('/mcp/servers');R()} -async function uMcp(id){const fd=new FormData();const f=document.getElementById('muf_'+id)?.files[0];if(!f)return alert('Selecione um arquivo .py'); - fd.append('file',f);try{await $api('/mcp/servers/'+id+'/upload',{method:'POST',body:fd,headers:{}});alert('Upload realizado!')}catch(e){alert(e.message)}} +async function uMcp(id){const fd=new FormData();const f=document.getElementById('muf_'+id)?.files[0];if(!f)return sm('mcpm_'+id,'Selecione um arquivo .py','e'); + fd.append('file',f);const btn=document.getElementById('mub_'+id);btn.disabled=true;btn.textContent='Enviando...';sm('mcpm_'+id,' Enviando arquivo...','i'); + try{await $api('/mcp/servers/'+id+'/upload',{method:'POST',body:fd,headers:{}});S.mcpSvr=await $api('/mcp/servers');sm('mcpm_'+id,'✅ Upload realizado!','s');R()}catch(e){sm('mcpm_'+id,e.message,'e');btn.disabled=false;btn.textContent='Upload .py'}} async function lnkMcp(id){const aid=document.getElementById('mlnk_'+id)?.value||''; - try{await $api('/mcp/servers/'+id+'/link-adb?adb_id='+aid,{method:'PUT'});S.mcpSvr=await $api('/mcp/servers');alert('Vinculado!');R()}catch(e){alert(e.message)}} + const btn=document.getElementById('mlb_'+id);btn.disabled=true;btn.textContent='Vinculando...'; + try{await $api('/mcp/servers/'+id+'/link-adb?adb_id='+aid,{method:'PUT'});S.mcpSvr=await $api('/mcp/servers');sm('mcpm_'+id,'✅ '+(aid?'Vinculado ao ADB!':'ADB desvinculado!'),'s');R()}catch(e){sm('mcpm_'+id,e.message,'e');btn.disabled=false;btn.textContent='Vincular ADB'}} /* ── ADB Vector ── */ function rADB(){return`
🗄️ Conexões Registradas
@@ -483,22 +487,23 @@ ${!S.adbCfg.length?'

Nenhuma conexão

Modelo OCI GenAI para gerar vetores.
- -
📤 Upload Wallet
+
+
📤 Upload Wallet
-
`} -async function sAdb(){try{await $api('/adb/config',{method:'POST',body:{config_name:document.getElementById('an').value,dsn:document.getElementById('adsn').value, +`} +async function sAdb(){const btn=document.getElementById('abtn');btn.disabled=true;btn.textContent='Salvando...';sm('am',' Salvando conexão...','i');try{await $api('/adb/config',{method:'POST',body:{config_name:document.getElementById('an').value,dsn:document.getElementById('adsn').value, username:document.getElementById('auser').value,password:document.getElementById('apw').value, wallet_password:document.getElementById('awpw').value||null,table_name:document.getElementById('atbl').value, genai_config_id:document.getElementById('agcfg').value||null, embedding_model_id:document.getElementById('aemb').value||'cohere.embed-multilingual-v3.0'}}); - S.adbCfg=await $api('/adb/configs');sm('am','✅ Conexão salva!','s');R()}catch(e){sm('am',e.message,'e')}} + S.adbCfg=await $api('/adb/configs');sm('am','✅ Conexão salva!','s');R()}catch(e){sm('am',e.message,'e');btn.disabled=false;btn.textContent='Salvar Conexão'}} async function tAdb(id){try{const d=await $api('/adb/test/'+id,{method:'POST'});alert(d.status==='success'?'✅ '+d.message:'❌ '+d.message)}catch(e){alert(e.message)}} async function dAdb(id){if(!confirm('Excluir conexão?'))return;await $api('/adb/configs/'+id,{method:'DELETE'});S.adbCfg=await $api('/adb/configs');R()} -async function uWallet(){const fd=new FormData();const f=document.getElementById('awf').files[0];if(!f)return alert('Selecione wallet ZIP'); - fd.append('wallet',f);const id=document.getElementById('awsel').value;if(!id)return alert('Selecione conexão'); - try{const d=await $api('/adb/'+id+'/upload-wallet',{method:'POST',body:fd,headers:{}});alert('Wallet enviada! Arquivos: '+d.files.join(', '))}catch(e){alert(e.message)}} +async function uWallet(){const fd=new FormData();const f=document.getElementById('awf').files[0];if(!f)return sm('wm','Selecione um arquivo wallet ZIP.','e'); + fd.append('wallet',f);const id=document.getElementById('awsel').value;if(!id)return sm('wm','Selecione uma conexão ADB.','e'); + const btn=document.getElementById('wbtn');btn.disabled=true;btn.textContent='Enviando...';sm('wm',' Enviando wallet...','i'); + try{const d=await $api('/adb/'+id+'/upload-wallet',{method:'POST',body:fd,headers:{}});S.adbCfg=await $api('/adb/configs');sm('wm','✅ Wallet enviada! Arquivos: '+d.files.join(', '),'s');R()}catch(e){sm('wm',e.message,'e');btn.disabled=false;btn.textContent='Upload Wallet'}} async function ensureTable(id){try{const d=await $api('/adb/'+id+'/ensure-table',{method:'POST'});alert('Tabela criada/verificada: '+d.table)}catch(e){alert('Erro: '+e.message)}} /* ── Embeddings ── */ @@ -515,12 +520,12 @@ function rEmbeddings(){
Gere embeddings a partir de relatórios CIS. Cada seção (IAM, Networking, etc.) gera um embedding separado.
- +
📄 Upload de Arquivo
Faça upload de um arquivo .txt para gerar embeddings automaticamente (chunking por parágrafos).
-
`} +`} async function loadEmbs(){const vid=document.getElementById('elsel').value;if(!vid)return; try{const d=await $api('/embeddings/'+vid+'/list'); @@ -533,13 +538,15 @@ async function loadEmbs(){const vid=document.getElementById('elsel').value;if(!v catch(e){document.getElementById('emb-list').innerHTML='
Erro: '+e.message+'
'}} async function embedReport(){const vid=document.getElementById('ersel').value;const rid=document.getElementById('errpt').value; - if(!vid||!rid)return alert('Selecione conexão ADB e relatório'); - try{const d=await $api('/embeddings/report/'+rid,{method:'POST',body:{adb_config_id:vid}});sm('erm','✅ '+d.message,'s')}catch(e){sm('erm',e.message,'e')}} + if(!vid||!rid)return sm('erm','Selecione conexão ADB e relatório.','e'); + const btn=document.getElementById('erbtn');btn.disabled=true;btn.textContent='Gerando...';sm('erm',' Gerando embeddings do relatório...','i'); + try{const d=await $api('/embeddings/report/'+rid,{method:'POST',body:{adb_config_id:vid}});sm('erm','✅ '+d.message,'s');btn.disabled=false;btn.textContent='Gerar Embeddings do Relatório'}catch(e){sm('erm',e.message,'e');btn.disabled=false;btn.textContent='Gerar Embeddings do Relatório'}} async function embedFile(){const vid=document.getElementById('efsel').value;const f=document.getElementById('eff').files[0]; - if(!vid||!f)return alert('Selecione conexão ADB e arquivo'); + if(!vid||!f)return sm('efm','Selecione conexão ADB e arquivo.','e'); const fd=new FormData();fd.append('file',f);fd.append('adb_config_id',vid); - try{const d=await $api('/embeddings/upload',{method:'POST',body:fd,headers:{}});sm('efm','✅ '+d.message,'s')}catch(e){sm('efm',e.message,'e')}} + const btn=document.getElementById('efbtn');btn.disabled=true;btn.textContent='Enviando...';sm('efm',' Enviando e gerando embeddings...','i'); + try{const d=await $api('/embeddings/upload',{method:'POST',body:fd,headers:{}});sm('efm','✅ '+d.message,'s');btn.disabled=false;btn.textContent='Upload e Gerar Embeddings'}catch(e){sm('efm',e.message,'e');btn.disabled=false;btn.textContent='Upload e Gerar Embeddings'}} async function delEmb(vid,docId){if(!confirm('Excluir este embedding?'))return; try{await $api('/embeddings/'+vid+'/'+docId,{method:'DELETE'});loadEmbs()}catch(e){alert('Erro: '+e.message)}}