<!-- Chat embutido (sem ocupar espaço) -->
<dta-chat label="DTA" class="chat-collapsed"></dta-chat>
<dta-chat-anchor size="22"></dta-chat-anchor>
<script defer src="https://assets.dta.totvs.ai/client/stable/dta_chat.js"></script>
<script>
// Fluxo /run
function getConfig() {
const baseUrl = 'https://totvs.dta.totvs.ai/api/flows/workflow/0690d394-fabd-7adb-8000-b0dae8fd0671';
return {
apiInit: {
url: baseUrl + '/run',
sendHeaders: ['x-dta-project', 'x-dta-api-key'],
},
apiMessage: {
url: baseUrl + '/run',
method: 'POST',
sendHeaders: ['x-dta-project', 'x-dta-api-key'],
},
header_session_prefix: null,
header_thread_prefix: null,
header_session: 'x-dta-session-id',
header_thread: 'x-dta-trace-id',
};
}
const wait = (ms) => new Promise(r => setTimeout(r, ms));
function uuid() {
if (crypto.randomUUID) return crypto.randomUUID();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
let api = null;
// —————— Injetar botão no header do shadow DOM ——————
function injectResetButtonIntoHeader(root) {
if (!root) return;
// cabeçalho e área de ações: cobrimos possíveis variações de seletor
const header = root.querySelector('[part="header"], .header, header');
if (!header) return;
// evita duplicar
if (root.getElementById('dta-reset-inline')) return;
// estilo no shadow DOM (garante visual padronizado)
const style = document.createElement('style');
style.textContent = `
#dta-reset-inline {
display:inline-flex;
align-items:center;
gap:8px;
padding:6px 12px;
border:none;
border-radius:999px;
background:#00c9eb;
color:#fff;
font:600 12px/1 'Segoe UI', Arial, sans-serif;
cursor:pointer;
box-shadow:0 1px 4px rgba(0,0,0,.15);
margin-left:auto; /* empurra para a direita dentro do header */
}
#dta-reset-inline:hover { background:#0098b3; }
`;
root.appendChild(style);
// botão
const btn = document.createElement('button');
btn.id = 'dta-reset-inline';
btn.type = 'button';
btn.textContent = '🔄 Nova conversa';
// tenta posicionar antes dos ícones (fullscreen/close)
const actions = root.querySelector('[part="header-actions"], .actions, .header-actions');
if (actions && actions.parentElement === header) {
header.insertBefore(btn, actions); // fica à esquerda dos ícones
} else {
header.appendChild(btn); // fallback: vai ao final do header
}
btn.addEventListener('click', async () => {
// inicia nova thread
const newThreadId = uuid();
api.addHeaders({ 'x-dta-trace-id': newThreadId });
if (typeof api.reset === 'function') {
api.reset();
} else {
// fecha e reabre como fallback
const anchor = document.querySelector('dta-chat-anchor');
if (anchor) {
anchor.click();
await wait(400);
anchor.click();
}
}
// mensagem após reset
await wait(400);
try {
await api.sendMessage("🔄 Nova conversa iniciada. Em que posso te ajudar agora?");
} catch (e) { console.warn(e); }
});
}
// observa o shadow DOM do <dta-chat> para injetar quando o painel abrir/atualizar
function attachHeaderObserver(host) {
if (!host || !host.shadowRoot) return;
const root = host.shadowRoot;
// injeta imediatamente se o header já existe
injectResetButtonIntoHeader(root);
// observa mudanças (ex.: abrir/fechar painel, recriar header)
const mo = new MutationObserver(() => {
injectResetButtonIntoHeader(root);
});
mo.observe(root, { childList:true, subtree:true });
}
// —————— Boot ——————
window.addEventListener('dta-chat-ready', async (ev) => {
api = ev.detail;
api.config(getConfig());
api.addHeaders({
'x-dta-project': 'dta-fiscal-protheus',
'x-dta-api-key': 'sk-F2lhwcFfMpMV1wL-B16cPkLPUw-9hJs1nL-0PXWko7IanoCR',
});
// abre o chat automaticamente
await wait(250);
try {
if (typeof api.open === 'function') api.open();
else document.querySelector('dta-chat-anchor')?.click();
} catch (e) { console.warn(e); }
// mensagem de boas-vindas simples
try {
await api.sendMessage("👋 Olá! Sou o assistente **DTA**. Como posso te ajudar hoje?");
} catch (e) { console.warn(e); }
// conecta no shadow DOM do componente para inserir o botão no header
const host = document.querySelector('dta-chat');
if (host) attachHeaderObserver(host);
}, { once:true });
// bloqueio de hotkeys
(function () {
const CHAT_TAGS = new Set(['DTA-CHAT','DTA-CHAT-ANCHOR']);
const CHAT_SELECTOR = 'dta-chat, dta-chat-anchor, dta-chat *, dta-chat-anchor *';
function cameFromChat(ev) {
const path = typeof ev.composedPath === 'function' ? ev.composedPath() : [];
for (const el of path) if (el && el.tagName && CHAT_TAGS.has(el.tagName)) return true;
const t = ev.target; return !!(t && typeof t.closest==='function' && t.closest(CHAT_SELECTOR));
}
function isPlainLetterOrHotkey(k) {
if (!k) return false; const key = k.length===1?k.toLowerCase():k.toLowerCase();
return /^[a-z]$/.test(key) || key==='/' || key==='?' || key==='g';
}
function stop(ev){ ev.stopImmediatePropagation(); ev.stopPropagation(); }
function handler(ev){
if (ev.isComposing) return;
if (!cameFromChat(ev)) return;
if (ev.ctrlKey||ev.metaKey||ev.altKey) return;
const k = (ev.key||'').toLowerCase();
if (isPlainLetterOrHotkey(k)) stop(ev);
}
['keydown','keypress','keyup'].forEach(t => document.addEventListener(t, handler, { capture:true }));
})();
</script>
<style>
/* sem espaço em branco */
dta-chat.chat-collapsed{
display:block;
height:0 !important;
min-height:0 !important;
margin:0 !important;
padding:0 !important;
overflow:visible !important;
}
</style> |