🔧 feat: Sistema de identidade dinâmica do agente - modal de configurações, avatares customizáveis, nome dinâmico sincronizado com Hermes/Telegram

This commit is contained in:
2026-05-26 19:40:28 +00:00
parent c78c4020cf
commit 6c35f7ed1b
5 changed files with 514 additions and 7 deletions
+184 -3
View File
@@ -94,6 +94,187 @@ const initApp = () => {
const searchClearAll = document.getElementById('searchClearAll');
const sidebarTags = document.getElementById('sidebarTags');
// Configuração de Identidade do Agente (Kemily/Camila)
const btnSettings = document.getElementById('btnSettings');
const settingsModal = document.getElementById('settingsModal');
const closeSettingsModal = document.getElementById('closeSettingsModal');
const btnSaveSettings = document.getElementById('btnSaveSettings');
const settingAgentName = document.getElementById('settingAgentName');
const previewKemilyAvatar = document.getElementById('previewKemilyAvatar');
const uploadKemilyAvatar = document.getElementById('uploadKemilyAvatar');
const previewCamilaAvatar = document.getElementById('previewCamilaAvatar');
const uploadCamilaAvatar = document.getElementById('uploadCamilaAvatar');
const welcomeTitle = document.getElementById('welcomeTitle');
const welcomeAvatarImg = document.getElementById('welcomeAvatarImg');
const sidebarAvatarImg = document.getElementById('sidebarAvatarImg');
window.agentConfig = {
agentName: "Kemily",
kemilyAvatarUrl: "assets/kemily.png",
camilaAvatarUrl: "assets/camila_prof.png"
};
// Carrega as configurações do servidor
const loadAgentConfig = async () => {
try {
const res = await fetch('/api/agent-config');
if (res.ok) {
window.agentConfig = await res.json();
updateAgentIdentityUI();
}
} catch (e) {
console.error('Erro ao carregar configurações do agente:', e);
}
};
const updateAgentIdentityUI = () => {
if (welcomeTitle) {
welcomeTitle.innerText = `Olá! Sou sua assistente virtual e me chamo ${window.agentConfig.agentName}. Como posso ajudar?`;
}
if (welcomeAvatarImg) {
welcomeAvatarImg.src = window.agentConfig.kemilyAvatarUrl;
}
if (sidebarAvatarImg) {
sidebarAvatarImg.src = window.agentConfig.camilaAvatarUrl;
}
if (settingAgentName) {
settingAgentName.value = window.agentConfig.agentName;
}
if (previewKemilyAvatar) {
previewKemilyAvatar.src = window.agentConfig.kemilyAvatarUrl;
}
if (previewCamilaAvatar) {
previewCamilaAvatar.src = window.agentConfig.camilaAvatarUrl;
}
};
// Variáveis temporárias para avatares (em base64 ou URLs novas)
let newKemilyAvatarData = null;
let newCamilaAvatarData = null;
// Eventos do Modal
if (btnSettings) {
btnSettings.addEventListener('click', () => {
newKemilyAvatarData = null;
newCamilaAvatarData = null;
if (settingAgentName) settingAgentName.value = window.agentConfig.agentName;
if (previewKemilyAvatar) previewKemilyAvatar.src = window.agentConfig.kemilyAvatarUrl;
if (previewCamilaAvatar) previewCamilaAvatar.src = window.agentConfig.camilaAvatarUrl;
settingsModal.style.display = 'flex';
});
}
if (closeSettingsModal) {
closeSettingsModal.addEventListener('click', () => {
settingsModal.style.display = 'none';
});
}
// Fechar clicando fora do modal-content
if (settingsModal) {
settingsModal.addEventListener('click', (e) => {
if (e.target === settingsModal) {
settingsModal.style.display = 'none';
}
});
}
// Previews de Imagem
const handleAvatarFileSelect = (input, previewImg, callback) => {
const file = input.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
previewImg.src = e.target.result;
callback(e.target.result);
};
reader.readAsDataURL(file);
}
};
if (uploadKemilyAvatar) {
uploadKemilyAvatar.addEventListener('change', () => {
handleAvatarFileSelect(uploadKemilyAvatar, previewKemilyAvatar, (base64) => {
newKemilyAvatarData = base64;
});
});
}
if (uploadCamilaAvatar) {
uploadCamilaAvatar.addEventListener('change', () => {
handleAvatarFileSelect(uploadCamilaAvatar, previewCamilaAvatar, (base64) => {
newCamilaAvatarData = base64;
});
});
}
// Salvar Configurações
if (btnSaveSettings) {
btnSaveSettings.addEventListener('click', async () => {
btnSaveSettings.disabled = true;
btnSaveSettings.innerText = 'Salvando...';
try {
let kemilyUrl = window.agentConfig.kemilyAvatarUrl;
let camilaUrl = window.agentConfig.camilaAvatarUrl;
// Se houver novas imagens, faz upload
if (newKemilyAvatarData) {
const res = await fetch('/api/upload-avatar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ avatarType: 'kemily', base64Data: newKemilyAvatarData })
});
if (res.ok) {
const data = await res.json();
kemilyUrl = data.url;
}
}
if (newCamilaAvatarData) {
const res = await fetch('/api/upload-avatar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ avatarType: 'camila', base64Data: newCamilaAvatarData })
});
if (res.ok) {
const data = await res.json();
camilaUrl = data.url;
}
}
// Envia as configurações gerais
const resConfig = await fetch('/api/agent-config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
agentName: settingAgentName.value,
kemilyAvatarUrl: kemilyUrl,
camilaAvatarUrl: camilaUrl
})
});
if (resConfig.ok) {
const result = await resConfig.json();
window.agentConfig = result.config;
updateAgentIdentityUI();
settingsModal.style.display = 'none';
} else {
alert('Erro ao salvar as configurações.');
}
} catch (err) {
console.error(err);
alert('Ocorreu um erro ao salvar.');
} finally {
btnSaveSettings.disabled = false;
btnSaveSettings.innerText = 'Salvar Configurações';
}
});
}
// Executa o carregamento inicial das configurações
loadAgentConfig();
// Variáveis de Estado
let chats = JSON.parse(localStorage.getItem('camila_chats')) || [];
// Migração: adicionar campos tags e pinned a chats antigos
@@ -918,8 +1099,8 @@ const initApp = () => {
row.className = `message-row ${role}`;
const avatarHtml = isUser
? `<div class="avatar user-avatar">U</div>`
: `<div class="avatar bot-avatar bot-avatar-img-wrapper"><img src="assets/kemily.png" alt="Kemily AI" class="bot-avatar-img"></div>`;
? `<div class="avatar user-avatar user-avatar-img-wrapper"><img src="${window.agentConfig?.camilaAvatarUrl || 'assets/camila_prof.png'}" alt="Camila" class="user-avatar-img"></div>`
: `<div class="avatar bot-avatar bot-avatar-img-wrapper"><img src="${window.agentConfig?.kemilyAvatarUrl || 'assets/kemily.png'}" alt="${window.agentConfig?.agentName || 'Kemily'}" class="bot-avatar-img"></div>`;
let contentHtml = '';
if (isUser) {
@@ -1270,7 +1451,7 @@ const initApp = () => {
botRow.innerHTML = `
<div class="message-icon">
<div class="avatar bot-avatar bot-avatar-img-wrapper"><img src="assets/kemily.png" alt="Kemily AI" class="bot-avatar-img"></div>
<div class="avatar bot-avatar bot-avatar-img-wrapper"><img src="${window.agentConfig?.kemilyAvatarUrl || 'assets/kemily.png'}" alt="${window.agentConfig?.agentName || 'Kemily'}" class="bot-avatar-img"></div>
</div>
<div class="message-content-wrapper">
<div class="message-content">