mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 08:34:07 -08:00
feat(editor): Improve how we show default Agent prompt and Memory session parameters (#11491)
This commit is contained in:
parent
e875bc5592
commit
565f8cd8c7
|
@ -21,7 +21,7 @@ import { sqlAgentAgentProperties } from './agents/SqlAgent/description';
|
||||||
import { sqlAgentAgentExecute } from './agents/SqlAgent/execute';
|
import { sqlAgentAgentExecute } from './agents/SqlAgent/execute';
|
||||||
import { toolsAgentProperties } from './agents/ToolsAgent/description';
|
import { toolsAgentProperties } from './agents/ToolsAgent/description';
|
||||||
import { toolsAgentExecute } from './agents/ToolsAgent/execute';
|
import { toolsAgentExecute } from './agents/ToolsAgent/execute';
|
||||||
import { promptTypeOptions, textInput } from '../../../utils/descriptions';
|
import { promptTypeOptions, textFromPreviousNode, textInput } from '../../../utils/descriptions';
|
||||||
|
|
||||||
// Function used in the inputs expression to figure out which inputs to
|
// Function used in the inputs expression to figure out which inputs to
|
||||||
// display based on the agent type
|
// display based on the agent type
|
||||||
|
@ -341,6 +341,17 @@ export class Agent implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
...textFromPreviousNode,
|
||||||
|
displayOptions: {
|
||||||
|
show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.7 } }] },
|
||||||
|
// SQL Agent has data source and credentials parameters so we need to include this input there manually
|
||||||
|
// to preserve the order
|
||||||
|
hide: {
|
||||||
|
agent: ['sqlAgent'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
...textInput,
|
...textInput,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import type { INodeProperties } from 'n8n-workflow';
|
import type { INodeProperties } from 'n8n-workflow';
|
||||||
import { promptTypeOptions, textInput } from '../../../../../utils/descriptions';
|
|
||||||
import { SQL_PREFIX, SQL_SUFFIX } from './other/prompts';
|
import { SQL_PREFIX, SQL_SUFFIX } from './other/prompts';
|
||||||
|
import {
|
||||||
|
promptTypeOptions,
|
||||||
|
textFromPreviousNode,
|
||||||
|
textInput,
|
||||||
|
} from '../../../../../utils/descriptions';
|
||||||
|
|
||||||
const dataSourceOptions: INodeProperties = {
|
const dataSourceOptions: INodeProperties = {
|
||||||
displayName: 'Data Source',
|
displayName: 'Data Source',
|
||||||
|
@ -114,6 +119,12 @@ export const sqlAgentAgentProperties: INodeProperties[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
...textFromPreviousNode,
|
||||||
|
displayOptions: {
|
||||||
|
show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.7 } }], agent: ['sqlAgent'] },
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
...textInput,
|
...textInput,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
|
||||||
|
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
|
||||||
|
import type { DataSource } from '@n8n/typeorm';
|
||||||
|
import type { SqlCreatePromptArgs } from 'langchain/agents/toolkits/sql';
|
||||||
|
import { SqlToolkit, createSqlAgent } from 'langchain/agents/toolkits/sql';
|
||||||
|
import { SqlDatabase } from 'langchain/sql_db';
|
||||||
import {
|
import {
|
||||||
type IExecuteFunctions,
|
type IExecuteFunctions,
|
||||||
type INodeExecutionData,
|
type INodeExecutionData,
|
||||||
|
@ -6,19 +12,12 @@ import {
|
||||||
type IDataObject,
|
type IDataObject,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { SqlDatabase } from 'langchain/sql_db';
|
import { getMysqlDataSource } from './other/handlers/mysql';
|
||||||
import type { SqlCreatePromptArgs } from 'langchain/agents/toolkits/sql';
|
import { getPostgresDataSource } from './other/handlers/postgres';
|
||||||
import { SqlToolkit, createSqlAgent } from 'langchain/agents/toolkits/sql';
|
import { getSqliteDataSource } from './other/handlers/sqlite';
|
||||||
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
|
import { SQL_PREFIX, SQL_SUFFIX } from './other/prompts';
|
||||||
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
|
|
||||||
import type { DataSource } from '@n8n/typeorm';
|
|
||||||
|
|
||||||
import { getPromptInputByType, serializeChatHistory } from '../../../../../utils/helpers';
|
import { getPromptInputByType, serializeChatHistory } from '../../../../../utils/helpers';
|
||||||
import { getTracingConfig } from '../../../../../utils/tracing';
|
import { getTracingConfig } from '../../../../../utils/tracing';
|
||||||
import { getSqliteDataSource } from './other/handlers/sqlite';
|
|
||||||
import { getPostgresDataSource } from './other/handlers/postgres';
|
|
||||||
import { SQL_PREFIX, SQL_SUFFIX } from './other/prompts';
|
|
||||||
import { getMysqlDataSource } from './other/handlers/mysql';
|
|
||||||
|
|
||||||
const parseTablesString = (tablesString: string) =>
|
const parseTablesString = (tablesString: string) =>
|
||||||
tablesString
|
tablesString
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { AgentExecutor } from 'langchain/agents';
|
import { AgentExecutor } from 'langchain/agents';
|
||||||
import { OpenAI as OpenAIClient } from 'openai';
|
import type { OpenAIToolType } from 'langchain/dist/experimental/openai_assistant/schema';
|
||||||
import { OpenAIAssistantRunnable } from 'langchain/experimental/openai_assistant';
|
import { OpenAIAssistantRunnable } from 'langchain/experimental/openai_assistant';
|
||||||
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
||||||
import type {
|
import type {
|
||||||
|
@ -8,10 +8,11 @@ import type {
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import type { OpenAIToolType } from 'langchain/dist/experimental/openai_assistant/schema';
|
import { OpenAI as OpenAIClient } from 'openai';
|
||||||
|
|
||||||
|
import { formatToOpenAIAssistantTool } from './utils';
|
||||||
import { getConnectedTools } from '../../../utils/helpers';
|
import { getConnectedTools } from '../../../utils/helpers';
|
||||||
import { getTracingConfig } from '../../../utils/tracing';
|
import { getTracingConfig } from '../../../utils/tracing';
|
||||||
import { formatToOpenAIAssistantTool } from './utils';
|
|
||||||
|
|
||||||
export class OpenAiAssistant implements INodeType {
|
export class OpenAiAssistant implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {
|
||||||
getCustomErrorMessage as getCustomOpenAiErrorMessage,
|
getCustomErrorMessage as getCustomOpenAiErrorMessage,
|
||||||
isOpenAiError,
|
isOpenAiError,
|
||||||
} from '../../vendors/OpenAi/helpers/error-handling';
|
} from '../../vendors/OpenAi/helpers/error-handling';
|
||||||
|
import { promptTypeOptions, textFromPreviousNode } from '../../../utils/descriptions';
|
||||||
|
|
||||||
interface MessagesTemplate {
|
interface MessagesTemplate {
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -253,7 +254,7 @@ export class ChainLlm implements INodeType {
|
||||||
name: 'chainLlm',
|
name: 'chainLlm',
|
||||||
icon: 'fa:link',
|
icon: 'fa:link',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2, 1.3, 1.4],
|
version: [1, 1.1, 1.2, 1.3, 1.4, 1.5],
|
||||||
description: 'A simple chain to prompt a large language model',
|
description: 'A simple chain to prompt a large language model',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Basic LLM Chain',
|
name: 'Basic LLM Chain',
|
||||||
|
@ -315,30 +316,16 @@ export class ChainLlm implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Prompt',
|
...promptTypeOptions,
|
||||||
name: 'promptType',
|
|
||||||
type: 'options',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
|
||||||
name: 'Take from previous node automatically',
|
|
||||||
value: 'auto',
|
|
||||||
description: 'Looks for an input field called chatInput',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
|
||||||
name: 'Define below',
|
|
||||||
value: 'define',
|
|
||||||
description:
|
|
||||||
'Use an expression to reference data in previous nodes or enter static text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
hide: {
|
hide: {
|
||||||
'@version': [1, 1.1, 1.2, 1.3],
|
'@version': [1, 1.1, 1.2, 1.3],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: 'auto',
|
},
|
||||||
|
{
|
||||||
|
...textFromPreviousNode,
|
||||||
|
displayOptions: { show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.5 } }] } },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Text',
|
displayName: 'Text',
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
|
||||||
|
import {
|
||||||
|
ChatPromptTemplate,
|
||||||
|
SystemMessagePromptTemplate,
|
||||||
|
HumanMessagePromptTemplate,
|
||||||
|
PromptTemplate,
|
||||||
|
} from '@langchain/core/prompts';
|
||||||
|
import type { BaseRetriever } from '@langchain/core/retrievers';
|
||||||
|
import { RetrievalQAChain } from 'langchain/chains';
|
||||||
import {
|
import {
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
type IExecuteFunctions,
|
type IExecuteFunctions,
|
||||||
|
@ -7,20 +16,12 @@ import {
|
||||||
NodeOperationError,
|
NodeOperationError,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { RetrievalQAChain } from 'langchain/chains';
|
import { promptTypeOptions, textFromPreviousNode } from '../../../utils/descriptions';
|
||||||
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
|
|
||||||
import type { BaseRetriever } from '@langchain/core/retrievers';
|
|
||||||
import {
|
|
||||||
ChatPromptTemplate,
|
|
||||||
SystemMessagePromptTemplate,
|
|
||||||
HumanMessagePromptTemplate,
|
|
||||||
PromptTemplate,
|
|
||||||
} from '@langchain/core/prompts';
|
|
||||||
import { getTemplateNoticeField } from '../../../utils/sharedFields';
|
|
||||||
import { getPromptInputByType, isChatInstance } from '../../../utils/helpers';
|
import { getPromptInputByType, isChatInstance } from '../../../utils/helpers';
|
||||||
|
import { getTemplateNoticeField } from '../../../utils/sharedFields';
|
||||||
import { getTracingConfig } from '../../../utils/tracing';
|
import { getTracingConfig } from '../../../utils/tracing';
|
||||||
|
|
||||||
const SYSTEM_PROMPT_TEMPLATE = `Use the following pieces of context to answer the users question.
|
const SYSTEM_PROMPT_TEMPLATE = `Use the following pieces of context to answer the users question.
|
||||||
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||||
----------------
|
----------------
|
||||||
{context}`;
|
{context}`;
|
||||||
|
@ -31,7 +32,7 @@ export class ChainRetrievalQa implements INodeType {
|
||||||
name: 'chainRetrievalQa',
|
name: 'chainRetrievalQa',
|
||||||
icon: 'fa:link',
|
icon: 'fa:link',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2, 1.3],
|
version: [1, 1.1, 1.2, 1.3, 1.4],
|
||||||
description: 'Answer questions about retrieved documents',
|
description: 'Answer questions about retrieved documents',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Question and Answer Chain',
|
name: 'Question and Answer Chain',
|
||||||
|
@ -108,30 +109,16 @@ export class ChainRetrievalQa implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Prompt',
|
...promptTypeOptions,
|
||||||
name: 'promptType',
|
|
||||||
type: 'options',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
|
||||||
name: 'Take from previous node automatically',
|
|
||||||
value: 'auto',
|
|
||||||
description: 'Looks for an input field called chatInput',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
|
||||||
name: 'Define below',
|
|
||||||
value: 'define',
|
|
||||||
description:
|
|
||||||
'Use an expression to reference data in previous nodes or enter static text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
hide: {
|
hide: {
|
||||||
'@version': [{ _cnd: { lte: 1.2 } }],
|
'@version': [{ _cnd: { lte: 1.2 } }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: 'auto',
|
},
|
||||||
|
{
|
||||||
|
...textFromPreviousNode,
|
||||||
|
displayOptions: { show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.4 } }] } },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Text',
|
displayName: 'Text',
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import type { BufferWindowMemoryInput } from 'langchain/memory';
|
||||||
|
import { BufferWindowMemory } from 'langchain/memory';
|
||||||
import {
|
import {
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
type INodeType,
|
type INodeType,
|
||||||
|
@ -6,12 +8,16 @@ import {
|
||||||
type ISupplyDataFunctions,
|
type ISupplyDataFunctions,
|
||||||
type SupplyData,
|
type SupplyData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import type { BufferWindowMemoryInput } from 'langchain/memory';
|
|
||||||
import { BufferWindowMemory } from 'langchain/memory';
|
import { getSessionId } from '../../../utils/helpers';
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
import { sessionIdOption, sessionKeyProperty, contextWindowLengthProperty } from '../descriptions';
|
import {
|
||||||
import { getSessionId } from '../../../utils/helpers';
|
sessionIdOption,
|
||||||
|
sessionKeyProperty,
|
||||||
|
contextWindowLengthProperty,
|
||||||
|
expressionSessionKeyProperty,
|
||||||
|
} from '../descriptions';
|
||||||
|
|
||||||
class MemoryChatBufferSingleton {
|
class MemoryChatBufferSingleton {
|
||||||
private static instance: MemoryChatBufferSingleton;
|
private static instance: MemoryChatBufferSingleton;
|
||||||
|
@ -72,7 +78,7 @@ export class MemoryBufferWindow implements INodeType {
|
||||||
name: 'memoryBufferWindow',
|
name: 'memoryBufferWindow',
|
||||||
icon: 'fa:database',
|
icon: 'fa:database',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2],
|
version: [1, 1.1, 1.2, 1.3],
|
||||||
description: 'Stores in n8n memory, so no credentials required',
|
description: 'Stores in n8n memory, so no credentials required',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Window Buffer Memory',
|
name: 'Window Buffer Memory',
|
||||||
|
@ -129,6 +135,7 @@ export class MemoryBufferWindow implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expressionSessionKeyProperty(1.3),
|
||||||
sessionKeyProperty,
|
sessionKeyProperty,
|
||||||
contextWindowLengthProperty,
|
contextWindowLengthProperty,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import { MotorheadMemory } from '@langchain/community/memory/motorhead_memory';
|
||||||
import {
|
import {
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
type INodeType,
|
type INodeType,
|
||||||
|
@ -7,11 +8,10 @@ import {
|
||||||
type SupplyData,
|
type SupplyData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { MotorheadMemory } from '@langchain/community/memory/motorhead_memory';
|
import { getSessionId } from '../../../utils/helpers';
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
import { sessionIdOption, sessionKeyProperty } from '../descriptions';
|
import { expressionSessionKeyProperty, sessionIdOption, sessionKeyProperty } from '../descriptions';
|
||||||
import { getSessionId } from '../../../utils/helpers';
|
|
||||||
|
|
||||||
export class MemoryMotorhead implements INodeType {
|
export class MemoryMotorhead implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
@ -19,7 +19,7 @@ export class MemoryMotorhead implements INodeType {
|
||||||
name: 'memoryMotorhead',
|
name: 'memoryMotorhead',
|
||||||
icon: 'fa:file-export',
|
icon: 'fa:file-export',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2],
|
version: [1, 1.1, 1.2, 1.3],
|
||||||
description: 'Use Motorhead Memory',
|
description: 'Use Motorhead Memory',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Motorhead',
|
name: 'Motorhead',
|
||||||
|
@ -82,6 +82,7 @@ export class MemoryMotorhead implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expressionSessionKeyProperty(1.3),
|
||||||
sessionKeyProperty,
|
sessionKeyProperty,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import { PostgresChatMessageHistory } from '@langchain/community/stores/message/postgres';
|
||||||
|
import { BufferMemory, BufferWindowMemory } from 'langchain/memory';
|
||||||
|
import type { PostgresNodeCredentials } from 'n8n-nodes-base/dist/nodes/Postgres/v2/helpers/interfaces';
|
||||||
|
import { postgresConnectionTest } from 'n8n-nodes-base/dist/nodes/Postgres/v2/methods/credentialTest';
|
||||||
|
import { configurePostgres } from 'n8n-nodes-base/dist/nodes/Postgres/v2/transport';
|
||||||
import type {
|
import type {
|
||||||
ISupplyDataFunctions,
|
ISupplyDataFunctions,
|
||||||
INodeType,
|
INodeType,
|
||||||
|
@ -6,16 +11,17 @@ import type {
|
||||||
SupplyData,
|
SupplyData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeConnectionType } from 'n8n-workflow';
|
import { NodeConnectionType } from 'n8n-workflow';
|
||||||
import { BufferMemory, BufferWindowMemory } from 'langchain/memory';
|
|
||||||
import { PostgresChatMessageHistory } from '@langchain/community/stores/message/postgres';
|
|
||||||
import type pg from 'pg';
|
import type pg from 'pg';
|
||||||
import { configurePostgres } from 'n8n-nodes-base/dist/nodes/Postgres/v2/transport';
|
|
||||||
import type { PostgresNodeCredentials } from 'n8n-nodes-base/dist/nodes/Postgres/v2/helpers/interfaces';
|
import { getSessionId } from '../../../utils/helpers';
|
||||||
import { postgresConnectionTest } from 'n8n-nodes-base/dist/nodes/Postgres/v2/methods/credentialTest';
|
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
import { sessionIdOption, sessionKeyProperty, contextWindowLengthProperty } from '../descriptions';
|
import {
|
||||||
import { getSessionId } from '../../../utils/helpers';
|
sessionIdOption,
|
||||||
|
sessionKeyProperty,
|
||||||
|
contextWindowLengthProperty,
|
||||||
|
expressionSessionKeyProperty,
|
||||||
|
} from '../descriptions';
|
||||||
|
|
||||||
export class MemoryPostgresChat implements INodeType {
|
export class MemoryPostgresChat implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
@ -23,7 +29,7 @@ export class MemoryPostgresChat implements INodeType {
|
||||||
name: 'memoryPostgresChat',
|
name: 'memoryPostgresChat',
|
||||||
icon: 'file:postgres.svg',
|
icon: 'file:postgres.svg',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1],
|
version: [1, 1.1, 1.2, 1.3],
|
||||||
description: 'Stores the chat history in Postgres table.',
|
description: 'Stores the chat history in Postgres table.',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Postgres Chat Memory',
|
name: 'Postgres Chat Memory',
|
||||||
|
@ -56,6 +62,7 @@ export class MemoryPostgresChat implements INodeType {
|
||||||
properties: [
|
properties: [
|
||||||
getConnectionHintNoticeField([NodeConnectionType.AiAgent]),
|
getConnectionHintNoticeField([NodeConnectionType.AiAgent]),
|
||||||
sessionIdOption,
|
sessionIdOption,
|
||||||
|
expressionSessionKeyProperty(1.2),
|
||||||
sessionKeyProperty,
|
sessionKeyProperty,
|
||||||
{
|
{
|
||||||
displayName: 'Table Name',
|
displayName: 'Table Name',
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import type { RedisChatMessageHistoryInput } from '@langchain/redis';
|
||||||
|
import { RedisChatMessageHistory } from '@langchain/redis';
|
||||||
|
import { BufferMemory, BufferWindowMemory } from 'langchain/memory';
|
||||||
import {
|
import {
|
||||||
NodeOperationError,
|
NodeOperationError,
|
||||||
type INodeType,
|
type INodeType,
|
||||||
|
@ -7,15 +10,18 @@ import {
|
||||||
type SupplyData,
|
type SupplyData,
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { BufferMemory, BufferWindowMemory } from 'langchain/memory';
|
|
||||||
import type { RedisChatMessageHistoryInput } from '@langchain/redis';
|
|
||||||
import { RedisChatMessageHistory } from '@langchain/redis';
|
|
||||||
import type { RedisClientOptions } from 'redis';
|
import type { RedisClientOptions } from 'redis';
|
||||||
import { createClient } from 'redis';
|
import { createClient } from 'redis';
|
||||||
|
|
||||||
|
import { getSessionId } from '../../../utils/helpers';
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
import { sessionIdOption, sessionKeyProperty, contextWindowLengthProperty } from '../descriptions';
|
import {
|
||||||
import { getSessionId } from '../../../utils/helpers';
|
sessionIdOption,
|
||||||
|
sessionKeyProperty,
|
||||||
|
contextWindowLengthProperty,
|
||||||
|
expressionSessionKeyProperty,
|
||||||
|
} from '../descriptions';
|
||||||
|
|
||||||
export class MemoryRedisChat implements INodeType {
|
export class MemoryRedisChat implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
@ -23,7 +29,7 @@ export class MemoryRedisChat implements INodeType {
|
||||||
name: 'memoryRedisChat',
|
name: 'memoryRedisChat',
|
||||||
icon: 'file:redis.svg',
|
icon: 'file:redis.svg',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2, 1.3],
|
version: [1, 1.1, 1.2, 1.3, 1.4],
|
||||||
description: 'Stores the chat history in Redis.',
|
description: 'Stores the chat history in Redis.',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Redis Chat Memory',
|
name: 'Redis Chat Memory',
|
||||||
|
@ -86,6 +92,7 @@ export class MemoryRedisChat implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expressionSessionKeyProperty(1.4),
|
||||||
sessionKeyProperty,
|
sessionKeyProperty,
|
||||||
{
|
{
|
||||||
displayName: 'Session Time To Live',
|
displayName: 'Session Time To Live',
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
|
||||||
|
import { XataChatMessageHistory } from '@langchain/community/stores/message/xata';
|
||||||
|
import { BaseClient } from '@xata.io/client';
|
||||||
|
import { BufferMemory, BufferWindowMemory } from 'langchain/memory';
|
||||||
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
||||||
import type {
|
import type {
|
||||||
ISupplyDataFunctions,
|
ISupplyDataFunctions,
|
||||||
|
@ -6,13 +9,16 @@ import type {
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
SupplyData,
|
SupplyData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { XataChatMessageHistory } from '@langchain/community/stores/message/xata';
|
|
||||||
import { BufferMemory, BufferWindowMemory } from 'langchain/memory';
|
import { getSessionId } from '../../../utils/helpers';
|
||||||
import { BaseClient } from '@xata.io/client';
|
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
import { sessionIdOption, sessionKeyProperty, contextWindowLengthProperty } from '../descriptions';
|
import {
|
||||||
import { getSessionId } from '../../../utils/helpers';
|
sessionIdOption,
|
||||||
|
sessionKeyProperty,
|
||||||
|
contextWindowLengthProperty,
|
||||||
|
expressionSessionKeyProperty,
|
||||||
|
} from '../descriptions';
|
||||||
|
|
||||||
export class MemoryXata implements INodeType {
|
export class MemoryXata implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
@ -20,7 +26,7 @@ export class MemoryXata implements INodeType {
|
||||||
name: 'memoryXata',
|
name: 'memoryXata',
|
||||||
icon: 'file:xata.svg',
|
icon: 'file:xata.svg',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2, 1.3],
|
version: [1, 1.1, 1.2, 1.3, 1.4],
|
||||||
description: 'Use Xata Memory',
|
description: 'Use Xata Memory',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Xata',
|
name: 'Xata',
|
||||||
|
@ -86,6 +92,7 @@ export class MemoryXata implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sessionKeyProperty,
|
sessionKeyProperty,
|
||||||
|
expressionSessionKeyProperty(1.4),
|
||||||
{
|
{
|
||||||
...contextWindowLengthProperty,
|
...contextWindowLengthProperty,
|
||||||
displayOptions: { hide: { '@version': [{ _cnd: { lt: 1.3 } }] } },
|
displayOptions: { hide: { '@version': [{ _cnd: { lt: 1.3 } }] } },
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { ZepCloudMemory } from '@langchain/community/memory/zep_cloud';
|
||||||
|
|
||||||
import { logWrapper } from '../../../utils/logWrapper';
|
import { logWrapper } from '../../../utils/logWrapper';
|
||||||
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
import { sessionIdOption, sessionKeyProperty } from '../descriptions';
|
import { expressionSessionKeyProperty, sessionIdOption, sessionKeyProperty } from '../descriptions';
|
||||||
import { getSessionId } from '../../../utils/helpers';
|
import { getSessionId } from '../../../utils/helpers';
|
||||||
import type { BaseChatMemory } from '@langchain/community/dist/memory/chat_memory';
|
import type { BaseChatMemory } from '@langchain/community/dist/memory/chat_memory';
|
||||||
import type { InputValues, MemoryVariables } from '@langchain/core/memory';
|
import type { InputValues, MemoryVariables } from '@langchain/core/memory';
|
||||||
|
@ -36,7 +36,7 @@ export class MemoryZep implements INodeType {
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
||||||
icon: 'file:zep.png',
|
icon: 'file:zep.png',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2],
|
version: [1, 1.1, 1.2, 1.3],
|
||||||
description: 'Use Zep Memory',
|
description: 'Use Zep Memory',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Zep',
|
name: 'Zep',
|
||||||
|
@ -99,6 +99,7 @@ export class MemoryZep implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expressionSessionKeyProperty(1.3),
|
||||||
sessionKeyProperty,
|
sessionKeyProperty,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,20 @@ export const sessionIdOption: INodeProperties = {
|
||||||
default: 'fromInput',
|
default: 'fromInput',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const expressionSessionKeyProperty = (fromVersion: number): INodeProperties => ({
|
||||||
|
displayName: 'Session Key From Previous Node',
|
||||||
|
name: 'sessionKey',
|
||||||
|
type: 'string',
|
||||||
|
default: '={{ $json.sessionId }}',
|
||||||
|
disabledOptions: { show: { sessionIdType: ['fromInput'] } },
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
sessionIdType: ['fromInput'],
|
||||||
|
'@version': [{ _cnd: { gte: fromVersion } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const sessionKeyProperty: INodeProperties = {
|
export const sessionKeyProperty: INodeProperties = {
|
||||||
displayName: 'Key',
|
displayName: 'Key',
|
||||||
name: 'sessionKey',
|
name: 'sessionKey',
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { OpenAI as OpenAIClient } from 'openai';
|
import { OpenAI as OpenAIClient } from 'openai';
|
||||||
|
|
||||||
|
import { promptTypeOptions, textFromPreviousNode } from '../../../../../utils/descriptions';
|
||||||
import { getConnectedTools } from '../../../../../utils/helpers';
|
import { getConnectedTools } from '../../../../../utils/helpers';
|
||||||
import { getTracingConfig } from '../../../../../utils/tracing';
|
import { getTracingConfig } from '../../../../../utils/tracing';
|
||||||
import { formatToOpenAIAssistantTool } from '../../helpers/utils';
|
import { formatToOpenAIAssistantTool } from '../../helpers/utils';
|
||||||
|
@ -26,24 +27,18 @@ import { assistantRLC } from '../descriptions';
|
||||||
const properties: INodeProperties[] = [
|
const properties: INodeProperties[] = [
|
||||||
assistantRLC,
|
assistantRLC,
|
||||||
{
|
{
|
||||||
displayName: 'Prompt',
|
...promptTypeOptions,
|
||||||
name: 'prompt',
|
name: 'prompt',
|
||||||
type: 'options',
|
},
|
||||||
options: [
|
{
|
||||||
{
|
...textFromPreviousNode,
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
disabledOptions: { show: { prompt: ['auto'] } },
|
||||||
name: 'Take from previous node automatically',
|
displayOptions: {
|
||||||
value: 'auto',
|
show: {
|
||||||
description: 'Looks for an input field called chatInput',
|
prompt: ['auto'],
|
||||||
|
'@version': [{ _cnd: { gte: 1.7 } }],
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
|
||||||
name: 'Define below',
|
|
||||||
value: 'define',
|
|
||||||
description: 'Use an expression to reference data in previous nodes or enter static text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
default: 'auto',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Text',
|
displayName: 'Text',
|
||||||
|
|
|
@ -77,7 +77,7 @@ export const versionDescription: INodeTypeDescription = {
|
||||||
name: 'openAi',
|
name: 'openAi',
|
||||||
icon: { light: 'file:openAi.svg', dark: 'file:openAi.dark.svg' },
|
icon: { light: 'file:openAi.svg', dark: 'file:openAi.dark.svg' },
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6],
|
version: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7],
|
||||||
subtitle: `={{(${prettifyOperation})($parameter.resource, $parameter.operation)}}`,
|
subtitle: `={{(${prettifyOperation})($parameter.resource, $parameter.operation)}}`,
|
||||||
description: 'Message an assistant or GPT, analyze images, generate audio, etc.',
|
description: 'Message an assistant or GPT, analyze images, generate audio, etc.',
|
||||||
defaults: {
|
defaults: {
|
||||||
|
|
|
@ -66,7 +66,7 @@ export const inputSchemaField: INodeProperties = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const promptTypeOptions: INodeProperties = {
|
export const promptTypeOptions: INodeProperties = {
|
||||||
displayName: 'Prompt',
|
displayName: 'Prompt Source',
|
||||||
name: 'promptType',
|
name: 'promptType',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
options: [
|
options: [
|
||||||
|
@ -97,3 +97,15 @@ export const textInput: INodeProperties = {
|
||||||
rows: 2,
|
rows: 2,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const textFromPreviousNode: INodeProperties = {
|
||||||
|
displayName: 'Text From Previous Node',
|
||||||
|
name: 'text',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
default: '={{ $json.chatInput }}',
|
||||||
|
typeOptions: {
|
||||||
|
rows: 2,
|
||||||
|
},
|
||||||
|
disabledOptions: { show: { promptType: ['auto'] } },
|
||||||
|
};
|
||||||
|
|
|
@ -74,7 +74,7 @@ const { segments, readEditorValue, editor, hasFocus, focus } = useExpressionEdit
|
||||||
editorRef: root,
|
editorRef: root,
|
||||||
editorValue,
|
editorValue,
|
||||||
extensions,
|
extensions,
|
||||||
isReadOnly: props.isReadOnly,
|
isReadOnly: computed(() => props.isReadOnly),
|
||||||
autocompleteTelemetry: { enabled: true, parameterPath: props.path },
|
autocompleteTelemetry: { enabled: true, parameterPath: props.path },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -110,7 +110,15 @@ defineExpose({ editor });
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
:global(.cm-content) {
|
.editor {
|
||||||
border-radius: var(--border-radius-base);
|
:global(.cm-content) {
|
||||||
|
border-radius: var(--border-radius-base);
|
||||||
|
&[aria-readonly='true'] {
|
||||||
|
--disabled-fill: var(--color-background-medium);
|
||||||
|
background-color: var(--disabled-fill, var(--color-background-light));
|
||||||
|
color: var(--disabled-color, var(--color-text-base));
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -56,6 +56,7 @@ const extensions = computed(() => [
|
||||||
infoBoxTooltips(),
|
infoBoxTooltips(),
|
||||||
]);
|
]);
|
||||||
const editorValue = ref<string>(removeExpressionPrefix(props.modelValue));
|
const editorValue = ref<string>(removeExpressionPrefix(props.modelValue));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
editor: editorRef,
|
editor: editorRef,
|
||||||
segments,
|
segments,
|
||||||
|
@ -68,7 +69,7 @@ const {
|
||||||
editorRef: root,
|
editorRef: root,
|
||||||
editorValue,
|
editorValue,
|
||||||
extensions,
|
extensions,
|
||||||
isReadOnly: props.isReadOnly,
|
isReadOnly: computed(() => props.isReadOnly),
|
||||||
autocompleteTelemetry: { enabled: true, parameterPath: props.path },
|
autocompleteTelemetry: { enabled: true, parameterPath: props.path },
|
||||||
additionalData: props.additionalData,
|
additionalData: props.additionalData,
|
||||||
});
|
});
|
||||||
|
@ -133,6 +134,17 @@ defineExpose({
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
:deep(.cm-content) {
|
:deep(.cm-content) {
|
||||||
|
--disabled-fill: var(--color-background-medium);
|
||||||
padding-left: var(--spacing-2xs);
|
padding-left: var(--spacing-2xs);
|
||||||
|
|
||||||
|
&[aria-readonly='true'] {
|
||||||
|
background-color: var(--disabled-fill, var(--color-background-light));
|
||||||
|
border-color: var(--disabled-border, var(--border-color-base));
|
||||||
|
color: var(--disabled-color, var(--color-text-base));
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -16,12 +16,14 @@ interface InlineExpressionEditorOutputProps {
|
||||||
editorState?: EditorState;
|
editorState?: EditorState;
|
||||||
selection?: SelectionRange;
|
selection?: SelectionRange;
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
|
isReadOnly?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<InlineExpressionEditorOutputProps>(), {
|
withDefaults(defineProps<InlineExpressionEditorOutputProps>(), {
|
||||||
visible: false,
|
visible: false,
|
||||||
editorState: undefined,
|
editorState: undefined,
|
||||||
selection: undefined,
|
selection: undefined,
|
||||||
|
isReadOnly: false,
|
||||||
unresolvedExpression: undefined,
|
unresolvedExpression: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -51,7 +53,7 @@ onBeforeUnmount(() => {
|
||||||
>
|
>
|
||||||
</ExpressionOutput>
|
</ExpressionOutput>
|
||||||
</n8n-text>
|
</n8n-text>
|
||||||
<div :class="$style.footer">
|
<div :class="$style.footer" v-if="!isReadOnly">
|
||||||
<InlineExpressionTip
|
<InlineExpressionTip
|
||||||
:editor-state="editorState"
|
:editor-state="editorState"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
|
|
|
@ -983,7 +983,7 @@ watch(remoteParameterOptionsLoading, () => {
|
||||||
|
|
||||||
// Focus input field when changing from fixed value to expression
|
// Focus input field when changing from fixed value to expression
|
||||||
watch(isModelValueExpression, async (isExpression, wasExpression) => {
|
watch(isModelValueExpression, async (isExpression, wasExpression) => {
|
||||||
if (isExpression && !wasExpression) {
|
if (!props.isReadOnly && isExpression && !wasExpression) {
|
||||||
await nextTick();
|
await nextTick();
|
||||||
inputField.value?.focus();
|
inputField.value?.focus();
|
||||||
}
|
}
|
||||||
|
@ -1497,7 +1497,7 @@ onUpdated(async () => {
|
||||||
:disabled="isReadOnly"
|
:disabled="isReadOnly"
|
||||||
@update:model-value="valueChanged"
|
@update:model-value="valueChanged"
|
||||||
/>
|
/>
|
||||||
<div v-if="showDragnDropTip" :class="$style.tip">
|
<div v-if="!isReadOnly && showDragnDropTip" :class="$style.tip">
|
||||||
<InlineExpressionTip />
|
<InlineExpressionTip />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import type { IUpdateInformation } from '@/Interface';
|
import type { IUpdateInformation } from '@/Interface';
|
||||||
|
|
||||||
import DraggableTarget from '@/components/DraggableTarget.vue';
|
import DraggableTarget from '@/components/DraggableTarget.vue';
|
||||||
|
@ -189,6 +189,16 @@ function onDrop(newParamValue: string) {
|
||||||
forceShowExpression.value = false;
|
forceShowExpression.value = false;
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When switching to read-only mode, reset the value to the default value
|
||||||
|
watch(
|
||||||
|
() => props.isReadOnly,
|
||||||
|
(isReadOnly) => {
|
||||||
|
if (isReadOnly) {
|
||||||
|
valueChanged({ name: props.path, value: props.parameter.default });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -322,7 +322,10 @@ function mustHideDuringCustomApiCall(
|
||||||
return !MUST_REMAIN_VISIBLE.includes(parameter.name);
|
return !MUST_REMAIN_VISIBLE.includes(parameter.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayNodeParameter(parameter: INodeProperties): boolean {
|
function displayNodeParameter(
|
||||||
|
parameter: INodeProperties,
|
||||||
|
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
|
||||||
|
): boolean {
|
||||||
if (parameter.type === 'hidden') {
|
if (parameter.type === 'hidden') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +346,7 @@ function displayNodeParameter(parameter: INodeProperties): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameter.displayOptions === undefined) {
|
if (parameter[displayKey] === undefined) {
|
||||||
// If it is not defined no need to do a proper check
|
// If it is not defined no need to do a proper check
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -402,13 +405,19 @@ function displayNodeParameter(parameter: INodeProperties): boolean {
|
||||||
if (props.path) {
|
if (props.path) {
|
||||||
rawValues = deepCopy(props.nodeValues);
|
rawValues = deepCopy(props.nodeValues);
|
||||||
set(rawValues, props.path, nodeValues);
|
set(rawValues, props.path, nodeValues);
|
||||||
return nodeHelpers.displayParameter(rawValues, parameter, props.path, node.value);
|
return nodeHelpers.displayParameter(rawValues, parameter, props.path, node.value, displayKey);
|
||||||
} else {
|
} else {
|
||||||
return nodeHelpers.displayParameter(nodeValues, parameter, '', node.value);
|
return nodeHelpers.displayParameter(nodeValues, parameter, '', node.value, displayKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeHelpers.displayParameter(props.nodeValues, parameter, props.path, node.value);
|
return nodeHelpers.displayParameter(
|
||||||
|
props.nodeValues,
|
||||||
|
parameter,
|
||||||
|
props.path,
|
||||||
|
node.value,
|
||||||
|
displayKey,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function valueChanged(parameterData: IUpdateInformation): void {
|
function valueChanged(parameterData: IUpdateInformation): void {
|
||||||
|
@ -620,7 +629,10 @@ function getParameterValue<T extends NodeParameterValueType = NodeParameterValue
|
||||||
:value="getParameterValue(parameter.name)"
|
:value="getParameterValue(parameter.name)"
|
||||||
:display-options="shouldShowOptions(parameter)"
|
:display-options="shouldShowOptions(parameter)"
|
||||||
:path="getPath(parameter.name)"
|
:path="getPath(parameter.name)"
|
||||||
:is-read-only="isReadOnly"
|
:is-read-only="
|
||||||
|
isReadOnly ||
|
||||||
|
(parameter.disabledOptions && displayNodeParameter(parameter, 'disabledOptions'))
|
||||||
|
"
|
||||||
:hide-label="false"
|
:hide-label="false"
|
||||||
:node-values="nodeValues"
|
:node-values="nodeValues"
|
||||||
@update="valueChanged"
|
@update="valueChanged"
|
||||||
|
|
|
@ -39,7 +39,7 @@ const isDefault = computed(() => props.parameter.default === props.value);
|
||||||
const isValueAnExpression = computed(() => isValueExpression(props.parameter, props.value));
|
const isValueAnExpression = computed(() => isValueExpression(props.parameter, props.value));
|
||||||
const isHtmlEditor = computed(() => getArgument('editor') === 'htmlEditor');
|
const isHtmlEditor = computed(() => getArgument('editor') === 'htmlEditor');
|
||||||
const shouldShowExpressionSelector = computed(
|
const shouldShowExpressionSelector = computed(
|
||||||
() => !props.parameter.noDataExpression && props.showExpressionSelector,
|
() => !props.parameter.noDataExpression && props.showExpressionSelector && !props.isReadOnly,
|
||||||
);
|
);
|
||||||
const shouldShowOptions = computed(() => {
|
const shouldShowOptions = computed(() => {
|
||||||
if (props.isReadOnly) {
|
if (props.isReadOnly) {
|
||||||
|
|
|
@ -120,8 +120,9 @@ export function useNodeHelpers() {
|
||||||
parameter: INodeProperties | INodeCredentialDescription,
|
parameter: INodeProperties | INodeCredentialDescription,
|
||||||
path: string,
|
path: string,
|
||||||
node: INodeUi | null,
|
node: INodeUi | null,
|
||||||
|
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
|
||||||
) {
|
) {
|
||||||
return NodeHelpers.displayParameterPath(nodeValues, parameter, path, node);
|
return NodeHelpers.displayParameterPath(nodeValues, parameter, path, node, displayKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshNodeIssues(): void {
|
function refreshNodeIssues(): void {
|
||||||
|
|
|
@ -1417,6 +1417,7 @@ export interface INodeProperties {
|
||||||
default: NodeParameterValueType;
|
default: NodeParameterValueType;
|
||||||
description?: string;
|
description?: string;
|
||||||
hint?: string;
|
hint?: string;
|
||||||
|
disabledOptions?: IDisplayOptions;
|
||||||
displayOptions?: IDisplayOptions;
|
displayOptions?: IDisplayOptions;
|
||||||
options?: Array<INodePropertyOptions | INodeProperties | INodePropertyCollection>;
|
options?: Array<INodePropertyOptions | INodeProperties | INodePropertyCollection>;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
@ -1657,6 +1658,7 @@ export interface INodeCredentialDescription {
|
||||||
name: string;
|
name: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
|
disabledOptions?: ICredentialsDisplayOptions;
|
||||||
displayOptions?: ICredentialsDisplayOptions;
|
displayOptions?: ICredentialsDisplayOptions;
|
||||||
testedBy?: ICredentialTestRequest | string; // Name of a function inside `loadOptions.credentialTest`
|
testedBy?: ICredentialTestRequest | string; // Name of a function inside `loadOptions.credentialTest`
|
||||||
}
|
}
|
||||||
|
|
|
@ -639,12 +639,13 @@ export function displayParameter(
|
||||||
parameter: INodeProperties | INodeCredentialDescription,
|
parameter: INodeProperties | INodeCredentialDescription,
|
||||||
node: Pick<INode, 'typeVersion'> | null, // Allow null as it does also get used by credentials and they do not have versioning yet
|
node: Pick<INode, 'typeVersion'> | null, // Allow null as it does also get used by credentials and they do not have versioning yet
|
||||||
nodeValuesRoot?: INodeParameters,
|
nodeValuesRoot?: INodeParameters,
|
||||||
|
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
|
||||||
) {
|
) {
|
||||||
if (!parameter.displayOptions) {
|
if (!parameter[displayKey]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { show, hide } = parameter.displayOptions;
|
const { show, hide } = parameter[displayKey];
|
||||||
|
|
||||||
nodeValuesRoot = nodeValuesRoot || nodeValues;
|
nodeValuesRoot = nodeValuesRoot || nodeValues;
|
||||||
|
|
||||||
|
@ -691,6 +692,7 @@ export function displayParameterPath(
|
||||||
parameter: INodeProperties | INodeCredentialDescription,
|
parameter: INodeProperties | INodeCredentialDescription,
|
||||||
path: string,
|
path: string,
|
||||||
node: Pick<INode, 'typeVersion'> | null,
|
node: Pick<INode, 'typeVersion'> | null,
|
||||||
|
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
|
||||||
) {
|
) {
|
||||||
let resolvedNodeValues = nodeValues;
|
let resolvedNodeValues = nodeValues;
|
||||||
if (path !== '') {
|
if (path !== '') {
|
||||||
|
@ -703,7 +705,7 @@ export function displayParameterPath(
|
||||||
nodeValuesRoot = get(nodeValues, 'parameters') as INodeParameters;
|
nodeValuesRoot = get(nodeValues, 'parameters') as INodeParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
return displayParameter(resolvedNodeValues, parameter, node, nodeValuesRoot);
|
return displayParameter(resolvedNodeValues, parameter, node, nodeValuesRoot, displayKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue