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.lmChatGroq',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatOllama',
|
'@n8n/n8n-nodes-langchain.lmChatOllama',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
'@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatGooglePalm',
|
|
||||||
'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',
|
'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',
|
'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatMistralCloud',
|
'@n8n/n8n-nodes-langchain.lmChatMistralCloud',
|
||||||
|
@ -111,11 +110,13 @@ function getInputs(
|
||||||
nodes: [
|
nodes: [
|
||||||
'@n8n/n8n-nodes-langchain.lmChatAnthropic',
|
'@n8n/n8n-nodes-langchain.lmChatAnthropic',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',
|
'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi',
|
||||||
|
'@n8n/n8n-nodes-langchain.lmChatAwsBedrock',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatMistralCloud',
|
'@n8n/n8n-nodes-langchain.lmChatMistralCloud',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatOllama',
|
'@n8n/n8n-nodes-langchain.lmChatOllama',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
'@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatGroq',
|
'@n8n/n8n-nodes-langchain.lmChatGroq',
|
||||||
'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',
|
'@n8n/n8n-nodes-langchain.lmChatGoogleVertex',
|
||||||
|
'@n8n/n8n-nodes-langchain.lmChatGoogleGemini',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import { BedrockEmbeddings } from '@langchain/aws';
|
||||||
import {
|
import {
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
type IExecuteFunctions,
|
type IExecuteFunctions,
|
||||||
|
@ -6,7 +7,6 @@ import {
|
||||||
type INodeTypeDescription,
|
type INodeTypeDescription,
|
||||||
type SupplyData,
|
type SupplyData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { BedrockEmbeddings } from '@langchain/community/embeddings/bedrock';
|
|
||||||
|
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
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 */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import { ChatBedrockConverse } from '@langchain/aws';
|
||||||
import {
|
import {
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
type IExecuteFunctions,
|
type IExecuteFunctions,
|
||||||
|
@ -6,13 +7,8 @@ import {
|
||||||
type INodeTypeDescription,
|
type INodeTypeDescription,
|
||||||
type SupplyData,
|
type SupplyData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { BedrockChat } from '@langchain/community/chat_models/bedrock';
|
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
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';
|
import { N8nLlmTracing } from '../N8nLlmTracing';
|
||||||
|
|
||||||
export class LmChatAwsBedrock implements INodeType {
|
export class LmChatAwsBedrock implements INodeType {
|
||||||
|
@ -144,7 +140,7 @@ export class LmChatAwsBedrock implements INodeType {
|
||||||
maxTokensToSample: number;
|
maxTokensToSample: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const model = new BedrockChat({
|
const model = new ChatBedrockConverse({
|
||||||
region: credentials.region as string,
|
region: credentials.region as string,
|
||||||
model: modelName,
|
model: modelName,
|
||||||
temperature: options.temperature,
|
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/EmbeddingsCohere/EmbeddingsCohere.node.js",
|
||||||
"dist/nodes/embeddings/EmbeddingsAwsBedrock/EmbeddingsAwsBedrock.node.js",
|
"dist/nodes/embeddings/EmbeddingsAwsBedrock/EmbeddingsAwsBedrock.node.js",
|
||||||
"dist/nodes/embeddings/EmbeddingsAzureOpenAi/EmbeddingsAzureOpenAi.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/EmbeddingsGoogleGemini/EmbeddingsGoogleGemini.node.js",
|
||||||
"dist/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.js",
|
"dist/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.js",
|
||||||
"dist/nodes/embeddings/EmbeddingsMistralCloud/EmbeddingsMistralCloud.node.js",
|
"dist/nodes/embeddings/EmbeddingsMistralCloud/EmbeddingsMistralCloud.node.js",
|
||||||
|
@ -65,9 +64,7 @@
|
||||||
"dist/nodes/embeddings/EmbeddingsOllama/EmbeddingsOllama.node.js",
|
"dist/nodes/embeddings/EmbeddingsOllama/EmbeddingsOllama.node.js",
|
||||||
"dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js",
|
"dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js",
|
||||||
"dist/nodes/llms/LmChatAzureOpenAi/LmChatAzureOpenAi.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/LmChatAwsBedrock/LmChatAwsBedrock.node.js",
|
||||||
"dist/nodes/llms/LmChatGooglePalm/LmChatGooglePalm.node.js",
|
|
||||||
"dist/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.js",
|
"dist/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.js",
|
||||||
"dist/nodes/llms/LmChatGoogleVertex/LmChatGoogleVertex.node.js",
|
"dist/nodes/llms/LmChatGoogleVertex/LmChatGoogleVertex.node.js",
|
||||||
"dist/nodes/llms/LmChatGroq/LmChatGroq.node.js",
|
"dist/nodes/llms/LmChatGroq/LmChatGroq.node.js",
|
||||||
|
@ -131,40 +128,38 @@
|
||||||
"n8n-core": "workspace:*"
|
"n8n-core": "workspace:*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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-cloud": "1.0.11",
|
||||||
"@getzep/zep-js": "0.9.0",
|
"@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-cloud/resource-manager": "5.3.0",
|
||||||
"@google/generative-ai": "0.17.1",
|
"@google/generative-ai": "0.19.0",
|
||||||
"@huggingface/inference": "2.8.0",
|
"@huggingface/inference": "2.8.0",
|
||||||
"@langchain/anthropic": "0.2.16",
|
"@langchain/anthropic": "0.3.1",
|
||||||
"@langchain/cohere": "0.2.2",
|
"@langchain/aws": "^0.1.0",
|
||||||
"@langchain/community": "0.2.32",
|
"@langchain/cohere": "0.3.0",
|
||||||
|
"@langchain/community": "0.3.2",
|
||||||
"@langchain/core": "catalog:",
|
"@langchain/core": "catalog:",
|
||||||
"@langchain/google-genai": "0.0.26",
|
"@langchain/google-genai": "0.1.0",
|
||||||
"@langchain/google-vertexai": "0.0.27",
|
"@langchain/google-vertexai": "0.1.0",
|
||||||
"@langchain/groq": "0.0.17",
|
"@langchain/groq": "0.1.2",
|
||||||
"@langchain/mistralai": "0.0.29",
|
"@langchain/mistralai": "0.1.1",
|
||||||
"@langchain/ollama": "0.0.4",
|
"@langchain/ollama": "0.1.0",
|
||||||
"@langchain/openai": "0.2.10",
|
"@langchain/openai": "0.3.0",
|
||||||
"@langchain/pinecone": "0.0.9",
|
"@langchain/pinecone": "0.1.0",
|
||||||
"@langchain/qdrant": "0.0.5",
|
"@langchain/qdrant": "0.1.0",
|
||||||
"@langchain/redis": "0.0.5",
|
"@langchain/redis": "0.1.0",
|
||||||
"@langchain/textsplitters": "0.0.3",
|
"@langchain/textsplitters": "0.1.0",
|
||||||
"@mozilla/readability": "^0.5.0",
|
"@mozilla/readability": "^0.5.0",
|
||||||
"@n8n/typeorm": "0.3.20-10",
|
"@n8n/typeorm": "0.3.20-10",
|
||||||
"@n8n/vm2": "3.9.25",
|
"@n8n/vm2": "3.9.25",
|
||||||
"@pinecone-database/pinecone": "3.0.0",
|
"@pinecone-database/pinecone": "3.0.3",
|
||||||
"@qdrant/js-client-rest": "1.9.0",
|
"@qdrant/js-client-rest": "1.11.0",
|
||||||
"@supabase/supabase-js": "2.45.3",
|
"@supabase/supabase-js": "2.45.4",
|
||||||
"@types/pg": "^8.11.6",
|
"@types/pg": "^8.11.6",
|
||||||
"@xata.io/client": "0.28.4",
|
"@xata.io/client": "0.30.0",
|
||||||
"basic-auth": "catalog:",
|
"basic-auth": "catalog:",
|
||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"cohere-ai": "7.13.0",
|
"cohere-ai": "7.13.2",
|
||||||
"d3-dsv": "2.0.0",
|
"d3-dsv": "2.0.0",
|
||||||
"epub2": "3.0.2",
|
"epub2": "3.0.2",
|
||||||
"form-data": "catalog:",
|
"form-data": "catalog:",
|
||||||
|
@ -172,12 +167,12 @@
|
||||||
"html-to-text": "9.0.5",
|
"html-to-text": "9.0.5",
|
||||||
"jsdom": "^23.0.1",
|
"jsdom": "^23.0.1",
|
||||||
"json-schema-to-zod": "2.1.0",
|
"json-schema-to-zod": "2.1.0",
|
||||||
"langchain": "0.2.18",
|
"langchain": "0.3.2",
|
||||||
"lodash": "catalog:",
|
"lodash": "catalog:",
|
||||||
"mammoth": "1.7.2",
|
"mammoth": "1.7.2",
|
||||||
"n8n-nodes-base": "workspace:*",
|
"n8n-nodes-base": "workspace:*",
|
||||||
"n8n-workflow": "workspace:*",
|
"n8n-workflow": "workspace:*",
|
||||||
"openai": "4.58.0",
|
"openai": "4.63.0",
|
||||||
"pdf-parse": "1.1.1",
|
"pdf-parse": "1.1.1",
|
||||||
"pg": "8.12.0",
|
"pg": "8.12.0",
|
||||||
"redis": "4.6.12",
|
"redis": "4.6.12",
|
||||||
|
@ -185,6 +180,6 @@
|
||||||
"temp": "0.9.4",
|
"temp": "0.9.4",
|
||||||
"tmp-promise": "3.0.3",
|
"tmp-promise": "3.0.3",
|
||||||
"zod": "catalog:",
|
"zod": "catalog:",
|
||||||
"zod-to-json-schema": "3.23.2"
|
"zod-to-json-schema": "3.23.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,7 @@ defineExpose({ inputRef });
|
||||||
:label="label"
|
:label="label"
|
||||||
:tooltip-text="tooltipText"
|
:tooltip-text="tooltipText"
|
||||||
:required="required && showRequiredAsterisk"
|
:required="required && showRequiredAsterisk"
|
||||||
|
:size="labelSize"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
{{ tooltipText }}
|
{{ tooltipText }}
|
||||||
|
@ -210,6 +211,7 @@ defineExpose({ inputRef });
|
||||||
:label="label"
|
:label="label"
|
||||||
:tooltip-text="tooltipText"
|
:tooltip-text="tooltipText"
|
||||||
:required="required && showRequiredAsterisk"
|
:required="required && showRequiredAsterisk"
|
||||||
|
:size="labelSize"
|
||||||
>
|
>
|
||||||
<div :class="showErrors ? $style.errorInput : ''" @keydown.stop @keydown.enter="onEnter">
|
<div :class="showErrors ? $style.errorInput : ''" @keydown.stop @keydown.enter="onEnter">
|
||||||
<slot v-if="hasDefaultSlot" />
|
<slot v-if="hasDefaultSlot" />
|
||||||
|
@ -223,6 +225,7 @@ defineExpose({ inputRef });
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:name="name"
|
:name="name"
|
||||||
:teleported="teleported"
|
:teleported="teleported"
|
||||||
|
:size="tagSize"
|
||||||
@update:model-value="onUpdateModelValue"
|
@update:model-value="onUpdateModelValue"
|
||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
|
@ -246,6 +249,7 @@ defineExpose({ inputRef });
|
||||||
:maxlength="maxlength"
|
:maxlength="maxlength"
|
||||||
:autocomplete="autocomplete"
|
:autocomplete="autocomplete"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
|
:size="tagSize"
|
||||||
@update:model-value="onUpdateModelValue"
|
@update:model-value="onUpdateModelValue"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
|
|
|
@ -5,7 +5,7 @@ import N8nIcon from '../N8nIcon';
|
||||||
import N8nText from '../N8nText';
|
import N8nText from '../N8nText';
|
||||||
import N8nTooltip from '../N8nTooltip';
|
import N8nTooltip from '../N8nTooltip';
|
||||||
|
|
||||||
const SIZE = ['small', 'medium'] as const;
|
const SIZE = ['small', 'medium', 'large'] as const;
|
||||||
|
|
||||||
interface InputLabelProps {
|
interface InputLabelProps {
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
|
|
|
@ -313,7 +313,6 @@ onBeforeUnmount(() => {
|
||||||
@open:contextmenu="onOpenContextMenuFromNode"
|
@open:contextmenu="onOpenContextMenuFromNode"
|
||||||
>
|
>
|
||||||
<NodeIcon
|
<NodeIcon
|
||||||
v-if="nodeTypeDescription"
|
|
||||||
:node-type="nodeTypeDescription"
|
:node-type="nodeTypeDescription"
|
||||||
:size="nodeIconSize"
|
:size="nodeIconSize"
|
||||||
:shrink="false"
|
:shrink="false"
|
||||||
|
|
|
@ -102,15 +102,6 @@ describe('useCanvasOperations', () => {
|
||||||
expect(result).toBe(expectedDescription);
|
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', () => {
|
it('should return node type description when only type is provided and it exists', () => {
|
||||||
const nodeTypesStore = useNodeTypesStore();
|
const nodeTypesStore = useNodeTypesStore();
|
||||||
const type = 'testTypeWithoutVersion';
|
const type = 'testTypeWithoutVersion';
|
||||||
|
@ -123,6 +114,25 @@ describe('useCanvasOperations', () => {
|
||||||
|
|
||||||
expect(result).toBe(expectedDescription);
|
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', () => {
|
describe('addNode', () => {
|
||||||
|
@ -616,7 +626,6 @@ describe('useCanvasOperations', () => {
|
||||||
deleteNode(id, { trackHistory: true });
|
deleteNode(id, { trackHistory: true });
|
||||||
|
|
||||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(id);
|
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(id);
|
||||||
expect(workflowsStore.removeNodeConnectionsById).toHaveBeenCalledWith(id);
|
|
||||||
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(id);
|
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(id);
|
||||||
expect(historyStore.pushCommandToUndo).toHaveBeenCalledWith(new RemoveNodeCommand(node));
|
expect(historyStore.pushCommandToUndo).toHaveBeenCalledWith(new RemoveNodeCommand(node));
|
||||||
});
|
});
|
||||||
|
@ -644,7 +653,6 @@ describe('useCanvasOperations', () => {
|
||||||
deleteNode(id, { trackHistory: false });
|
deleteNode(id, { trackHistory: false });
|
||||||
|
|
||||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(id);
|
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(id);
|
||||||
expect(workflowsStore.removeNodeConnectionsById).toHaveBeenCalledWith(id);
|
|
||||||
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(id);
|
expect(workflowsStore.removeNodeExecutionDataById).toHaveBeenCalledWith(id);
|
||||||
expect(historyStore.pushCommandToUndo).not.toHaveBeenCalled();
|
expect(historyStore.pushCommandToUndo).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
@ -714,7 +722,6 @@ describe('useCanvasOperations', () => {
|
||||||
deleteNode(nodes[1].id);
|
deleteNode(nodes[1].id);
|
||||||
|
|
||||||
expect(workflowsStore.removeNodeById).toHaveBeenCalledWith(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.removeNodeExecutionDataById).toHaveBeenCalledWith(nodes[1].id);
|
||||||
expect(workflowsStore.removeNodeById).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', () => {
|
describe('duplicateNodes', () => {
|
||||||
it('should duplicate nodes', async () => {
|
it('should duplicate nodes', async () => {
|
||||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||||
|
|
|
@ -236,7 +236,7 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
await renameNode(currentName, previousName);
|
await renameNode(currentName, previousName);
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectAdjacentNodes(id: string) {
|
function connectAdjacentNodes(id: string, { trackHistory = false } = {}) {
|
||||||
const node = workflowsStore.getNodeById(id);
|
const node = workflowsStore.getNodeById(id);
|
||||||
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
|
@ -262,6 +262,23 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
|
|
||||||
if (!outgoingNodeId) continue;
|
if (!outgoingNodeId) continue;
|
||||||
|
|
||||||
|
if (trackHistory) {
|
||||||
|
historyStore.pushCommandToUndo(
|
||||||
|
new AddConnectionCommand([
|
||||||
|
{
|
||||||
|
node: incomingConnection.node,
|
||||||
|
type,
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
node: outgoingConnection.node,
|
||||||
|
type,
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
createConnection({
|
createConnection({
|
||||||
source: incomingNodeId,
|
source: incomingNodeId,
|
||||||
sourceHandle: createCanvasConnectionHandleString({
|
sourceHandle: createCanvasConnectionHandleString({
|
||||||
|
@ -289,8 +306,13 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
historyStore.startRecordingUndo();
|
historyStore.startRecordingUndo();
|
||||||
}
|
}
|
||||||
|
|
||||||
connectAdjacentNodes(id);
|
if (uiStore.lastInteractedWithNodeId === id) {
|
||||||
workflowsStore.removeNodeConnectionsById(id);
|
uiStore.lastInteractedWithNodeId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectAdjacentNodes(id, { trackHistory });
|
||||||
|
deleteConnectionsByNodeId(id, { trackHistory, trackBulk: false });
|
||||||
|
|
||||||
workflowsStore.removeNodeExecutionDataById(id);
|
workflowsStore.removeNodeExecutionDataById(id);
|
||||||
workflowsStore.removeNodeById(id);
|
workflowsStore.removeNodeById(id);
|
||||||
|
|
||||||
|
@ -423,16 +445,23 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
historyStore.stopRecordingUndo();
|
historyStore.stopRecordingUndo();
|
||||||
}
|
}
|
||||||
|
|
||||||
function requireNodeTypeDescription(type: INodeUi['type'], version?: INodeUi['typeVersion']) {
|
function requireNodeTypeDescription(
|
||||||
const nodeTypeDescription = nodeTypesStore.getNodeType(type, version);
|
type: INodeUi['type'],
|
||||||
if (!nodeTypeDescription) {
|
version?: INodeUi['typeVersion'],
|
||||||
throw new Error(
|
): INodeTypeDescription {
|
||||||
i18n.baseText('nodeView.showMessage.addNodeButton.message', {
|
return (
|
||||||
interpolate: { nodeTypeName: type },
|
nodeTypesStore.getNodeType(type, version) ?? {
|
||||||
}),
|
properties: [],
|
||||||
);
|
displayName: type,
|
||||||
}
|
name: type,
|
||||||
return nodeTypeDescription;
|
group: [],
|
||||||
|
description: '',
|
||||||
|
version: version ?? 1,
|
||||||
|
defaults: {},
|
||||||
|
inputs: [],
|
||||||
|
outputs: [],
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addNodes(
|
async function addNodes(
|
||||||
|
@ -1135,6 +1164,72 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, connection));
|
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(
|
function deleteConnection(
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
{ trackHistory = false, trackBulk = true } = {},
|
{ trackHistory = false, trackBulk = true } = {},
|
||||||
|
@ -1777,6 +1872,7 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
revertCreateConnection,
|
revertCreateConnection,
|
||||||
deleteConnection,
|
deleteConnection,
|
||||||
revertDeleteConnection,
|
revertDeleteConnection,
|
||||||
|
deleteConnectionsByNodeId,
|
||||||
isConnectionAllowed,
|
isConnectionAllowed,
|
||||||
importWorkflowData,
|
importWorkflowData,
|
||||||
fetchWorkflowDataFromUrl,
|
fetchWorkflowDataFromUrl,
|
||||||
|
|
|
@ -1525,8 +1525,6 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeNode(node);
|
removeNode(node);
|
||||||
|
|
||||||
// @TODO When removing node connected between two nodes, create a connection between them
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeNodeConnectionsById(nodeId: string): void {
|
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
|
xml2js: 0.6.2
|
||||||
xss: 1.0.15
|
xss: 1.0.15
|
||||||
zod: 3.23.8
|
zod: 3.23.8
|
||||||
'@langchain/core': 0.2.31
|
'@langchain/core': 0.3.3
|
||||||
|
|
||||||
catalogs:
|
catalogs:
|
||||||
frontend:
|
frontend:
|
||||||
|
|
Loading…
Reference in a new issue