@n8n/n8n-nodes-langchain 1.94.1 → 1.95.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nodes/chains/InformationExtractor/processItem.js +6 -0
- package/dist/nodes/chains/InformationExtractor/processItem.js.map +1 -1
- package/dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js +2 -2
- package/dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js.map +1 -1
- package/dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js +1 -1
- package/dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js.map +1 -1
- package/dist/nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.js +109 -17
- package/dist/nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.js.map +1 -1
- package/dist/nodes/vector_store/shared/MemoryManager/MemoryVectorStoreManager.js +3 -0
- package/dist/nodes/vector_store/shared/MemoryManager/MemoryVectorStoreManager.js.map +1 -1
- package/dist/nodes/vector_store/shared/createVectorStoreNode/createVectorStoreNode.js +2 -1
- package/dist/nodes/vector_store/shared/createVectorStoreNode/createVectorStoreNode.js.map +1 -1
- package/dist/nodes/vector_store/shared/createVectorStoreNode/types.js.map +1 -1
- package/dist/types/nodes.json +9 -9
- package/package.json +4 -4
|
@@ -23,10 +23,16 @@ __export(processItem_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(processItem_exports);
|
|
24
24
|
var import_messages = require("@langchain/core/messages");
|
|
25
25
|
var import_prompts = require("@langchain/core/prompts");
|
|
26
|
+
var import_n8n_workflow = require("n8n-workflow");
|
|
26
27
|
var import_tracing = require("../../../utils/tracing");
|
|
27
28
|
var import_constants = require("./constants");
|
|
28
29
|
async function processItem(ctx, itemIndex, llm, parser) {
|
|
29
30
|
const input = ctx.getNodeParameter("text", itemIndex);
|
|
31
|
+
if (!input?.trim()) {
|
|
32
|
+
throw new import_n8n_workflow.NodeOperationError(ctx.getNode(), `Text for item ${itemIndex} is not defined`, {
|
|
33
|
+
itemIndex
|
|
34
|
+
});
|
|
35
|
+
}
|
|
30
36
|
const inputPrompt = new import_messages.HumanMessage(input);
|
|
31
37
|
const options = ctx.getNodeParameter("options", itemIndex, {});
|
|
32
38
|
const systemPromptTemplate = import_prompts.SystemMessagePromptTemplate.fromTemplate(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/chains/InformationExtractor/processItem.ts"],"sourcesContent":["import type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { HumanMessage } from '@langchain/core/messages';\nimport { ChatPromptTemplate, SystemMessagePromptTemplate } from '@langchain/core/prompts';\nimport type { OutputFixingParser } from 'langchain/output_parsers';\nimport type
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/chains/InformationExtractor/processItem.ts"],"sourcesContent":["import type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { HumanMessage } from '@langchain/core/messages';\nimport { ChatPromptTemplate, SystemMessagePromptTemplate } from '@langchain/core/prompts';\nimport type { OutputFixingParser } from 'langchain/output_parsers';\nimport { NodeOperationError, type IExecuteFunctions } from 'n8n-workflow';\n\nimport { getTracingConfig } from '@utils/tracing';\n\nimport { SYSTEM_PROMPT_TEMPLATE } from './constants';\n\nexport async function processItem(\n\tctx: IExecuteFunctions,\n\titemIndex: number,\n\tllm: BaseLanguageModel,\n\tparser: OutputFixingParser<object>,\n) {\n\tconst input = ctx.getNodeParameter('text', itemIndex) as string;\n\tif (!input?.trim()) {\n\t\tthrow new NodeOperationError(ctx.getNode(), `Text for item ${itemIndex} is not defined`, {\n\t\t\titemIndex,\n\t\t});\n\t}\n\tconst inputPrompt = new HumanMessage(input);\n\n\tconst options = ctx.getNodeParameter('options', itemIndex, {}) as {\n\t\tsystemPromptTemplate?: string;\n\t};\n\n\tconst systemPromptTemplate = SystemMessagePromptTemplate.fromTemplate(\n\t\t`${options.systemPromptTemplate ?? SYSTEM_PROMPT_TEMPLATE}\n{format_instructions}`,\n\t);\n\n\tconst messages = [\n\t\tawait systemPromptTemplate.format({\n\t\t\tformat_instructions: parser.getFormatInstructions(),\n\t\t}),\n\t\tinputPrompt,\n\t];\n\tconst prompt = ChatPromptTemplate.fromMessages(messages);\n\tconst chain = prompt.pipe(llm).pipe(parser).withConfig(getTracingConfig(ctx));\n\n\treturn await chain.invoke(messages);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAA6B;AAC7B,qBAAgE;AAEhE,0BAA2D;AAE3D,qBAAiC;AAEjC,uBAAuC;AAEvC,eAAsB,YACrB,KACA,WACA,KACA,QACC;AACD,QAAM,QAAQ,IAAI,iBAAiB,QAAQ,SAAS;AACpD,MAAI,CAAC,OAAO,KAAK,GAAG;AACnB,UAAM,IAAI,uCAAmB,IAAI,QAAQ,GAAG,iBAAiB,SAAS,mBAAmB;AAAA,MACxF;AAAA,IACD,CAAC;AAAA,EACF;AACA,QAAM,cAAc,IAAI,6BAAa,KAAK;AAE1C,QAAM,UAAU,IAAI,iBAAiB,WAAW,WAAW,CAAC,CAAC;AAI7D,QAAM,uBAAuB,2CAA4B;AAAA,IACxD,GAAG,QAAQ,wBAAwB,uCAAsB;AAAA;AAAA,EAE1D;AAEA,QAAM,WAAW;AAAA,IAChB,MAAM,qBAAqB,OAAO;AAAA,MACjC,qBAAqB,OAAO,sBAAsB;AAAA,IACnD,CAAC;AAAA,IACD;AAAA,EACD;AACA,QAAM,SAAS,kCAAmB,aAAa,QAAQ;AACvD,QAAM,QAAQ,OAAO,KAAK,GAAG,EAAE,KAAK,MAAM,EAAE,eAAW,iCAAiB,GAAG,CAAC;AAE5E,SAAO,MAAM,MAAM,OAAO,QAAQ;AACnC;","names":[]}
|
|
@@ -162,8 +162,8 @@ class LmChatAnthropic {
|
|
|
162
162
|
type: "resourceLocator",
|
|
163
163
|
default: {
|
|
164
164
|
mode: "list",
|
|
165
|
-
value: "claude-
|
|
166
|
-
cachedResultName: "Claude
|
|
165
|
+
value: "claude-sonnet-4-20250514",
|
|
166
|
+
cachedResultName: "Claude 4 Sonnet"
|
|
167
167
|
},
|
|
168
168
|
required: true,
|
|
169
169
|
modes: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts"],"sourcesContent":["/* eslint-disable n8n-nodes-base/node-dirname-against-convention */\n\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport type { LLMResult } from '@langchain/core/outputs';\nimport {\n\tNodeConnectionTypes,\n\ttype INodePropertyOptions,\n\ttype INodeProperties,\n\ttype ISupplyDataFunctions,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { getHttpProxyAgent } from '@utils/httpProxyAgent';\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\n\nimport { searchModels } from './methods/searchModels';\nimport { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';\nimport { N8nLlmTracing } from '../N8nLlmTracing';\n\nconst modelField: INodeProperties = {\n\tdisplayName: 'Model',\n\tname: 'model',\n\ttype: 'options',\n\t// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items\n\toptions: [\n\t\t{\n\t\t\tname: 'Claude 3.5 Sonnet(20241022)',\n\t\t\tvalue: 'claude-3-5-sonnet-20241022',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3 Opus(20240229)',\n\t\t\tvalue: 'claude-3-opus-20240229',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3.5 Sonnet(20240620)',\n\t\t\tvalue: 'claude-3-5-sonnet-20240620',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3 Sonnet(20240229)',\n\t\t\tvalue: 'claude-3-sonnet-20240229',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3.5 Haiku(20241022)',\n\t\t\tvalue: 'claude-3-5-haiku-20241022',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3 Haiku(20240307)',\n\t\t\tvalue: 'claude-3-haiku-20240307',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude 2',\n\t\t\tvalue: 'claude-2',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude 2.1',\n\t\t\tvalue: 'claude-2.1',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude Instant 1.2',\n\t\t\tvalue: 'claude-instant-1.2',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude Instant 1',\n\t\t\tvalue: 'claude-instant-1',\n\t\t},\n\t],\n\tdescription:\n\t\t'The model which will generate the completion. <a href=\"https://docs.anthropic.com/claude/docs/models-overview\">Learn more</a>.',\n\tdefault: 'claude-2',\n};\n\nconst MIN_THINKING_BUDGET = 1024;\nconst DEFAULT_MAX_TOKENS = 4096;\nexport class LmChatAnthropic implements INodeType {\n\tmethods = {\n\t\tlistSearch: {\n\t\t\tsearchModels,\n\t\t},\n\t};\n\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Anthropic Chat Model',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-name-miscased\n\t\tname: 'lmChatAnthropic',\n\t\ticon: 'file:anthropic.svg',\n\t\tgroup: ['transform'],\n\t\tversion: [1, 1.1, 1.2, 1.3],\n\t\tdefaultVersion: 1.3,\n\t\tdescription: 'Language Model Anthropic',\n\t\tdefaults: {\n\t\t\tname: 'Anthropic Chat Model',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Language Models', 'Root Nodes'],\n\t\t\t\t'Language Models': ['Chat Models (Recommended)'],\n\t\t\t},\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatanthropic/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\talias: ['claude', 'sonnet', 'opus'],\n\t\t},\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node\n\t\tinputs: [],\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong\n\t\toutputs: [NodeConnectionTypes.AiLanguageModel],\n\t\toutputNames: ['Model'],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'anthropicApi',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiChain, NodeConnectionTypes.AiChain]),\n\t\t\t{\n\t\t\t\t...modelField,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...modelField,\n\t\t\t\tdefault: 'claude-3-sonnet-20240229',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...modelField,\n\t\t\t\tdefault: 'claude-3-5-sonnet-20240620',\n\t\t\t\toptions: (modelField.options ?? []).filter(\n\t\t\t\t\t(o): o is INodePropertyOptions => 'name' in o && !o.name.toString().startsWith('LEGACY'),\n\t\t\t\t),\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Model',\n\t\t\t\tname: 'model',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: {\n\t\t\t\t\tmode: 'list',\n\t\t\t\t\tvalue: 'claude-3-7-sonnet-20250219',\n\t\t\t\t\tcachedResultName: 'Claude 3.7 Sonnet',\n\t\t\t\t},\n\t\t\t\trequired: true,\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\tplaceholder: 'Select a model...',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'searchModels',\n\t\t\t\t\t\t\tsearchable: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'ID',\n\t\t\t\t\t\tname: 'id',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'Claude Sonnet',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdescription:\n\t\t\t\t\t'The model. Choose from the list, or specify an ID. <a href=\"https://docs.anthropic.com/claude/docs/models-overview\">Learn more</a>.',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.3 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to add',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Maximum Number of Tokens',\n\t\t\t\t\t\tname: 'maxTokensToSample',\n\t\t\t\t\t\tdefault: DEFAULT_MAX_TOKENS,\n\t\t\t\t\t\tdescription: 'The maximum number of tokens to generate in the completion',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Sampling Temperature',\n\t\t\t\t\t\tname: 'temperature',\n\t\t\t\t\t\tdefault: 0.7,\n\t\t\t\t\t\ttypeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Top K',\n\t\t\t\t\t\tname: 'topK',\n\t\t\t\t\t\tdefault: -1,\n\t\t\t\t\t\ttypeOptions: { maxValue: 1, minValue: -1, numberPrecision: 1 },\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Used to remove \"long tail\" low probability responses. Defaults to -1, which disables it.',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Top P',\n\t\t\t\t\t\tname: 'topP',\n\t\t\t\t\t\tdefault: 1,\n\t\t\t\t\t\ttypeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Controls diversity via nucleus sampling: 0.5 means half of all likelihood-weighted options are considered. We generally recommend altering this or temperature but not both.',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Enable Thinking',\n\t\t\t\t\t\tname: 'thinking',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to enable thinking mode for the model',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Thinking Budget (Tokens)',\n\t\t\t\t\t\tname: 'thinkingBudget',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: MIN_THINKING_BUDGET,\n\t\t\t\t\t\tdescription: 'The maximum number of tokens to use for thinking',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tconst credentials = await this.getCredentials<{ url?: string; apiKey?: string }>(\n\t\t\t'anthropicApi',\n\t\t);\n\t\tconst baseURL = credentials.url ?? 'https://api.anthropic.com';\n\t\tconst version = this.getNode().typeVersion;\n\t\tconst modelName =\n\t\t\tversion >= 1.3\n\t\t\t\t? (this.getNodeParameter('model.value', itemIndex) as string)\n\t\t\t\t: (this.getNodeParameter('model', itemIndex) as string);\n\n\t\tconst options = this.getNodeParameter('options', itemIndex, {}) as {\n\t\t\tmaxTokensToSample?: number;\n\t\t\ttemperature: number;\n\t\t\ttopK?: number;\n\t\t\ttopP?: number;\n\t\t\tthinking?: boolean;\n\t\t\tthinkingBudget?: number;\n\t\t};\n\t\tlet invocationKwargs = {};\n\n\t\tconst tokensUsageParser = (llmOutput: LLMResult['llmOutput']) => {\n\t\t\tconst usage = (llmOutput?.usage as { input_tokens: number; output_tokens: number }) ?? {\n\t\t\t\tinput_tokens: 0,\n\t\t\t\toutput_tokens: 0,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcompletionTokens: usage.output_tokens,\n\t\t\t\tpromptTokens: usage.input_tokens,\n\t\t\t\ttotalTokens: usage.input_tokens + usage.output_tokens,\n\t\t\t};\n\t\t};\n\n\t\tif (options.thinking) {\n\t\t\tinvocationKwargs = {\n\t\t\t\tthinking: {\n\t\t\t\t\ttype: 'enabled',\n\t\t\t\t\t// If thinking is enabled, we need to set a budget.\n\t\t\t\t\t// We fallback to 1024 as that is the minimum\n\t\t\t\t\tbudget_tokens: options.thinkingBudget ?? MIN_THINKING_BUDGET,\n\t\t\t\t},\n\t\t\t\t// The default Langchain max_tokens is -1 (no limit) but Anthropic requires a number\n\t\t\t\t// higher than budget_tokens\n\t\t\t\tmax_tokens: options.maxTokensToSample ?? DEFAULT_MAX_TOKENS,\n\t\t\t\t// These need to be unset when thinking is enabled.\n\t\t\t\t// Because the invocationKwargs will override the model options\n\t\t\t\t// we can pass options to the model and then override them here\n\t\t\t\ttop_k: undefined,\n\t\t\t\ttop_p: undefined,\n\t\t\t\ttemperature: undefined,\n\t\t\t};\n\t\t}\n\n\t\tconst model = new ChatAnthropic({\n\t\t\tanthropicApiKey: credentials.apiKey,\n\t\t\tmodelName,\n\t\t\tanthropicApiUrl: baseURL,\n\t\t\tmaxTokens: options.maxTokensToSample,\n\t\t\ttemperature: options.temperature,\n\t\t\ttopK: options.topK,\n\t\t\ttopP: options.topP,\n\t\t\tcallbacks: [new N8nLlmTracing(this, { tokensUsageParser })],\n\t\t\tonFailedAttempt: makeN8nLlmFailedAttemptHandler(this),\n\t\t\tinvocationKwargs,\n\t\t\tclientOptions: {\n\t\t\t\thttpAgent: getHttpProxyAgent(),\n\t\t\t},\n\t\t});\n\n\t\treturn {\n\t\t\tresponse: model,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts"],"sourcesContent":["/* eslint-disable n8n-nodes-base/node-dirname-against-convention */\n\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport type { LLMResult } from '@langchain/core/outputs';\nimport {\n\tNodeConnectionTypes,\n\ttype INodePropertyOptions,\n\ttype INodeProperties,\n\ttype ISupplyDataFunctions,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { getHttpProxyAgent } from '@utils/httpProxyAgent';\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\n\nimport { searchModels } from './methods/searchModels';\nimport { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';\nimport { N8nLlmTracing } from '../N8nLlmTracing';\n\nconst modelField: INodeProperties = {\n\tdisplayName: 'Model',\n\tname: 'model',\n\ttype: 'options',\n\t// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items\n\toptions: [\n\t\t{\n\t\t\tname: 'Claude 3.5 Sonnet(20241022)',\n\t\t\tvalue: 'claude-3-5-sonnet-20241022',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3 Opus(20240229)',\n\t\t\tvalue: 'claude-3-opus-20240229',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3.5 Sonnet(20240620)',\n\t\t\tvalue: 'claude-3-5-sonnet-20240620',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3 Sonnet(20240229)',\n\t\t\tvalue: 'claude-3-sonnet-20240229',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3.5 Haiku(20241022)',\n\t\t\tvalue: 'claude-3-5-haiku-20241022',\n\t\t},\n\t\t{\n\t\t\tname: 'Claude 3 Haiku(20240307)',\n\t\t\tvalue: 'claude-3-haiku-20240307',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude 2',\n\t\t\tvalue: 'claude-2',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude 2.1',\n\t\t\tvalue: 'claude-2.1',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude Instant 1.2',\n\t\t\tvalue: 'claude-instant-1.2',\n\t\t},\n\t\t{\n\t\t\tname: 'LEGACY: Claude Instant 1',\n\t\t\tvalue: 'claude-instant-1',\n\t\t},\n\t],\n\tdescription:\n\t\t'The model which will generate the completion. <a href=\"https://docs.anthropic.com/claude/docs/models-overview\">Learn more</a>.',\n\tdefault: 'claude-2',\n};\n\nconst MIN_THINKING_BUDGET = 1024;\nconst DEFAULT_MAX_TOKENS = 4096;\nexport class LmChatAnthropic implements INodeType {\n\tmethods = {\n\t\tlistSearch: {\n\t\t\tsearchModels,\n\t\t},\n\t};\n\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Anthropic Chat Model',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-name-miscased\n\t\tname: 'lmChatAnthropic',\n\t\ticon: 'file:anthropic.svg',\n\t\tgroup: ['transform'],\n\t\tversion: [1, 1.1, 1.2, 1.3],\n\t\tdefaultVersion: 1.3,\n\t\tdescription: 'Language Model Anthropic',\n\t\tdefaults: {\n\t\t\tname: 'Anthropic Chat Model',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Language Models', 'Root Nodes'],\n\t\t\t\t'Language Models': ['Chat Models (Recommended)'],\n\t\t\t},\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatanthropic/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\talias: ['claude', 'sonnet', 'opus'],\n\t\t},\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node\n\t\tinputs: [],\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong\n\t\toutputs: [NodeConnectionTypes.AiLanguageModel],\n\t\toutputNames: ['Model'],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'anthropicApi',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiChain, NodeConnectionTypes.AiChain]),\n\t\t\t{\n\t\t\t\t...modelField,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...modelField,\n\t\t\t\tdefault: 'claude-3-sonnet-20240229',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...modelField,\n\t\t\t\tdefault: 'claude-3-5-sonnet-20240620',\n\t\t\t\toptions: (modelField.options ?? []).filter(\n\t\t\t\t\t(o): o is INodePropertyOptions => 'name' in o && !o.name.toString().startsWith('LEGACY'),\n\t\t\t\t),\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Model',\n\t\t\t\tname: 'model',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: {\n\t\t\t\t\tmode: 'list',\n\t\t\t\t\tvalue: 'claude-sonnet-4-20250514',\n\t\t\t\t\tcachedResultName: 'Claude 4 Sonnet',\n\t\t\t\t},\n\t\t\t\trequired: true,\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\tplaceholder: 'Select a model...',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'searchModels',\n\t\t\t\t\t\t\tsearchable: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'ID',\n\t\t\t\t\t\tname: 'id',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'Claude Sonnet',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdescription:\n\t\t\t\t\t'The model. Choose from the list, or specify an ID. <a href=\"https://docs.anthropic.com/claude/docs/models-overview\">Learn more</a>.',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.3 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to add',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Maximum Number of Tokens',\n\t\t\t\t\t\tname: 'maxTokensToSample',\n\t\t\t\t\t\tdefault: DEFAULT_MAX_TOKENS,\n\t\t\t\t\t\tdescription: 'The maximum number of tokens to generate in the completion',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Sampling Temperature',\n\t\t\t\t\t\tname: 'temperature',\n\t\t\t\t\t\tdefault: 0.7,\n\t\t\t\t\t\ttypeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Top K',\n\t\t\t\t\t\tname: 'topK',\n\t\t\t\t\t\tdefault: -1,\n\t\t\t\t\t\ttypeOptions: { maxValue: 1, minValue: -1, numberPrecision: 1 },\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Used to remove \"long tail\" low probability responses. Defaults to -1, which disables it.',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Top P',\n\t\t\t\t\t\tname: 'topP',\n\t\t\t\t\t\tdefault: 1,\n\t\t\t\t\t\ttypeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Controls diversity via nucleus sampling: 0.5 means half of all likelihood-weighted options are considered. We generally recommend altering this or temperature but not both.',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Enable Thinking',\n\t\t\t\t\t\tname: 'thinking',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to enable thinking mode for the model',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Thinking Budget (Tokens)',\n\t\t\t\t\t\tname: 'thinkingBudget',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: MIN_THINKING_BUDGET,\n\t\t\t\t\t\tdescription: 'The maximum number of tokens to use for thinking',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tthinking: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tconst credentials = await this.getCredentials<{ url?: string; apiKey?: string }>(\n\t\t\t'anthropicApi',\n\t\t);\n\t\tconst baseURL = credentials.url ?? 'https://api.anthropic.com';\n\t\tconst version = this.getNode().typeVersion;\n\t\tconst modelName =\n\t\t\tversion >= 1.3\n\t\t\t\t? (this.getNodeParameter('model.value', itemIndex) as string)\n\t\t\t\t: (this.getNodeParameter('model', itemIndex) as string);\n\n\t\tconst options = this.getNodeParameter('options', itemIndex, {}) as {\n\t\t\tmaxTokensToSample?: number;\n\t\t\ttemperature: number;\n\t\t\ttopK?: number;\n\t\t\ttopP?: number;\n\t\t\tthinking?: boolean;\n\t\t\tthinkingBudget?: number;\n\t\t};\n\t\tlet invocationKwargs = {};\n\n\t\tconst tokensUsageParser = (llmOutput: LLMResult['llmOutput']) => {\n\t\t\tconst usage = (llmOutput?.usage as { input_tokens: number; output_tokens: number }) ?? {\n\t\t\t\tinput_tokens: 0,\n\t\t\t\toutput_tokens: 0,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcompletionTokens: usage.output_tokens,\n\t\t\t\tpromptTokens: usage.input_tokens,\n\t\t\t\ttotalTokens: usage.input_tokens + usage.output_tokens,\n\t\t\t};\n\t\t};\n\n\t\tif (options.thinking) {\n\t\t\tinvocationKwargs = {\n\t\t\t\tthinking: {\n\t\t\t\t\ttype: 'enabled',\n\t\t\t\t\t// If thinking is enabled, we need to set a budget.\n\t\t\t\t\t// We fallback to 1024 as that is the minimum\n\t\t\t\t\tbudget_tokens: options.thinkingBudget ?? MIN_THINKING_BUDGET,\n\t\t\t\t},\n\t\t\t\t// The default Langchain max_tokens is -1 (no limit) but Anthropic requires a number\n\t\t\t\t// higher than budget_tokens\n\t\t\t\tmax_tokens: options.maxTokensToSample ?? DEFAULT_MAX_TOKENS,\n\t\t\t\t// These need to be unset when thinking is enabled.\n\t\t\t\t// Because the invocationKwargs will override the model options\n\t\t\t\t// we can pass options to the model and then override them here\n\t\t\t\ttop_k: undefined,\n\t\t\t\ttop_p: undefined,\n\t\t\t\ttemperature: undefined,\n\t\t\t};\n\t\t}\n\n\t\tconst model = new ChatAnthropic({\n\t\t\tanthropicApiKey: credentials.apiKey,\n\t\t\tmodelName,\n\t\t\tanthropicApiUrl: baseURL,\n\t\t\tmaxTokens: options.maxTokensToSample,\n\t\t\ttemperature: options.temperature,\n\t\t\ttopK: options.topK,\n\t\t\ttopP: options.topP,\n\t\t\tcallbacks: [new N8nLlmTracing(this, { tokensUsageParser })],\n\t\t\tonFailedAttempt: makeN8nLlmFailedAttemptHandler(this),\n\t\t\tinvocationKwargs,\n\t\t\tclientOptions: {\n\t\t\t\thttpAgent: getHttpProxyAgent(),\n\t\t\t},\n\t\t});\n\n\t\treturn {\n\t\t\tresponse: model,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -526,7 +526,7 @@ ${import_constants.cssVariables}
|
|
|
526
526
|
return {
|
|
527
527
|
webhookResponse: { data: messages }
|
|
528
528
|
};
|
|
529
|
-
} else if (options?.loadPreviousSession === "notSupported") {
|
|
529
|
+
} else if (!options?.loadPreviousSession || options?.loadPreviousSession === "notSupported") {
|
|
530
530
|
return {
|
|
531
531
|
webhookResponse: { data: [] }
|
|
532
532
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/trigger/ChatTrigger/ChatTrigger.node.ts"],"sourcesContent":["import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';\nimport { pick } from 'lodash';\nimport { Node, NodeConnectionTypes } from 'n8n-workflow';\nimport type {\n\tIDataObject,\n\tIWebhookFunctions,\n\tIWebhookResponseData,\n\tINodeTypeDescription,\n\tMultiPartFormData,\n\tINodeExecutionData,\n\tIBinaryData,\n\tINodeProperties,\n} from 'n8n-workflow';\n\nimport { cssVariables } from './constants';\nimport { validateAuth } from './GenericFunctions';\nimport { createPage } from './templates';\nimport type { LoadPreviousSessionChatOption } from './types';\n\nconst CHAT_TRIGGER_PATH_IDENTIFIER = 'chat';\nconst allowFileUploadsOption: INodeProperties = {\n\tdisplayName: 'Allow File Uploads',\n\tname: 'allowFileUploads',\n\ttype: 'boolean',\n\tdefault: false,\n\tdescription: 'Whether to allow file uploads in the chat',\n};\nconst allowedFileMimeTypeOption: INodeProperties = {\n\tdisplayName: 'Allowed File Mime Types',\n\tname: 'allowedFilesMimeTypes',\n\ttype: 'string',\n\tdefault: '*',\n\tplaceholder: 'e.g. image/*, text/*, application/pdf',\n\tdescription:\n\t\t'Allowed file types for upload. Comma-separated list of <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\" target=\"_blank\">MIME types</a>.',\n};\n\nexport class ChatTrigger extends Node {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Chat Trigger',\n\t\tname: 'chatTrigger',\n\t\ticon: 'fa:comments',\n\t\ticonColor: 'black',\n\t\tgroup: ['trigger'],\n\t\tversion: [1, 1.1],\n\t\tdescription: 'Runs the workflow when an n8n generated webchat is submitted',\n\t\tdefaults: {\n\t\t\tname: 'When chat message received',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['Core Nodes'],\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.chattrigger/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tmaxNodes: 1,\n\t\tinputs: `={{ (() => {\n\t\t\tif (!['hostedChat', 'webhook'].includes($parameter.mode)) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tif ($parameter.options?.loadPreviousSession !== 'memory') {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Memory',\n\t\t\t\t\tmaxConnections: 1,\n\t\t\t\t\ttype: '${NodeConnectionTypes.AiMemory}',\n\t\t\t\t\trequired: true,\n\t\t\t\t}\n\t\t\t];\n\t\t })() }}`,\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed\n\t\t\t\tname: 'httpBasicAuth',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['basicAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twebhooks: [\n\t\t\t{\n\t\t\t\tname: 'setup',\n\t\t\t\thttpMethod: 'GET',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tpath: CHAT_TRIGGER_PATH_IDENTIFIER,\n\t\t\t\tndvHideUrl: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'POST',\n\t\t\t\tresponseMode: '={{$parameter.options?.[\"responseMode\"] || \"lastNode\" }}',\n\t\t\t\tpath: CHAT_TRIGGER_PATH_IDENTIFIER,\n\t\t\t\tndvHideMethod: true,\n\t\t\t\tndvHideUrl: '={{ !$parameter.public }}',\n\t\t\t},\n\t\t],\n\t\teventTriggerDescription: 'Waiting for you to submit the chat',\n\t\tactivationMessage: 'You can now make calls to your production chat URL.',\n\t\ttriggerPanel: false,\n\t\tproperties: [\n\t\t\t/**\n\t\t\t * @note If we change this property, also update it in ChatEmbedModal.vue\n\t\t\t */\n\t\t\t{\n\t\t\t\tdisplayName: 'Make Chat Publicly Available',\n\t\t\t\tname: 'public',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether the chat should be publicly available or only accessible through the manual chat interface',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Mode',\n\t\t\t\tname: 'mode',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Hosted Chat',\n\t\t\t\t\t\tvalue: 'hostedChat',\n\t\t\t\t\t\tdescription: 'Chat on a page served by n8n',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Embedded Chat',\n\t\t\t\t\t\tvalue: 'webhook',\n\t\t\t\t\t\tdescription: 'Chat through a widget embedded in another page, or by calling a webhook',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'hostedChat',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t'Chat will be live at the URL above once you activate this workflow. Live executions will show up in the ‘executions’ tab',\n\t\t\t\tname: 'hostedChatNotice',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['hostedChat'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t'Follow the instructions <a href=\"https://www.npmjs.com/package/@n8n/chat\" target=\"_blank\">here</a> to embed chat in a webpage (or just call the webhook URL at the top of this section). Chat will be live once you activate this workflow',\n\t\t\t\tname: 'embeddedChatNotice',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['webhook'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Authentication',\n\t\t\t\tname: 'authentication',\n\t\t\t\ttype: 'options',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Basic Auth',\n\t\t\t\t\t\tvalue: 'basicAuth',\n\t\t\t\t\t\tdescription: 'Simple username and password (the same one for all users)',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased\n\t\t\t\t\t\tname: 'n8n User Auth',\n\t\t\t\t\t\tvalue: 'n8nUserAuth',\n\t\t\t\t\t\tdescription: 'Require user to be logged in with their n8n account',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'None',\n\t\t\t\t\t\tvalue: 'none',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'none',\n\t\t\t\tdescription: 'The way to authenticate',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Initial Message(s)',\n\t\t\t\tname: 'initialMessages',\n\t\t\t\ttype: 'string',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['hostedChat'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 3,\n\t\t\t\t},\n\t\t\t\tdefault: 'Hi there! 👋\\nMy name is Nathan. How can I assist you today?',\n\t\t\t\tdescription: 'Default messages shown at the start of the chat, one per line',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpublic: [false],\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.1 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tplaceholder: 'Add Field',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [allowFileUploadsOption, allowedFileMimeTypeOption],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['hostedChat', 'webhook'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tplaceholder: 'Add Field',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t// CORS parameters are only valid for when chat is used in hosted or webhook mode\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Allowed Origins (CORS)',\n\t\t\t\t\t\tname: 'allowedOrigins',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: '*',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Comma-separated list of URLs allowed for cross-origin non-preflight requests. Use * (default) to allow all origins.',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat', 'webhook'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...allowFileUploadsOption,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...allowedFileMimeTypeOption,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Input Placeholder',\n\t\t\t\t\t\tname: 'inputPlaceholder',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 'Type your question..',\n\t\t\t\t\t\tplaceholder: 'e.g. Type your message here',\n\t\t\t\t\t\tdescription: 'Shown as placeholder text in the chat input field',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Load Previous Session',\n\t\t\t\t\t\tname: 'loadPreviousSession',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Off',\n\t\t\t\t\t\t\t\tvalue: 'notSupported',\n\t\t\t\t\t\t\t\tdescription: 'Loading messages of previous session is turned off',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'From Memory',\n\t\t\t\t\t\t\t\tvalue: 'memory',\n\t\t\t\t\t\t\t\tdescription: 'Load session messages from memory',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Manually',\n\t\t\t\t\t\t\t\tvalue: 'manually',\n\t\t\t\t\t\t\t\tdescription: 'Manually return messages of session',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'notSupported',\n\t\t\t\t\t\tdescription: 'If loading messages of a previous session should be enabled',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Response Mode',\n\t\t\t\t\t\tname: 'responseMode',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'When Last Node Finishes',\n\t\t\t\t\t\t\t\tvalue: 'lastNode',\n\t\t\t\t\t\t\t\tdescription: 'Returns data of the last-executed node',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: \"Using 'Respond to Webhook' Node\",\n\t\t\t\t\t\t\t\tvalue: 'responseNode',\n\t\t\t\t\t\t\t\tdescription: 'Response defined in that node',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'lastNode',\n\t\t\t\t\t\tdescription: 'When and how to respond to the webhook',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Require Button Click to Start Chat',\n\t\t\t\t\t\tname: 'showWelcomeScreen',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to show the welcome screen at the start of the chat',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Start Conversation Button Text',\n\t\t\t\t\t\tname: 'getStarted',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tshowWelcomeScreen: [true],\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 'New Conversation',\n\t\t\t\t\t\tplaceholder: 'e.g. New Conversation',\n\t\t\t\t\t\tdescription: 'Shown as part of the welcome screen, in the middle of the chat window',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Subtitle',\n\t\t\t\t\t\tname: 'subtitle',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: \"Start a chat. We're here to help you 24/7.\",\n\t\t\t\t\t\tplaceholder: \"e.g. We're here for you\",\n\t\t\t\t\t\tdescription: 'Shown at the top of the chat, under the title',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Title',\n\t\t\t\t\t\tname: 'title',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 'Hi there! 👋',\n\t\t\t\t\t\tplaceholder: 'e.g. Welcome',\n\t\t\t\t\t\tdescription: 'Shown at the top of the chat',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Custom Chat Styling',\n\t\t\t\t\t\tname: 'customCss',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\trows: 10,\n\t\t\t\t\t\t\teditor: 'cssEditor',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: `\n${cssVariables}\n\n/* You can override any class styles, too. Right-click inspect in Chat UI to find class to override. */\n.chat-message {\n\tmax-width: 50%;\n}\n`.trim(),\n\t\t\t\t\t\tdescription: 'Override default styling of the public chat interface with CSS',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tprivate async handleFormData(context: IWebhookFunctions) {\n\t\tconst req = context.getRequestObject() as MultiPartFormData.Request;\n\t\tconst options = context.getNodeParameter('options', {}) as IDataObject;\n\t\tconst { data, files } = req.body;\n\n\t\tconst returnItem: INodeExecutionData = {\n\t\t\tjson: data,\n\t\t};\n\n\t\tif (files && Object.keys(files).length) {\n\t\t\treturnItem.json.files = [] as Array<Omit<IBinaryData, 'data'>>;\n\t\t\treturnItem.binary = {};\n\n\t\t\tconst count = 0;\n\t\t\tfor (const fileKey of Object.keys(files)) {\n\t\t\t\tconst processedFiles: MultiPartFormData.File[] = [];\n\t\t\t\tif (Array.isArray(files[fileKey])) {\n\t\t\t\t\tprocessedFiles.push(...files[fileKey]);\n\t\t\t\t} else {\n\t\t\t\t\tprocessedFiles.push(files[fileKey]);\n\t\t\t\t}\n\n\t\t\t\tlet fileIndex = 0;\n\t\t\t\tfor (const file of processedFiles) {\n\t\t\t\t\tlet binaryPropertyName = 'data';\n\n\t\t\t\t\t// Remove the '[]' suffix from the binaryPropertyName if it exists\n\t\t\t\t\tif (binaryPropertyName.endsWith('[]')) {\n\t\t\t\t\t\tbinaryPropertyName = binaryPropertyName.slice(0, -2);\n\t\t\t\t\t}\n\t\t\t\t\tif (options.binaryPropertyName) {\n\t\t\t\t\t\tbinaryPropertyName = `${options.binaryPropertyName.toString()}${count}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst binaryFile = await context.nodeHelpers.copyBinaryFile(\n\t\t\t\t\t\tfile.filepath,\n\t\t\t\t\t\tfile.originalFilename ?? file.newFilename,\n\t\t\t\t\t\tfile.mimetype,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst binaryKey = `${binaryPropertyName}${fileIndex}`;\n\n\t\t\t\t\tconst binaryInfo = {\n\t\t\t\t\t\t...pick(binaryFile, ['fileName', 'fileSize', 'fileType', 'mimeType', 'fileExtension']),\n\t\t\t\t\t\tbinaryKey,\n\t\t\t\t\t};\n\n\t\t\t\t\treturnItem.binary = Object.assign(returnItem.binary ?? {}, {\n\t\t\t\t\t\t[`${binaryKey}`]: binaryFile,\n\t\t\t\t\t});\n\t\t\t\t\treturnItem.json.files = [\n\t\t\t\t\t\t...(returnItem.json.files as Array<Omit<IBinaryData, 'data'>>),\n\t\t\t\t\t\tbinaryInfo,\n\t\t\t\t\t];\n\t\t\t\t\tfileIndex += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn returnItem;\n\t}\n\n\tasync webhook(ctx: IWebhookFunctions): Promise<IWebhookResponseData> {\n\t\tconst res = ctx.getResponseObject();\n\n\t\tconst isPublic = ctx.getNodeParameter('public', false) as boolean;\n\t\tconst nodeMode = ctx.getNodeParameter('mode', 'hostedChat') as string;\n\t\tif (!isPublic) {\n\t\t\tres.status(404).end();\n\t\t\treturn {\n\t\t\t\tnoWebhookResponse: true,\n\t\t\t};\n\t\t}\n\n\t\tconst options = ctx.getNodeParameter('options', {}) as {\n\t\t\tgetStarted?: string;\n\t\t\tinputPlaceholder?: string;\n\t\t\tloadPreviousSession?: LoadPreviousSessionChatOption;\n\t\t\tshowWelcomeScreen?: boolean;\n\t\t\tsubtitle?: string;\n\t\t\ttitle?: string;\n\t\t\tallowFileUploads?: boolean;\n\t\t\tallowedFilesMimeTypes?: string;\n\t\t\tcustomCss?: string;\n\t\t};\n\n\t\tconst req = ctx.getRequestObject();\n\t\tconst webhookName = ctx.getWebhookName();\n\t\tconst mode = ctx.getMode() === 'manual' ? 'test' : 'production';\n\t\tconst bodyData = ctx.getBodyData() ?? {};\n\n\t\ttry {\n\t\t\tawait validateAuth(ctx);\n\t\t} catch (error) {\n\t\t\tif (error) {\n\t\t\t\tres.writeHead((error as IDataObject).responseCode as number, {\n\t\t\t\t\t'www-authenticate': 'Basic realm=\"Webhook\"',\n\t\t\t\t});\n\t\t\t\tres.end((error as IDataObject).message as string);\n\t\t\t\treturn { noWebhookResponse: true };\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tif (nodeMode === 'hostedChat') {\n\t\t\t// Show the chat on GET request\n\t\t\tif (webhookName === 'setup') {\n\t\t\t\tconst webhookUrlRaw = ctx.getNodeWebhookUrl('default') as string;\n\t\t\t\tconst webhookUrl =\n\t\t\t\t\tmode === 'test' ? webhookUrlRaw.replace('/webhook', '/webhook-test') : webhookUrlRaw;\n\t\t\t\tconst authentication = ctx.getNodeParameter('authentication') as\n\t\t\t\t\t| 'none'\n\t\t\t\t\t| 'basicAuth'\n\t\t\t\t\t| 'n8nUserAuth';\n\t\t\t\tconst initialMessagesRaw = ctx.getNodeParameter('initialMessages', '') as string;\n\t\t\t\tconst initialMessages = initialMessagesRaw\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.filter((line) => line)\n\t\t\t\t\t.map((line) => line.trim());\n\t\t\t\tconst instanceId = ctx.getInstanceId();\n\n\t\t\t\tconst i18nConfig = pick(options, ['getStarted', 'inputPlaceholder', 'subtitle', 'title']);\n\n\t\t\t\tconst page = createPage({\n\t\t\t\t\ti18n: {\n\t\t\t\t\t\ten: i18nConfig,\n\t\t\t\t\t},\n\t\t\t\t\tshowWelcomeScreen: options.showWelcomeScreen,\n\t\t\t\t\tloadPreviousSession: options.loadPreviousSession,\n\t\t\t\t\tinitialMessages,\n\t\t\t\t\twebhookUrl,\n\t\t\t\t\tmode,\n\t\t\t\t\tinstanceId,\n\t\t\t\t\tauthentication,\n\t\t\t\t\tallowFileUploads: options.allowFileUploads,\n\t\t\t\t\tallowedFilesMimeTypes: options.allowedFilesMimeTypes,\n\t\t\t\t\tcustomCss: options.customCss,\n\t\t\t\t});\n\n\t\t\t\tres.status(200).send(page).end();\n\t\t\t\treturn {\n\t\t\t\t\tnoWebhookResponse: true,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (bodyData.action === 'loadPreviousSession') {\n\t\t\tif (options?.loadPreviousSession === 'memory') {\n\t\t\t\tconst memory = (await ctx.getInputConnectionData(NodeConnectionTypes.AiMemory, 0)) as\n\t\t\t\t\t| BaseChatMemory\n\t\t\t\t\t| undefined;\n\t\t\t\tconst messages = ((await memory?.chatHistory.getMessages()) ?? [])\n\t\t\t\t\t.filter((message) => !message?.additional_kwargs?.hideFromUI)\n\t\t\t\t\t.map((message) => message?.toJSON());\n\t\t\t\treturn {\n\t\t\t\t\twebhookResponse: { data: messages },\n\t\t\t\t};\n\t\t\t} else if (options?.loadPreviousSession === 'notSupported') {\n\t\t\t\t// If messages of a previous session should not be loaded, simply return an empty array\n\t\t\t\treturn {\n\t\t\t\t\twebhookResponse: { data: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tlet returnData: INodeExecutionData[];\n\t\tconst webhookResponse: IDataObject = { status: 200 };\n\t\tif (req.contentType === 'multipart/form-data') {\n\t\t\treturnData = [await this.handleFormData(ctx)];\n\t\t\treturn {\n\t\t\t\twebhookResponse,\n\t\t\t\tworkflowData: [returnData],\n\t\t\t};\n\t\t} else {\n\t\t\treturnData = [{ json: bodyData }];\n\t\t}\n\n\t\treturn {\n\t\t\twebhookResponse,\n\t\t\tworkflowData: [ctx.helpers.returnJsonArray(returnData)],\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/trigger/ChatTrigger/ChatTrigger.node.ts"],"sourcesContent":["import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';\nimport { pick } from 'lodash';\nimport { Node, NodeConnectionTypes } from 'n8n-workflow';\nimport type {\n\tIDataObject,\n\tIWebhookFunctions,\n\tIWebhookResponseData,\n\tINodeTypeDescription,\n\tMultiPartFormData,\n\tINodeExecutionData,\n\tIBinaryData,\n\tINodeProperties,\n} from 'n8n-workflow';\n\nimport { cssVariables } from './constants';\nimport { validateAuth } from './GenericFunctions';\nimport { createPage } from './templates';\nimport type { LoadPreviousSessionChatOption } from './types';\n\nconst CHAT_TRIGGER_PATH_IDENTIFIER = 'chat';\nconst allowFileUploadsOption: INodeProperties = {\n\tdisplayName: 'Allow File Uploads',\n\tname: 'allowFileUploads',\n\ttype: 'boolean',\n\tdefault: false,\n\tdescription: 'Whether to allow file uploads in the chat',\n};\nconst allowedFileMimeTypeOption: INodeProperties = {\n\tdisplayName: 'Allowed File Mime Types',\n\tname: 'allowedFilesMimeTypes',\n\ttype: 'string',\n\tdefault: '*',\n\tplaceholder: 'e.g. image/*, text/*, application/pdf',\n\tdescription:\n\t\t'Allowed file types for upload. Comma-separated list of <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\" target=\"_blank\">MIME types</a>.',\n};\n\nexport class ChatTrigger extends Node {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Chat Trigger',\n\t\tname: 'chatTrigger',\n\t\ticon: 'fa:comments',\n\t\ticonColor: 'black',\n\t\tgroup: ['trigger'],\n\t\tversion: [1, 1.1],\n\t\tdescription: 'Runs the workflow when an n8n generated webchat is submitted',\n\t\tdefaults: {\n\t\t\tname: 'When chat message received',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['Core Nodes'],\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.chattrigger/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tmaxNodes: 1,\n\t\tinputs: `={{ (() => {\n\t\t\tif (!['hostedChat', 'webhook'].includes($parameter.mode)) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tif ($parameter.options?.loadPreviousSession !== 'memory') {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Memory',\n\t\t\t\t\tmaxConnections: 1,\n\t\t\t\t\ttype: '${NodeConnectionTypes.AiMemory}',\n\t\t\t\t\trequired: true,\n\t\t\t\t}\n\t\t\t];\n\t\t })() }}`,\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed\n\t\t\t\tname: 'httpBasicAuth',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['basicAuth'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twebhooks: [\n\t\t\t{\n\t\t\t\tname: 'setup',\n\t\t\t\thttpMethod: 'GET',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tpath: CHAT_TRIGGER_PATH_IDENTIFIER,\n\t\t\t\tndvHideUrl: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'POST',\n\t\t\t\tresponseMode: '={{$parameter.options?.[\"responseMode\"] || \"lastNode\" }}',\n\t\t\t\tpath: CHAT_TRIGGER_PATH_IDENTIFIER,\n\t\t\t\tndvHideMethod: true,\n\t\t\t\tndvHideUrl: '={{ !$parameter.public }}',\n\t\t\t},\n\t\t],\n\t\teventTriggerDescription: 'Waiting for you to submit the chat',\n\t\tactivationMessage: 'You can now make calls to your production chat URL.',\n\t\ttriggerPanel: false,\n\t\tproperties: [\n\t\t\t/**\n\t\t\t * @note If we change this property, also update it in ChatEmbedModal.vue\n\t\t\t */\n\t\t\t{\n\t\t\t\tdisplayName: 'Make Chat Publicly Available',\n\t\t\t\tname: 'public',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether the chat should be publicly available or only accessible through the manual chat interface',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Mode',\n\t\t\t\tname: 'mode',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Hosted Chat',\n\t\t\t\t\t\tvalue: 'hostedChat',\n\t\t\t\t\t\tdescription: 'Chat on a page served by n8n',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Embedded Chat',\n\t\t\t\t\t\tvalue: 'webhook',\n\t\t\t\t\t\tdescription: 'Chat through a widget embedded in another page, or by calling a webhook',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'hostedChat',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t'Chat will be live at the URL above once you activate this workflow. Live executions will show up in the ‘executions’ tab',\n\t\t\t\tname: 'hostedChatNotice',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['hostedChat'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t'Follow the instructions <a href=\"https://www.npmjs.com/package/@n8n/chat\" target=\"_blank\">here</a> to embed chat in a webpage (or just call the webhook URL at the top of this section). Chat will be live once you activate this workflow',\n\t\t\t\tname: 'embeddedChatNotice',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['webhook'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Authentication',\n\t\t\t\tname: 'authentication',\n\t\t\t\ttype: 'options',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Basic Auth',\n\t\t\t\t\t\tvalue: 'basicAuth',\n\t\t\t\t\t\tdescription: 'Simple username and password (the same one for all users)',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased\n\t\t\t\t\t\tname: 'n8n User Auth',\n\t\t\t\t\t\tvalue: 'n8nUserAuth',\n\t\t\t\t\t\tdescription: 'Require user to be logged in with their n8n account',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'None',\n\t\t\t\t\t\tvalue: 'none',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'none',\n\t\t\t\tdescription: 'The way to authenticate',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Initial Message(s)',\n\t\t\t\tname: 'initialMessages',\n\t\t\t\ttype: 'string',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['hostedChat'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 3,\n\t\t\t\t},\n\t\t\t\tdefault: 'Hi there! 👋\\nMy name is Nathan. How can I assist you today?',\n\t\t\t\tdescription: 'Default messages shown at the start of the chat, one per line',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpublic: [false],\n\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.1 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tplaceholder: 'Add Field',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [allowFileUploadsOption, allowedFileMimeTypeOption],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tmode: ['hostedChat', 'webhook'],\n\t\t\t\t\t\tpublic: [true],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tplaceholder: 'Add Field',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t// CORS parameters are only valid for when chat is used in hosted or webhook mode\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Allowed Origins (CORS)',\n\t\t\t\t\t\tname: 'allowedOrigins',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: '*',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Comma-separated list of URLs allowed for cross-origin non-preflight requests. Use * (default) to allow all origins.',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat', 'webhook'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...allowFileUploadsOption,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...allowedFileMimeTypeOption,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Input Placeholder',\n\t\t\t\t\t\tname: 'inputPlaceholder',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 'Type your question..',\n\t\t\t\t\t\tplaceholder: 'e.g. Type your message here',\n\t\t\t\t\t\tdescription: 'Shown as placeholder text in the chat input field',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Load Previous Session',\n\t\t\t\t\t\tname: 'loadPreviousSession',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Off',\n\t\t\t\t\t\t\t\tvalue: 'notSupported',\n\t\t\t\t\t\t\t\tdescription: 'Loading messages of previous session is turned off',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'From Memory',\n\t\t\t\t\t\t\t\tvalue: 'memory',\n\t\t\t\t\t\t\t\tdescription: 'Load session messages from memory',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Manually',\n\t\t\t\t\t\t\t\tvalue: 'manually',\n\t\t\t\t\t\t\t\tdescription: 'Manually return messages of session',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'notSupported',\n\t\t\t\t\t\tdescription: 'If loading messages of a previous session should be enabled',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Response Mode',\n\t\t\t\t\t\tname: 'responseMode',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'When Last Node Finishes',\n\t\t\t\t\t\t\t\tvalue: 'lastNode',\n\t\t\t\t\t\t\t\tdescription: 'Returns data of the last-executed node',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: \"Using 'Respond to Webhook' Node\",\n\t\t\t\t\t\t\t\tvalue: 'responseNode',\n\t\t\t\t\t\t\t\tdescription: 'Response defined in that node',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'lastNode',\n\t\t\t\t\t\tdescription: 'When and how to respond to the webhook',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Require Button Click to Start Chat',\n\t\t\t\t\t\tname: 'showWelcomeScreen',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to show the welcome screen at the start of the chat',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Start Conversation Button Text',\n\t\t\t\t\t\tname: 'getStarted',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tshowWelcomeScreen: [true],\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 'New Conversation',\n\t\t\t\t\t\tplaceholder: 'e.g. New Conversation',\n\t\t\t\t\t\tdescription: 'Shown as part of the welcome screen, in the middle of the chat window',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Subtitle',\n\t\t\t\t\t\tname: 'subtitle',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: \"Start a chat. We're here to help you 24/7.\",\n\t\t\t\t\t\tplaceholder: \"e.g. We're here for you\",\n\t\t\t\t\t\tdescription: 'Shown at the top of the chat, under the title',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Title',\n\t\t\t\t\t\tname: 'title',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: 'Hi there! 👋',\n\t\t\t\t\t\tplaceholder: 'e.g. Welcome',\n\t\t\t\t\t\tdescription: 'Shown at the top of the chat',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Custom Chat Styling',\n\t\t\t\t\t\tname: 'customCss',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\trows: 10,\n\t\t\t\t\t\t\teditor: 'cssEditor',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'/mode': ['hostedChat'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: `\n${cssVariables}\n\n/* You can override any class styles, too. Right-click inspect in Chat UI to find class to override. */\n.chat-message {\n\tmax-width: 50%;\n}\n`.trim(),\n\t\t\t\t\t\tdescription: 'Override default styling of the public chat interface with CSS',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tprivate async handleFormData(context: IWebhookFunctions) {\n\t\tconst req = context.getRequestObject() as MultiPartFormData.Request;\n\t\tconst options = context.getNodeParameter('options', {}) as IDataObject;\n\t\tconst { data, files } = req.body;\n\n\t\tconst returnItem: INodeExecutionData = {\n\t\t\tjson: data,\n\t\t};\n\n\t\tif (files && Object.keys(files).length) {\n\t\t\treturnItem.json.files = [] as Array<Omit<IBinaryData, 'data'>>;\n\t\t\treturnItem.binary = {};\n\n\t\t\tconst count = 0;\n\t\t\tfor (const fileKey of Object.keys(files)) {\n\t\t\t\tconst processedFiles: MultiPartFormData.File[] = [];\n\t\t\t\tif (Array.isArray(files[fileKey])) {\n\t\t\t\t\tprocessedFiles.push(...files[fileKey]);\n\t\t\t\t} else {\n\t\t\t\t\tprocessedFiles.push(files[fileKey]);\n\t\t\t\t}\n\n\t\t\t\tlet fileIndex = 0;\n\t\t\t\tfor (const file of processedFiles) {\n\t\t\t\t\tlet binaryPropertyName = 'data';\n\n\t\t\t\t\t// Remove the '[]' suffix from the binaryPropertyName if it exists\n\t\t\t\t\tif (binaryPropertyName.endsWith('[]')) {\n\t\t\t\t\t\tbinaryPropertyName = binaryPropertyName.slice(0, -2);\n\t\t\t\t\t}\n\t\t\t\t\tif (options.binaryPropertyName) {\n\t\t\t\t\t\tbinaryPropertyName = `${options.binaryPropertyName.toString()}${count}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst binaryFile = await context.nodeHelpers.copyBinaryFile(\n\t\t\t\t\t\tfile.filepath,\n\t\t\t\t\t\tfile.originalFilename ?? file.newFilename,\n\t\t\t\t\t\tfile.mimetype,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst binaryKey = `${binaryPropertyName}${fileIndex}`;\n\n\t\t\t\t\tconst binaryInfo = {\n\t\t\t\t\t\t...pick(binaryFile, ['fileName', 'fileSize', 'fileType', 'mimeType', 'fileExtension']),\n\t\t\t\t\t\tbinaryKey,\n\t\t\t\t\t};\n\n\t\t\t\t\treturnItem.binary = Object.assign(returnItem.binary ?? {}, {\n\t\t\t\t\t\t[`${binaryKey}`]: binaryFile,\n\t\t\t\t\t});\n\t\t\t\t\treturnItem.json.files = [\n\t\t\t\t\t\t...(returnItem.json.files as Array<Omit<IBinaryData, 'data'>>),\n\t\t\t\t\t\tbinaryInfo,\n\t\t\t\t\t];\n\t\t\t\t\tfileIndex += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn returnItem;\n\t}\n\n\tasync webhook(ctx: IWebhookFunctions): Promise<IWebhookResponseData> {\n\t\tconst res = ctx.getResponseObject();\n\n\t\tconst isPublic = ctx.getNodeParameter('public', false) as boolean;\n\t\tconst nodeMode = ctx.getNodeParameter('mode', 'hostedChat') as string;\n\t\tif (!isPublic) {\n\t\t\tres.status(404).end();\n\t\t\treturn {\n\t\t\t\tnoWebhookResponse: true,\n\t\t\t};\n\t\t}\n\n\t\tconst options = ctx.getNodeParameter('options', {}) as {\n\t\t\tgetStarted?: string;\n\t\t\tinputPlaceholder?: string;\n\t\t\tloadPreviousSession?: LoadPreviousSessionChatOption;\n\t\t\tshowWelcomeScreen?: boolean;\n\t\t\tsubtitle?: string;\n\t\t\ttitle?: string;\n\t\t\tallowFileUploads?: boolean;\n\t\t\tallowedFilesMimeTypes?: string;\n\t\t\tcustomCss?: string;\n\t\t};\n\n\t\tconst req = ctx.getRequestObject();\n\t\tconst webhookName = ctx.getWebhookName();\n\t\tconst mode = ctx.getMode() === 'manual' ? 'test' : 'production';\n\t\tconst bodyData = ctx.getBodyData() ?? {};\n\n\t\ttry {\n\t\t\tawait validateAuth(ctx);\n\t\t} catch (error) {\n\t\t\tif (error) {\n\t\t\t\tres.writeHead((error as IDataObject).responseCode as number, {\n\t\t\t\t\t'www-authenticate': 'Basic realm=\"Webhook\"',\n\t\t\t\t});\n\t\t\t\tres.end((error as IDataObject).message as string);\n\t\t\t\treturn { noWebhookResponse: true };\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tif (nodeMode === 'hostedChat') {\n\t\t\t// Show the chat on GET request\n\t\t\tif (webhookName === 'setup') {\n\t\t\t\tconst webhookUrlRaw = ctx.getNodeWebhookUrl('default') as string;\n\t\t\t\tconst webhookUrl =\n\t\t\t\t\tmode === 'test' ? webhookUrlRaw.replace('/webhook', '/webhook-test') : webhookUrlRaw;\n\t\t\t\tconst authentication = ctx.getNodeParameter('authentication') as\n\t\t\t\t\t| 'none'\n\t\t\t\t\t| 'basicAuth'\n\t\t\t\t\t| 'n8nUserAuth';\n\t\t\t\tconst initialMessagesRaw = ctx.getNodeParameter('initialMessages', '') as string;\n\t\t\t\tconst initialMessages = initialMessagesRaw\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.filter((line) => line)\n\t\t\t\t\t.map((line) => line.trim());\n\t\t\t\tconst instanceId = ctx.getInstanceId();\n\n\t\t\t\tconst i18nConfig = pick(options, ['getStarted', 'inputPlaceholder', 'subtitle', 'title']);\n\n\t\t\t\tconst page = createPage({\n\t\t\t\t\ti18n: {\n\t\t\t\t\t\ten: i18nConfig,\n\t\t\t\t\t},\n\t\t\t\t\tshowWelcomeScreen: options.showWelcomeScreen,\n\t\t\t\t\tloadPreviousSession: options.loadPreviousSession,\n\t\t\t\t\tinitialMessages,\n\t\t\t\t\twebhookUrl,\n\t\t\t\t\tmode,\n\t\t\t\t\tinstanceId,\n\t\t\t\t\tauthentication,\n\t\t\t\t\tallowFileUploads: options.allowFileUploads,\n\t\t\t\t\tallowedFilesMimeTypes: options.allowedFilesMimeTypes,\n\t\t\t\t\tcustomCss: options.customCss,\n\t\t\t\t});\n\n\t\t\t\tres.status(200).send(page).end();\n\t\t\t\treturn {\n\t\t\t\t\tnoWebhookResponse: true,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (bodyData.action === 'loadPreviousSession') {\n\t\t\tif (options?.loadPreviousSession === 'memory') {\n\t\t\t\tconst memory = (await ctx.getInputConnectionData(NodeConnectionTypes.AiMemory, 0)) as\n\t\t\t\t\t| BaseChatMemory\n\t\t\t\t\t| undefined;\n\t\t\t\tconst messages = ((await memory?.chatHistory.getMessages()) ?? [])\n\t\t\t\t\t.filter((message) => !message?.additional_kwargs?.hideFromUI)\n\t\t\t\t\t.map((message) => message?.toJSON());\n\t\t\t\treturn {\n\t\t\t\t\twebhookResponse: { data: messages },\n\t\t\t\t};\n\t\t\t} else if (!options?.loadPreviousSession || options?.loadPreviousSession === 'notSupported') {\n\t\t\t\t// If messages of a previous session should not be loaded, simply return an empty array\n\t\t\t\treturn {\n\t\t\t\t\twebhookResponse: { data: [] },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tlet returnData: INodeExecutionData[];\n\t\tconst webhookResponse: IDataObject = { status: 200 };\n\t\tif (req.contentType === 'multipart/form-data') {\n\t\t\treturnData = [await this.handleFormData(ctx)];\n\t\t\treturn {\n\t\t\t\twebhookResponse,\n\t\t\t\tworkflowData: [returnData],\n\t\t\t};\n\t\t} else {\n\t\t\treturnData = [{ json: bodyData }];\n\t\t}\n\n\t\treturn {\n\t\t\twebhookResponse,\n\t\t\tworkflowData: [ctx.helpers.returnJsonArray(returnData)],\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -21,23 +21,37 @@ __export(VectorStoreInMemory_node_exports, {
|
|
|
21
21
|
VectorStoreInMemory: () => VectorStoreInMemory
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(VectorStoreInMemory_node_exports);
|
|
24
|
+
var import_n8n_workflow = require("n8n-workflow");
|
|
24
25
|
var import_createVectorStoreNode = require("../shared/createVectorStoreNode/createVectorStoreNode");
|
|
25
26
|
var import_MemoryVectorStoreManager = require("../shared/MemoryManager/MemoryVectorStoreManager");
|
|
27
|
+
const warningBanner = {
|
|
28
|
+
displayName: '<strong>For experimental use only</strong>: Data is stored in memory and will be lost if n8n restarts. Data may also be cleared if available memory gets low, and is accessible to all users of this instance. <a href="https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/">More info</a>',
|
|
29
|
+
name: "notice",
|
|
30
|
+
type: "notice",
|
|
31
|
+
default: ""
|
|
32
|
+
};
|
|
26
33
|
const insertFields = [
|
|
27
|
-
{
|
|
28
|
-
displayName: '<strong>For experimental use only</strong>: Data is stored in memory and will be lost if n8n restarts. Data may also be cleared if available memory gets low. <a href="https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/">More info</a>',
|
|
29
|
-
name: "notice",
|
|
30
|
-
type: "notice",
|
|
31
|
-
default: ""
|
|
32
|
-
},
|
|
33
34
|
{
|
|
34
35
|
displayName: "Clear Store",
|
|
35
36
|
name: "clearStore",
|
|
36
37
|
type: "boolean",
|
|
37
38
|
default: false,
|
|
38
39
|
description: "Whether to clear the store before inserting new data"
|
|
39
|
-
}
|
|
40
|
+
},
|
|
41
|
+
warningBanner
|
|
40
42
|
];
|
|
43
|
+
const DEFAULT_MEMORY_KEY = "vector_store_key";
|
|
44
|
+
function getMemoryKey(context, itemIndex) {
|
|
45
|
+
const node = context.getNode();
|
|
46
|
+
if (node.typeVersion <= 1.1) {
|
|
47
|
+
const memoryKeyParam = context.getNodeParameter("memoryKey", itemIndex);
|
|
48
|
+
const workflowId = context.getWorkflow().id;
|
|
49
|
+
return `${workflowId}__${memoryKeyParam}`;
|
|
50
|
+
} else {
|
|
51
|
+
const memoryKeyParam = context.getNodeParameter("memoryKey", itemIndex);
|
|
52
|
+
return memoryKeyParam.value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
41
55
|
class VectorStoreInMemory extends (0, import_createVectorStoreNode.createVectorStoreNode)({
|
|
42
56
|
meta: {
|
|
43
57
|
displayName: "Simple Vector Store",
|
|
@@ -52,25 +66,103 @@ class VectorStoreInMemory extends (0, import_createVectorStoreNode.createVectorS
|
|
|
52
66
|
displayName: "Memory Key",
|
|
53
67
|
name: "memoryKey",
|
|
54
68
|
type: "string",
|
|
55
|
-
default:
|
|
56
|
-
description: "The key to use to store the vector memory in the workflow data. The key will be prefixed with the workflow ID to avoid collisions."
|
|
69
|
+
default: DEFAULT_MEMORY_KEY,
|
|
70
|
+
description: "The key to use to store the vector memory in the workflow data. The key will be prefixed with the workflow ID to avoid collisions.",
|
|
71
|
+
displayOptions: {
|
|
72
|
+
show: {
|
|
73
|
+
"@version": [{ _cnd: { lte: 1.1 } }]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
displayName: "Memory Key",
|
|
79
|
+
name: "memoryKey",
|
|
80
|
+
type: "resourceLocator",
|
|
81
|
+
required: true,
|
|
82
|
+
default: { mode: "list", value: DEFAULT_MEMORY_KEY },
|
|
83
|
+
description: "The key to use to store the vector memory in the workflow data. These keys are shared between workflows.",
|
|
84
|
+
displayOptions: {
|
|
85
|
+
show: {
|
|
86
|
+
"@version": [{ _cnd: { gte: 1.2 } }]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
modes: [
|
|
90
|
+
{
|
|
91
|
+
displayName: "From List",
|
|
92
|
+
name: "list",
|
|
93
|
+
type: "list",
|
|
94
|
+
typeOptions: {
|
|
95
|
+
searchListMethod: "vectorStoresSearch",
|
|
96
|
+
searchable: true,
|
|
97
|
+
allowNewResource: {
|
|
98
|
+
label: "resourceLocator.mode.list.addNewResource.vectorStoreInMemory",
|
|
99
|
+
defaultName: DEFAULT_MEMORY_KEY,
|
|
100
|
+
method: "createVectorStore"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
displayName: "Manual",
|
|
106
|
+
name: "id",
|
|
107
|
+
type: "string",
|
|
108
|
+
placeholder: DEFAULT_MEMORY_KEY
|
|
109
|
+
}
|
|
110
|
+
]
|
|
57
111
|
}
|
|
58
112
|
],
|
|
113
|
+
methods: {
|
|
114
|
+
listSearch: {
|
|
115
|
+
async vectorStoresSearch(filter) {
|
|
116
|
+
const vectorStoreSingleton = import_MemoryVectorStoreManager.MemoryVectorStoreManager.getInstance(
|
|
117
|
+
{},
|
|
118
|
+
// Real Embeddings are provided when executing the node
|
|
119
|
+
this.logger
|
|
120
|
+
);
|
|
121
|
+
const searchOptions = vectorStoreSingleton.getMemoryKeysList().map((key) => {
|
|
122
|
+
return {
|
|
123
|
+
name: key,
|
|
124
|
+
value: key
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
let results = searchOptions;
|
|
128
|
+
if (filter) {
|
|
129
|
+
results = results.filter((option) => option.name.includes(filter));
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
results
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
actionHandler: {
|
|
137
|
+
async createVectorStore(payload) {
|
|
138
|
+
if (!payload || typeof payload === "string") {
|
|
139
|
+
throw new import_n8n_workflow.ApplicationError("Invalid payload type");
|
|
140
|
+
}
|
|
141
|
+
const { name } = payload;
|
|
142
|
+
const vectorStoreSingleton = import_MemoryVectorStoreManager.MemoryVectorStoreManager.getInstance(
|
|
143
|
+
{},
|
|
144
|
+
// Real Embeddings are provided when executing the node
|
|
145
|
+
this.logger
|
|
146
|
+
);
|
|
147
|
+
const memoryKey = !!name ? name : DEFAULT_MEMORY_KEY;
|
|
148
|
+
await vectorStoreSingleton.getVectorStore(memoryKey);
|
|
149
|
+
return memoryKey;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
59
153
|
insertFields,
|
|
60
|
-
loadFields: [],
|
|
61
|
-
retrieveFields: [],
|
|
154
|
+
loadFields: [warningBanner],
|
|
155
|
+
retrieveFields: [warningBanner],
|
|
62
156
|
async getVectorStoreClient(context, _filter, embeddings, itemIndex) {
|
|
63
|
-
const
|
|
64
|
-
const memoryKey = context.getNodeParameter("memoryKey", itemIndex);
|
|
157
|
+
const memoryKey = getMemoryKey(context, itemIndex);
|
|
65
158
|
const vectorStoreSingleton = import_MemoryVectorStoreManager.MemoryVectorStoreManager.getInstance(embeddings, context.logger);
|
|
66
|
-
return await vectorStoreSingleton.getVectorStore(
|
|
159
|
+
return await vectorStoreSingleton.getVectorStore(memoryKey);
|
|
67
160
|
},
|
|
68
161
|
async populateVectorStore(context, embeddings, documents, itemIndex) {
|
|
69
|
-
const memoryKey = context
|
|
162
|
+
const memoryKey = getMemoryKey(context, itemIndex);
|
|
70
163
|
const clearStore = context.getNodeParameter("clearStore", itemIndex);
|
|
71
|
-
const workflowId = context.getWorkflow().id;
|
|
72
164
|
const vectorStoreInstance = import_MemoryVectorStoreManager.MemoryVectorStoreManager.getInstance(embeddings, context.logger);
|
|
73
|
-
await vectorStoreInstance.addDocuments(
|
|
165
|
+
await vectorStoreInstance.addDocuments(memoryKey, documents, clearStore);
|
|
74
166
|
}
|
|
75
167
|
}) {
|
|
76
168
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.ts"],"sourcesContent":["import type { MemoryVectorStore } from 'langchain/vectorstores/memory';\nimport
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.ts"],"sourcesContent":["import type { Embeddings } from '@langchain/core/embeddings';\nimport type { MemoryVectorStore } from 'langchain/vectorstores/memory';\nimport {\n\ttype INodeProperties,\n\ttype ILoadOptionsFunctions,\n\ttype INodeListSearchResult,\n\ttype IDataObject,\n\ttype NodeParameterValueType,\n\ttype IExecuteFunctions,\n\ttype ISupplyDataFunctions,\n\tApplicationError,\n} from 'n8n-workflow';\n\nimport { createVectorStoreNode } from '../shared/createVectorStoreNode/createVectorStoreNode';\nimport { MemoryVectorStoreManager } from '../shared/MemoryManager/MemoryVectorStoreManager';\n\nconst warningBanner: INodeProperties = {\n\tdisplayName:\n\t\t'<strong>For experimental use only</strong>: Data is stored in memory and will be lost if n8n restarts. Data may also be cleared if available memory gets low, and is accessible to all users of this instance. <a href=\"https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/\">More info</a>',\n\tname: 'notice',\n\ttype: 'notice',\n\tdefault: '',\n};\n\nconst insertFields: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'Clear Store',\n\t\tname: 'clearStore',\n\t\ttype: 'boolean',\n\t\tdefault: false,\n\t\tdescription: 'Whether to clear the store before inserting new data',\n\t},\n\twarningBanner,\n];\n\nconst DEFAULT_MEMORY_KEY = 'vector_store_key';\n\nfunction getMemoryKey(context: IExecuteFunctions | ISupplyDataFunctions, itemIndex: number) {\n\tconst node = context.getNode();\n\tif (node.typeVersion <= 1.1) {\n\t\tconst memoryKeyParam = context.getNodeParameter('memoryKey', itemIndex) as string;\n\t\tconst workflowId = context.getWorkflow().id;\n\n\t\treturn `${workflowId}__${memoryKeyParam}`;\n\t} else {\n\t\tconst memoryKeyParam = context.getNodeParameter('memoryKey', itemIndex) as {\n\t\t\tmode: string;\n\t\t\tvalue: string;\n\t\t};\n\n\t\treturn memoryKeyParam.value;\n\t}\n}\n\nexport class VectorStoreInMemory extends createVectorStoreNode<MemoryVectorStore>({\n\tmeta: {\n\t\tdisplayName: 'Simple Vector Store',\n\t\tname: 'vectorStoreInMemory',\n\t\tdescription:\n\t\t\t\"Work with your data in a Simple Vector Store. Don't use this for production usage.\",\n\t\ticon: 'fa:database',\n\t\ticonColor: 'black',\n\t\tdocsUrl:\n\t\t\t'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/',\n\t},\n\tsharedFields: [\n\t\t{\n\t\t\tdisplayName: 'Memory Key',\n\t\t\tname: 'memoryKey',\n\t\t\ttype: 'string',\n\t\t\tdefault: DEFAULT_MEMORY_KEY,\n\t\t\tdescription:\n\t\t\t\t'The key to use to store the vector memory in the workflow data. The key will be prefixed with the workflow ID to avoid collisions.',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\t'@version': [{ _cnd: { lte: 1.1 } }],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Memory Key',\n\t\t\tname: 'memoryKey',\n\t\t\ttype: 'resourceLocator',\n\t\t\trequired: true,\n\t\t\tdefault: { mode: 'list', value: DEFAULT_MEMORY_KEY },\n\t\t\tdescription:\n\t\t\t\t'The key to use to store the vector memory in the workflow data. These keys are shared between workflows.',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\t'@version': [{ _cnd: { gte: 1.2 } }],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmodes: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\tname: 'list',\n\t\t\t\t\ttype: 'list',\n\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\tsearchListMethod: 'vectorStoresSearch',\n\t\t\t\t\t\tsearchable: true,\n\t\t\t\t\t\tallowNewResource: {\n\t\t\t\t\t\t\tlabel: 'resourceLocator.mode.list.addNewResource.vectorStoreInMemory',\n\t\t\t\t\t\t\tdefaultName: DEFAULT_MEMORY_KEY,\n\t\t\t\t\t\t\tmethod: 'createVectorStore',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Manual',\n\t\t\t\t\tname: 'id',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tplaceholder: DEFAULT_MEMORY_KEY,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n\tmethods: {\n\t\tlistSearch: {\n\t\t\tasync vectorStoresSearch(\n\t\t\t\tthis: ILoadOptionsFunctions,\n\t\t\t\tfilter?: string,\n\t\t\t): Promise<INodeListSearchResult> {\n\t\t\t\tconst vectorStoreSingleton = MemoryVectorStoreManager.getInstance(\n\t\t\t\t\t{} as Embeddings, // Real Embeddings are provided when executing the node\n\t\t\t\t\tthis.logger,\n\t\t\t\t);\n\n\t\t\t\tconst searchOptions: INodeListSearchResult['results'] = vectorStoreSingleton\n\t\t\t\t\t.getMemoryKeysList()\n\t\t\t\t\t.map((key) => {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: key,\n\t\t\t\t\t\t\tvalue: key,\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\n\t\t\t\tlet results = searchOptions;\n\t\t\t\tif (filter) {\n\t\t\t\t\tresults = results.filter((option) => option.name.includes(filter));\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tresults,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\tactionHandler: {\n\t\t\tasync createVectorStore(\n\t\t\t\tthis: ILoadOptionsFunctions,\n\t\t\t\tpayload: string | IDataObject | undefined,\n\t\t\t): Promise<NodeParameterValueType> {\n\t\t\t\tif (!payload || typeof payload === 'string') {\n\t\t\t\t\tthrow new ApplicationError('Invalid payload type');\n\t\t\t\t}\n\n\t\t\t\tconst { name } = payload;\n\n\t\t\t\tconst vectorStoreSingleton = MemoryVectorStoreManager.getInstance(\n\t\t\t\t\t{} as Embeddings, // Real Embeddings are provided when executing the node\n\t\t\t\t\tthis.logger,\n\t\t\t\t);\n\n\t\t\t\tconst memoryKey = !!name ? (name as string) : DEFAULT_MEMORY_KEY;\n\t\t\t\tawait vectorStoreSingleton.getVectorStore(memoryKey);\n\n\t\t\t\treturn memoryKey;\n\t\t\t},\n\t\t},\n\t},\n\tinsertFields,\n\tloadFields: [warningBanner],\n\tretrieveFields: [warningBanner],\n\tasync getVectorStoreClient(context, _filter, embeddings, itemIndex) {\n\t\tconst memoryKey = getMemoryKey(context, itemIndex);\n\t\tconst vectorStoreSingleton = MemoryVectorStoreManager.getInstance(embeddings, context.logger);\n\n\t\treturn await vectorStoreSingleton.getVectorStore(memoryKey);\n\t},\n\tasync populateVectorStore(context, embeddings, documents, itemIndex) {\n\t\tconst memoryKey = getMemoryKey(context, itemIndex);\n\t\tconst clearStore = context.getNodeParameter('clearStore', itemIndex) as boolean;\n\t\tconst vectorStoreInstance = MemoryVectorStoreManager.getInstance(embeddings, context.logger);\n\n\t\tawait vectorStoreInstance.addDocuments(memoryKey, documents, clearStore);\n\t},\n}) {}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,0BASO;AAEP,mCAAsC;AACtC,sCAAyC;AAEzC,MAAM,gBAAiC;AAAA,EACtC,aACC;AAAA,EACD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AACV;AAEA,MAAM,eAAkC;AAAA,EACvC;AAAA,IACC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AACD;AAEA,MAAM,qBAAqB;AAE3B,SAAS,aAAa,SAAmD,WAAmB;AAC3F,QAAM,OAAO,QAAQ,QAAQ;AAC7B,MAAI,KAAK,eAAe,KAAK;AAC5B,UAAM,iBAAiB,QAAQ,iBAAiB,aAAa,SAAS;AACtE,UAAM,aAAa,QAAQ,YAAY,EAAE;AAEzC,WAAO,GAAG,UAAU,KAAK,cAAc;AAAA,EACxC,OAAO;AACN,UAAM,iBAAiB,QAAQ,iBAAiB,aAAa,SAAS;AAKtE,WAAO,eAAe;AAAA,EACvB;AACD;AAEO,MAAM,gCAA4B,oDAAyC;AAAA,EACjF,MAAM;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aACC;AAAA,IACD,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SACC;AAAA,EACF;AAAA,EACA,cAAc;AAAA,IACb;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aACC;AAAA,MACD,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;AAAA,QACpC;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,EAAE,MAAM,QAAQ,OAAO,mBAAmB;AAAA,MACnD,aACC;AAAA,MACD,gBAAgB;AAAA,QACf,MAAM;AAAA,UACL,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;AAAA,QACpC;AAAA,MACD;AAAA,MACA,OAAO;AAAA,QACN;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,YACZ,kBAAkB;AAAA,YAClB,YAAY;AAAA,YACZ,kBAAkB;AAAA,cACjB,OAAO;AAAA,cACP,aAAa;AAAA,cACb,QAAQ;AAAA,YACT;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,QACd;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EACA,SAAS;AAAA,IACR,YAAY;AAAA,MACX,MAAM,mBAEL,QACiC;AACjC,cAAM,uBAAuB,yDAAyB;AAAA,UACrD,CAAC;AAAA;AAAA,UACD,KAAK;AAAA,QACN;AAEA,cAAM,gBAAkD,qBACtD,kBAAkB,EAClB,IAAI,CAAC,QAAQ;AACb,iBAAO;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACR;AAAA,QACD,CAAC;AAEF,YAAI,UAAU;AACd,YAAI,QAAQ;AACX,oBAAU,QAAQ,OAAO,CAAC,WAAW,OAAO,KAAK,SAAS,MAAM,CAAC;AAAA,QAClE;AAEA,eAAO;AAAA,UACN;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA,eAAe;AAAA,MACd,MAAM,kBAEL,SACkC;AAClC,YAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC5C,gBAAM,IAAI,qCAAiB,sBAAsB;AAAA,QAClD;AAEA,cAAM,EAAE,KAAK,IAAI;AAEjB,cAAM,uBAAuB,yDAAyB;AAAA,UACrD,CAAC;AAAA;AAAA,UACD,KAAK;AAAA,QACN;AAEA,cAAM,YAAY,CAAC,CAAC,OAAQ,OAAkB;AAC9C,cAAM,qBAAqB,eAAe,SAAS;AAEnD,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAAA,EACA;AAAA,EACA,YAAY,CAAC,aAAa;AAAA,EAC1B,gBAAgB,CAAC,aAAa;AAAA,EAC9B,MAAM,qBAAqB,SAAS,SAAS,YAAY,WAAW;AACnE,UAAM,YAAY,aAAa,SAAS,SAAS;AACjD,UAAM,uBAAuB,yDAAyB,YAAY,YAAY,QAAQ,MAAM;AAE5F,WAAO,MAAM,qBAAqB,eAAe,SAAS;AAAA,EAC3D;AAAA,EACA,MAAM,oBAAoB,SAAS,YAAY,WAAW,WAAW;AACpE,UAAM,YAAY,aAAa,SAAS,SAAS;AACjD,UAAM,aAAa,QAAQ,iBAAiB,cAAc,SAAS;AACnE,UAAM,sBAAsB,yDAAyB,YAAY,YAAY,QAAQ,MAAM;AAE3F,UAAM,oBAAoB,aAAa,WAAW,WAAW,UAAU;AAAA,EACxE;AACD,CAAC,EAAE;AAAC;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../nodes/vector_store/shared/MemoryManager/MemoryVectorStoreManager.ts"],"sourcesContent":["import type { Document } from '@langchain/core/documents';\nimport type { Embeddings } from '@langchain/core/embeddings';\nimport { MemoryVectorStore } from 'langchain/vectorstores/memory';\nimport type { Logger } from 'n8n-workflow';\n\nimport { getConfig, mbToBytes, hoursToMs } from './config';\nimport { MemoryCalculator } from './MemoryCalculator';\nimport { StoreCleanupService } from './StoreCleanupService';\nimport type { VectorStoreMetadata, VectorStoreStats } from './types';\n\n/**\n * Manages in-memory vector stores with memory limits and auto-cleanup\n */\nexport class MemoryVectorStoreManager {\n\tprivate static instance: MemoryVectorStoreManager | null = null;\n\n\t// Storage\n\tprotected vectorStoreBuffer: Map<string, MemoryVectorStore>;\n\n\tprotected storeMetadata: Map<string, VectorStoreMetadata>;\n\n\tprotected memoryUsageBytes: number = 0;\n\n\t// Dependencies\n\tprotected memoryCalculator: MemoryCalculator;\n\n\tprotected cleanupService: StoreCleanupService;\n\n\tprotected static logger: Logger;\n\n\t// Config values\n\tprotected maxMemorySizeBytes: number;\n\n\tprotected inactiveTtlMs: number;\n\n\t// Inactive TTL cleanup timer\n\tprotected ttlCleanupIntervalId: NodeJS.Timeout | null = null;\n\n\tprotected constructor(\n\t\tprotected embeddings: Embeddings,\n\t\tprotected logger: Logger,\n\t) {\n\t\t// Initialize storage\n\t\tthis.vectorStoreBuffer = new Map();\n\t\tthis.storeMetadata = new Map();\n\t\tthis.logger = logger;\n\n\t\tconst config = getConfig();\n\t\tthis.maxMemorySizeBytes = mbToBytes(config.maxMemoryMB);\n\t\tthis.inactiveTtlMs = hoursToMs(config.ttlHours);\n\n\t\t// Initialize services\n\t\tthis.memoryCalculator = new MemoryCalculator();\n\t\tthis.cleanupService = new StoreCleanupService(\n\t\t\tthis.maxMemorySizeBytes,\n\t\t\tthis.inactiveTtlMs,\n\t\t\tthis.vectorStoreBuffer,\n\t\t\tthis.storeMetadata,\n\t\t\tthis.handleCleanup.bind(this),\n\t\t);\n\n\t\tthis.setupTtlCleanup();\n\t}\n\n\t/**\n\t * Get singleton instance\n\t */\n\tstatic getInstance(embeddings: Embeddings, logger: Logger): MemoryVectorStoreManager {\n\t\tif (!MemoryVectorStoreManager.instance) {\n\t\t\tMemoryVectorStoreManager.instance = new MemoryVectorStoreManager(embeddings, logger);\n\t\t} else {\n\t\t\t// We need to update the embeddings in the existing instance.\n\t\t\t// This is important as embeddings instance is wrapped in a logWrapper,\n\t\t\t// which relies on supplyDataFunctions context which changes on each workflow run\n\t\t\tMemoryVectorStoreManager.instance.embeddings = embeddings;\n\t\t\tMemoryVectorStoreManager.instance.vectorStoreBuffer.forEach((vectorStoreInstance) => {\n\t\t\t\tvectorStoreInstance.embeddings = embeddings;\n\t\t\t});\n\t\t}\n\n\t\treturn MemoryVectorStoreManager.instance;\n\t}\n\n\t/**\n\t * Set up timer for TTL-based cleanup\n\t */\n\tprivate setupTtlCleanup(): void {\n\t\t// Skip setup if TTL is disabled\n\t\tif (this.inactiveTtlMs <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Cleanup check interval (run every hour)\n\t\tconst CLEANUP_INTERVAL_MS = 60 * 60 * 1000;\n\n\t\t// Clear any existing interval\n\t\tif (this.ttlCleanupIntervalId) {\n\t\t\tclearInterval(this.ttlCleanupIntervalId);\n\t\t}\n\n\t\t// Setup new interval for TTL cleanup\n\t\tthis.ttlCleanupIntervalId = setInterval(() => {\n\t\t\tthis.cleanupService.cleanupInactiveStores();\n\t\t}, CLEANUP_INTERVAL_MS);\n\t}\n\n\t/**\n\t * Handle cleanup events from the cleanup service\n\t */\n\tprivate handleCleanup(removedKeys: string[], freedBytes: number, reason: 'ttl' | 'memory'): void {\n\t\t// Update total memory usage\n\t\tthis.memoryUsageBytes -= freedBytes;\n\n\t\t// Log cleanup event\n\t\tif (reason === 'ttl') {\n\t\t\tconst ttlHours = Math.round(this.inactiveTtlMs / (60 * 60 * 1000));\n\t\t\tthis.logger.info(\n\t\t\t\t`TTL cleanup: removed ${removedKeys.length} inactive vector stores (${ttlHours}h TTL) to free ${Math.round(freedBytes / (1024 * 1024))}MB of memory`,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.logger.info(\n\t\t\t\t`Memory cleanup: removed ${removedKeys.length} oldest vector stores to free ${Math.round(freedBytes / (1024 * 1024))}MB of memory`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get or create a vector store by key\n\t */\n\tasync getVectorStore(memoryKey: string): Promise<MemoryVectorStore> {\n\t\tlet vectorStoreInstance = this.vectorStoreBuffer.get(memoryKey);\n\n\t\tif (!vectorStoreInstance) {\n\t\t\tvectorStoreInstance = await MemoryVectorStore.fromExistingIndex(this.embeddings);\n\t\t\tthis.vectorStoreBuffer.set(memoryKey, vectorStoreInstance);\n\n\t\t\tthis.storeMetadata.set(memoryKey, {\n\t\t\t\tsize: 0,\n\t\t\t\tcreatedAt: new Date(),\n\t\t\t\tlastAccessed: new Date(),\n\t\t\t});\n\t\t} else {\n\t\t\tconst metadata = this.storeMetadata.get(memoryKey);\n\t\t\tif (metadata) {\n\t\t\t\tmetadata.lastAccessed = new Date();\n\t\t\t}\n\t\t}\n\n\t\treturn vectorStoreInstance;\n\t}\n\n\t/**\n\t * Reset a store's metadata when it's cleared\n\t */\n\tprotected clearStoreMetadata(memoryKey: string): void {\n\t\tconst metadata = this.storeMetadata.get(memoryKey);\n\t\tif (metadata) {\n\t\t\tthis.memoryUsageBytes -= metadata.size;\n\t\t\tmetadata.size = 0;\n\t\t\tmetadata.lastAccessed = new Date();\n\t\t}\n\t}\n\n\t/**\n\t * Get memory usage in bytes\n\t */\n\tgetMemoryUsage(): number {\n\t\treturn this.memoryUsageBytes;\n\t}\n\n\t/**\n\t * Get memory usage as a formatted string (MB)\n\t */\n\tgetMemoryUsageFormatted(): string {\n\t\treturn `${Math.round(this.memoryUsageBytes / (1024 * 1024))}MB`;\n\t}\n\n\t/**\n\t * Recalculate memory usage from actual vector store contents\n\t * This ensures tracking accuracy for large stores\n\t */\n\trecalculateMemoryUsage(): void {\n\t\tthis.memoryUsageBytes = 0;\n\n\t\t// Recalculate for each store\n\t\tfor (const [key, vectorStore] of this.vectorStoreBuffer.entries()) {\n\t\t\tconst storeSize = this.memoryCalculator.calculateVectorStoreSize(vectorStore);\n\n\t\t\t// Update metadata\n\t\t\tconst metadata = this.storeMetadata.get(key);\n\t\t\tif (metadata) {\n\t\t\t\tmetadata.size = storeSize;\n\t\t\t\tthis.memoryUsageBytes += storeSize;\n\t\t\t}\n\t\t}\n\n\t\tthis.logger.debug(`Recalculated vector store memory: ${this.getMemoryUsageFormatted()}`);\n\t}\n\n\t/**\n\t * Add documents to a vector store\n\t */\n\tasync addDocuments(\n\t\tmemoryKey: string,\n\t\tdocuments: Document[],\n\t\tclearStore?: boolean,\n\t): Promise<void> {\n\t\tif (clearStore) {\n\t\t\tthis.clearStoreMetadata(memoryKey);\n\t\t\tthis.vectorStoreBuffer.delete(memoryKey);\n\t\t}\n\n\t\t// Fast batch estimation instead of per-document calculation\n\t\tconst estimatedAddedSize = this.memoryCalculator.estimateBatchSize(documents);\n\n\t\t// Clean up old stores if necessary\n\t\tthis.cleanupService.cleanupOldestStores(estimatedAddedSize);\n\n\t\tconst vectorStoreInstance = await this.getVectorStore(memoryKey);\n\n\t\t// Get vector count before adding documents\n\t\tconst vectorCountBefore = vectorStoreInstance.memoryVectors?.length || 0;\n\n\t\tawait vectorStoreInstance.addDocuments(documents);\n\n\t\t// Update store metadata and memory tracking\n\t\tconst metadata = this.storeMetadata.get(memoryKey);\n\t\tif (metadata) {\n\t\t\tmetadata.size += estimatedAddedSize;\n\t\t\tmetadata.lastAccessed = new Date();\n\t\t\tthis.memoryUsageBytes += estimatedAddedSize;\n\t\t}\n\n\t\t// Get updated vector count\n\t\tconst vectorCount = vectorStoreInstance.memoryVectors?.length || 0;\n\n\t\t// Periodically recalculate actual memory usage to avoid drift\n\t\tif (\n\t\t\t(vectorCount > 0 && vectorCount % 100 === 0) ||\n\t\t\tdocuments.length > 20 ||\n\t\t\t(vectorCountBefore === 0 && vectorCount > 0)\n\t\t) {\n\t\t\tthis.recalculateMemoryUsage();\n\t\t}\n\n\t\t// Logging memory usage\n\t\tconst maxMemoryMB =\n\t\t\tthis.maxMemorySizeBytes > 0\n\t\t\t\t? (this.maxMemorySizeBytes / (1024 * 1024)).toFixed(0)\n\t\t\t\t: 'unlimited';\n\n\t\tthis.logger.debug(\n\t\t\t`Vector store memory: ${this.getMemoryUsageFormatted()}/${maxMemoryMB}MB (${vectorCount} vectors in ${this.vectorStoreBuffer.size} stores)`,\n\t\t);\n\t}\n\n\t/**\n\t * Get statistics about the vector store memory usage\n\t */\n\tgetStats(): VectorStoreStats {\n\t\tconst now = Date.now();\n\t\tlet inactiveStoreCount = 0;\n\n\t\t// Always recalculate when getting stats to ensure accuracy\n\t\tthis.recalculateMemoryUsage();\n\n\t\tconst stats: VectorStoreStats = {\n\t\t\ttotalSizeBytes: this.memoryUsageBytes,\n\t\t\ttotalSizeMB: Math.round((this.memoryUsageBytes / (1024 * 1024)) * 100) / 100,\n\t\t\tpercentOfLimit:\n\t\t\t\tthis.maxMemorySizeBytes > 0\n\t\t\t\t\t? Math.round((this.memoryUsageBytes / this.maxMemorySizeBytes) * 100)\n\t\t\t\t\t: 0,\n\t\t\tmaxMemoryMB: this.maxMemorySizeBytes > 0 ? this.maxMemorySizeBytes / (1024 * 1024) : -1, // -1 indicates unlimited\n\t\t\tstoreCount: this.vectorStoreBuffer.size,\n\t\t\tinactiveStoreCount: 0,\n\t\t\tttlHours: this.inactiveTtlMs > 0 ? this.inactiveTtlMs / (60 * 60 * 1000) : -1, // -1 indicates disabled\n\t\t\tstores: {},\n\t\t};\n\n\t\t// Add stats for each store\n\t\tfor (const [key, metadata] of this.storeMetadata.entries()) {\n\t\t\tconst store = this.vectorStoreBuffer.get(key);\n\n\t\t\tif (store) {\n\t\t\t\tconst lastAccessedTime = metadata.lastAccessed.getTime();\n\t\t\t\tconst inactiveTimeMs = now - lastAccessedTime;\n\t\t\t\tconst isInactive = this.cleanupService.isStoreInactive(metadata);\n\n\t\t\t\tif (isInactive) {\n\t\t\t\t\tinactiveStoreCount++;\n\t\t\t\t}\n\n\t\t\t\tstats.stores[key] = {\n\t\t\t\t\tsizeBytes: metadata.size,\n\t\t\t\t\tsizeMB: Math.round((metadata.size / (1024 * 1024)) * 100) / 100,\n\t\t\t\t\tpercentOfTotal: Math.round((metadata.size / this.memoryUsageBytes) * 100) || 0,\n\t\t\t\t\tvectors: store.memoryVectors?.length || 0,\n\t\t\t\t\tcreatedAt: metadata.createdAt.toISOString(),\n\t\t\t\t\tlastAccessed: metadata.lastAccessed.toISOString(),\n\t\t\t\t\tinactive: isInactive,\n\t\t\t\t\tinactiveForHours: Math.round(inactiveTimeMs / (60 * 60 * 1000)),\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tstats.inactiveStoreCount = inactiveStoreCount;\n\n\t\treturn stats;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAAkC;AAGlC,oBAAgD;AAChD,8BAAiC;AACjC,iCAAoC;AAM7B,MAAM,4BAAN,MAAM,0BAAyB;AAAA,EAyB3B,YACC,YACA,QACT;AAFS;AACA;AAnBX,SAAU,mBAA2B;AAerC;AAAA,SAAU,uBAA8C;AAOvD,SAAK,oBAAoB,oBAAI,IAAI;AACjC,SAAK,gBAAgB,oBAAI,IAAI;AAC7B,SAAK,SAAS;AAEd,UAAM,aAAS,yBAAU;AACzB,SAAK,yBAAqB,yBAAU,OAAO,WAAW;AACtD,SAAK,oBAAgB,yBAAU,OAAO,QAAQ;AAG9C,SAAK,mBAAmB,IAAI,yCAAiB;AAC7C,SAAK,iBAAiB,IAAI;AAAA,MACzB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,cAAc,KAAK,IAAI;AAAA,IAC7B;AAEA,SAAK,gBAAgB;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,YAAY,YAAwB,QAA0C;AACpF,QAAI,CAAC,0BAAyB,UAAU;AACvC,gCAAyB,WAAW,IAAI,0BAAyB,YAAY,MAAM;AAAA,IACpF,OAAO;AAIN,gCAAyB,SAAS,aAAa;AAC/C,gCAAyB,SAAS,kBAAkB,QAAQ,CAAC,wBAAwB;AACpF,4BAAoB,aAAa;AAAA,MAClC,CAAC;AAAA,IACF;AAEA,WAAO,0BAAyB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAwB;AAE/B,QAAI,KAAK,iBAAiB,GAAG;AAC5B;AAAA,IACD;AAGA,UAAM,sBAAsB,KAAK,KAAK;AAGtC,QAAI,KAAK,sBAAsB;AAC9B,oBAAc,KAAK,oBAAoB;AAAA,IACxC;AAGA,SAAK,uBAAuB,YAAY,MAAM;AAC7C,WAAK,eAAe,sBAAsB;AAAA,IAC3C,GAAG,mBAAmB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,aAAuB,YAAoB,QAAgC;AAEhG,SAAK,oBAAoB;AAGzB,QAAI,WAAW,OAAO;AACrB,YAAM,WAAW,KAAK,MAAM,KAAK,iBAAiB,KAAK,KAAK,IAAK;AACjE,WAAK,OAAO;AAAA,QACX,wBAAwB,YAAY,MAAM,4BAA4B,QAAQ,kBAAkB,KAAK,MAAM,cAAc,OAAO,KAAK,CAAC;AAAA,MACvI;AAAA,IACD,OAAO;AACN,WAAK,OAAO;AAAA,QACX,2BAA2B,YAAY,MAAM,iCAAiC,KAAK,MAAM,cAAc,OAAO,KAAK,CAAC;AAAA,MACrH;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAA+C;AACnE,QAAI,sBAAsB,KAAK,kBAAkB,IAAI,SAAS;AAE9D,QAAI,CAAC,qBAAqB;AACzB,4BAAsB,MAAM,gCAAkB,kBAAkB,KAAK,UAAU;AAC/E,WAAK,kBAAkB,IAAI,WAAW,mBAAmB;AAEzD,WAAK,cAAc,IAAI,WAAW;AAAA,QACjC,MAAM;AAAA,QACN,WAAW,oBAAI,KAAK;AAAA,QACpB,cAAc,oBAAI,KAAK;AAAA,MACxB,CAAC;AAAA,IACF,OAAO;AACN,YAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,UAAI,UAAU;AACb,iBAAS,eAAe,oBAAI,KAAK;AAAA,MAClC;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKU,mBAAmB,WAAyB;AACrD,UAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,QAAI,UAAU;AACb,WAAK,oBAAoB,SAAS;AAClC,eAAS,OAAO;AAChB,eAAS,eAAe,oBAAI,KAAK;AAAA,IAClC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,0BAAkC;AACjC,WAAO,GAAG,KAAK,MAAM,KAAK,oBAAoB,OAAO,KAAK,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAA+B;AAC9B,SAAK,mBAAmB;AAGxB,eAAW,CAAC,KAAK,WAAW,KAAK,KAAK,kBAAkB,QAAQ,GAAG;AAClE,YAAM,YAAY,KAAK,iBAAiB,yBAAyB,WAAW;AAG5E,YAAM,WAAW,KAAK,cAAc,IAAI,GAAG;AAC3C,UAAI,UAAU;AACb,iBAAS,OAAO;AAChB,aAAK,oBAAoB;AAAA,MAC1B;AAAA,IACD;AAEA,SAAK,OAAO,MAAM,qCAAqC,KAAK,wBAAwB,CAAC,EAAE;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACL,WACA,WACA,YACgB;AAChB,QAAI,YAAY;AACf,WAAK,mBAAmB,SAAS;AACjC,WAAK,kBAAkB,OAAO,SAAS;AAAA,IACxC;AAGA,UAAM,qBAAqB,KAAK,iBAAiB,kBAAkB,SAAS;AAG5E,SAAK,eAAe,oBAAoB,kBAAkB;AAE1D,UAAM,sBAAsB,MAAM,KAAK,eAAe,SAAS;AAG/D,UAAM,oBAAoB,oBAAoB,eAAe,UAAU;AAEvE,UAAM,oBAAoB,aAAa,SAAS;AAGhD,UAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,QAAI,UAAU;AACb,eAAS,QAAQ;AACjB,eAAS,eAAe,oBAAI,KAAK;AACjC,WAAK,oBAAoB;AAAA,IAC1B;AAGA,UAAM,cAAc,oBAAoB,eAAe,UAAU;AAGjE,QACE,cAAc,KAAK,cAAc,QAAQ,KAC1C,UAAU,SAAS,MAClB,sBAAsB,KAAK,cAAc,GACzC;AACD,WAAK,uBAAuB;AAAA,IAC7B;AAGA,UAAM,cACL,KAAK,qBAAqB,KACtB,KAAK,sBAAsB,OAAO,OAAO,QAAQ,CAAC,IACnD;AAEJ,SAAK,OAAO;AAAA,MACX,wBAAwB,KAAK,wBAAwB,CAAC,IAAI,WAAW,OAAO,WAAW,eAAe,KAAK,kBAAkB,IAAI;AAAA,IAClI;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,WAA6B;AAC5B,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,qBAAqB;AAGzB,SAAK,uBAAuB;AAE5B,UAAM,QAA0B;AAAA,MAC/B,gBAAgB,KAAK;AAAA,MACrB,aAAa,KAAK,MAAO,KAAK,oBAAoB,OAAO,QAAS,GAAG,IAAI;AAAA,MACzE,gBACC,KAAK,qBAAqB,IACvB,KAAK,MAAO,KAAK,mBAAmB,KAAK,qBAAsB,GAAG,IAClE;AAAA,MACJ,aAAa,KAAK,qBAAqB,IAAI,KAAK,sBAAsB,OAAO,QAAQ;AAAA;AAAA,MACrF,YAAY,KAAK,kBAAkB;AAAA,MACnC,oBAAoB;AAAA,MACpB,UAAU,KAAK,gBAAgB,IAAI,KAAK,iBAAiB,KAAK,KAAK,OAAQ;AAAA;AAAA,MAC3E,QAAQ,CAAC;AAAA,IACV;AAGA,eAAW,CAAC,KAAK,QAAQ,KAAK,KAAK,cAAc,QAAQ,GAAG;AAC3D,YAAM,QAAQ,KAAK,kBAAkB,IAAI,GAAG;AAE5C,UAAI,OAAO;AACV,cAAM,mBAAmB,SAAS,aAAa,QAAQ;AACvD,cAAM,iBAAiB,MAAM;AAC7B,cAAM,aAAa,KAAK,eAAe,gBAAgB,QAAQ;AAE/D,YAAI,YAAY;AACf;AAAA,QACD;AAEA,cAAM,OAAO,GAAG,IAAI;AAAA,UACnB,WAAW,SAAS;AAAA,UACpB,QAAQ,KAAK,MAAO,SAAS,QAAQ,OAAO,QAAS,GAAG,IAAI;AAAA,UAC5D,gBAAgB,KAAK,MAAO,SAAS,OAAO,KAAK,mBAAoB,GAAG,KAAK;AAAA,UAC7E,SAAS,MAAM,eAAe,UAAU;AAAA,UACxC,WAAW,SAAS,UAAU,YAAY;AAAA,UAC1C,cAAc,SAAS,aAAa,YAAY;AAAA,UAChD,UAAU;AAAA,UACV,kBAAkB,KAAK,MAAM,kBAAkB,KAAK,KAAK,IAAK;AAAA,QAC/D;AAAA,MACD;AAAA,IACD;AAEA,UAAM,qBAAqB;AAE3B,WAAO;AAAA,EACR;AACD;AAzSa,0BACG,WAA4C;AADrD,IAAM,2BAAN;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../nodes/vector_store/shared/MemoryManager/MemoryVectorStoreManager.ts"],"sourcesContent":["import type { Document } from '@langchain/core/documents';\nimport type { Embeddings } from '@langchain/core/embeddings';\nimport { MemoryVectorStore } from 'langchain/vectorstores/memory';\nimport type { Logger } from 'n8n-workflow';\n\nimport { getConfig, mbToBytes, hoursToMs } from './config';\nimport { MemoryCalculator } from './MemoryCalculator';\nimport { StoreCleanupService } from './StoreCleanupService';\nimport type { VectorStoreMetadata, VectorStoreStats } from './types';\n\n/**\n * Manages in-memory vector stores with memory limits and auto-cleanup\n */\nexport class MemoryVectorStoreManager {\n\tprivate static instance: MemoryVectorStoreManager | null = null;\n\n\t// Storage\n\tprotected vectorStoreBuffer: Map<string, MemoryVectorStore>;\n\n\tprotected storeMetadata: Map<string, VectorStoreMetadata>;\n\n\tprotected memoryUsageBytes: number = 0;\n\n\t// Dependencies\n\tprotected memoryCalculator: MemoryCalculator;\n\n\tprotected cleanupService: StoreCleanupService;\n\n\tprotected static logger: Logger;\n\n\t// Config values\n\tprotected maxMemorySizeBytes: number;\n\n\tprotected inactiveTtlMs: number;\n\n\t// Inactive TTL cleanup timer\n\tprotected ttlCleanupIntervalId: NodeJS.Timeout | null = null;\n\n\tprotected constructor(\n\t\tprotected embeddings: Embeddings,\n\t\tprotected logger: Logger,\n\t) {\n\t\t// Initialize storage\n\t\tthis.vectorStoreBuffer = new Map();\n\t\tthis.storeMetadata = new Map();\n\t\tthis.logger = logger;\n\n\t\tconst config = getConfig();\n\t\tthis.maxMemorySizeBytes = mbToBytes(config.maxMemoryMB);\n\t\tthis.inactiveTtlMs = hoursToMs(config.ttlHours);\n\n\t\t// Initialize services\n\t\tthis.memoryCalculator = new MemoryCalculator();\n\t\tthis.cleanupService = new StoreCleanupService(\n\t\t\tthis.maxMemorySizeBytes,\n\t\t\tthis.inactiveTtlMs,\n\t\t\tthis.vectorStoreBuffer,\n\t\t\tthis.storeMetadata,\n\t\t\tthis.handleCleanup.bind(this),\n\t\t);\n\n\t\tthis.setupTtlCleanup();\n\t}\n\n\t/**\n\t * Get singleton instance\n\t */\n\tstatic getInstance(embeddings: Embeddings, logger: Logger): MemoryVectorStoreManager {\n\t\tif (!MemoryVectorStoreManager.instance) {\n\t\t\tMemoryVectorStoreManager.instance = new MemoryVectorStoreManager(embeddings, logger);\n\t\t} else {\n\t\t\t// We need to update the embeddings in the existing instance.\n\t\t\t// This is important as embeddings instance is wrapped in a logWrapper,\n\t\t\t// which relies on supplyDataFunctions context which changes on each workflow run\n\t\t\tMemoryVectorStoreManager.instance.embeddings = embeddings;\n\t\t\tMemoryVectorStoreManager.instance.vectorStoreBuffer.forEach((vectorStoreInstance) => {\n\t\t\t\tvectorStoreInstance.embeddings = embeddings;\n\t\t\t});\n\t\t}\n\n\t\treturn MemoryVectorStoreManager.instance;\n\t}\n\n\t/**\n\t * Set up timer for TTL-based cleanup\n\t */\n\tprivate setupTtlCleanup(): void {\n\t\t// Skip setup if TTL is disabled\n\t\tif (this.inactiveTtlMs <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Cleanup check interval (run every hour)\n\t\tconst CLEANUP_INTERVAL_MS = 60 * 60 * 1000;\n\n\t\t// Clear any existing interval\n\t\tif (this.ttlCleanupIntervalId) {\n\t\t\tclearInterval(this.ttlCleanupIntervalId);\n\t\t}\n\n\t\t// Setup new interval for TTL cleanup\n\t\tthis.ttlCleanupIntervalId = setInterval(() => {\n\t\t\tthis.cleanupService.cleanupInactiveStores();\n\t\t}, CLEANUP_INTERVAL_MS);\n\t}\n\n\t/**\n\t * Handle cleanup events from the cleanup service\n\t */\n\tprivate handleCleanup(removedKeys: string[], freedBytes: number, reason: 'ttl' | 'memory'): void {\n\t\t// Update total memory usage\n\t\tthis.memoryUsageBytes -= freedBytes;\n\n\t\t// Log cleanup event\n\t\tif (reason === 'ttl') {\n\t\t\tconst ttlHours = Math.round(this.inactiveTtlMs / (60 * 60 * 1000));\n\t\t\tthis.logger.info(\n\t\t\t\t`TTL cleanup: removed ${removedKeys.length} inactive vector stores (${ttlHours}h TTL) to free ${Math.round(freedBytes / (1024 * 1024))}MB of memory`,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.logger.info(\n\t\t\t\t`Memory cleanup: removed ${removedKeys.length} oldest vector stores to free ${Math.round(freedBytes / (1024 * 1024))}MB of memory`,\n\t\t\t);\n\t\t}\n\t}\n\n\tgetMemoryKeysList(): string[] {\n\t\treturn Array.from(this.vectorStoreBuffer.keys());\n\t}\n\n\t/**\n\t * Get or create a vector store by key\n\t */\n\tasync getVectorStore(memoryKey: string): Promise<MemoryVectorStore> {\n\t\tlet vectorStoreInstance = this.vectorStoreBuffer.get(memoryKey);\n\n\t\tif (!vectorStoreInstance) {\n\t\t\tvectorStoreInstance = await MemoryVectorStore.fromExistingIndex(this.embeddings);\n\t\t\tthis.vectorStoreBuffer.set(memoryKey, vectorStoreInstance);\n\n\t\t\tthis.storeMetadata.set(memoryKey, {\n\t\t\t\tsize: 0,\n\t\t\t\tcreatedAt: new Date(),\n\t\t\t\tlastAccessed: new Date(),\n\t\t\t});\n\t\t} else {\n\t\t\tconst metadata = this.storeMetadata.get(memoryKey);\n\t\t\tif (metadata) {\n\t\t\t\tmetadata.lastAccessed = new Date();\n\t\t\t}\n\t\t}\n\n\t\treturn vectorStoreInstance;\n\t}\n\n\t/**\n\t * Reset a store's metadata when it's cleared\n\t */\n\tprotected clearStoreMetadata(memoryKey: string): void {\n\t\tconst metadata = this.storeMetadata.get(memoryKey);\n\t\tif (metadata) {\n\t\t\tthis.memoryUsageBytes -= metadata.size;\n\t\t\tmetadata.size = 0;\n\t\t\tmetadata.lastAccessed = new Date();\n\t\t}\n\t}\n\n\t/**\n\t * Get memory usage in bytes\n\t */\n\tgetMemoryUsage(): number {\n\t\treturn this.memoryUsageBytes;\n\t}\n\n\t/**\n\t * Get memory usage as a formatted string (MB)\n\t */\n\tgetMemoryUsageFormatted(): string {\n\t\treturn `${Math.round(this.memoryUsageBytes / (1024 * 1024))}MB`;\n\t}\n\n\t/**\n\t * Recalculate memory usage from actual vector store contents\n\t * This ensures tracking accuracy for large stores\n\t */\n\trecalculateMemoryUsage(): void {\n\t\tthis.memoryUsageBytes = 0;\n\n\t\t// Recalculate for each store\n\t\tfor (const [key, vectorStore] of this.vectorStoreBuffer.entries()) {\n\t\t\tconst storeSize = this.memoryCalculator.calculateVectorStoreSize(vectorStore);\n\n\t\t\t// Update metadata\n\t\t\tconst metadata = this.storeMetadata.get(key);\n\t\t\tif (metadata) {\n\t\t\t\tmetadata.size = storeSize;\n\t\t\t\tthis.memoryUsageBytes += storeSize;\n\t\t\t}\n\t\t}\n\n\t\tthis.logger.debug(`Recalculated vector store memory: ${this.getMemoryUsageFormatted()}`);\n\t}\n\n\t/**\n\t * Add documents to a vector store\n\t */\n\tasync addDocuments(\n\t\tmemoryKey: string,\n\t\tdocuments: Document[],\n\t\tclearStore?: boolean,\n\t): Promise<void> {\n\t\tif (clearStore) {\n\t\t\tthis.clearStoreMetadata(memoryKey);\n\t\t\tthis.vectorStoreBuffer.delete(memoryKey);\n\t\t}\n\n\t\t// Fast batch estimation instead of per-document calculation\n\t\tconst estimatedAddedSize = this.memoryCalculator.estimateBatchSize(documents);\n\n\t\t// Clean up old stores if necessary\n\t\tthis.cleanupService.cleanupOldestStores(estimatedAddedSize);\n\n\t\tconst vectorStoreInstance = await this.getVectorStore(memoryKey);\n\n\t\t// Get vector count before adding documents\n\t\tconst vectorCountBefore = vectorStoreInstance.memoryVectors?.length || 0;\n\n\t\tawait vectorStoreInstance.addDocuments(documents);\n\n\t\t// Update store metadata and memory tracking\n\t\tconst metadata = this.storeMetadata.get(memoryKey);\n\t\tif (metadata) {\n\t\t\tmetadata.size += estimatedAddedSize;\n\t\t\tmetadata.lastAccessed = new Date();\n\t\t\tthis.memoryUsageBytes += estimatedAddedSize;\n\t\t}\n\n\t\t// Get updated vector count\n\t\tconst vectorCount = vectorStoreInstance.memoryVectors?.length || 0;\n\n\t\t// Periodically recalculate actual memory usage to avoid drift\n\t\tif (\n\t\t\t(vectorCount > 0 && vectorCount % 100 === 0) ||\n\t\t\tdocuments.length > 20 ||\n\t\t\t(vectorCountBefore === 0 && vectorCount > 0)\n\t\t) {\n\t\t\tthis.recalculateMemoryUsage();\n\t\t}\n\n\t\t// Logging memory usage\n\t\tconst maxMemoryMB =\n\t\t\tthis.maxMemorySizeBytes > 0\n\t\t\t\t? (this.maxMemorySizeBytes / (1024 * 1024)).toFixed(0)\n\t\t\t\t: 'unlimited';\n\n\t\tthis.logger.debug(\n\t\t\t`Vector store memory: ${this.getMemoryUsageFormatted()}/${maxMemoryMB}MB (${vectorCount} vectors in ${this.vectorStoreBuffer.size} stores)`,\n\t\t);\n\t}\n\n\t/**\n\t * Get statistics about the vector store memory usage\n\t */\n\tgetStats(): VectorStoreStats {\n\t\tconst now = Date.now();\n\t\tlet inactiveStoreCount = 0;\n\n\t\t// Always recalculate when getting stats to ensure accuracy\n\t\tthis.recalculateMemoryUsage();\n\n\t\tconst stats: VectorStoreStats = {\n\t\t\ttotalSizeBytes: this.memoryUsageBytes,\n\t\t\ttotalSizeMB: Math.round((this.memoryUsageBytes / (1024 * 1024)) * 100) / 100,\n\t\t\tpercentOfLimit:\n\t\t\t\tthis.maxMemorySizeBytes > 0\n\t\t\t\t\t? Math.round((this.memoryUsageBytes / this.maxMemorySizeBytes) * 100)\n\t\t\t\t\t: 0,\n\t\t\tmaxMemoryMB: this.maxMemorySizeBytes > 0 ? this.maxMemorySizeBytes / (1024 * 1024) : -1, // -1 indicates unlimited\n\t\t\tstoreCount: this.vectorStoreBuffer.size,\n\t\t\tinactiveStoreCount: 0,\n\t\t\tttlHours: this.inactiveTtlMs > 0 ? this.inactiveTtlMs / (60 * 60 * 1000) : -1, // -1 indicates disabled\n\t\t\tstores: {},\n\t\t};\n\n\t\t// Add stats for each store\n\t\tfor (const [key, metadata] of this.storeMetadata.entries()) {\n\t\t\tconst store = this.vectorStoreBuffer.get(key);\n\n\t\t\tif (store) {\n\t\t\t\tconst lastAccessedTime = metadata.lastAccessed.getTime();\n\t\t\t\tconst inactiveTimeMs = now - lastAccessedTime;\n\t\t\t\tconst isInactive = this.cleanupService.isStoreInactive(metadata);\n\n\t\t\t\tif (isInactive) {\n\t\t\t\t\tinactiveStoreCount++;\n\t\t\t\t}\n\n\t\t\t\tstats.stores[key] = {\n\t\t\t\t\tsizeBytes: metadata.size,\n\t\t\t\t\tsizeMB: Math.round((metadata.size / (1024 * 1024)) * 100) / 100,\n\t\t\t\t\tpercentOfTotal: Math.round((metadata.size / this.memoryUsageBytes) * 100) || 0,\n\t\t\t\t\tvectors: store.memoryVectors?.length || 0,\n\t\t\t\t\tcreatedAt: metadata.createdAt.toISOString(),\n\t\t\t\t\tlastAccessed: metadata.lastAccessed.toISOString(),\n\t\t\t\t\tinactive: isInactive,\n\t\t\t\t\tinactiveForHours: Math.round(inactiveTimeMs / (60 * 60 * 1000)),\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tstats.inactiveStoreCount = inactiveStoreCount;\n\n\t\treturn stats;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAAkC;AAGlC,oBAAgD;AAChD,8BAAiC;AACjC,iCAAoC;AAM7B,MAAM,4BAAN,MAAM,0BAAyB;AAAA,EAyB3B,YACC,YACA,QACT;AAFS;AACA;AAnBX,SAAU,mBAA2B;AAerC;AAAA,SAAU,uBAA8C;AAOvD,SAAK,oBAAoB,oBAAI,IAAI;AACjC,SAAK,gBAAgB,oBAAI,IAAI;AAC7B,SAAK,SAAS;AAEd,UAAM,aAAS,yBAAU;AACzB,SAAK,yBAAqB,yBAAU,OAAO,WAAW;AACtD,SAAK,oBAAgB,yBAAU,OAAO,QAAQ;AAG9C,SAAK,mBAAmB,IAAI,yCAAiB;AAC7C,SAAK,iBAAiB,IAAI;AAAA,MACzB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,cAAc,KAAK,IAAI;AAAA,IAC7B;AAEA,SAAK,gBAAgB;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,YAAY,YAAwB,QAA0C;AACpF,QAAI,CAAC,0BAAyB,UAAU;AACvC,gCAAyB,WAAW,IAAI,0BAAyB,YAAY,MAAM;AAAA,IACpF,OAAO;AAIN,gCAAyB,SAAS,aAAa;AAC/C,gCAAyB,SAAS,kBAAkB,QAAQ,CAAC,wBAAwB;AACpF,4BAAoB,aAAa;AAAA,MAClC,CAAC;AAAA,IACF;AAEA,WAAO,0BAAyB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAwB;AAE/B,QAAI,KAAK,iBAAiB,GAAG;AAC5B;AAAA,IACD;AAGA,UAAM,sBAAsB,KAAK,KAAK;AAGtC,QAAI,KAAK,sBAAsB;AAC9B,oBAAc,KAAK,oBAAoB;AAAA,IACxC;AAGA,SAAK,uBAAuB,YAAY,MAAM;AAC7C,WAAK,eAAe,sBAAsB;AAAA,IAC3C,GAAG,mBAAmB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,aAAuB,YAAoB,QAAgC;AAEhG,SAAK,oBAAoB;AAGzB,QAAI,WAAW,OAAO;AACrB,YAAM,WAAW,KAAK,MAAM,KAAK,iBAAiB,KAAK,KAAK,IAAK;AACjE,WAAK,OAAO;AAAA,QACX,wBAAwB,YAAY,MAAM,4BAA4B,QAAQ,kBAAkB,KAAK,MAAM,cAAc,OAAO,KAAK,CAAC;AAAA,MACvI;AAAA,IACD,OAAO;AACN,WAAK,OAAO;AAAA,QACX,2BAA2B,YAAY,MAAM,iCAAiC,KAAK,MAAM,cAAc,OAAO,KAAK,CAAC;AAAA,MACrH;AAAA,IACD;AAAA,EACD;AAAA,EAEA,oBAA8B;AAC7B,WAAO,MAAM,KAAK,KAAK,kBAAkB,KAAK,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAA+C;AACnE,QAAI,sBAAsB,KAAK,kBAAkB,IAAI,SAAS;AAE9D,QAAI,CAAC,qBAAqB;AACzB,4BAAsB,MAAM,gCAAkB,kBAAkB,KAAK,UAAU;AAC/E,WAAK,kBAAkB,IAAI,WAAW,mBAAmB;AAEzD,WAAK,cAAc,IAAI,WAAW;AAAA,QACjC,MAAM;AAAA,QACN,WAAW,oBAAI,KAAK;AAAA,QACpB,cAAc,oBAAI,KAAK;AAAA,MACxB,CAAC;AAAA,IACF,OAAO;AACN,YAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,UAAI,UAAU;AACb,iBAAS,eAAe,oBAAI,KAAK;AAAA,MAClC;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKU,mBAAmB,WAAyB;AACrD,UAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,QAAI,UAAU;AACb,WAAK,oBAAoB,SAAS;AAClC,eAAS,OAAO;AAChB,eAAS,eAAe,oBAAI,KAAK;AAAA,IAClC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,0BAAkC;AACjC,WAAO,GAAG,KAAK,MAAM,KAAK,oBAAoB,OAAO,KAAK,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAA+B;AAC9B,SAAK,mBAAmB;AAGxB,eAAW,CAAC,KAAK,WAAW,KAAK,KAAK,kBAAkB,QAAQ,GAAG;AAClE,YAAM,YAAY,KAAK,iBAAiB,yBAAyB,WAAW;AAG5E,YAAM,WAAW,KAAK,cAAc,IAAI,GAAG;AAC3C,UAAI,UAAU;AACb,iBAAS,OAAO;AAChB,aAAK,oBAAoB;AAAA,MAC1B;AAAA,IACD;AAEA,SAAK,OAAO,MAAM,qCAAqC,KAAK,wBAAwB,CAAC,EAAE;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACL,WACA,WACA,YACgB;AAChB,QAAI,YAAY;AACf,WAAK,mBAAmB,SAAS;AACjC,WAAK,kBAAkB,OAAO,SAAS;AAAA,IACxC;AAGA,UAAM,qBAAqB,KAAK,iBAAiB,kBAAkB,SAAS;AAG5E,SAAK,eAAe,oBAAoB,kBAAkB;AAE1D,UAAM,sBAAsB,MAAM,KAAK,eAAe,SAAS;AAG/D,UAAM,oBAAoB,oBAAoB,eAAe,UAAU;AAEvE,UAAM,oBAAoB,aAAa,SAAS;AAGhD,UAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,QAAI,UAAU;AACb,eAAS,QAAQ;AACjB,eAAS,eAAe,oBAAI,KAAK;AACjC,WAAK,oBAAoB;AAAA,IAC1B;AAGA,UAAM,cAAc,oBAAoB,eAAe,UAAU;AAGjE,QACE,cAAc,KAAK,cAAc,QAAQ,KAC1C,UAAU,SAAS,MAClB,sBAAsB,KAAK,cAAc,GACzC;AACD,WAAK,uBAAuB;AAAA,IAC7B;AAGA,UAAM,cACL,KAAK,qBAAqB,KACtB,KAAK,sBAAsB,OAAO,OAAO,QAAQ,CAAC,IACnD;AAEJ,SAAK,OAAO;AAAA,MACX,wBAAwB,KAAK,wBAAwB,CAAC,IAAI,WAAW,OAAO,WAAW,eAAe,KAAK,kBAAkB,IAAI;AAAA,IAClI;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,WAA6B;AAC5B,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,qBAAqB;AAGzB,SAAK,uBAAuB;AAE5B,UAAM,QAA0B;AAAA,MAC/B,gBAAgB,KAAK;AAAA,MACrB,aAAa,KAAK,MAAO,KAAK,oBAAoB,OAAO,QAAS,GAAG,IAAI;AAAA,MACzE,gBACC,KAAK,qBAAqB,IACvB,KAAK,MAAO,KAAK,mBAAmB,KAAK,qBAAsB,GAAG,IAClE;AAAA,MACJ,aAAa,KAAK,qBAAqB,IAAI,KAAK,sBAAsB,OAAO,QAAQ;AAAA;AAAA,MACrF,YAAY,KAAK,kBAAkB;AAAA,MACnC,oBAAoB;AAAA,MACpB,UAAU,KAAK,gBAAgB,IAAI,KAAK,iBAAiB,KAAK,KAAK,OAAQ;AAAA;AAAA,MAC3E,QAAQ,CAAC;AAAA,IACV;AAGA,eAAW,CAAC,KAAK,QAAQ,KAAK,KAAK,cAAc,QAAQ,GAAG;AAC3D,YAAM,QAAQ,KAAK,kBAAkB,IAAI,GAAG;AAE5C,UAAI,OAAO;AACV,cAAM,mBAAmB,SAAS,aAAa,QAAQ;AACvD,cAAM,iBAAiB,MAAM;AAC7B,cAAM,aAAa,KAAK,eAAe,gBAAgB,QAAQ;AAE/D,YAAI,YAAY;AACf;AAAA,QACD;AAEA,cAAM,OAAO,GAAG,IAAI;AAAA,UACnB,WAAW,SAAS;AAAA,UACpB,QAAQ,KAAK,MAAO,SAAS,QAAQ,OAAO,QAAS,GAAG,IAAI;AAAA,UAC5D,gBAAgB,KAAK,MAAO,SAAS,OAAO,KAAK,mBAAoB,GAAG,KAAK;AAAA,UAC7E,SAAS,MAAM,eAAe,UAAU;AAAA,UACxC,WAAW,SAAS,UAAU,YAAY;AAAA,UAC1C,cAAc,SAAS,aAAa,YAAY;AAAA,UAChD,UAAU;AAAA,UACV,kBAAkB,KAAK,MAAM,kBAAkB,KAAK,KAAK,IAAK;AAAA,QAC/D;AAAA,MACD;AAAA,IACD;AAEA,UAAM,qBAAqB;AAE3B,WAAO;AAAA,EACR;AACD;AA7Sa,0BACG,WAA4C;AADrD,IAAM,2BAAN;","names":[]}
|
|
@@ -34,7 +34,8 @@ const createVectorStoreNode = (args) => class VectorStoreNodeType {
|
|
|
34
34
|
icon: args.meta.icon,
|
|
35
35
|
iconColor: args.meta.iconColor,
|
|
36
36
|
group: ["transform"],
|
|
37
|
-
|
|
37
|
+
// 1.2 has changes to VectorStoreInMemory node.
|
|
38
|
+
version: [1, 1.1, 1.2],
|
|
38
39
|
defaults: {
|
|
39
40
|
name: args.meta.displayName
|
|
40
41
|
},
|