UNPKG

@n8n-plus/n8n-plus

Version:

n8n Workflow Automation Tool (plus edition)

254 lines 8.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseStoredMessages = parseStoredMessages; const api_types_1 = require("@n8n/api-types"); const internal_messages_1 = require("./internal-messages"); function extractTextFromContent(content) { if (typeof content === 'string') return content; if (Array.isArray(content)) return extractTextFromParts(content); return ''; } function extractReasoningFromContent(content) { if (typeof content === 'string') return ''; if (Array.isArray(content)) return extractReasoningFromParts(content); return ''; } function extractTextFromParts(parts) { return parts .filter((p) => typeof p === 'object' && p !== null && 'type' in p && p.type === 'text' && 'text' in p && typeof p.text === 'string') .map((p) => p.text) .join(''); } function extractReasoningFromParts(parts) { return parts .filter((p) => typeof p === 'object' && p !== null && 'type' in p && p.type === 'reasoning' && 'text' in p && typeof p.text === 'string') .map((p) => p.text) .join(''); } function extractParts(content) { if (Array.isArray(content)) return content.filter(isStoredContentPart); return undefined; } function isStoredContentPart(value) { return typeof value === 'object' && value !== null && 'type' in value; } function nativeToolPartToInvocation(part) { if (part.type === 'tool-call' && part.toolCallId && part.toolName) { return { state: 'call', toolCallId: part.toolCallId, toolName: part.toolName, args: part.input ?? {}, }; } if (part.type === 'tool-result' && part.toolCallId && part.toolName) { return { state: 'result', toolCallId: part.toolCallId, toolName: part.toolName, args: part.input ?? {}, result: part.result, }; } return undefined; } function extractToolInvocations(content) { if (typeof content === 'string') return []; if (Array.isArray(content)) return content.filter(isStoredContentPart).flatMap((part) => { const invocation = nativeToolPartToInvocation(part); return invocation ? [invocation] : []; }); return []; } function buildToolCallState(invocation) { const isCompleted = invocation.state === 'result'; return { toolCallId: invocation.toolCallId, toolName: invocation.toolName, args: invocation.args, result: isCompleted ? invocation.result : undefined, isLoading: !isCompleted, renderHint: (0, api_types_1.getRenderHint)(invocation.toolName), }; } function buildTimeline(textContent, toolCalls, parts) { if (parts?.length) { const timeline = []; for (const part of parts) { if (part.type === 'text' && part.text) { timeline.push({ type: 'text', content: part.text }); } else if ((part.type === 'tool-call' || part.type === 'tool-result') && part.toolCallId) { timeline.push({ type: 'tool-call', toolCallId: part.toolCallId }); } } return timeline; } const timeline = []; for (const tc of toolCalls) { timeline.push({ type: 'tool-call', toolCallId: tc.toolCallId }); } if (textContent) { timeline.push({ type: 'text', content: textContent }); } return timeline; } function buildFlatAgentTree(textContent, reasoning, toolCalls, parts) { return { agentId: 'agent-001', role: 'orchestrator', status: 'completed', textContent, reasoning, toolCalls, children: [], timeline: buildTimeline(textContent, toolCalls, parts), }; } function snapshotTimestamp(snapshot) { return (snapshot.updatedAt ?? snapshot.createdAt ?? new Date(0)).toISOString(); } function snapshotCreatedAtMs(snapshot) { return snapshot.createdAt?.getTime(); } function messageCreatedAtMs(message) { return message.createdAt.getTime(); } function getNextConversationMessageTimestamp(messages, currentIndex) { for (let i = currentIndex + 1; i < messages.length; i++) { const role = messages[i].role; if (role === 'user' || role === 'assistant') return messageCreatedAtMs(messages[i]); } return undefined; } function buildSnapshotMessage(snapshot) { const groupId = snapshot.messageGroupId ?? snapshot.runId; return { id: groupId, runId: snapshot.runId, messageGroupId: snapshot.messageGroupId, runIds: snapshot.runIds, role: 'assistant', createdAt: snapshotTimestamp(snapshot), content: snapshot.tree.textContent, reasoning: snapshot.tree.reasoning, isStreaming: false, agentTree: snapshot.tree, }; } function parseStoredMessages(storedMessages, snapshots) { const messages = []; const snapshotList = snapshots ?? []; const conversationMessages = storedMessages.filter((message) => 'role' in message); let nextSnapshotIdx = 0; const consumedSnapshots = new Set(); let lastUserMessageId; function appendChronologicalOrphansBefore(message) { const messageTimestamp = messageCreatedAtMs(message); while (nextSnapshotIdx < snapshotList.length) { const snapshot = snapshotList[nextSnapshotIdx]; const snapshotTimestamp = snapshotCreatedAtMs(snapshot); if (snapshotTimestamp === undefined || snapshotTimestamp >= messageTimestamp) return; consumedSnapshots.add(snapshot); messages.push(buildSnapshotMessage(snapshot)); nextSnapshotIdx++; } } function takeSnapshotForAssistant(message, messageIndex) { appendChronologicalOrphansBefore(message); const snapshot = snapshotList[nextSnapshotIdx]; if (!snapshot) return undefined; const nextMessageTimestamp = getNextConversationMessageTimestamp(conversationMessages, messageIndex); const snapshotTimestamp = snapshotCreatedAtMs(snapshot); if (snapshotTimestamp === undefined || (nextMessageTimestamp !== undefined && snapshotTimestamp > nextMessageTimestamp)) { return undefined; } consumedSnapshots.add(snapshot); nextSnapshotIdx++; return snapshot; } for (const [messageIndex, msg] of conversationMessages.entries()) { appendChronologicalOrphansBefore(msg); const text = extractTextFromContent(msg.content); if (msg.role === 'user') { lastUserMessageId = msg.id; const content = (0, internal_messages_1.cleanStoredUserMessage)(text); if (content === null) continue; messages.push({ id: msg.id, role: 'user', createdAt: msg.createdAt.toISOString(), content, reasoning: '', isStreaming: false, }); continue; } if (msg.role === 'assistant') { const reasoning = extractReasoningFromContent(msg.content); const invocations = extractToolInvocations(msg.content); const toolCalls = invocations.map(buildToolCallState); const parts = extractParts(msg.content); const snapshot = takeSnapshotForAssistant(msg, messageIndex); const runId = snapshot?.runId ?? lastUserMessageId ?? msg.id; const agentTree = snapshot?.tree ?? (toolCalls.length > 0 || text ? buildFlatAgentTree(text, reasoning, toolCalls, parts) : undefined); messages.push({ id: msg.id, runId, messageGroupId: snapshot?.messageGroupId, runIds: snapshot?.runIds, role: 'assistant', createdAt: msg.createdAt.toISOString(), content: text, reasoning, isStreaming: false, agentTree, }); continue; } } for (const snapshot of snapshots ?? []) { if (consumedSnapshots.has(snapshot)) continue; messages.push(buildSnapshotMessage(snapshot)); } const seen = new Set(); for (let i = messages.length - 1; i >= 0; i--) { const gid = messages[i].messageGroupId; if (!gid) continue; if (seen.has(gid)) { messages.splice(i, 1); } else { seen.add(gid); } } return messages; } //# sourceMappingURL=message-parser.js.map