@n8n/n8n-nodes-langchain 1.101.1 → 1.102.0

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.
Files changed (114) hide show
  1. package/dist/credentials/CohereApi.credentials.js +7 -1
  2. package/dist/credentials/CohereApi.credentials.js.map +1 -1
  3. package/dist/known/credentials.json +2 -0
  4. package/dist/known/nodes.json +12 -0
  5. package/dist/nodes/agents/Agent/Agent.node.js +1 -0
  6. package/dist/nodes/agents/Agent/Agent.node.js.map +1 -1
  7. package/dist/nodes/agents/Agent/AgentTool.node.js +57 -0
  8. package/dist/nodes/agents/Agent/AgentTool.node.js.map +1 -0
  9. package/dist/nodes/agents/Agent/V2/AgentToolV2.node.js +104 -0
  10. package/dist/nodes/agents/Agent/V2/AgentToolV2.node.js.map +1 -0
  11. package/dist/nodes/agents/Agent/V2/AgentV2.node.js +4 -66
  12. package/dist/nodes/agents/Agent/V2/AgentV2.node.js.map +1 -1
  13. package/dist/nodes/agents/Agent/V2/utils.js +92 -0
  14. package/dist/nodes/agents/Agent/V2/utils.js.map +1 -0
  15. package/dist/nodes/agents/Agent/agents/ToolsAgent/V2/description.js +13 -10
  16. package/dist/nodes/agents/Agent/agents/ToolsAgent/V2/description.js.map +1 -1
  17. package/dist/nodes/agents/Agent/agents/ToolsAgent/V2/execute.js +14 -7
  18. package/dist/nodes/agents/Agent/agents/ToolsAgent/V2/execute.js.map +1 -1
  19. package/dist/nodes/agents/Agent/agents/ToolsAgent/common.js.map +1 -1
  20. package/dist/nodes/chains/SentimentAnalysis/SentimentAnalysis.node.js +1 -1
  21. package/dist/nodes/chains/SentimentAnalysis/SentimentAnalysis.node.js.map +1 -1
  22. package/dist/nodes/embeddings/EmbeddingsOpenAI/EmbeddingsOpenAi.node.js +6 -0
  23. package/dist/nodes/embeddings/EmbeddingsOpenAI/EmbeddingsOpenAi.node.js.map +1 -1
  24. package/dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js +2 -2
  25. package/dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js.map +1 -1
  26. package/dist/nodes/llms/LmChatCohere/LmChatCohere.node.js +181 -0
  27. package/dist/nodes/llms/LmChatCohere/LmChatCohere.node.js.map +1 -0
  28. package/dist/nodes/llms/LmChatCohere/cohere.dark.svg +5 -0
  29. package/dist/nodes/llms/LmChatCohere/cohere.svg +5 -0
  30. package/dist/nodes/llms/N8nLlmTracing.js +4 -4
  31. package/dist/nodes/llms/N8nLlmTracing.js.map +1 -1
  32. package/dist/nodes/mcp/McpTrigger/McpTrigger.node.js +1 -1
  33. package/dist/nodes/mcp/McpTrigger/McpTrigger.node.js.map +1 -1
  34. package/dist/nodes/text_splitters/TextSplitterTokenSplitter/TokenTextSplitter.js +1 -3
  35. package/dist/nodes/text_splitters/TextSplitterTokenSplitter/TokenTextSplitter.js.map +1 -1
  36. package/dist/nodes/tools/ToolCode/ToolCode.node.js +1 -2
  37. package/dist/nodes/tools/ToolCode/ToolCode.node.js.map +1 -1
  38. package/dist/nodes/tools/ToolVectorStore/ToolVectorStore.node.js +1 -2
  39. package/dist/nodes/tools/ToolVectorStore/ToolVectorStore.node.js.map +1 -1
  40. package/dist/nodes/tools/ToolWorkflow/v2/ToolWorkflowV2.node.js +2 -2
  41. package/dist/nodes/tools/ToolWorkflow/v2/ToolWorkflowV2.node.js.map +1 -1
  42. package/dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js +2 -1
  43. package/dist/nodes/trigger/ChatTrigger/ChatTrigger.node.js.map +1 -1
  44. package/dist/nodes/trigger/ChatTrigger/templates.js +3 -1
  45. package/dist/nodes/trigger/ChatTrigger/templates.js.map +1 -1
  46. package/dist/nodes/vector_store/shared/createVectorStoreNode/operations/retrieveAsToolOperation.js +2 -1
  47. package/dist/nodes/vector_store/shared/createVectorStoreNode/operations/retrieveAsToolOperation.js.map +1 -1
  48. package/dist/nodes/vendors/GoogleGemini/GoogleGemini.node.js +42 -0
  49. package/dist/nodes/vendors/GoogleGemini/GoogleGemini.node.js.map +1 -0
  50. package/dist/nodes/vendors/GoogleGemini/actions/audio/analyze.operation.js +125 -0
  51. package/dist/nodes/vendors/GoogleGemini/actions/audio/analyze.operation.js.map +1 -0
  52. package/dist/nodes/vendors/GoogleGemini/actions/audio/index.js +74 -0
  53. package/dist/nodes/vendors/GoogleGemini/actions/audio/index.js.map +1 -0
  54. package/dist/nodes/vendors/GoogleGemini/actions/audio/transcribe.operation.js +184 -0
  55. package/dist/nodes/vendors/GoogleGemini/actions/audio/transcribe.operation.js.map +1 -0
  56. package/dist/nodes/vendors/GoogleGemini/actions/descriptions.js +52 -0
  57. package/dist/nodes/vendors/GoogleGemini/actions/descriptions.js.map +1 -0
  58. package/dist/nodes/vendors/GoogleGemini/actions/document/analyze.operation.js +125 -0
  59. package/dist/nodes/vendors/GoogleGemini/actions/document/analyze.operation.js.map +1 -0
  60. package/dist/nodes/vendors/GoogleGemini/actions/document/index.js +64 -0
  61. package/dist/nodes/vendors/GoogleGemini/actions/document/index.js.map +1 -0
  62. package/dist/nodes/vendors/GoogleGemini/actions/file/index.js +64 -0
  63. package/dist/nodes/vendors/GoogleGemini/actions/file/index.js.map +1 -0
  64. package/dist/nodes/vendors/GoogleGemini/actions/file/upload.operation.js +119 -0
  65. package/dist/nodes/vendors/GoogleGemini/actions/file/upload.operation.js.map +1 -0
  66. package/dist/nodes/vendors/GoogleGemini/actions/image/analyze.operation.js +125 -0
  67. package/dist/nodes/vendors/GoogleGemini/actions/image/analyze.operation.js.map +1 -0
  68. package/dist/nodes/vendors/GoogleGemini/actions/image/generate.operation.js +167 -0
  69. package/dist/nodes/vendors/GoogleGemini/actions/image/generate.operation.js.map +1 -0
  70. package/dist/nodes/vendors/GoogleGemini/actions/image/index.js +74 -0
  71. package/dist/nodes/vendors/GoogleGemini/actions/image/index.js.map +1 -0
  72. package/dist/nodes/vendors/GoogleGemini/actions/node.type.js +17 -0
  73. package/dist/nodes/vendors/GoogleGemini/actions/node.type.js.map +1 -0
  74. package/dist/nodes/vendors/GoogleGemini/actions/router.js +97 -0
  75. package/dist/nodes/vendors/GoogleGemini/actions/router.js.map +1 -0
  76. package/dist/nodes/vendors/GoogleGemini/actions/text/index.js +64 -0
  77. package/dist/nodes/vendors/GoogleGemini/actions/text/index.js.map +1 -0
  78. package/dist/nodes/vendors/GoogleGemini/actions/text/message.operation.js +339 -0
  79. package/dist/nodes/vendors/GoogleGemini/actions/text/message.operation.js.map +1 -0
  80. package/dist/nodes/vendors/GoogleGemini/actions/versionDescription.js +131 -0
  81. package/dist/nodes/vendors/GoogleGemini/actions/versionDescription.js.map +1 -0
  82. package/dist/nodes/vendors/GoogleGemini/actions/video/analyze.operation.js +125 -0
  83. package/dist/nodes/vendors/GoogleGemini/actions/video/analyze.operation.js.map +1 -0
  84. package/dist/nodes/vendors/GoogleGemini/actions/video/download.operation.js +88 -0
  85. package/dist/nodes/vendors/GoogleGemini/actions/video/download.operation.js.map +1 -0
  86. package/dist/nodes/vendors/GoogleGemini/actions/video/generate.operation.js +228 -0
  87. package/dist/nodes/vendors/GoogleGemini/actions/video/generate.operation.js.map +1 -0
  88. package/dist/nodes/vendors/GoogleGemini/actions/video/index.js +84 -0
  89. package/dist/nodes/vendors/GoogleGemini/actions/video/index.js.map +1 -0
  90. package/dist/nodes/vendors/GoogleGemini/gemini.svg +1 -0
  91. package/dist/nodes/vendors/GoogleGemini/helpers/baseAnalyze.js +100 -0
  92. package/dist/nodes/vendors/GoogleGemini/helpers/baseAnalyze.js.map +1 -0
  93. package/dist/nodes/vendors/GoogleGemini/helpers/interfaces.js +17 -0
  94. package/dist/nodes/vendors/GoogleGemini/helpers/interfaces.js.map +1 -0
  95. package/dist/nodes/vendors/GoogleGemini/helpers/utils.js +91 -0
  96. package/dist/nodes/vendors/GoogleGemini/helpers/utils.js.map +1 -0
  97. package/dist/nodes/vendors/GoogleGemini/methods/index.js +39 -0
  98. package/dist/nodes/vendors/GoogleGemini/methods/index.js.map +1 -0
  99. package/dist/nodes/vendors/GoogleGemini/methods/listSearch.js +74 -0
  100. package/dist/nodes/vendors/GoogleGemini/methods/listSearch.js.map +1 -0
  101. package/dist/nodes/vendors/GoogleGemini/transport/index.js +48 -0
  102. package/dist/nodes/vendors/GoogleGemini/transport/index.js.map +1 -0
  103. package/dist/types/credentials.json +2 -2
  104. package/dist/types/nodes.json +4 -1
  105. package/dist/utils/descriptions.js +13 -2
  106. package/dist/utils/descriptions.js.map +1 -1
  107. package/dist/utils/helpers.js +2 -7
  108. package/dist/utils/helpers.js.map +1 -1
  109. package/dist/utils/output_parsers/N8nOutputParser.js.map +1 -1
  110. package/dist/utils/tokenizer/tiktoken.js +27 -30
  111. package/dist/utils/tokenizer/tiktoken.js.map +1 -1
  112. package/dist/utils/tokenizer/token-estimator.js +1 -1
  113. package/dist/utils/tokenizer/token-estimator.js.map +1 -1
  114. package/package.json +9 -5
