mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Merge branch 'master' into node-1608-credential-parameters-tech-debt-project
This commit is contained in:
commit
269c6e70ef
|
@ -85,7 +85,6 @@ function getInputs(
|
|||
'@n8n/n8n-nodes-langchain.lmChatGroq',
|
||||
'@n8n/n8n-nodes-langchain.lmChatOllama',
|
||||
'@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
||||
'@n8n/n8n-nodes-langchain.lmChatGooglePalm',
|
||||
'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',
|
||||
'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',
|
||||
'@n8n/n8n-nodes-langchain.lmChatMistralCloud',
|
||||
|
@ -111,11 +110,13 @@ function getInputs(
|
|||
nodes: [
|
||||
'@n8n/n8n-nodes-langchain.lmChatAnthropic',
|
||||
'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',
|
||||
'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',
|
||||
'@n8n/n8n-nodes-langchain.lmChatMistralCloud',
|
||||
'@n8n/n8n-nodes-langchain.lmChatOllama',
|
||||
'@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
||||
'@n8n/n8n-nodes-langchain.lmChatGroq',
|
||||
'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',
|
||||
'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||
import { BedrockEmbeddings } from '@langchain/aws';
|
||||
import {
|
||||
NodeConnectionType,
|
||||
type IExecuteFunctions,
|
||||
|
@ -6,7 +7,6 @@ import {
|
|||
type INodeTypeDescription,
|
||||
type SupplyData,
|
||||
} from 'n8n-workflow';
|
||||
import { BedrockEmbeddings } from '@langchain/community/embeddings/bedrock';
|
||||
|
||||
import { logWrapper } from '../../../utils/logWrapper';
|
||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||
import {
|
||||
NodeConnectionType,
|
||||
type IExecuteFunctions,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
type SupplyData,
|
||||
} from 'n8n-workflow';
|
||||
import { GooglePaLMEmbeddings } from '@langchain/community/embeddings/googlepalm';
|
||||
import { logWrapper } from '../../../utils/logWrapper';
|
||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||
|
||||
export class EmbeddingsGooglePalm implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Embeddings Google PaLM',
|
||||
name: 'embeddingsGooglePalm',
|
||||
icon: 'file:google.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
description: 'Use Google PaLM Embeddings',
|
||||
defaults: {
|
||||
name: 'Embeddings Google PaLM',
|
||||
},
|
||||
requestDefaults: {
|
||||
ignoreHttpStatusErrors: true,
|
||||
baseURL: '={{ $credentials.host }}',
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'googlePalmApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
codex: {
|
||||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Embeddings'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
{
|
||||
url: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.embeddingsgooglepalm/',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
||||
inputs: [],
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong
|
||||
outputs: [NodeConnectionType.AiEmbedding],
|
||||
outputNames: ['Embeddings'],
|
||||
properties: [
|
||||
getConnectionHintNoticeField([NodeConnectionType.AiVectorStore]),
|
||||
{
|
||||
displayName:
|
||||
'Each model is using different dimensional density for embeddings. Please make sure to use the same dimensionality for your vector store. The default model is using 768-dimensional embeddings.',
|
||||
name: 'notice',
|
||||
type: 'notice',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Model',
|
||||
name: 'modelName',
|
||||
type: 'options',
|
||||
description:
|
||||
'The model which will generate the embeddings. <a href="https://developers.generativeai.google/api/rest/generativelanguage/models/list">Learn more</a>.',
|
||||
typeOptions: {
|
||||
loadOptions: {
|
||||
routing: {
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: '/v1beta3/models',
|
||||
},
|
||||
output: {
|
||||
postReceive: [
|
||||
{
|
||||
type: 'rootProperty',
|
||||
properties: {
|
||||
property: 'models',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'filter',
|
||||
properties: {
|
||||
pass: "={{ $responseItem.name.startsWith('models/embedding') }}",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'setKeyValue',
|
||||
properties: {
|
||||
name: '={{$responseItem.name}}',
|
||||
value: '={{$responseItem.name}}',
|
||||
description: '={{$responseItem.description}}',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'sort',
|
||||
properties: {
|
||||
key: 'name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
routing: {
|
||||
send: {
|
||||
type: 'body',
|
||||
property: 'model',
|
||||
},
|
||||
},
|
||||
default: 'models/embedding-gecko-001',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async supplyData(this: IExecuteFunctions, itemIndex: number): Promise<SupplyData> {
|
||||
this.logger.debug('Supply data for embeddings Google PaLM');
|
||||
const modelName = this.getNodeParameter(
|
||||
'modelName',
|
||||
itemIndex,
|
||||
'models/embedding-gecko-001',
|
||||
) as string;
|
||||
const credentials = await this.getCredentials('googlePalmApi');
|
||||
const embeddings = new GooglePaLMEmbeddings({
|
||||
apiKey: credentials.apiKey as string,
|
||||
modelName,
|
||||
});
|
||||
|
||||
return {
|
||||
response: logWrapper(embeddings, this),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48"><defs><path id="a" d="M44.5 20H24v8.5h11.8C34.7 33.9 30.1 37 24 37c-7.2 0-13-5.8-13-13s5.8-13 13-13c3.1 0 5.9 1.1 8.1 2.9l6.4-6.4C34.6 4.1 29.6 2 24 2 11.8 2 2 11.8 2 24s9.8 22 22 22c11 0 21-8 21-22 0-1.3-.2-2.7-.5-4"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><path fill="#FBBC05" d="M0 37V11l17 13z" clip-path="url(#b)"/><path fill="#EA4335" d="m0 11 17 13 7-6.1L48 14V0H0z" clip-path="url(#b)"/><path fill="#34A853" d="m0 37 30-23 7.9 1L48 0v48H0z" clip-path="url(#b)"/><path fill="#4285F4" d="M48 48 17 24l-4-3 35-10z" clip-path="url(#b)"/></svg>
|
Before Width: | Height: | Size: 687 B |
|
@ -1,4 +1,5 @@
|
|||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||
import { ChatBedrockConverse } from '@langchain/aws';
|
||||
import {
|
||||
NodeConnectionType,
|
||||
type IExecuteFunctions,
|
||||
|
@ -6,13 +7,8 @@ import {
|
|||
type INodeTypeDescription,
|
||||
type SupplyData,
|
||||
} from 'n8n-workflow';
|
||||
import { BedrockChat } from '@langchain/community/chat_models/bedrock';
|
||||
|
||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||
// Dependencies needed underneath the hood. We add them
|
||||
// here only to track where what dependency is used
|
||||
import '@aws-sdk/credential-provider-node';
|
||||
import '@aws-sdk/client-bedrock-runtime';
|
||||
import '@aws-sdk/client-sso-oidc';
|
||||
import { N8nLlmTracing } from '../N8nLlmTracing';
|
||||
|
||||
export class LmChatAwsBedrock implements INodeType {
|
||||
|
@ -144,7 +140,7 @@ export class LmChatAwsBedrock implements INodeType {
|
|||
maxTokensToSample: number;
|
||||
};
|
||||
|
||||
const model = new BedrockChat({
|
||||
const model = new ChatBedrockConverse({
|
||||
region: credentials.region as string,
|
||||
model: modelName,
|
||||
temperature: options.temperature,
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||
import {
|
||||
NodeConnectionType,
|
||||
type IExecuteFunctions,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
type SupplyData,
|
||||
} from 'n8n-workflow';
|
||||
import { ChatGooglePaLM } from '@langchain/community/chat_models/googlepalm';
|
||||
import { N8nLlmTracing } from '../N8nLlmTracing';
|
||||
|
||||
export class LmChatGooglePalm implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Google PaLM Chat Model',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-name-miscased
|
||||
name: 'lmChatGooglePalm',
|
||||
icon: 'file:google.svg',
|
||||
hidden: true,
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
description: 'Chat Model Google PaLM',
|
||||
defaults: {
|
||||
name: 'Google PaLM Chat Model',
|
||||
},
|
||||
codex: {
|
||||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models', 'Root Nodes'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
{
|
||||
url: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatgooglepalm/',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
||||
inputs: [],
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong
|
||||
outputs: [NodeConnectionType.AiLanguageModel],
|
||||
outputNames: ['Model'],
|
||||
credentials: [
|
||||
{
|
||||
name: 'googlePalmApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
requestDefaults: {
|
||||
ignoreHttpStatusErrors: true,
|
||||
baseURL: '={{ $credentials.host }}',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName:
|
||||
"Google PaLM API is <a href='https://ai.google.dev/palm_docs/deprecation' target='_blank'>deprecated</a>. Please use Google Vertex or Google Gemini nodes instead.",
|
||||
name: 'deprecated',
|
||||
type: 'notice',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Model',
|
||||
name: 'modelName',
|
||||
type: 'options',
|
||||
description:
|
||||
'The model which will generate the completion. <a href="https://developers.generativeai.google/api/rest/generativelanguage/models/list">Learn more</a>.',
|
||||
typeOptions: {
|
||||
loadOptions: {
|
||||
routing: {
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: '/v1beta3/models',
|
||||
},
|
||||
output: {
|
||||
postReceive: [
|
||||
{
|
||||
type: 'rootProperty',
|
||||
properties: {
|
||||
property: 'models',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'filter',
|
||||
properties: {
|
||||
pass: "={{ $responseItem.name.startsWith('models/chat') }}",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'setKeyValue',
|
||||
properties: {
|
||||
name: '={{$responseItem.name}}',
|
||||
value: '={{$responseItem.name}}',
|
||||
description: '={{$responseItem.description}}',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'sort',
|
||||
properties: {
|
||||
key: 'name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
routing: {
|
||||
send: {
|
||||
type: 'body',
|
||||
property: 'model',
|
||||
},
|
||||
},
|
||||
default: 'models/chat-bison-001',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
placeholder: 'Add Option',
|
||||
description: 'Additional options to add',
|
||||
type: 'collection',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sampling Temperature',
|
||||
name: 'temperature',
|
||||
default: 0.7,
|
||||
typeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },
|
||||
description:
|
||||
'Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
displayName: 'Top K',
|
||||
name: 'topK',
|
||||
default: 40,
|
||||
typeOptions: { maxValue: 1, minValue: -1, numberPrecision: 1 },
|
||||
description:
|
||||
'Used to remove "long tail" low probability responses. Defaults to -1, which disables it.',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
displayName: 'Top P',
|
||||
name: 'topP',
|
||||
default: 0.9,
|
||||
typeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },
|
||||
description:
|
||||
'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.',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async supplyData(this: IExecuteFunctions, itemIndex: number): Promise<SupplyData> {
|
||||
const credentials = await this.getCredentials('googlePalmApi');
|
||||
|
||||
const modelName = this.getNodeParameter('modelName', itemIndex) as string;
|
||||
const options = this.getNodeParameter('options', itemIndex, {}) as object;
|
||||
|
||||
const model = new ChatGooglePaLM({
|
||||
apiKey: credentials.apiKey as string,
|
||||
modelName,
|
||||
...options,
|
||||
callbacks: [new N8nLlmTracing(this)],
|
||||
});
|
||||
|
||||
return {
|
||||
response: model,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48"><defs><path id="a" d="M44.5 20H24v8.5h11.8C34.7 33.9 30.1 37 24 37c-7.2 0-13-5.8-13-13s5.8-13 13-13c3.1 0 5.9 1.1 8.1 2.9l6.4-6.4C34.6 4.1 29.6 2 24 2 11.8 2 2 11.8 2 24s9.8 22 22 22c11 0 21-8 21-22 0-1.3-.2-2.7-.5-4"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><path fill="#FBBC05" d="M0 37V11l17 13z" clip-path="url(#b)"/><path fill="#EA4335" d="m0 11 17 13 7-6.1L48 14V0H0z" clip-path="url(#b)"/><path fill="#34A853" d="m0 37 30-23 7.9 1L48 0v48H0z" clip-path="url(#b)"/><path fill="#4285F4" d="M48 48 17 24l-4-3 35-10z" clip-path="url(#b)"/></svg>
|
Before Width: | Height: | Size: 687 B |
|
@ -1,180 +0,0 @@
|
|||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||
import {
|
||||
NodeConnectionType,
|
||||
type IExecuteFunctions,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
type SupplyData,
|
||||
} from 'n8n-workflow';
|
||||
import { GooglePaLM } from '@langchain/community/llms/googlepalm';
|
||||
import { N8nLlmTracing } from '../N8nLlmTracing';
|
||||
|
||||
export class LmGooglePalm implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Google PaLM Language Model',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-name-miscased
|
||||
name: 'lmGooglePalm',
|
||||
hidden: true,
|
||||
icon: 'file:google.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
description: 'Language Model Google PaLM',
|
||||
defaults: {
|
||||
name: 'Google PaLM Language Model',
|
||||
},
|
||||
codex: {
|
||||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models', 'Root Nodes'],
|
||||
'Language Models': ['Text Completion Models'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
{
|
||||
url: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmgooglepalm/',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
||||
inputs: [],
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong
|
||||
outputs: [NodeConnectionType.AiLanguageModel],
|
||||
outputNames: ['Model'],
|
||||
credentials: [
|
||||
{
|
||||
name: 'googlePalmApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
requestDefaults: {
|
||||
ignoreHttpStatusErrors: true,
|
||||
baseURL: '={{ $credentials.host }}',
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName:
|
||||
"Google PaLM API is <a href='https://ai.google.dev/palm_docs/deprecation' target='_blank'>deprecated</a>. Please use Google Vertex or Google Gemini nodes instead.",
|
||||
name: 'deprecated',
|
||||
type: 'notice',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Model',
|
||||
name: 'modelName',
|
||||
type: 'options',
|
||||
description:
|
||||
'The model which will generate the completion. <a href="https://developers.generativeai.google/api/rest/generativelanguage/models/list">Learn more</a>.',
|
||||
typeOptions: {
|
||||
loadOptions: {
|
||||
routing: {
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: '/v1beta3/models',
|
||||
},
|
||||
output: {
|
||||
postReceive: [
|
||||
{
|
||||
type: 'rootProperty',
|
||||
properties: {
|
||||
property: 'models',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'filter',
|
||||
properties: {
|
||||
pass: "={{ $responseItem.name.startsWith('models/text') }}",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'setKeyValue',
|
||||
properties: {
|
||||
name: '={{$responseItem.name}}',
|
||||
value: '={{$responseItem.name}}',
|
||||
description: '={{$responseItem.description}}',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'sort',
|
||||
properties: {
|
||||
key: 'name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
routing: {
|
||||
send: {
|
||||
type: 'body',
|
||||
property: 'model',
|
||||
},
|
||||
},
|
||||
default: 'models/text-bison-001',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
placeholder: 'Add Option',
|
||||
description: 'Additional options to add',
|
||||
type: 'collection',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Maximum Number of Tokens',
|
||||
name: 'maxOutputTokens',
|
||||
default: 1024,
|
||||
description: 'The maximum number of tokens to generate in the completion',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
displayName: 'Sampling Temperature',
|
||||
name: 'temperature',
|
||||
default: 0.7,
|
||||
typeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },
|
||||
description:
|
||||
'Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
displayName: 'Top K',
|
||||
name: 'topK',
|
||||
default: 40,
|
||||
typeOptions: { maxValue: 1, minValue: -1, numberPrecision: 1 },
|
||||
description:
|
||||
'Used to remove "long tail" low probability responses. Defaults to -1, which disables it.',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
displayName: 'Top P',
|
||||
name: 'topP',
|
||||
default: 0.9,
|
||||
typeOptions: { maxValue: 1, minValue: 0, numberPrecision: 1 },
|
||||
description:
|
||||
'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.',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async supplyData(this: IExecuteFunctions, itemIndex: number): Promise<SupplyData> {
|
||||
const credentials = await this.getCredentials('googlePalmApi');
|
||||
|
||||
const modelName = this.getNodeParameter('modelName', itemIndex) as string;
|
||||
const options = this.getNodeParameter('options', itemIndex, {}) as object;
|
||||
|
||||
const model = new GooglePaLM({
|
||||
apiKey: credentials.apiKey as string,
|
||||
modelName,
|
||||
...options,
|
||||
callbacks: [new N8nLlmTracing(this)],
|
||||
});
|
||||
|
||||
return {
|
||||
response: model,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48"><defs><path id="a" d="M44.5 20H24v8.5h11.8C34.7 33.9 30.1 37 24 37c-7.2 0-13-5.8-13-13s5.8-13 13-13c3.1 0 5.9 1.1 8.1 2.9l6.4-6.4C34.6 4.1 29.6 2 24 2 11.8 2 2 11.8 2 24s9.8 22 22 22c11 0 21-8 21-22 0-1.3-.2-2.7-.5-4"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><path fill="#FBBC05" d="M0 37V11l17 13z" clip-path="url(#b)"/><path fill="#EA4335" d="m0 11 17 13 7-6.1L48 14V0H0z" clip-path="url(#b)"/><path fill="#34A853" d="m0 37 30-23 7.9 1L48 0v48H0z" clip-path="url(#b)"/><path fill="#4285F4" d="M48 48 17 24l-4-3 35-10z" clip-path="url(#b)"/></svg>
|
Before Width: | Height: | Size: 687 B |
|
@ -57,7 +57,6 @@
|
|||
"dist/nodes/embeddings/EmbeddingsCohere/EmbeddingsCohere.node.js",
|
||||
"dist/nodes/embeddings/EmbeddingsAwsBedrock/EmbeddingsAwsBedrock.node.js",
|
||||
"dist/nodes/embeddings/EmbeddingsAzureOpenAi/EmbeddingsAzureOpenAi.node.js",
|
||||
"dist/nodes/embeddings/EmbeddingsGooglePalm/EmbeddingsGooglePalm.node.js",
|
||||
"dist/nodes/embeddings/EmbeddingsGoogleGemini/EmbeddingsGoogleGemini.node.js",
|
||||
"dist/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.js",
|
||||
"dist/nodes/embeddings/EmbeddingsMistralCloud/EmbeddingsMistralCloud.node.js",
|
||||
|
@ -65,9 +64,7 @@
|
|||
"dist/nodes/embeddings/EmbeddingsOllama/EmbeddingsOllama.node.js",
|
||||
"dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js",
|
||||
"dist/nodes/llms/LmChatAzureOpenAi/LmChatAzureOpenAi.node.js",
|
||||
"dist/nodes/llms/LmGooglePalm/LmGooglePalm.node.js",
|
||||
"dist/nodes/llms/LmChatAwsBedrock/LmChatAwsBedrock.node.js",
|
||||
"dist/nodes/llms/LmChatGooglePalm/LmChatGooglePalm.node.js",
|
||||
"dist/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.js",
|
||||
"dist/nodes/llms/LmChatGoogleVertex/LmChatGoogleVertex.node.js",
|
||||
"dist/nodes/llms/LmChatGroq/LmChatGroq.node.js",
|
||||
|
@ -131,40 +128,38 @@
|
|||
"n8n-core": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "3.645.0",
|
||||
"@aws-sdk/client-sso-oidc": "^3.645.0",
|
||||
"@aws-sdk/credential-provider-node": "3.645.0",
|
||||
"@getzep/zep-cloud": "1.0.11",
|
||||
"@getzep/zep-js": "0.9.0",
|
||||
"@google-ai/generativelanguage": "2.5.0",
|
||||
"@google-ai/generativelanguage": "2.6.0",
|
||||
"@google-cloud/resource-manager": "5.3.0",
|
||||
"@google/generative-ai": "0.17.1",
|
||||
"@google/generative-ai": "0.19.0",
|
||||
"@huggingface/inference": "2.8.0",
|
||||
"@langchain/anthropic": "0.2.16",
|
||||
"@langchain/cohere": "0.2.2",
|
||||
"@langchain/community": "0.2.32",
|
||||
"@langchain/anthropic": "0.3.1",
|
||||
"@langchain/aws": "^0.1.0",
|
||||
"@langchain/cohere": "0.3.0",
|
||||
"@langchain/community": "0.3.2",
|
||||
"@langchain/core": "catalog:",
|
||||
"@langchain/google-genai": "0.0.26",
|
||||
"@langchain/google-vertexai": "0.0.27",
|
||||
"@langchain/groq": "0.0.17",
|
||||
"@langchain/mistralai": "0.0.29",
|
||||
"@langchain/ollama": "0.0.4",
|
||||
"@langchain/openai": "0.2.10",
|
||||
"@langchain/pinecone": "0.0.9",
|
||||
"@langchain/qdrant": "0.0.5",
|
||||
"@langchain/redis": "0.0.5",
|
||||
"@langchain/textsplitters": "0.0.3",
|
||||
"@langchain/google-genai": "0.1.0",
|
||||
"@langchain/google-vertexai": "0.1.0",
|
||||
"@langchain/groq": "0.1.2",
|
||||
"@langchain/mistralai": "0.1.1",
|
||||
"@langchain/ollama": "0.1.0",
|
||||
"@langchain/openai": "0.3.0",
|
||||
"@langchain/pinecone": "0.1.0",
|
||||
"@langchain/qdrant": "0.1.0",
|
||||
"@langchain/redis": "0.1.0",
|
||||
"@langchain/textsplitters": "0.1.0",
|
||||
"@mozilla/readability": "^0.5.0",
|
||||
"@n8n/typeorm": "0.3.20-10",
|
||||
"@n8n/vm2": "3.9.25",
|
||||
"@pinecone-database/pinecone": "3.0.0",
|
||||
"@qdrant/js-client-rest": "1.9.0",
|
||||
"@supabase/supabase-js": "2.45.3",
|
||||
"@pinecone-database/pinecone": "3.0.3",
|
||||
"@qdrant/js-client-rest": "1.11.0",
|
||||
"@supabase/supabase-js": "2.45.4",
|
||||
"@types/pg": "^8.11.6",
|
||||
"@xata.io/client": "0.28.4",
|
||||
"@xata.io/client": "0.30.0",
|
||||
"basic-auth": "catalog:",
|
||||
"cheerio": "1.0.0-rc.12",
|
||||
"cohere-ai": "7.13.0",
|
||||
"cohere-ai": "7.13.2",
|
||||
"d3-dsv": "2.0.0",
|
||||
"epub2": "3.0.2",
|
||||
"form-data": "catalog:",
|
||||
|
@ -172,12 +167,12 @@
|
|||
"html-to-text": "9.0.5",
|
||||
"jsdom": "^23.0.1",
|
||||
"json-schema-to-zod": "2.1.0",
|
||||
"langchain": "0.2.18",
|
||||
"langchain": "0.3.2",
|
||||
"lodash": "catalog:",
|
||||
"mammoth": "1.7.2",
|
||||
"n8n-nodes-base": "workspace:*",
|
||||
"n8n-workflow": "workspace:*",
|
||||
"openai": "4.58.0",
|
||||
"openai": "4.63.0",
|
||||
"pdf-parse": "1.1.1",
|
||||
"pg": "8.12.0",
|
||||
"redis": "4.6.12",
|
||||
|
@ -185,6 +180,6 @@
|
|||
"temp": "0.9.4",
|
||||
"tmp-promise": "3.0.3",
|
||||
"zod": "catalog:",
|
||||
"zod-to-json-schema": "3.23.2"
|
||||
"zod-to-json-schema": "3.23.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,6 +193,7 @@ defineExpose({ inputRef });
|
|||
:label="label"
|
||||
:tooltip-text="tooltipText"
|
||||
:required="required && showRequiredAsterisk"
|
||||
:size="labelSize"
|
||||
>
|
||||
<template #content>
|
||||
{{ tooltipText }}
|
||||
|
@ -210,6 +211,7 @@ defineExpose({ inputRef });
|
|||
:label="label"
|
||||
:tooltip-text="tooltipText"
|
||||
:required="required && showRequiredAsterisk"
|
||||
:size="labelSize"
|
||||
>
|
||||
<div :class="showErrors ? $style.errorInput : ''" @keydown.stop @keydown.enter="onEnter">
|
||||
<slot v-if="hasDefaultSlot" />
|
||||
|
@ -223,6 +225,7 @@ defineExpose({ inputRef });
|
|||
:disabled="disabled"
|
||||
:name="name"
|
||||
:teleported="teleported"
|
||||
:size="tagSize"
|
||||
@update:model-value="onUpdateModelValue"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
|
@ -246,6 +249,7 @@ defineExpose({ inputRef });
|
|||
:maxlength="maxlength"
|
||||
:autocomplete="autocomplete"
|
||||
:disabled="disabled"
|
||||
:size="tagSize"
|
||||
@update:model-value="onUpdateModelValue"
|
||||
@blur="onBlur"
|
||||
@focus="onFocus"
|
||||
|
|
|
@ -5,7 +5,7 @@ import N8nIcon from '../N8nIcon';
|
|||
import N8nText from '../N8nText';
|
||||
import N8nTooltip from '../N8nTooltip';
|
||||
|
||||
const SIZE = ['small', 'medium'] as const;
|
||||
const SIZE = ['small', 'medium', 'large'] as const;
|
||||
|
||||
interface InputLabelProps {
|
||||
compact?: boolean;
|
||||
|
|
|
@ -313,7 +313,6 @@ onBeforeUnmount(() => {
|
|||
@open:contextmenu="onOpenContextMenuFromNode"
|
||||
>
|
||||
<NodeIcon
|
||||
v-if="nodeTypeDescription"
|
||||
:node-type="nodeTypeDescription"
|
||||
:size="nodeIconSize"
|
||||
:shrink="false"
|
||||
|
|
|
@ -102,15 +102,6 @@ describe('useCanvasOperations', () => {
|
|||
expect(result).toBe(expectedDescription);
|
||||
});
|
||||
|
||||
it('should throw an error when node type does not exist', () => {
|
||||
const type = 'nonexistentType';
|
||||
const { requireNodeTypeDescription } = useCanvasOperations({ router });
|
||||
|
||||
expect(() => {
|
||||
requireNodeTypeDescription(type);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('should return node type description when only type is provided and it exists', () => {
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const type = 'testTypeWithoutVersion';
|
||||
|
@ -123,6 +114,25 @@ describe('useCanvasOperations', () => {
|
|||
|
||||
expect(result).toBe(expectedDescription);
|
||||
});
|
||||
|
||||
it("should return placeholder node type description if node type doesn't exist", () => {
|
||||
const type = 'nonexistentType';
|
||||
|
||||
const { requireNodeTypeDescription } = useCanvasOperations({ router });
|
||||
const result = requireNodeTypeDescription(type);
|
||||
|
||||
expect(result).toEqual({
|
||||
name: type,
|
||||
displayName: type,
|
||||
description: '',
|
||||
defaults: {},
|
||||
group: [],
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
properties: [],
|
||||
version: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addNode', () => {
|
||||
|
@ -616,7 +626,6 @@ describe('useCanvasOperations', () => {
|
|||
deleteNode(id, { trackHistory: true });
|
||||
|
||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(id);
|
||||
expect(workflowsStore.removeNodeConnectionsById).toHaveBeenCalledWith(id);
|
||||
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(id);
|
||||
expect(historyStore.pushCommandToUndo).toHaveBeenCalledWith(new RemoveNodeCommand(node));
|
||||
});
|
||||
|
@ -644,7 +653,6 @@ describe('useCanvasOperations', () => {
|
|||
deleteNode(id, { trackHistory: false });
|
||||
|
||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(id);
|
||||
expect(workflowsStore.removeNodeConnectionsById).toHaveBeenCalledWith(id);
|
||||
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(id);
|
||||
expect(historyStore.pushCommandToUndo).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@ -714,7 +722,6 @@ describe('useCanvasOperations', () => {
|
|||
deleteNode(nodes[1].id);
|
||||
|
||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(nodes[1].id);
|
||||
expect(workflowsStore.removeNodeConnectionsById).toHaveBeenCalledWith(nodes[1].id);
|
||||
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(nodes[1].id);
|
||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(nodes[1].id);
|
||||
});
|
||||
|
@ -1356,6 +1363,62 @@ describe('useCanvasOperations', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('deleteConnectionsByNodeId', () => {
|
||||
it('should delete all connections for a given node ID', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const { deleteConnectionsByNodeId } = useCanvasOperations({ router });
|
||||
|
||||
const node1 = createTestNode({ id: 'node1', name: 'Node 1' });
|
||||
const node2 = createTestNode({ id: 'node2', name: 'Node 1' });
|
||||
|
||||
workflowsStore.workflow.connections = {
|
||||
[node1.name]: {
|
||||
[NodeConnectionType.Main]: [
|
||||
[{ node: node2.name, type: NodeConnectionType.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
node2: {
|
||||
[NodeConnectionType.Main]: [
|
||||
[{ node: node1.name, type: NodeConnectionType.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
workflowsStore.getNodeById.mockReturnValue(node1);
|
||||
workflowsStore.getNodeByName.mockReturnValueOnce(node1).mockReturnValueOnce(node2);
|
||||
|
||||
deleteConnectionsByNodeId(node1.id);
|
||||
|
||||
expect(workflowsStore.removeConnection).toHaveBeenCalledWith({
|
||||
connection: [
|
||||
{ node: node1.name, type: NodeConnectionType.Main, index: 0 },
|
||||
{ node: node2.name, type: NodeConnectionType.Main, index: 0 },
|
||||
],
|
||||
});
|
||||
|
||||
expect(workflowsStore.removeConnection).toHaveBeenCalledWith({
|
||||
connection: [
|
||||
{ node: node2.name, type: NodeConnectionType.Main, index: 0 },
|
||||
{ node: node1.name, type: NodeConnectionType.Main, index: 0 },
|
||||
],
|
||||
});
|
||||
|
||||
expect(workflowsStore.workflow.connections[node1.name]).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not delete connections if node ID does not exist', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const { deleteConnectionsByNodeId } = useCanvasOperations({ router });
|
||||
|
||||
const nodeId = 'nonexistent';
|
||||
workflowsStore.getNodeById.mockReturnValue(undefined);
|
||||
|
||||
deleteConnectionsByNodeId(nodeId);
|
||||
|
||||
expect(workflowsStore.removeConnection).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('duplicateNodes', () => {
|
||||
it('should duplicate nodes', async () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
|
|
|
@ -236,7 +236,7 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
await renameNode(currentName, previousName);
|
||||
}
|
||||
|
||||
function connectAdjacentNodes(id: string) {
|
||||
function connectAdjacentNodes(id: string, { trackHistory = false } = {}) {
|
||||
const node = workflowsStore.getNodeById(id);
|
||||
|
||||
if (!node) {
|
||||
|
@ -262,6 +262,23 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
|
||||
if (!outgoingNodeId) continue;
|
||||
|
||||
if (trackHistory) {
|
||||
historyStore.pushCommandToUndo(
|
||||
new AddConnectionCommand([
|
||||
{
|
||||
node: incomingConnection.node,
|
||||
type,
|
||||
index: 0,
|
||||
},
|
||||
{
|
||||
node: outgoingConnection.node,
|
||||
type,
|
||||
index: 0,
|
||||
},
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
createConnection({
|
||||
source: incomingNodeId,
|
||||
sourceHandle: createCanvasConnectionHandleString({
|
||||
|
@ -289,8 +306,13 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
historyStore.startRecordingUndo();
|
||||
}
|
||||
|
||||
connectAdjacentNodes(id);
|
||||
workflowsStore.removeNodeConnectionsById(id);
|
||||
if (uiStore.lastInteractedWithNodeId === id) {
|
||||
uiStore.lastInteractedWithNodeId = null;
|
||||
}
|
||||
|
||||
connectAdjacentNodes(id, { trackHistory });
|
||||
deleteConnectionsByNodeId(id, { trackHistory, trackBulk: false });
|
||||
|
||||
workflowsStore.removeNodeExecutionDataById(id);
|
||||
workflowsStore.removeNodeById(id);
|
||||
|
||||
|
@ -423,16 +445,23 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
historyStore.stopRecordingUndo();
|
||||
}
|
||||
|
||||
function requireNodeTypeDescription(type: INodeUi['type'], version?: INodeUi['typeVersion']) {
|
||||
const nodeTypeDescription = nodeTypesStore.getNodeType(type, version);
|
||||
if (!nodeTypeDescription) {
|
||||
throw new Error(
|
||||
i18n.baseText('nodeView.showMessage.addNodeButton.message', {
|
||||
interpolate: { nodeTypeName: type },
|
||||
}),
|
||||
);
|
||||
}
|
||||
return nodeTypeDescription;
|
||||
function requireNodeTypeDescription(
|
||||
type: INodeUi['type'],
|
||||
version?: INodeUi['typeVersion'],
|
||||
): INodeTypeDescription {
|
||||
return (
|
||||
nodeTypesStore.getNodeType(type, version) ?? {
|
||||
properties: [],
|
||||
displayName: type,
|
||||
name: type,
|
||||
group: [],
|
||||
description: '',
|
||||
version: version ?? 1,
|
||||
defaults: {},
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function addNodes(
|
||||
|
@ -1135,6 +1164,72 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, connection));
|
||||
}
|
||||
|
||||
function deleteConnectionsByNodeId(
|
||||
targetNodeId: string,
|
||||
{ trackHistory = false, trackBulk = true } = {},
|
||||
) {
|
||||
const targetNode = workflowsStore.getNodeById(targetNodeId);
|
||||
if (!targetNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (trackHistory && trackBulk) {
|
||||
historyStore.startRecordingUndo();
|
||||
}
|
||||
|
||||
const connections = workflowsStore.workflow.connections;
|
||||
for (const nodeName of Object.keys(connections)) {
|
||||
const node = workflowsStore.getNodeByName(nodeName);
|
||||
if (!node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const type of Object.keys(connections[nodeName])) {
|
||||
for (const index of Object.keys(connections[nodeName][type])) {
|
||||
for (const connectionIndex of Object.keys(
|
||||
connections[nodeName][type][parseInt(index, 10)],
|
||||
)) {
|
||||
const connectionData =
|
||||
connections[nodeName][type][parseInt(index, 10)][parseInt(connectionIndex, 10)];
|
||||
if (!connectionData) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const connectionDataNode = workflowsStore.getNodeByName(connectionData.node);
|
||||
if (
|
||||
connectionDataNode &&
|
||||
(connectionDataNode.id === targetNode.id || node.name === targetNode.name)
|
||||
) {
|
||||
deleteConnection(
|
||||
{
|
||||
source: node.id,
|
||||
sourceHandle: createCanvasConnectionHandleString({
|
||||
mode: CanvasConnectionMode.Output,
|
||||
type: type as NodeConnectionType,
|
||||
index: parseInt(index, 10),
|
||||
}),
|
||||
target: connectionDataNode.id,
|
||||
targetHandle: createCanvasConnectionHandleString({
|
||||
mode: CanvasConnectionMode.Input,
|
||||
type: connectionData.type as NodeConnectionType,
|
||||
index: connectionData.index,
|
||||
}),
|
||||
},
|
||||
{ trackHistory, trackBulk: false },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete workflowsStore.workflow.connections[targetNode.name];
|
||||
|
||||
if (trackHistory && trackBulk) {
|
||||
historyStore.stopRecordingUndo();
|
||||
}
|
||||
}
|
||||
|
||||
function deleteConnection(
|
||||
connection: Connection,
|
||||
{ trackHistory = false, trackBulk = true } = {},
|
||||
|
@ -1777,6 +1872,7 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
revertCreateConnection,
|
||||
deleteConnection,
|
||||
revertDeleteConnection,
|
||||
deleteConnectionsByNodeId,
|
||||
isConnectionAllowed,
|
||||
importWorkflowData,
|
||||
fetchWorkflowDataFromUrl,
|
||||
|
|
|
@ -1525,8 +1525,6 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
|
|||
}
|
||||
|
||||
removeNode(node);
|
||||
|
||||
// @TODO When removing node connected between two nodes, create a connection between them
|
||||
}
|
||||
|
||||
function removeNodeConnectionsById(nodeId: string): void {
|
||||
|
|
2007
pnpm-lock.yaml
2007
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,7 @@ catalog:
|
|||
xml2js: 0.6.2
|
||||
xss: 1.0.15
|
||||
zod: 3.23.8
|
||||
'@langchain/core': 0.2.31
|
||||
'@langchain/core': 0.3.3
|
||||
|
||||
catalogs:
|
||||
frontend:
|
||||
|
|
Loading…
Reference in a new issue