| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /**
- * Func 标签: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 }
|