/** * fun 标签:smart-chat-append * * 约定:src/pages/processing/func/ 目录下每个文件名就是一个"可用标签/能力"。 * 本文件用于声明该标签存在(供文档/提示词/后续动态加载使用)。 * * 语义:智能合并历史聊天记录和当前聊天记录,自动检测并去除连续重合部分后返回新的聊天记录字符串。 * 输入和输出都是 JSON 字符串格式(参考 chat-history.txt 格式)。 */ const tagName = 'smart-chat-append' const schema = { description: '智能合并历史聊天记录和当前聊天记录,自动检测并去除连续重合部分后返回新的聊天记录字符串(JSON格式)。', inputs: { history: '历史聊天记录的 JSON 字符串', current: '当前聊天记录的 JSON 字符串', }, outputs: { result: '合并去重后的聊天记录 JSON 字符串', }, }; /** * 解析 chat-history.txt 格式的 JSON 字符串为条目数组 * 格式:{"data":"时间戳","friend":"消息","me":"消息"},允许重复键 * @param {string} jsonString - JSON 字符串 * @returns {Array<{type: string, value: string}>} */ function parseChatHistoryJson(jsonString) { const entries = []; if (!jsonString || typeof jsonString !== 'string') { return entries; } try { // 由于JSON不支持重复键,我们需要从文本解析每一行 const lines = jsonString.split('\n'); for (const line of lines) { // 匹配格式:\t"key":"value", 或 \t"key":"value" 或 "key":"value" const match = line.match(/^\s*"([^"]+)":\s*"([^"]*)"\s*,?\s*$/); if (match) { entries.push({ type: match[1], value: match[2] }); } } } catch (e) { // 解析失败,返回空数组 return entries; } return entries; } /** * 将条目数组格式化为 chat-history.txt 格式的 JSON 字符串 * @param {Array<{type: string, value: string}>} entries - 条目数组 * @returns {string} 格式化的 JSON 字符串 */ function formatChatHistoryJson(entries) { const formattedLines = []; formattedLines.push('{'); for (let i = 0; i < entries.length; i++) { const item = entries[i]; const key = JSON.stringify(item.type); const value = JSON.stringify(item.value); const comma = i < entries.length - 1 ? ',' : ''; formattedLines.push(`\t${key}:${value}${comma}`); } formattedLines.push('}'); return formattedLines.join('\n'); } /** * 查找两个条目数组之间的连续重合部分 * 从 historyEntries 的末尾和 currentEntries 的开头查找连续匹配的条目 * @param {Array<{type: string, value: string}>} historyEntries - 历史记录条目数组 * @param {Array<{type: string, value: string}>} currentEntries - 当前记录条目数组 * @returns {number} 重合部分的长度(连续匹配的条目数量),如果没有重合返回 0 */ function findOverlapLength(historyEntries, currentEntries) { if (historyEntries.length === 0 || currentEntries.length === 0) { return 0; } // 从 historyEntries 的末尾开始,尝试匹配 currentEntries 的开头 // 尝试的重合长度从 min(historyEntries.length, currentEntries.length) 到 1 const maxOverlap = Math.min(historyEntries.length, currentEntries.length); for (let overlapLen = maxOverlap; overlapLen > 0; overlapLen--) { // 检查 historyEntries 的最后 overlapLen 个条目是否与 currentEntries 的前 overlapLen 个条目完全相同 let isMatch = true; for (let i = 0; i < overlapLen; i++) { const historyIdx = historyEntries.length - overlapLen + i; const currentIdx = i; const historyEntry = historyEntries[historyIdx]; const currentEntry = currentEntries[currentIdx]; // 比较 type 和 value 是否完全相同 if (historyEntry.type !== currentEntry.type || historyEntry.value !== currentEntry.value) { isMatch = false; break; } } if (isMatch) { return overlapLen; } } return 0; } /** * 执行智能合并聊天记录 * 智能去重:先检查 chatHistoryMessage 的最后几行和 currentChatMessage 的最初几行是否有连续重合部分 * 如果有重合,删除 currentChatMessage 的重合部分,再用剩余部分和原来的 chatHistoryMessage 合并 * @param {Object} params - 参数对象 * @param {string} params.history - 历史聊天记录的 JSON 字符串 * @param {string} params.current - 当前聊天记录的 JSON 字符串 * @returns {Promise<{success: boolean, error?: string, result?: string}>} */ async function executeSmartChatAppend({ history, current }) { try { // 如果历史记录为空字符串,直接返回当前记录 if (!history || history.trim() === '') { const result = typeof current === 'string' ? current : formatChatHistoryJson(parseChatHistoryJson(current || '')); return { success: true, result: result }; } // 解析历史记录 const historyEntries = parseChatHistoryJson(history || ''); // 解析当前记录 const currentEntries = parseChatHistoryJson(current || ''); // 如果历史记录解析后为空,直接返回当前记录 if (historyEntries.length === 0) { const result = formatChatHistoryJson(currentEntries); return { success: true, result: result }; } // 如果当前记录为空,直接返回历史记录 if (currentEntries.length === 0) { const result = formatChatHistoryJson(historyEntries); return { success: true, result: result }; } // 查找重合部分:从 historyEntries 的末尾和 currentEntries 的开头查找连续重合的条目 const overlapLength = findOverlapLength(historyEntries, currentEntries); // 如果有重合部分,删除 currentEntries 中的重合部分 const remainingCurrentEntries = overlapLength > 0 ? currentEntries.slice(overlapLength) : currentEntries; // 合并历史记录和剩余的当前记录 const mergedEntries = [...historyEntries, ...remainingCurrentEntries]; // 格式化为 JSON 字符串 const result = formatChatHistoryJson(mergedEntries); return { success: true, result: result }; } catch (error) { return { success: false, error: error.message || '合并聊天记录失败' }; } } module.exports = { tagName, schema, executeSmartChatAppend }