feat: port quality, escalation, KB version, site-map KB, experiments and metrics

This commit is contained in:
wangliang
2026-10-23 11:41:09 +08:00
parent 81b49c9350
commit b778570045
33 changed files with 2446 additions and 344 deletions
+36
View File
@@ -0,0 +1,36 @@
'use strict';
function stripHtml(value) {
return String(value || '')
.replace(/<br\s*\/?>/gi, '\n')
.replace(/<[^>]+>/g, ' ')
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/\s+/g, ' ')
.trim();
}
// 把完整会话记录作为 Note 挂到商机(旧 bridge crm/chatLogger 的 LibreDesk 版)。
async function attachChatToOpportunity({ client, twenty, convUuid, opportunityId, maxMessages = 100 }) {
if (!client || !twenty || !convUuid || !opportunityId) return null;
const messages = await client.getMessages(convUuid, maxMessages);
const lines = (messages || [])
.filter((m) => m && !m.private && (m.text_content || m.content))
.sort((a, b) => Number(a.id) - Number(b.id))
.map((m) => {
const role = m.sender_type === 'contact' ? 'Customer' : 'Agent';
return `[${role}] ${stripHtml(m.text_content || m.content).slice(0, 300)}`;
})
.filter((line) => line.trim().length > 12);
if (!lines.length) return null;
const text = lines.join('\n\n---\n\n').slice(0, 20000);
const noteId = await twenty.createNote(text);
if (noteId) await twenty.linkNoteToOpportunity(noteId, opportunityId);
console.log(JSON.stringify({ ts: new Date().toISOString(), crm: 'chat_note', conversation: convUuid, opportunity: opportunityId, note_id: noteId }));
return noteId;
}
module.exports = { attachChatToOpportunity, stripHtml };