import type { ChatMessage, Dataset, PrologueItem } from './index'; import { useUserInfo } from '/@/stores/userInfo'; import { Session } from '/@/utils/storage'; import { getObj } from '/@/api/knowledge/aiMcpConfig'; import { getObj as getDataObj } from '/@/api/knowledge/aiData'; /** * Process a message to extract any thought content enclosed in tags * and update the message object accordingly */ export function withMessageThought(message: ChatMessage, startTime?: number) { const content = message.content; // If message already has reasoning_content, calculate thinking time if (message.reasoning_content) { const thinkingTime = startTime ? ((Date.now() - startTime) / 1000).toFixed(1) : '0.5'; message.thinking_time = thinkingTime; // @ts-ignore - Add isThinking flag message.isThinking = false; return message; } const thinkPattern = /(.*?)<\/think>/s; const matches = content.match(thinkPattern); if (matches) { const reasoning_content = matches[1].trim(); const remainingContent = content.replace(thinkPattern, '').trim(); message.content = remainingContent; if (reasoning_content) { // Calculate thinking time const thinkingTime = startTime ? ((Date.now() - startTime) / 1000).toFixed(1) : '0.5'; // @ts-ignore - Add reasoning properties message.reasoning_content = reasoning_content; message.thinking_time = thinkingTime; // @ts-ignore - Add isThinking flag message.isThinking = true; return message; } } return message; } /** * 检查字符串是否为 Markdown 数组格式(以 '- ' 开头) * @param {string} val - 要检查的字符串 * @returns {boolean} 是否为 Markdown 数组格式 */ export const isMdArray = (val: string): boolean => { return Boolean(val.match(/^-\s.*/m)); }; /** * 解析欢迎消息字符串为 PrologueItem 数组 * @param {string} welcomeMsg - 欢迎消息字符串 * @returns {PrologueItem[]} 解析后的 PrologueItem 数组 */ export const parseWelcomeMessage = (welcomeMsg?: string): PrologueItem[] => { const lines = welcomeMsg?.split('\n'); if (!lines) return []; return lines .reduce((pre_array: PrologueItem[], current: string, index: number) => { const currentObj = isMdArray(current) ? { type: 'question' as const, str: current.replace(/^-\s+/, ''), index: index, } : { type: 'md' as const, str: current, index: index, }; if (pre_array.length > 0) { const pre = pre_array[pre_array.length - 1]; if (!isMdArray(current) && pre.type === 'md') { pre.str = [pre.str, current].join('\n'); pre.index = index; return pre_array; } else { pre_array.push(currentObj); } } else { pre_array.push(currentObj); } return pre_array; }, []) .sort((pre, next) => pre.index - next.index); }; /** * 处理 prologue items,包括从 MCP 获取元数据的逻辑 * @param {Dataset} selectedKnowledge - 选中的知识库 * @param {PrologueItem[]} initialPrologueList - 初始的 prologue 列表 * @returns {Promise} 处理后的 prologue items */ export const processPrologueItems = async (selectedKnowledge: Dataset, initialPrologueList: PrologueItem[]): Promise => { // 如果存在 mcpId,从后端获取 MCP 元数据 if (selectedKnowledge?.mcpId) { const { data } = await getObj(selectedKnowledge.mcpId); if (data && data.description) { // 使用 parseWelcomeMessage 解析 MCP 的描述信息 return parseWelcomeMessage(data.description); } } // 如果存在 dataId,从后端获取数据集元数据 if (selectedKnowledge?.dataId) { const { data } = await getDataObj(selectedKnowledge.dataId); if (data && data.description) { // 使用 parseWelcomeMessage 解析数据集的描述信息 return parseWelcomeMessage(data.description); } } // 如果没有 mcpId 和 dataId 或获取失败,返回初始列表 return initialPrologueList; }; /** * 从会话存储中获取访问令牌 * @returns {string} 访问令牌 */ const token = computed(() => { return Session.getToken(); }); /** * 生成会话存储的key * @param {string} knowledgeId - 知识库ID * @param {boolean} notime - 是否不包含时间戳 * @param {string} mcpId - MCP服务ID(可选) * @param {string} dataId - 数据ID(可选) * @returns {string} 会话存储key */ export const generateConversationKey = (knowledgeId: string, notime?: boolean, mcpId?: string, dataId?: string) => { // 构建基础key let key = `chat-${knowledgeId}-${useUserInfo().userInfos.user.userId}-${token.value}`; // 如果有mcpId,添加到key中 if (mcpId) { key += `-mcp-${mcpId}`; } // 如果有dataId,添加到key中 if (dataId) { key += `-data-${dataId}`; } // 如果需要时间戳,添加到key末尾 if (!notime) { key += `-${Date.now()}`; } return key; };