UNPKG

@n8n/n8n-nodes-langchain

Version:
155 lines 5.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractToolCallId = extractToolCallId; exports.buildMessagesFromSteps = buildMessagesFromSteps; exports.buildToolContext = buildToolContext; exports.cleanupOrphanedMessages = cleanupOrphanedMessages; exports.loadMemory = loadMemory; exports.saveToMemory = saveToMemory; const messages_1 = require("@langchain/core/messages"); function extractToolCallId(toolCallId, toolName) { if (typeof toolCallId === 'string' && toolCallId.length > 0) { return toolCallId; } if (typeof toolCallId === 'object' && toolCallId !== null && !Array.isArray(toolCallId) && 'id' in toolCallId) { const id = toolCallId.id; if (typeof id === 'string' && id.length > 0) { return id; } } if (Array.isArray(toolCallId) && toolCallId.length > 0) { return extractToolCallId(toolCallId[0], toolName); } return `synthetic_${toolName}_${Date.now()}`; } function buildMessagesFromSteps(steps) { const messages = []; for (let i = 0; i < steps.length; i++) { const step = steps[i]; const existingAIMessage = step.action.messageLog?.[0]; const existingToolCallId = existingAIMessage?.tool_calls?.[0]?.id; const toolCallId = existingToolCallId ?? extractToolCallId(step.action.toolCallId, step.action.tool); if (existingAIMessage) { messages.push(existingAIMessage); } else if (i === 0) { messages.push(new messages_1.AIMessage({ content: `Calling ${step.action.tool} with input: ${JSON.stringify(step.action.toolInput)}`, tool_calls: [ { id: toolCallId, name: step.action.tool, args: step.action.toolInput, type: 'tool_call', }, ], })); } messages.push(new messages_1.ToolMessage({ content: step.observation, tool_call_id: toolCallId, name: step.action.tool, })); } return messages; } function buildToolContext(steps) { return steps .map((step) => `Tool: ${step.action.tool}, Input: ${JSON.stringify(step.action.toolInput)}, Result: ${step.observation}`) .join('; '); } function cleanupOrphanedMessages(chatHistory) { const result = [...chatHistory]; let changed = true; while (changed && result.length > 0) { changed = false; while (result.length > 0 && result[0] instanceof messages_1.ToolMessage) { result.shift(); changed = true; } if (result.length > 0) { const firstMessage = result[0]; const hasOrphanedAIMessage = firstMessage instanceof messages_1.AIMessage && (firstMessage.tool_calls?.length ?? 0) > 0 && !(result[1] instanceof messages_1.ToolMessage); if (hasOrphanedAIMessage) { result.shift(); changed = true; } } } changed = true; while (changed && result.length > 0) { changed = false; const lastIdx = result.length - 1; const lastMessage = result[lastIdx]; if (lastMessage instanceof messages_1.ToolMessage) { let precedingIdx = lastIdx - 1; while (precedingIdx >= 0 && result[precedingIdx] instanceof messages_1.ToolMessage) { precedingIdx--; } const precedingMessage = precedingIdx >= 0 ? result[precedingIdx] : undefined; const isPaired = precedingMessage instanceof messages_1.AIMessage && (precedingMessage.tool_calls?.length ?? 0) > 0; if (!isPaired) { result.pop(); changed = true; } } else if (lastMessage instanceof messages_1.AIMessage && (lastMessage.tool_calls?.length ?? 0) > 0) { result.pop(); changed = true; } } return result; } async function loadMemory(memory, model, maxTokens) { if (!memory) { return undefined; } const memoryVariables = await memory.loadMemoryVariables({}); let chatHistory = memoryVariables['chat_history'] || []; chatHistory = cleanupOrphanedMessages(chatHistory); if (maxTokens && model) { chatHistory = await (0, messages_1.trimMessages)(chatHistory, { strategy: 'last', maxTokens, tokenCounter: model, includeSystem: true, startOn: 'human', allowPartial: true, }); chatHistory = cleanupOrphanedMessages(chatHistory); } return chatHistory; } async function saveToMemory(input, output, memory, steps, previousStepsCount) { if (!output || !memory) { return; } if (!steps || steps.length === 0) { await memory.saveContext({ input }, { output }); return; } const newSteps = previousStepsCount ? steps.slice(previousStepsCount) : steps; if (newSteps.length === 0) { await memory.saveContext({ input }, { output }); return; } if (!('addMessages' in memory.chatHistory) || typeof memory.chatHistory.addMessages !== 'function') { const toolContext = buildToolContext(newSteps); const fullOutput = `[Used tools: ${toolContext}] ${output}`; await memory.saveContext({ input }, { output: fullOutput }); return; } const messages = []; messages.push(new messages_1.HumanMessage(input)); const toolMessages = buildMessagesFromSteps(newSteps); messages.push.apply(messages, toolMessages); messages.push(new messages_1.AIMessage(output)); await memory.chatHistory.addMessages(messages); } //# sourceMappingURL=memoryManagement.js.map