/** * 从 GraphChatBar.vue 抽出来的纯逻辑:graph-console 底部聊天条要不要把"当前选中的 * task/goal"拼进发给 agent 的消息里。 * * 抽成不依赖组件实例的纯函数,是为了能在不挂载整个 Vue 组件的前提下对它做回归测试 * (照抄 agentChatEvents.js 的先例)。 */ /** context 的身份 key —— 只看 taskId/goalId,title/status 变了不算"context 变了" */ export function contextKey(context) { if (!context) return ''; return `${context.taskId || ''}|${context.goalId || ''}`; } function contextLine(context) { return `[当前上下文] 任务 ${context.taskId}《${context.taskTitle}》(状态: ${context.taskStatus}) · 目标 ${context.goalId}《${context.goalTitle}》`; } /** * 算出实际要发给后端的消息文本。 * * context 跟上次发送时不同才在文本前面拼一行说明,agent 不用用户手动复述在看哪个 * 任务;没变化就原样发,避免每条消息都重复刷一遍同一句上下文。 * * @param {string} text 用户输入的原文(聊天气泡里展示的也是这个,不受影响) * @param {object|null} context 当前选中的 task/goal,见 GraphConsole.vue 的 chatContext * @param {string} lastSentKey 上一次实际发送时的 contextKey() * @returns {{ payload: string, nextKey: string }} payload 是要 POST 的 message 字段; * nextKey 供调用方回写 lastSentContextKey,没有 context 时透传 lastSentKey 不变 */ export function buildOutgoingMessage(text, context, lastSentKey) { const key = contextKey(context); if (context && key !== lastSentKey) { return { payload: `${contextLine(context)}\n\n${text}`, nextKey: key }; } return { payload: text, nextKey: lastSentKey }; }