🔧 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:
+184
-3
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user