@@ -26,7 +26,8 @@ __export(descriptions_exports, {
26
26
  promptTypeOptions: () => promptTypeOptions,
27
27
  schemaTypeField: () => schemaTypeField,
28
28
  textFromPreviousNode: () => textFromPreviousNode,
29
- textInput: () => textInput
29
+ textInput: () => textInput,
30
+ toolDescription: () => toolDescription
30
31
  });
31
32
  module.exports = __toCommonJS(descriptions_exports);
32
33
  const schemaTypeField = {
@@ -148,6 +149,15 @@ const textFromPreviousNode = {
148
149
  },
149
150
  disabledOptions: { show: { promptType: ["auto"] } }
150
151
  };
152
+ const toolDescription = {
153
+ displayName: "Description",
154
+ name: "toolDescription",
155
+ type: "string",
156
+ default: "AI Agent that can call other tools",
157
+ required: true,
158
+ typeOptions: { rows: 2 },
159
+ description: "Explain to the LLM what this tool does, a good, specific description would allow LLMs to produce expected results much more often"
160
+ };
151
161
  // Annotate the CommonJS export names for ESM import in node:
152
162
  0 && (module.exports = {
153
163
  buildInputSchemaField,
@@ -158,6 +168,7 @@ const textFromPreviousNode = {
158
168
  promptTypeOptions,
159
169
  schemaTypeField,
160
170
  textFromPreviousNode,
161
- textInput
171
+ textInput,
172
+ toolDescription
162
173
  });
163
174
  //# sourceMappingURL=descriptions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../utils/descriptions.ts"],"sourcesContent":["import type { DisplayCondition, INodeProperties, NodeParameterValue } from 'n8n-workflow';\n\nexport const schemaTypeField: INodeProperties = {\n\tdisplayName: 'Schema Type',\n\tname: 'schemaType',\n\ttype: 'options',\n\tnoDataExpression: true,\n\toptions: [\n\t\t{\n\t\t\tname: 'Generate From JSON Example',\n\t\t\tvalue: 'fromJson',\n\t\t\tdescription: 'Generate a schema from an example JSON object',\n\t\t},\n\t\t{\n\t\t\tname: 'Define using JSON Schema',\n\t\t\tvalue: 'manual',\n\t\t\tdescription: 'Define the JSON schema manually',\n\t\t},\n\t],\n\tdefault: 'fromJson',\n\tdescription: 'How to specify the schema for the function',\n};\n\n/**\n * Returns a field for inputting a JSON example that can be used to generate the schema.\n * @param props\n */\nexport const buildJsonSchemaExampleField = (props?: {\n\tshowExtraProps?: Record<string, Array<NodeParameterValue | DisplayCondition> | undefined>;\n}): INodeProperties => ({\n\tdisplayName: 'JSON Example',\n\tname: 'jsonSchemaExample',\n\ttype: 'json',\n\tdefault: `{\n\t\"some_input\": \"some_value\"\n}`,\n\tnoDataExpression: true,\n\ttypeOptions: {\n\t\trows: 10,\n\t},\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t...props?.showExtraProps,\n\t\t\tschemaType: ['fromJson'],\n\t\t},\n\t},\n\tdescription: 'Example JSON object to use to generate the schema',\n});\n\n/**\n * Returns a notice field about the generated schema properties being required by default.\n * @param props\n */\nexport const buildJsonSchemaExampleNotice = (props?: {\n\tshowExtraProps?: Record<string, Array<NodeParameterValue | DisplayCondition> | undefined>;\n}): INodeProperties => ({\n\tdisplayName:\n\t\t\"All properties will be required. To make them optional, use the 'JSON Schema' schema type instead\",\n\tname: 'notice',\n\ttype: 'notice',\n\tdefault: '',\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t...props?.showExtraProps,\n\t\t\tschemaType: ['fromJson'],\n\t\t},\n\t},\n});\n\nexport const jsonSchemaExampleField = buildJsonSchemaExampleField();\n\nexport const buildInputSchemaField = (props?: {\n\tshowExtraProps?: Record<string, Array<NodeParameterValue | DisplayCondition> | undefined>;\n}): INodeProperties => ({\n\tdisplayName: 'Input Schema',\n\tname: 'inputSchema',\n\ttype: 'json',\n\tdefault: `{\n\"type\": \"object\",\n\"properties\": {\n\t\"some_input\": {\n\t\t\"type\": \"string\",\n\t\t\"description\": \"Some input to the function\"\n\t\t}\n\t}\n}`,\n\tnoDataExpression: false,\n\ttypeOptions: {\n\t\trows: 10,\n\t},\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t...props?.showExtraProps,\n\t\t\tschemaType: ['manual'],\n\t\t},\n\t},\n\tdescription: 'Schema to use for the function',\n\thint: 'Use <a target=\"_blank\" href=\"https://json-schema.org/\">JSON Schema</a> format (<a target=\"_blank\" href=\"https://json-schema.org/learn/miscellaneous-examples.html\">examples</a>). $refs syntax is currently not supported.',\n});\n\nexport const inputSchemaField = buildInputSchemaField();\n\nexport const promptTypeOptions: INodeProperties = {\n\tdisplayName: 'Source for Prompt (User Message)',\n\tname: 'promptType',\n\ttype: 'options',\n\toptions: [\n\t\t{\n\t\t\tname: 'Connected Chat Trigger Node',\n\t\t\tvalue: 'auto',\n\t\t\tdescription:\n\t\t\t\t\"Looks for an input field called 'chatInput' that is coming from a directly connected Chat Trigger\",\n\t\t},\n\t\t{\n\t\t\tname: 'Define below',\n\t\t\tvalue: 'define',\n\t\t\tdescription: 'Use an expression to reference data in previous nodes or enter static text',\n\t\t},\n\t],\n\tdefault: 'auto',\n};\n\nexport const textInput: INodeProperties = {\n\tdisplayName: 'Prompt (User Message)',\n\tname: 'text',\n\ttype: 'string',\n\trequired: true,\n\tdefault: '',\n\tplaceholder: 'e.g. Hello, how can you help me?',\n\ttypeOptions: {\n\t\trows: 2,\n\t},\n};\n\nexport const textFromPreviousNode: INodeProperties = {\n\tdisplayName: 'Prompt (User Message)',\n\tname: 'text',\n\ttype: 'string',\n\trequired: true,\n\tdefault: '={{ $json.chatInput }}',\n\ttypeOptions: {\n\t\trows: 2,\n\t},\n\tdisabledOptions: { show: { promptType: ['auto'] } },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,kBAAmC;AAAA,EAC/C,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,SAAS;AAAA,IACR;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACd;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACd;AAAA,EACD;AAAA,EACA,SAAS;AAAA,EACT,aAAa;AACd;AAMO,MAAM,8BAA8B,CAAC,WAEpB;AAAA,EACvB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA;AAAA;AAAA,EAGT,kBAAkB;AAAA,EAClB,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AAAA,EACA,gBAAgB;AAAA,IACf,MAAM;AAAA,MACL,GAAG,OAAO;AAAA,MACV,YAAY,CAAC,UAAU;AAAA,IACxB;AAAA,EACD;AAAA,EACA,aAAa;AACd;AAMO,MAAM,+BAA+B,CAAC,WAErB;AAAA,EACvB,aACC;AAAA,EACD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,gBAAgB;AAAA,IACf,MAAM;AAAA,MACL,GAAG,OAAO;AAAA,MACV,YAAY,CAAC,UAAU;AAAA,IACxB;AAAA,EACD;AACD;AAEO,MAAM,yBAAyB,4BAA4B;AAE3D,MAAM,wBAAwB,CAAC,WAEd;AAAA,EACvB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,kBAAkB;AAAA,EAClB,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AAAA,EACA,gBAAgB;AAAA,IACf,MAAM;AAAA,MACL,GAAG,OAAO;AAAA,MACV,YAAY,CAAC,QAAQ;AAAA,IACtB;AAAA,EACD;AAAA,EACA,aAAa;AAAA,EACb,MAAM;AACP;AAEO,MAAM,mBAAmB,sBAAsB;AAE/C,MAAM,oBAAqC;AAAA,EACjD,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,IACR;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACC;AAAA,IACF;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACd;AAAA,EACD;AAAA,EACA,SAAS;AACV;AAEO,MAAM,YAA6B;AAAA,EACzC,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AACD;AAEO,MAAM,uBAAwC;AAAA,EACpD,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AAAA,EACA,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,EAAE;AACnD;","names":[]}
1
+ {"version":3,"sources":["../../utils/descriptions.ts"],"sourcesContent":["import type { DisplayCondition, INodeProperties, NodeParameterValue } from 'n8n-workflow';\n\nexport const schemaTypeField: INodeProperties = {\n\tdisplayName: 'Schema Type',\n\tname: 'schemaType',\n\ttype: 'options',\n\tnoDataExpression: true,\n\toptions: [\n\t\t{\n\t\t\tname: 'Generate From JSON Example',\n\t\t\tvalue: 'fromJson',\n\t\t\tdescription: 'Generate a schema from an example JSON object',\n\t\t},\n\t\t{\n\t\t\tname: 'Define using JSON Schema',\n\t\t\tvalue: 'manual',\n\t\t\tdescription: 'Define the JSON schema manually',\n\t\t},\n\t],\n\tdefault: 'fromJson',\n\tdescription: 'How to specify the schema for the function',\n};\n\n/**\n * Returns a field for inputting a JSON example that can be used to generate the schema.\n * @param props\n */\nexport const buildJsonSchemaExampleField = (props?: {\n\tshowExtraProps?: Record<string, Array<NodeParameterValue | DisplayCondition> | undefined>;\n}): INodeProperties => ({\n\tdisplayName: 'JSON Example',\n\tname: 'jsonSchemaExample',\n\ttype: 'json',\n\tdefault: `{\n\t\"some_input\": \"some_value\"\n}`,\n\tnoDataExpression: true,\n\ttypeOptions: {\n\t\trows: 10,\n\t},\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t...props?.showExtraProps,\n\t\t\tschemaType: ['fromJson'],\n\t\t},\n\t},\n\tdescription: 'Example JSON object to use to generate the schema',\n});\n\n/**\n * Returns a notice field about the generated schema properties being required by default.\n * @param props\n */\nexport const buildJsonSchemaExampleNotice = (props?: {\n\tshowExtraProps?: Record<string, Array<NodeParameterValue | DisplayCondition> | undefined>;\n}): INodeProperties => ({\n\tdisplayName:\n\t\t\"All properties will be required. To make them optional, use the 'JSON Schema' schema type instead\",\n\tname: 'notice',\n\ttype: 'notice',\n\tdefault: '',\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t...props?.showExtraProps,\n\t\t\tschemaType: ['fromJson'],\n\t\t},\n\t},\n});\n\nexport const jsonSchemaExampleField = buildJsonSchemaExampleField();\n\nexport const buildInputSchemaField = (props?: {\n\tshowExtraProps?: Record<string, Array<NodeParameterValue | DisplayCondition> | undefined>;\n}): INodeProperties => ({\n\tdisplayName: 'Input Schema',\n\tname: 'inputSchema',\n\ttype: 'json',\n\tdefault: `{\n\"type\": \"object\",\n\"properties\": {\n\t\"some_input\": {\n\t\t\"type\": \"string\",\n\t\t\"description\": \"Some input to the function\"\n\t\t}\n\t}\n}`,\n\tnoDataExpression: false,\n\ttypeOptions: {\n\t\trows: 10,\n\t},\n\tdisplayOptions: {\n\t\tshow: {\n\t\t\t...props?.showExtraProps,\n\t\t\tschemaType: ['manual'],\n\t\t},\n\t},\n\tdescription: 'Schema to use for the function',\n\thint: 'Use <a target=\"_blank\" href=\"https://json-schema.org/\">JSON Schema</a> format (<a target=\"_blank\" href=\"https://json-schema.org/learn/miscellaneous-examples.html\">examples</a>). $refs syntax is currently not supported.',\n});\n\nexport const inputSchemaField = buildInputSchemaField();\n\nexport const promptTypeOptions: INodeProperties = {\n\tdisplayName: 'Source for Prompt (User Message)',\n\tname: 'promptType',\n\ttype: 'options',\n\toptions: [\n\t\t{\n\t\t\tname: 'Connected Chat Trigger Node',\n\t\t\tvalue: 'auto',\n\t\t\tdescription:\n\t\t\t\t\"Looks for an input field called 'chatInput' that is coming from a directly connected Chat Trigger\",\n\t\t},\n\t\t{\n\t\t\tname: 'Define below',\n\t\t\tvalue: 'define',\n\t\t\tdescription: 'Use an expression to reference data in previous nodes or enter static text',\n\t\t},\n\t],\n\tdefault: 'auto',\n};\n\nexport const textInput: INodeProperties = {\n\tdisplayName: 'Prompt (User Message)',\n\tname: 'text',\n\ttype: 'string',\n\trequired: true,\n\tdefault: '',\n\tplaceholder: 'e.g. Hello, how can you help me?',\n\ttypeOptions: {\n\t\trows: 2,\n\t},\n};\n\nexport const textFromPreviousNode: INodeProperties = {\n\tdisplayName: 'Prompt (User Message)',\n\tname: 'text',\n\ttype: 'string',\n\trequired: true,\n\tdefault: '={{ $json.chatInput }}',\n\ttypeOptions: {\n\t\trows: 2,\n\t},\n\tdisabledOptions: { show: { promptType: ['auto'] } },\n};\n\nexport const toolDescription: INodeProperties = {\n\tdisplayName: 'Description',\n\tname: 'toolDescription',\n\ttype: 'string',\n\tdefault: 'AI Agent that can call other tools',\n\trequired: true,\n\ttypeOptions: { rows: 2 },\n\tdescription:\n\t\t'Explain to the LLM what this tool does, a good, specific description would allow LLMs to produce expected results much more often',\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,kBAAmC;AAAA,EAC/C,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,SAAS;AAAA,IACR;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACd;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACd;AAAA,EACD;AAAA,EACA,SAAS;AAAA,EACT,aAAa;AACd;AAMO,MAAM,8BAA8B,CAAC,WAEpB;AAAA,EACvB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA;AAAA;AAAA,EAGT,kBAAkB;AAAA,EAClB,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AAAA,EACA,gBAAgB;AAAA,IACf,MAAM;AAAA,MACL,GAAG,OAAO;AAAA,MACV,YAAY,CAAC,UAAU;AAAA,IACxB;AAAA,EACD;AAAA,EACA,aAAa;AACd;AAMO,MAAM,+BAA+B,CAAC,WAErB;AAAA,EACvB,aACC;AAAA,EACD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,gBAAgB;AAAA,IACf,MAAM;AAAA,MACL,GAAG,OAAO;AAAA,MACV,YAAY,CAAC,UAAU;AAAA,IACxB;AAAA,EACD;AACD;AAEO,MAAM,yBAAyB,4BAA4B;AAE3D,MAAM,wBAAwB,CAAC,WAEd;AAAA,EACvB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,kBAAkB;AAAA,EAClB,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AAAA,EACA,gBAAgB;AAAA,IACf,MAAM;AAAA,MACL,GAAG,OAAO;AAAA,MACV,YAAY,CAAC,QAAQ;AAAA,IACtB;AAAA,EACD;AAAA,EACA,aAAa;AAAA,EACb,MAAM;AACP;AAEO,MAAM,mBAAmB,sBAAsB;AAE/C,MAAM,oBAAqC;AAAA,EACjD,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,IACR;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACC;AAAA,IACF;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACd;AAAA,EACD;AAAA,EACA,SAAS;AACV;AAEO,MAAM,YAA6B;AAAA,EACzC,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AACD;AAEO,MAAM,uBAAwC;AAAA,EACpD,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,IACZ,MAAM;AAAA,EACP;AAAA,EACA,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,EAAE;AACnD;AAEO,MAAM,kBAAmC;AAAA,EAC/C,aAAa;AAAA,EACb,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA,EACV,aAAa,EAAE,MAAM,EAAE;AAAA,EACvB,aACC;AACF;","names":[]}
@@ -29,7 +29,6 @@ __export(helpers_exports, {
29
29
  isChatInstance: () => isChatInstance,
30
30
  isToolsInstance: () => isToolsInstance,
31
31
  logAiEvent: () => logAiEvent,
32
- nodeNameToToolName: () => nodeNameToToolName,
33
32
  serializeChatHistory: () => serializeChatHistory,
34
33
  unwrapNestedOutput: () => unwrapNestedOutput
35
34
  });
@@ -73,9 +72,9 @@ function isToolsInstance(model) {
73
72
  }
74
73
  function getPromptInputByType(options) {
75
74
  const { ctx, i, promptTypeKey, inputKey } = options;
76
- const prompt = ctx.getNodeParameter(promptTypeKey, i);
75
+ const promptType = ctx.getNodeParameter(promptTypeKey, i, "define");
77
76
  let input;
78
- if (prompt === "auto") {
77
+ if (promptType === "auto") {
79
78
  input = ctx.evaluateExpression('{{ $json["chatInput"] }}', i);
80
79
  } else {
81
80
  input = ctx.getNodeParameter(inputKey, i);
@@ -174,9 +173,6 @@ function unwrapNestedOutput(output) {
174
173
  }
175
174
  return output;
176
175
  }
177
- function nodeNameToToolName(node) {
178
- return node.name.replace(/[\s.?!=+#@&*()[\]{}:;,<>\/\\'"^%$]/g, "_").replace(/_+/g, "_");
179
- }
180
176
  function hasLongSequentialRepeat(text, threshold = 1e3) {
181
177
  try {
182
178
  if (text === null || typeof text !== "string" || text.length === 0 || threshold <= 0 || text.length < threshold) {
@@ -217,7 +213,6 @@ function hasLongSequentialRepeat(text, threshold = 1e3) {
217
213
  isChatInstance,
218
214
  isToolsInstance,
219
215
  logAiEvent,
220
- nodeNameToToolName,
221
216
  serializeChatHistory,
222
217
  unwrapNestedOutput
223
218
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../utils/helpers.ts"],"sourcesContent":["import type { BaseChatMessageHistory } from '@langchain/core/chat_history';\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { BaseLLM } from '@langchain/core/language_models/llms';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport type { Tool } from '@langchain/core/tools';\nimport { Toolkit } from 'langchain/agents';\nimport type { BaseChatMemory } from 'langchain/memory';\nimport { NodeConnectionTypes, NodeOperationError, jsonStringify } from 'n8n-workflow';\nimport type {\n\tAiEvent,\n\tINode,\n\tIDataObject,\n\tIExecuteFunctions,\n\tISupplyDataFunctions,\n\tIWebhookFunctions,\n} from 'n8n-workflow';\n\nimport { N8nTool } from './N8nTool';\n\nfunction hasMethods<T>(obj: unknown, ...methodNames: Array<string | symbol>): obj is T {\n\treturn methodNames.every(\n\t\t(methodName) =>\n\t\t\ttypeof obj === 'object' &&\n\t\t\tobj !== null &&\n\t\t\tmethodName in obj &&\n\t\t\ttypeof (obj as Record<string | symbol, unknown>)[methodName] === 'function',\n\t);\n}\n\nexport function getMetadataFiltersValues(\n\tctx: IExecuteFunctions | ISupplyDataFunctions,\n\titemIndex: number,\n): Record<string, never> | undefined {\n\tconst options = ctx.getNodeParameter('options', itemIndex, {});\n\n\tif (options.metadata) {\n\t\tconst { metadataValues: metadata } = options.metadata as {\n\t\t\tmetadataValues: Array<{\n\t\t\t\tname: string;\n\t\t\t\tvalue: string;\n\t\t\t}>;\n\t\t};\n\t\tif (metadata.length > 0) {\n\t\t\treturn metadata.reduce((acc, { name, value }) => ({ ...acc, [name]: value }), {});\n\t\t}\n\t}\n\n\tif (options.searchFilterJson) {\n\t\treturn ctx.getNodeParameter('options.searchFilterJson', itemIndex, '', {\n\t\t\tensureType: 'object',\n\t\t}) as Record<string, never>;\n\t}\n\n\treturn undefined;\n}\n\nexport function isBaseChatMemory(obj: unknown) {\n\treturn hasMethods<BaseChatMemory>(obj, 'loadMemoryVariables', 'saveContext');\n}\n\nexport function isBaseChatMessageHistory(obj: unknown) {\n\treturn hasMethods<BaseChatMessageHistory>(obj, 'getMessages', 'addMessage');\n}\n\nexport function isChatInstance(model: unknown): model is BaseChatModel {\n\tconst namespace = (model as BaseLLM)?.lc_namespace ?? [];\n\n\treturn namespace.includes('chat_models');\n}\n\nexport function isToolsInstance(model: unknown): model is Tool {\n\tconst namespace = (model as Tool)?.lc_namespace ?? [];\n\n\treturn namespace.includes('tools');\n}\n\nexport function getPromptInputByType(options: {\n\tctx: IExecuteFunctions;\n\ti: number;\n\tpromptTypeKey: string;\n\tinputKey: string;\n}) {\n\tconst { ctx, i, promptTypeKey, inputKey } = options;\n\tconst prompt = ctx.getNodeParameter(promptTypeKey, i) as string;\n\n\tlet input;\n\tif (prompt === 'auto') {\n\t\tinput = ctx.evaluateExpression('{{ $json[\"chatInput\"] }}', i) as string;\n\t} else {\n\t\tinput = ctx.getNodeParameter(inputKey, i) as string;\n\t}\n\n\tif (input === undefined) {\n\t\tthrow new NodeOperationError(ctx.getNode(), 'No prompt specified', {\n\t\t\tdescription:\n\t\t\t\t\"Expected to find the prompt in an input field called 'chatInput' (this is what the chat trigger node outputs). To use something else, change the 'Prompt' parameter\",\n\t\t});\n\t}\n\n\treturn input;\n}\n\nexport function getSessionId(\n\tctx: ISupplyDataFunctions | IWebhookFunctions,\n\titemIndex: number,\n\tselectorKey = 'sessionIdType',\n\tautoSelect = 'fromInput',\n\tcustomKey = 'sessionKey',\n) {\n\tlet sessionId = '';\n\tconst selectorType = ctx.getNodeParameter(selectorKey, itemIndex) as string;\n\n\tif (selectorType === autoSelect) {\n\t\t// If memory node is used in webhook like node(like chat trigger node), it doesn't have access to evaluateExpression\n\t\t// so we try to extract sessionId from the bodyData\n\t\tif ('getBodyData' in ctx) {\n\t\t\tconst bodyData = ctx.getBodyData() ?? {};\n\t\t\tsessionId = bodyData.sessionId as string;\n\t\t} else {\n\t\t\tsessionId = ctx.evaluateExpression('{{ $json.sessionId }}', itemIndex) as string;\n\t\t}\n\n\t\tif (sessionId === '' || sessionId === undefined) {\n\t\t\tthrow new NodeOperationError(ctx.getNode(), 'No session ID found', {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Expected to find the session ID in an input field called 'sessionId' (this is what the chat trigger node outputs). To use something else, change the 'Session ID' parameter\",\n\t\t\t\titemIndex,\n\t\t\t});\n\t\t}\n\t} else {\n\t\tsessionId = ctx.getNodeParameter(customKey, itemIndex, '') as string;\n\t\tif (sessionId === '' || sessionId === undefined) {\n\t\t\tthrow new NodeOperationError(ctx.getNode(), 'Key parameter is empty', {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Provide a key to use as session ID in the 'Key' parameter or use the 'Connected Chat Trigger Node' option to use the session ID from your Chat Trigger\",\n\t\t\t\titemIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn sessionId;\n}\n\nexport function logAiEvent(\n\texecuteFunctions: IExecuteFunctions | ISupplyDataFunctions,\n\tevent: AiEvent,\n\tdata?: IDataObject,\n) {\n\ttry {\n\t\texecuteFunctions.logAiEvent(event, data ? jsonStringify(data) : undefined);\n\t} catch (error) {\n\t\texecuteFunctions.logger.debug(`Error logging AI event: ${event}`);\n\t}\n}\n\nexport function serializeChatHistory(chatHistory: BaseMessage[]): string {\n\treturn chatHistory\n\t\t.map((chatMessage) => {\n\t\t\tif (chatMessage._getType() === 'human') {\n\t\t\t\treturn `Human: ${chatMessage.content}`;\n\t\t\t} else if (chatMessage._getType() === 'ai') {\n\t\t\t\treturn `Assistant: ${chatMessage.content}`;\n\t\t\t} else {\n\t\t\t\treturn `${chatMessage.content}`;\n\t\t\t}\n\t\t})\n\t\t.join('\\n');\n}\n\nexport function escapeSingleCurlyBrackets(text?: string): string | undefined {\n\tif (text === undefined) return undefined;\n\n\tlet result = text;\n\n\tresult = result\n\t\t// First handle triple brackets to avoid interference with double brackets\n\t\t.replace(/(?<!{){{{(?!{)/g, '{{{{')\n\t\t.replace(/(?<!})}}}(?!})/g, '}}}}')\n\t\t// Then handle single brackets, but only if they're not part of double brackets\n\t\t// Convert single { to {{ if it's not already part of {{ or {{{\n\t\t.replace(/(?<!{){(?!{)/g, '{{')\n\t\t// Convert single } to }} if it's not already part of }} or }}}\n\t\t.replace(/(?<!})}(?!})/g, '}}');\n\n\treturn result;\n}\n\nexport const getConnectedTools = async (\n\tctx: IExecuteFunctions | IWebhookFunctions,\n\tenforceUniqueNames: boolean,\n\tconvertStructuredTool: boolean = true,\n\tescapeCurlyBrackets: boolean = false,\n) => {\n\tconst connectedTools = (\n\t\t((await ctx.getInputConnectionData(NodeConnectionTypes.AiTool, 0)) as Array<Toolkit | Tool>) ??\n\t\t[]\n\t).flatMap((toolOrToolkit) => {\n\t\tif (toolOrToolkit instanceof Toolkit) {\n\t\t\treturn toolOrToolkit.getTools() as Tool[];\n\t\t}\n\n\t\treturn toolOrToolkit;\n\t});\n\n\tif (!enforceUniqueNames) return connectedTools;\n\n\tconst seenNames = new Set<string>();\n\n\tconst finalTools: Tool[] = [];\n\n\tfor (const tool of connectedTools) {\n\t\tconst { name } = tool;\n\t\tif (seenNames.has(name)) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tctx.getNode(),\n\t\t\t\t`You have multiple tools with the same name: '${name}', please rename them to avoid conflicts`,\n\t\t\t);\n\t\t}\n\t\tseenNames.add(name);\n\n\t\tif (escapeCurlyBrackets) {\n\t\t\ttool.description = escapeSingleCurlyBrackets(tool.description) ?? tool.description;\n\t\t}\n\n\t\tif (convertStructuredTool && tool instanceof N8nTool) {\n\t\t\tfinalTools.push(tool.asDynamicTool());\n\t\t} else {\n\t\t\tfinalTools.push(tool);\n\t\t}\n\t}\n\n\treturn finalTools;\n};\n\n/**\n * Sometimes model output is wrapped in an additional object property.\n * This function unwraps the output if it is in the format { output: { output: { ... } } }\n */\nexport function unwrapNestedOutput(output: Record<string, unknown>): Record<string, unknown> {\n\tif (\n\t\t'output' in output &&\n\t\tObject.keys(output).length === 1 &&\n\t\ttypeof output.output === 'object' &&\n\t\toutput.output !== null &&\n\t\t'output' in output.output &&\n\t\tObject.keys(output.output).length === 1\n\t) {\n\t\treturn output.output as Record<string, unknown>;\n\t}\n\n\treturn output;\n}\n\n/**\n * Converts a node name to a valid tool name by replacing special characters with underscores\n * and collapsing consecutive underscores into a single one.\n */\nexport function nodeNameToToolName(node: INode): string {\n\treturn node.name.replace(/[\\s.?!=+#@&*()[\\]{}:;,<>\\/\\\\'\"^%$]/g, '_').replace(/_+/g, '_');\n}\n\n/**\n * Detects if a text contains a character that repeats sequentially for a specified threshold.\n * This is used to prevent performance issues with tiktoken on highly repetitive content.\n * @param text The text to check\n * @param threshold The minimum number of sequential repeats to detect (default: 1000)\n * @returns true if a character repeats sequentially for at least the threshold amount\n */\nexport function hasLongSequentialRepeat(text: string, threshold = 1000): boolean {\n\ttry {\n\t\t// Validate inputs\n\t\tif (\n\t\t\ttext === null ||\n\t\t\ttypeof text !== 'string' ||\n\t\t\ttext.length === 0 ||\n\t\t\tthreshold <= 0 ||\n\t\t\ttext.length < threshold\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\t// Use string iterator to avoid creating array copy (memory efficient)\n\t\tconst iterator = text[Symbol.iterator]();\n\t\tlet prev = iterator.next();\n\n\t\tif (prev.done) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet count = 1;\n\t\tfor (const char of iterator) {\n\t\t\tif (char === prev.value) {\n\t\t\t\tcount++;\n\t\t\t\tif (count >= threshold) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcount = 1;\n\t\t\t\tprev = { value: char, done: false };\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t} catch (error) {\n\t\t// On any error, return false to allow normal processing\n\t\treturn false;\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../utils/helpers.ts"],"sourcesContent":["import type { BaseChatMessageHistory } from '@langchain/core/chat_history';\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { BaseLLM } from '@langchain/core/language_models/llms';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport type { Tool } from '@langchain/core/tools';\nimport { Toolkit } from 'langchain/agents';\nimport type { BaseChatMemory } from 'langchain/memory';\nimport { NodeConnectionTypes, NodeOperationError, jsonStringify } from 'n8n-workflow';\nimport type {\n\tAiEvent,\n\tIDataObject,\n\tIExecuteFunctions,\n\tISupplyDataFunctions,\n\tIWebhookFunctions,\n} from 'n8n-workflow';\n\nimport { N8nTool } from './N8nTool';\n\nfunction hasMethods<T>(obj: unknown, ...methodNames: Array<string | symbol>): obj is T {\n\treturn methodNames.every(\n\t\t(methodName) =>\n\t\t\ttypeof obj === 'object' &&\n\t\t\tobj !== null &&\n\t\t\tmethodName in obj &&\n\t\t\ttypeof (obj as Record<string | symbol, unknown>)[methodName] === 'function',\n\t);\n}\n\nexport function getMetadataFiltersValues(\n\tctx: IExecuteFunctions | ISupplyDataFunctions,\n\titemIndex: number,\n): Record<string, never> | undefined {\n\tconst options = ctx.getNodeParameter('options', itemIndex, {});\n\n\tif (options.metadata) {\n\t\tconst { metadataValues: metadata } = options.metadata as {\n\t\t\tmetadataValues: Array<{\n\t\t\t\tname: string;\n\t\t\t\tvalue: string;\n\t\t\t}>;\n\t\t};\n\t\tif (metadata.length > 0) {\n\t\t\treturn metadata.reduce((acc, { name, value }) => ({ ...acc, [name]: value }), {});\n\t\t}\n\t}\n\n\tif (options.searchFilterJson) {\n\t\treturn ctx.getNodeParameter('options.searchFilterJson', itemIndex, '', {\n\t\t\tensureType: 'object',\n\t\t}) as Record<string, never>;\n\t}\n\n\treturn undefined;\n}\n\nexport function isBaseChatMemory(obj: unknown) {\n\treturn hasMethods<BaseChatMemory>(obj, 'loadMemoryVariables', 'saveContext');\n}\n\nexport function isBaseChatMessageHistory(obj: unknown) {\n\treturn hasMethods<BaseChatMessageHistory>(obj, 'getMessages', 'addMessage');\n}\n\nexport function isChatInstance(model: unknown): model is BaseChatModel {\n\tconst namespace = (model as BaseLLM)?.lc_namespace ?? [];\n\n\treturn namespace.includes('chat_models');\n}\n\nexport function isToolsInstance(model: unknown): model is Tool {\n\tconst namespace = (model as Tool)?.lc_namespace ?? [];\n\n\treturn namespace.includes('tools');\n}\n\nexport function getPromptInputByType(options: {\n\tctx: IExecuteFunctions | ISupplyDataFunctions;\n\ti: number;\n\tpromptTypeKey: string;\n\tinputKey: string;\n}) {\n\tconst { ctx, i, promptTypeKey, inputKey } = options;\n\tconst promptType = ctx.getNodeParameter(promptTypeKey, i, 'define') as string;\n\n\tlet input;\n\tif (promptType === 'auto') {\n\t\tinput = ctx.evaluateExpression('{{ $json[\"chatInput\"] }}', i) as string;\n\t} else {\n\t\tinput = ctx.getNodeParameter(inputKey, i) as string;\n\t}\n\n\tif (input === undefined) {\n\t\tthrow new NodeOperationError(ctx.getNode(), 'No prompt specified', {\n\t\t\tdescription:\n\t\t\t\t\"Expected to find the prompt in an input field called 'chatInput' (this is what the chat trigger node outputs). To use something else, change the 'Prompt' parameter\",\n\t\t});\n\t}\n\n\treturn input;\n}\n\nexport function getSessionId(\n\tctx: ISupplyDataFunctions | IWebhookFunctions,\n\titemIndex: number,\n\tselectorKey = 'sessionIdType',\n\tautoSelect = 'fromInput',\n\tcustomKey = 'sessionKey',\n) {\n\tlet sessionId = '';\n\tconst selectorType = ctx.getNodeParameter(selectorKey, itemIndex) as string;\n\n\tif (selectorType === autoSelect) {\n\t\t// If memory node is used in webhook like node(like chat trigger node), it doesn't have access to evaluateExpression\n\t\t// so we try to extract sessionId from the bodyData\n\t\tif ('getBodyData' in ctx) {\n\t\t\tconst bodyData = ctx.getBodyData() ?? {};\n\t\t\tsessionId = bodyData.sessionId as string;\n\t\t} else {\n\t\t\tsessionId = ctx.evaluateExpression('{{ $json.sessionId }}', itemIndex) as string;\n\t\t}\n\n\t\tif (sessionId === '' || sessionId === undefined) {\n\t\t\tthrow new NodeOperationError(ctx.getNode(), 'No session ID found', {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Expected to find the session ID in an input field called 'sessionId' (this is what the chat trigger node outputs). To use something else, change the 'Session ID' parameter\",\n\t\t\t\titemIndex,\n\t\t\t});\n\t\t}\n\t} else {\n\t\tsessionId = ctx.getNodeParameter(customKey, itemIndex, '') as string;\n\t\tif (sessionId === '' || sessionId === undefined) {\n\t\t\tthrow new NodeOperationError(ctx.getNode(), 'Key parameter is empty', {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Provide a key to use as session ID in the 'Key' parameter or use the 'Connected Chat Trigger Node' option to use the session ID from your Chat Trigger\",\n\t\t\t\titemIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn sessionId;\n}\n\nexport function logAiEvent(\n\texecuteFunctions: IExecuteFunctions | ISupplyDataFunctions,\n\tevent: AiEvent,\n\tdata?: IDataObject,\n) {\n\ttry {\n\t\texecuteFunctions.logAiEvent(event, data ? jsonStringify(data) : undefined);\n\t} catch (error) {\n\t\texecuteFunctions.logger.debug(`Error logging AI event: ${event}`);\n\t}\n}\n\nexport function serializeChatHistory(chatHistory: BaseMessage[]): string {\n\treturn chatHistory\n\t\t.map((chatMessage) => {\n\t\t\tif (chatMessage._getType() === 'human') {\n\t\t\t\treturn `Human: ${chatMessage.content}`;\n\t\t\t} else if (chatMessage._getType() === 'ai') {\n\t\t\t\treturn `Assistant: ${chatMessage.content}`;\n\t\t\t} else {\n\t\t\t\treturn `${chatMessage.content}`;\n\t\t\t}\n\t\t})\n\t\t.join('\\n');\n}\n\nexport function escapeSingleCurlyBrackets(text?: string): string | undefined {\n\tif (text === undefined) return undefined;\n\n\tlet result = text;\n\n\tresult = result\n\t\t// First handle triple brackets to avoid interference with double brackets\n\t\t.replace(/(?<!{){{{(?!{)/g, '{{{{')\n\t\t.replace(/(?<!})}}}(?!})/g, '}}}}')\n\t\t// Then handle single brackets, but only if they're not part of double brackets\n\t\t// Convert single { to {{ if it's not already part of {{ or {{{\n\t\t.replace(/(?<!{){(?!{)/g, '{{')\n\t\t// Convert single } to }} if it's not already part of }} or }}}\n\t\t.replace(/(?<!})}(?!})/g, '}}');\n\n\treturn result;\n}\n\nexport const getConnectedTools = async (\n\tctx: IExecuteFunctions | IWebhookFunctions | ISupplyDataFunctions,\n\tenforceUniqueNames: boolean,\n\tconvertStructuredTool: boolean = true,\n\tescapeCurlyBrackets: boolean = false,\n) => {\n\tconst connectedTools = (\n\t\t((await ctx.getInputConnectionData(NodeConnectionTypes.AiTool, 0)) as Array<Toolkit | Tool>) ??\n\t\t[]\n\t).flatMap((toolOrToolkit) => {\n\t\tif (toolOrToolkit instanceof Toolkit) {\n\t\t\treturn toolOrToolkit.getTools() as Tool[];\n\t\t}\n\n\t\treturn toolOrToolkit;\n\t});\n\n\tif (!enforceUniqueNames) return connectedTools;\n\n\tconst seenNames = new Set<string>();\n\n\tconst finalTools: Tool[] = [];\n\n\tfor (const tool of connectedTools) {\n\t\tconst { name } = tool;\n\t\tif (seenNames.has(name)) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tctx.getNode(),\n\t\t\t\t`You have multiple tools with the same name: '${name}', please rename them to avoid conflicts`,\n\t\t\t);\n\t\t}\n\t\tseenNames.add(name);\n\n\t\tif (escapeCurlyBrackets) {\n\t\t\ttool.description = escapeSingleCurlyBrackets(tool.description) ?? tool.description;\n\t\t}\n\n\t\tif (convertStructuredTool && tool instanceof N8nTool) {\n\t\t\tfinalTools.push(tool.asDynamicTool());\n\t\t} else {\n\t\t\tfinalTools.push(tool);\n\t\t}\n\t}\n\n\treturn finalTools;\n};\n\n/**\n * Sometimes model output is wrapped in an additional object property.\n * This function unwraps the output if it is in the format { output: { output: { ... } } }\n */\nexport function unwrapNestedOutput(output: Record<string, unknown>): Record<string, unknown> {\n\tif (\n\t\t'output' in output &&\n\t\tObject.keys(output).length === 1 &&\n\t\ttypeof output.output === 'object' &&\n\t\toutput.output !== null &&\n\t\t'output' in output.output &&\n\t\tObject.keys(output.output).length === 1\n\t) {\n\t\treturn output.output as Record<string, unknown>;\n\t}\n\n\treturn output;\n}\n\n/**\n * Detects if a text contains a character that repeats sequentially for a specified threshold.\n * This is used to prevent performance issues with tiktoken on highly repetitive content.\n * @param text The text to check\n * @param threshold The minimum number of sequential repeats to detect (default: 1000)\n * @returns true if a character repeats sequentially for at least the threshold amount\n */\nexport function hasLongSequentialRepeat(text: string, threshold = 1000): boolean {\n\ttry {\n\t\t// Validate inputs\n\t\tif (\n\t\t\ttext === null ||\n\t\t\ttypeof text !== 'string' ||\n\t\t\ttext.length === 0 ||\n\t\t\tthreshold <= 0 ||\n\t\t\ttext.length < threshold\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\t// Use string iterator to avoid creating array copy (memory efficient)\n\t\tconst iterator = text[Symbol.iterator]();\n\t\tlet prev = iterator.next();\n\n\t\tif (prev.done) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet count = 1;\n\t\tfor (const char of iterator) {\n\t\t\tif (char === prev.value) {\n\t\t\t\tcount++;\n\t\t\t\tif (count >= threshold) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcount = 1;\n\t\t\t\tprev = { value: char, done: false };\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t} catch (error) {\n\t\t// On any error, return false to allow normal processing\n\t\treturn false;\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../utils/output_parsers/N8nOutputParser.ts"],"sourcesContent":["import type { IExecuteFunctions } from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { N8nItemListOutputParser } from './N8nItemListOutputParser';\nimport { N8nOutputFixingParser } from './N8nOutputFixingParser';\nimport { N8nStructuredOutputParser } from './N8nStructuredOutputParser';\n\nexport type N8nOutputParser =\n\t| N8nOutputFixingParser\n\t| N8nStructuredOutputParser\n\t| N8nItemListOutputParser;\n\nexport { N8nOutputFixingParser, N8nItemListOutputParser, N8nStructuredOutputParser };\n\nexport async function getOptionalOutputParser(\n\tctx: IExecuteFunctions,\n\tindex: number = 0,\n): Promise<N8nOutputParser | undefined> {\n\tlet outputParser: N8nOutputParser | undefined;\n\n\tif (ctx.getNodeParameter('hasOutputParser', 0, true) === true) {\n\t\toutputParser = (await ctx.getInputConnectionData(\n\t\t\tNodeConnectionTypes.AiOutputParser,\n\t\t\tindex,\n\t\t)) as N8nOutputParser;\n\t}\n\n\treturn outputParser;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAoC;AAEpC,qCAAwC;AACxC,mCAAsC;AACtC,uCAA0C;AAS1C,eAAsB,wBACrB,KACA,QAAgB,GACuB;AACvC,MAAI;AAEJ,MAAI,IAAI,iBAAiB,mBAAmB,GAAG,IAAI,MAAM,MAAM;AAC9D,mBAAgB,MAAM,IAAI;AAAA,MACzB,wCAAoB;AAAA,MACpB;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;","names":[]}
1
+ {"version":3,"sources":["../../../utils/output_parsers/N8nOutputParser.ts"],"sourcesContent":["import type { IExecuteFunctions, ISupplyDataFunctions } from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { N8nItemListOutputParser } from './N8nItemListOutputParser';\nimport { N8nOutputFixingParser } from './N8nOutputFixingParser';\nimport { N8nStructuredOutputParser } from './N8nStructuredOutputParser';\n\nexport type N8nOutputParser =\n\t| N8nOutputFixingParser\n\t| N8nStructuredOutputParser\n\t| N8nItemListOutputParser;\n\nexport { N8nOutputFixingParser, N8nItemListOutputParser, N8nStructuredOutputParser };\n\nexport async function getOptionalOutputParser(\n\tctx: IExecuteFunctions | ISupplyDataFunctions,\n\tindex: number = 0,\n): Promise<N8nOutputParser | undefined> {\n\tlet outputParser: N8nOutputParser | undefined;\n\n\tif (ctx.getNodeParameter('hasOutputParser', 0, true) === true) {\n\t\toutputParser = (await ctx.getInputConnectionData(\n\t\t\tNodeConnectionTypes.AiOutputParser,\n\t\t\tindex,\n\t\t)) as N8nOutputParser;\n\t}\n\n\treturn outputParser;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAoC;AAEpC,qCAAwC;AACxC,mCAAsC;AACtC,uCAA0C;AAS1C,eAAsB,wBACrB,KACA,QAAgB,GACuB;AACvC,MAAI;AAEJ,MAAI,IAAI,iBAAiB,mBAAmB,GAAG,IAAI,MAAM,MAAM;AAC9D,mBAAgB,MAAM,IAAI;AAAA,MACzB,wCAAoB;AAAA,MACpB;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;","names":[]}
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var tiktoken_exports = {};
30
20
  __export(tiktoken_exports, {
@@ -32,29 +22,36 @@ __export(tiktoken_exports, {
32
22
  getEncoding: () => getEncoding
33
23
  });
34
24
  module.exports = __toCommonJS(tiktoken_exports);
25
+ var import_fs = require("fs");
35
26
  var import_lite = require("js-tiktoken/lite");
36
- var import_cl100k_base = __toESM(require("./cl100k_base.json"));
37
- var import_o200k_base = __toESM(require("./o200k_base.json"));
38
- async function getEncoding(encoding) {
39
- const encodings = {
40
- cl100k_base: import_cl100k_base.default,
41
- o200k_base: import_o200k_base.default
42
- };
43
- const encodingsMap = {
44
- cl100k_base: encodings.cl100k_base,
45
- p50k_base: encodings.cl100k_base,
46
- r50k_base: encodings.cl100k_base,
47
- gpt2: encodings.cl100k_base,
48
- p50k_edit: encodings.cl100k_base,
49
- o200k_base: encodings.o200k_base
50
- };
51
- if (!(encoding in encodingsMap)) {
52
- return new import_lite.Tiktoken(import_cl100k_base.default);
27
+ var import_n8n_workflow = require("n8n-workflow");
28
+ var import_path = require("path");
29
+ const cache = {};
30
+ const loadJSONFile = (filename) => {
31
+ const filePath = (0, import_path.join)(__dirname, filename);
32
+ const content = (0, import_fs.readFileSync)(filePath, "utf-8");
33
+ return (0, import_n8n_workflow.jsonParse)(content);
34
+ };
35
+ function getEncoding(encoding) {
36
+ if (cache[encoding]) {
37
+ return cache[encoding];
38
+ }
39
+ let jsonData;
40
+ switch (encoding) {
41
+ case "o200k_base":
42
+ jsonData = loadJSONFile("./o200k_base.json");
43
+ break;
44
+ case "cl100k_base":
45
+ jsonData = loadJSONFile("./cl100k_base.json");
46
+ break;
47
+ default:
48
+ jsonData = loadJSONFile("./cl100k_base.json");
53
49
  }
54
- return new import_lite.Tiktoken(encodingsMap[encoding]);
50
+ cache[encoding] = new import_lite.Tiktoken(jsonData);
51
+ return cache[encoding];
55
52
  }
56
- async function encodingForModel(model) {
57
- return await getEncoding((0, import_lite.getEncodingNameForModel)(model));
53
+ function encodingForModel(model) {
54
+ return getEncoding((0, import_lite.getEncodingNameForModel)(model));
58
55
  }
59
56
  // Annotate the CommonJS export names for ESM import in node:
60
57
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../utils/tokenizer/tiktoken.ts"],"sourcesContent":["import type { TiktokenBPE, TiktokenEncoding, TiktokenModel } from 'js-tiktoken/lite';\nimport { Tiktoken, getEncodingNameForModel } from 'js-tiktoken/lite';\n\nimport cl100k_base from './cl100k_base.json';\nimport o200k_base from './o200k_base.json';\n\nexport async function getEncoding(encoding: TiktokenEncoding) {\n\tconst encodings = {\n\t\tcl100k_base: cl100k_base as TiktokenBPE,\n\t\to200k_base: o200k_base as TiktokenBPE,\n\t};\n\tconst encodingsMap: Record<TiktokenEncoding, TiktokenBPE> = {\n\t\tcl100k_base: encodings.cl100k_base,\n\t\tp50k_base: encodings.cl100k_base,\n\t\tr50k_base: encodings.cl100k_base,\n\t\tgpt2: encodings.cl100k_base,\n\t\tp50k_edit: encodings.cl100k_base,\n\t\to200k_base: encodings.o200k_base,\n\t};\n\n\tif (!(encoding in encodingsMap)) {\n\t\treturn new Tiktoken(cl100k_base);\n\t}\n\n\treturn new Tiktoken(encodingsMap[encoding]);\n}\n\nexport async function encodingForModel(model: TiktokenModel) {\n\treturn await getEncoding(getEncodingNameForModel(model));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAkD;AAElD,yBAAwB;AACxB,wBAAuB;AAEvB,eAAsB,YAAY,UAA4B;AAC7D,QAAM,YAAY;AAAA,IACjB,aAAa,mBAAAA;AAAA,IACb,YAAY,kBAAAC;AAAA,EACb;AACA,QAAM,eAAsD;AAAA,IAC3D,aAAa,UAAU;AAAA,IACvB,WAAW,UAAU;AAAA,IACrB,WAAW,UAAU;AAAA,IACrB,MAAM,UAAU;AAAA,IAChB,WAAW,UAAU;AAAA,IACrB,YAAY,UAAU;AAAA,EACvB;AAEA,MAAI,EAAE,YAAY,eAAe;AAChC,WAAO,IAAI,qBAAS,mBAAAD,OAAW;AAAA,EAChC;AAEA,SAAO,IAAI,qBAAS,aAAa,QAAQ,CAAC;AAC3C;AAEA,eAAsB,iBAAiB,OAAsB;AAC5D,SAAO,MAAM,gBAAY,qCAAwB,KAAK,CAAC;AACxD;","names":["cl100k_base","o200k_base"]}
1
+ {"version":3,"sources":["../../../utils/tokenizer/tiktoken.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport type { TiktokenBPE, TiktokenEncoding, TiktokenModel } from 'js-tiktoken/lite';\nimport { Tiktoken, getEncodingNameForModel } from 'js-tiktoken/lite';\nimport { jsonParse } from 'n8n-workflow';\nimport { join } from 'path';\n\nconst cache: Record<string, Tiktoken> = {};\n\nconst loadJSONFile = (filename: string): TiktokenBPE => {\n\tconst filePath = join(__dirname, filename);\n\tconst content = readFileSync(filePath, 'utf-8');\n\treturn jsonParse(content);\n};\n\nexport function getEncoding(encoding: TiktokenEncoding): Tiktoken {\n\tif (cache[encoding]) {\n\t\treturn cache[encoding];\n\t}\n\n\tlet jsonData: TiktokenBPE;\n\n\tswitch (encoding) {\n\t\tcase 'o200k_base':\n\t\t\tjsonData = loadJSONFile('./o200k_base.json');\n\t\t\tbreak;\n\t\tcase 'cl100k_base':\n\t\t\tjsonData = loadJSONFile('./cl100k_base.json');\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// Fall back to cl100k_base for unsupported encodings\n\t\t\tjsonData = loadJSONFile('./cl100k_base.json');\n\t}\n\n\tcache[encoding] = new Tiktoken(jsonData);\n\treturn cache[encoding];\n}\n\nexport function encodingForModel(model: TiktokenModel): Tiktoken {\n\treturn getEncoding(getEncodingNameForModel(model));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAA6B;AAE7B,kBAAkD;AAClD,0BAA0B;AAC1B,kBAAqB;AAErB,MAAM,QAAkC,CAAC;AAEzC,MAAM,eAAe,CAAC,aAAkC;AACvD,QAAM,eAAW,kBAAK,WAAW,QAAQ;AACzC,QAAM,cAAU,wBAAa,UAAU,OAAO;AAC9C,aAAO,+BAAU,OAAO;AACzB;AAEO,SAAS,YAAY,UAAsC;AACjE,MAAI,MAAM,QAAQ,GAAG;AACpB,WAAO,MAAM,QAAQ;AAAA,EACtB;AAEA,MAAI;AAEJ,UAAQ,UAAU;AAAA,IACjB,KAAK;AACJ,iBAAW,aAAa,mBAAmB;AAC3C;AAAA,IACD,KAAK;AACJ,iBAAW,aAAa,oBAAoB;AAC5C;AAAA,IACD;AAEC,iBAAW,aAAa,oBAAoB;AAAA,EAC9C;AAEA,QAAM,QAAQ,IAAI,IAAI,qBAAS,QAAQ;AACvC,SAAO,MAAM,QAAQ;AACtB;AAEO,SAAS,iBAAiB,OAAgC;AAChE,SAAO,gBAAY,qCAAwB,KAAK,CAAC;AAClD;","names":[]}
@@ -82,7 +82,7 @@ async function estimateTokensFromStringList(list, model) {
82
82
  if (!Array.isArray(list)) {
83
83
  return 0;
84
84
  }
85
- const encoder = await (0, import_tiktoken.encodingForModel)(model);
85
+ const encoder = (0, import_tiktoken.encodingForModel)(model);
86
86
  const encodedListLength = await Promise.all(
87
87
  list.map(async (text) => {
88
88
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../utils/tokenizer/token-estimator.ts"],"sourcesContent":["/**\n * Token estimation utilities for handling text without using tiktoken.\n * This is used as a fallback when tiktoken would be too slow (e.g., with repetitive content).\n */\n\nimport type { TiktokenModel } from 'js-tiktoken';\n\nimport { encodingForModel } from './tiktoken';\nimport { hasLongSequentialRepeat } from '../helpers';\n\n/**\n * Model-specific average characters per token ratios.\n * These are approximate values based on typical English text.\n */\nconst MODEL_CHAR_PER_TOKEN_RATIOS: Record<string, number> = {\n\t'gpt-4o': 3.8,\n\t'gpt-4': 4.0,\n\t'gpt-3.5-turbo': 4.0,\n\tcl100k_base: 4.0,\n\to200k_base: 3.5,\n\tp50k_base: 4.2,\n\tr50k_base: 4.2,\n};\n\n/**\n * Estimates the number of tokens in a text based on character count.\n * This is much faster than tiktoken but less accurate.\n *\n * @param text The text to estimate tokens for\n * @param model The model or encoding name (optional)\n * @returns Estimated number of tokens\n */\nexport function estimateTokensByCharCount(text: string, model: string = 'cl100k_base'): number {\n\ttry {\n\t\t// Validate input\n\t\tif (!text || typeof text !== 'string' || text.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Get the ratio for the specific model, or use default\n\t\tconst charsPerToken = MODEL_CHAR_PER_TOKEN_RATIOS[model] || 4.0;\n\n\t\t// Validate ratio\n\t\tif (!Number.isFinite(charsPerToken) || charsPerToken <= 0) {\n\t\t\t// Fallback to default ratio\n\t\t\tconst estimatedTokens = Math.ceil(text.length / 4.0);\n\t\t\treturn estimatedTokens;\n\t\t}\n\n\t\t// Calculate estimated tokens\n\t\tconst estimatedTokens = Math.ceil(text.length / charsPerToken);\n\n\t\treturn estimatedTokens;\n\t} catch (error) {\n\t\t// Return conservative estimate on error\n\t\treturn Math.ceil((text?.length || 0) / 4.0);\n\t}\n}\n\n/**\n * Estimates tokens for text splitting purposes.\n * Returns chunk boundaries based on character positions rather than token positions.\n *\n * @param text The text to split\n * @param chunkSize Target chunk size in tokens\n * @param chunkOverlap Overlap between chunks in tokens\n * @param model The model or encoding name (optional)\n * @returns Array of text chunks\n */\nexport function estimateTextSplitsByTokens(\n\ttext: string,\n\tchunkSize: number,\n\tchunkOverlap: number,\n\tmodel: string = 'cl100k_base',\n): string[] {\n\ttry {\n\t\t// Validate inputs\n\t\tif (!text || typeof text !== 'string' || text.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Validate numeric parameters\n\t\tif (!Number.isFinite(chunkSize) || chunkSize <= 0) {\n\t\t\t// Return whole text as single chunk if invalid chunk size\n\t\t\treturn [text];\n\t\t}\n\n\t\t// Ensure overlap is valid and less than chunk size\n\t\tconst validOverlap =\n\t\t\tNumber.isFinite(chunkOverlap) && chunkOverlap >= 0\n\t\t\t\t? Math.min(chunkOverlap, chunkSize - 1)\n\t\t\t\t: 0;\n\n\t\tconst charsPerToken = MODEL_CHAR_PER_TOKEN_RATIOS[model] || 4.0;\n\t\tconst chunkSizeInChars = Math.floor(chunkSize * charsPerToken);\n\t\tconst overlapInChars = Math.floor(validOverlap * charsPerToken);\n\n\t\tconst chunks: string[] = [];\n\t\tlet start = 0;\n\n\t\twhile (start < text.length) {\n\t\t\tconst end = Math.min(start + chunkSizeInChars, text.length);\n\t\t\tchunks.push(text.slice(start, end));\n\n\t\t\tif (end >= text.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Move to next chunk with overlap\n\t\t\tstart = Math.max(end - overlapInChars, start + 1);\n\t\t}\n\n\t\treturn chunks;\n\t} catch (error) {\n\t\t// Return text as single chunk on error\n\t\treturn text ? [text] : [];\n\t}\n}\n\n/**\n * Estimates the total number of tokens for a list of strings.\n * Uses tiktoken for normal text but falls back to character-based estimation\n * for repetitive content or on errors.\n *\n * @param list Array of strings to estimate tokens for\n * @param model The model or encoding name to use for estimation\n * @returns Total estimated number of tokens across all strings\n */\nexport async function estimateTokensFromStringList(\n\tlist: string[],\n\tmodel: TiktokenModel,\n): Promise<number> {\n\ttry {\n\t\t// Validate input\n\t\tif (!Array.isArray(list)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst encoder = await encodingForModel(model);\n\t\tconst encodedListLength = await Promise.all(\n\t\t\tlist.map(async (text) => {\n\t\t\t\ttry {\n\t\t\t\t\t// Handle null/undefined text\n\t\t\t\t\tif (!text || typeof text !== 'string') {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for repetitive content\n\t\t\t\t\tif (hasLongSequentialRepeat(text)) {\n\t\t\t\t\t\tconst estimatedTokens = estimateTokensByCharCount(text, model);\n\t\t\t\t\t\treturn estimatedTokens;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Use tiktoken for normal text\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst tokens = encoder.encode(text);\n\t\t\t\t\t\treturn tokens.length;\n\t\t\t\t\t} catch (encodingError) {\n\t\t\t\t\t\t// Fall back to estimation if tiktoken fails\n\t\t\t\t\t\treturn estimateTokensByCharCount(text, model);\n\t\t\t\t\t}\n\t\t\t\t} catch (itemError) {\n\t\t\t\t\t// Return 0 for individual item errors\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\tconst totalTokens = encodedListLength.reduce((acc, curr) => acc + curr, 0);\n\n\t\treturn totalTokens;\n\t} catch (error) {\n\t\t// Return 0 on complete failure\n\t\treturn 0;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAiC;AACjC,qBAAwC;AAMxC,MAAM,8BAAsD;AAAA,EAC3D,UAAU;AAAA,EACV,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AACZ;AAUO,SAAS,0BAA0B,MAAc,QAAgB,eAAuB;AAC9F,MAAI;AAEH,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AAC3D,aAAO;AAAA,IACR;AAGA,UAAM,gBAAgB,4BAA4B,KAAK,KAAK;AAG5D,QAAI,CAAC,OAAO,SAAS,aAAa,KAAK,iBAAiB,GAAG;AAE1D,YAAMA,mBAAkB,KAAK,KAAK,KAAK,SAAS,CAAG;AACnD,aAAOA;AAAA,IACR;AAGA,UAAM,kBAAkB,KAAK,KAAK,KAAK,SAAS,aAAa;AAE7D,WAAO;AAAA,EACR,SAAS,OAAO;AAEf,WAAO,KAAK,MAAM,MAAM,UAAU,KAAK,CAAG;AAAA,EAC3C;AACD;AAYO,SAAS,2BACf,MACA,WACA,cACA,QAAgB,eACL;AACX,MAAI;AAEH,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AAC3D,aAAO,CAAC;AAAA,IACT;AAGA,QAAI,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,GAAG;AAElD,aAAO,CAAC,IAAI;AAAA,IACb;AAGA,UAAM,eACL,OAAO,SAAS,YAAY,KAAK,gBAAgB,IAC9C,KAAK,IAAI,cAAc,YAAY,CAAC,IACpC;AAEJ,UAAM,gBAAgB,4BAA4B,KAAK,KAAK;AAC5D,UAAM,mBAAmB,KAAK,MAAM,YAAY,aAAa;AAC7D,UAAM,iBAAiB,KAAK,MAAM,eAAe,aAAa;AAE9D,UAAM,SAAmB,CAAC;AAC1B,QAAI,QAAQ;AAEZ,WAAO,QAAQ,KAAK,QAAQ;AAC3B,YAAM,MAAM,KAAK,IAAI,QAAQ,kBAAkB,KAAK,MAAM;AAC1D,aAAO,KAAK,KAAK,MAAM,OAAO,GAAG,CAAC;AAElC,UAAI,OAAO,KAAK,QAAQ;AACvB;AAAA,MACD;AAGA,cAAQ,KAAK,IAAI,MAAM,gBAAgB,QAAQ,CAAC;AAAA,IACjD;AAEA,WAAO;AAAA,EACR,SAAS,OAAO;AAEf,WAAO,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,EACzB;AACD;AAWA,eAAsB,6BACrB,MACA,OACkB;AAClB,MAAI;AAEH,QAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACzB,aAAO;AAAA,IACR;AAEA,UAAM,UAAU,UAAM,kCAAiB,KAAK;AAC5C,UAAM,oBAAoB,MAAM,QAAQ;AAAA,MACvC,KAAK,IAAI,OAAO,SAAS;AACxB,YAAI;AAEH,cAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACtC,mBAAO;AAAA,UACR;AAGA,kBAAI,wCAAwB,IAAI,GAAG;AAClC,kBAAM,kBAAkB,0BAA0B,MAAM,KAAK;AAC7D,mBAAO;AAAA,UACR;AAGA,cAAI;AACH,kBAAM,SAAS,QAAQ,OAAO,IAAI;AAClC,mBAAO,OAAO;AAAA,UACf,SAAS,eAAe;AAEvB,mBAAO,0BAA0B,MAAM,KAAK;AAAA,UAC7C;AAAA,QACD,SAAS,WAAW;AAEnB,iBAAO;AAAA,QACR;AAAA,MACD,CAAC;AAAA,IACF;AAEA,UAAM,cAAc,kBAAkB,OAAO,CAAC,KAAK,SAAS,MAAM,MAAM,CAAC;AAEzE,WAAO;AAAA,EACR,SAAS,OAAO;AAEf,WAAO;AAAA,EACR;AACD;","names":["estimatedTokens"]}
1
+ {"version":3,"sources":["../../../utils/tokenizer/token-estimator.ts"],"sourcesContent":["/**\n * Token estimation utilities for handling text without using tiktoken.\n * This is used as a fallback when tiktoken would be too slow (e.g., with repetitive content).\n */\n\nimport type { TiktokenModel } from 'js-tiktoken';\n\nimport { encodingForModel } from './tiktoken';\nimport { hasLongSequentialRepeat } from '../helpers';\n\n/**\n * Model-specific average characters per token ratios.\n * These are approximate values based on typical English text.\n */\nconst MODEL_CHAR_PER_TOKEN_RATIOS: Record<string, number> = {\n\t'gpt-4o': 3.8,\n\t'gpt-4': 4.0,\n\t'gpt-3.5-turbo': 4.0,\n\tcl100k_base: 4.0,\n\to200k_base: 3.5,\n\tp50k_base: 4.2,\n\tr50k_base: 4.2,\n};\n\n/**\n * Estimates the number of tokens in a text based on character count.\n * This is much faster than tiktoken but less accurate.\n *\n * @param text The text to estimate tokens for\n * @param model The model or encoding name (optional)\n * @returns Estimated number of tokens\n */\nexport function estimateTokensByCharCount(text: string, model: string = 'cl100k_base'): number {\n\ttry {\n\t\t// Validate input\n\t\tif (!text || typeof text !== 'string' || text.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Get the ratio for the specific model, or use default\n\t\tconst charsPerToken = MODEL_CHAR_PER_TOKEN_RATIOS[model] || 4.0;\n\n\t\t// Validate ratio\n\t\tif (!Number.isFinite(charsPerToken) || charsPerToken <= 0) {\n\t\t\t// Fallback to default ratio\n\t\t\tconst estimatedTokens = Math.ceil(text.length / 4.0);\n\t\t\treturn estimatedTokens;\n\t\t}\n\n\t\t// Calculate estimated tokens\n\t\tconst estimatedTokens = Math.ceil(text.length / charsPerToken);\n\n\t\treturn estimatedTokens;\n\t} catch (error) {\n\t\t// Return conservative estimate on error\n\t\treturn Math.ceil((text?.length || 0) / 4.0);\n\t}\n}\n\n/**\n * Estimates tokens for text splitting purposes.\n * Returns chunk boundaries based on character positions rather than token positions.\n *\n * @param text The text to split\n * @param chunkSize Target chunk size in tokens\n * @param chunkOverlap Overlap between chunks in tokens\n * @param model The model or encoding name (optional)\n * @returns Array of text chunks\n */\nexport function estimateTextSplitsByTokens(\n\ttext: string,\n\tchunkSize: number,\n\tchunkOverlap: number,\n\tmodel: string = 'cl100k_base',\n): string[] {\n\ttry {\n\t\t// Validate inputs\n\t\tif (!text || typeof text !== 'string' || text.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Validate numeric parameters\n\t\tif (!Number.isFinite(chunkSize) || chunkSize <= 0) {\n\t\t\t// Return whole text as single chunk if invalid chunk size\n\t\t\treturn [text];\n\t\t}\n\n\t\t// Ensure overlap is valid and less than chunk size\n\t\tconst validOverlap =\n\t\t\tNumber.isFinite(chunkOverlap) && chunkOverlap >= 0\n\t\t\t\t? Math.min(chunkOverlap, chunkSize - 1)\n\t\t\t\t: 0;\n\n\t\tconst charsPerToken = MODEL_CHAR_PER_TOKEN_RATIOS[model] || 4.0;\n\t\tconst chunkSizeInChars = Math.floor(chunkSize * charsPerToken);\n\t\tconst overlapInChars = Math.floor(validOverlap * charsPerToken);\n\n\t\tconst chunks: string[] = [];\n\t\tlet start = 0;\n\n\t\twhile (start < text.length) {\n\t\t\tconst end = Math.min(start + chunkSizeInChars, text.length);\n\t\t\tchunks.push(text.slice(start, end));\n\n\t\t\tif (end >= text.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Move to next chunk with overlap\n\t\t\tstart = Math.max(end - overlapInChars, start + 1);\n\t\t}\n\n\t\treturn chunks;\n\t} catch (error) {\n\t\t// Return text as single chunk on error\n\t\treturn text ? [text] : [];\n\t}\n}\n\n/**\n * Estimates the total number of tokens for a list of strings.\n * Uses tiktoken for normal text but falls back to character-based estimation\n * for repetitive content or on errors.\n *\n * @param list Array of strings to estimate tokens for\n * @param model The model or encoding name to use for estimation\n * @returns Total estimated number of tokens across all strings\n */\nexport async function estimateTokensFromStringList(\n\tlist: string[],\n\tmodel: TiktokenModel,\n): Promise<number> {\n\ttry {\n\t\t// Validate input\n\t\tif (!Array.isArray(list)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst encoder = encodingForModel(model);\n\t\tconst encodedListLength = await Promise.all(\n\t\t\tlist.map(async (text) => {\n\t\t\t\ttry {\n\t\t\t\t\t// Handle null/undefined text\n\t\t\t\t\tif (!text || typeof text !== 'string') {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for repetitive content\n\t\t\t\t\tif (hasLongSequentialRepeat(text)) {\n\t\t\t\t\t\tconst estimatedTokens = estimateTokensByCharCount(text, model);\n\t\t\t\t\t\treturn estimatedTokens;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Use tiktoken for normal text\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst tokens = encoder.encode(text);\n\t\t\t\t\t\treturn tokens.length;\n\t\t\t\t\t} catch (encodingError) {\n\t\t\t\t\t\t// Fall back to estimation if tiktoken fails\n\t\t\t\t\t\treturn estimateTokensByCharCount(text, model);\n\t\t\t\t\t}\n\t\t\t\t} catch (itemError) {\n\t\t\t\t\t// Return 0 for individual item errors\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\tconst totalTokens = encodedListLength.reduce((acc, curr) => acc + curr, 0);\n\n\t\treturn totalTokens;\n\t} catch (error) {\n\t\t// Return 0 on complete failure\n\t\treturn 0;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,sBAAiC;AACjC,qBAAwC;AAMxC,MAAM,8BAAsD;AAAA,EAC3D,UAAU;AAAA,EACV,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AACZ;AAUO,SAAS,0BAA0B,MAAc,QAAgB,eAAuB;AAC9F,MAAI;AAEH,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AAC3D,aAAO;AAAA,IACR;AAGA,UAAM,gBAAgB,4BAA4B,KAAK,KAAK;AAG5D,QAAI,CAAC,OAAO,SAAS,aAAa,KAAK,iBAAiB,GAAG;AAE1D,YAAMA,mBAAkB,KAAK,KAAK,KAAK,SAAS,CAAG;AACnD,aAAOA;AAAA,IACR;AAGA,UAAM,kBAAkB,KAAK,KAAK,KAAK,SAAS,aAAa;AAE7D,WAAO;AAAA,EACR,SAAS,OAAO;AAEf,WAAO,KAAK,MAAM,MAAM,UAAU,KAAK,CAAG;AAAA,EAC3C;AACD;AAYO,SAAS,2BACf,MACA,WACA,cACA,QAAgB,eACL;AACX,MAAI;AAEH,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AAC3D,aAAO,CAAC;AAAA,IACT;AAGA,QAAI,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,GAAG;AAElD,aAAO,CAAC,IAAI;AAAA,IACb;AAGA,UAAM,eACL,OAAO,SAAS,YAAY,KAAK,gBAAgB,IAC9C,KAAK,IAAI,cAAc,YAAY,CAAC,IACpC;AAEJ,UAAM,gBAAgB,4BAA4B,KAAK,KAAK;AAC5D,UAAM,mBAAmB,KAAK,MAAM,YAAY,aAAa;AAC7D,UAAM,iBAAiB,KAAK,MAAM,eAAe,aAAa;AAE9D,UAAM,SAAmB,CAAC;AAC1B,QAAI,QAAQ;AAEZ,WAAO,QAAQ,KAAK,QAAQ;AAC3B,YAAM,MAAM,KAAK,IAAI,QAAQ,kBAAkB,KAAK,MAAM;AAC1D,aAAO,KAAK,KAAK,MAAM,OAAO,GAAG,CAAC;AAElC,UAAI,OAAO,KAAK,QAAQ;AACvB;AAAA,MACD;AAGA,cAAQ,KAAK,IAAI,MAAM,gBAAgB,QAAQ,CAAC;AAAA,IACjD;AAEA,WAAO;AAAA,EACR,SAAS,OAAO;AAEf,WAAO,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,EACzB;AACD;AAWA,eAAsB,6BACrB,MACA,OACkB;AAClB,MAAI;AAEH,QAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACzB,aAAO;AAAA,IACR;AAEA,UAAM,cAAU,kCAAiB,KAAK;AACtC,UAAM,oBAAoB,MAAM,QAAQ;AAAA,MACvC,KAAK,IAAI,OAAO,SAAS;AACxB,YAAI;AAEH,cAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACtC,mBAAO;AAAA,UACR;AAGA,kBAAI,wCAAwB,IAAI,GAAG;AAClC,kBAAM,kBAAkB,0BAA0B,MAAM,KAAK;AAC7D,mBAAO;AAAA,UACR;AAGA,cAAI;AACH,kBAAM,SAAS,QAAQ,OAAO,IAAI;AAClC,mBAAO,OAAO;AAAA,UACf,SAAS,eAAe;AAEvB,mBAAO,0BAA0B,MAAM,KAAK;AAAA,UAC7C;AAAA,QACD,SAAS,WAAW;AAEnB,iBAAO;AAAA,QACR;AAAA,MACD,CAAC;AAAA,IACF;AAEA,UAAM,cAAc,kBAAkB,OAAO,CAAC,KAAK,SAAS,MAAM,MAAM,CAAC;AAEzE,WAAO;AAAA,EACR,SAAS,OAAO;AAEf,WAAO;AAAA,EACR;AACD;","names":["estimatedTokens"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n8n/n8n-nodes-langchain",
3
- "version": "1.101.1",
3
+ "version": "1.102.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -35,8 +35,10 @@
35
35
  "dist/credentials/ZepApi.credentials.js"
36
36
  ],
37
37
  "nodes": [
38
+ "dist/nodes/vendors/GoogleGemini/GoogleGemini.node.js",
38
39
  "dist/nodes/vendors/OpenAi/OpenAi.node.js",
39
40
  "dist/nodes/agents/Agent/Agent.node.js",
41
+ "dist/nodes/agents/Agent/AgentTool.node.js",
40
42
  "dist/nodes/agents/OpenAiAssistant/OpenAiAssistant.node.js",
41
43
  "dist/nodes/chains/ChainSummarization/ChainSummarization.node.js",
42
44
  "dist/nodes/chains/ChainLLM/ChainLlm.node.js",
@@ -61,6 +63,7 @@
61
63
  "dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js",
62
64
  "dist/nodes/llms/LmChatAzureOpenAi/LmChatAzureOpenAi.node.js",
63
65
  "dist/nodes/llms/LmChatAwsBedrock/LmChatAwsBedrock.node.js",
66
+ "dist/nodes/llms/LmChatCohere/LmChatCohere.node.js",
64
67
  "dist/nodes/llms/LmChatDeepSeek/LmChatDeepSeek.node.js",
65
68
  "dist/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.js",
66
69
  "dist/nodes/llms/LmChatGoogleVertex/LmChatGoogleVertex.node.js",
@@ -140,7 +143,8 @@
140
143
  "@types/temp": "^0.9.1",
141
144
  "fast-glob": "3.2.12",
142
145
  "tsup": "^8.5.0",
143
- "n8n-core": "1.101.1"
146
+ "jest-mock-extended": "^3.0.4",
147
+ "n8n-core": "1.102.0"
144
148
  },
145
149
  "dependencies": {
146
150
  "@aws-sdk/client-sso-oidc": "3.808.0",
@@ -209,8 +213,8 @@
209
213
  "@n8n/client-oauth2": "0.27.0",
210
214
  "@n8n/json-schema-to-zod": "1.4.0",
211
215
  "@n8n/typescript-config": "1.3.0",
212
- "n8n-workflow": "1.99.1",
213
- "n8n-nodes-base": "1.100.1"
216
+ "n8n-nodes-base": "1.101.0",
217
+ "n8n-workflow": "1.100.0"
214
218
  },
215
219
  "license": "SEE LICENSE IN LICENSE.md",
216
220
  "homepage": "https://n8n.io",
@@ -233,7 +237,7 @@
233
237
  "format:check": "biome ci .",
234
238
  "lint": "eslint nodes credentials utils --quiet",
235
239
  "lintfix": "eslint nodes credentials utils --fix",
236
- "watch": "tsup --watch --tsconfig tsconfig.build.json --onSuccess \"pnpm copy-nodes-json && tsc-alias -p tsconfig.build.json && pnpm n8n-generate-metadata\"",
240
+ "watch": "tsup --watch nodes --watch credentials --watch utils --watch types --tsconfig tsconfig.build.json --onSuccess \"node ./scripts/post-build.js\"",
237
241
  "test": "jest",
238
242
  "test:dev": "jest --watch"
239
243
  }