resolve merge conflicts

This commit is contained in:
Mutasem Aldmour 2024-12-16 14:07:16 +01:00
commit 4ab2b39c62
No known key found for this signature in database
GPG key ID: 3DFA8122BB7FD6B8
546 changed files with 21254 additions and 9731 deletions

View file

@ -1,3 +1,43 @@
# [1.72.0](https://github.com/n8n-io/n8n/compare/n8n@1.71.0...n8n@1.72.0) (2024-12-11)
### Bug Fixes
* Allow disabling MFA with recovery codes ([#12014](https://github.com/n8n-io/n8n/issues/12014)) ([95d56fe](https://github.com/n8n-io/n8n/commit/95d56fee8d0168b75fca6dcf41702d2f10c930a8))
* Chat triggers don't work with the new partial execution flow ([#11952](https://github.com/n8n-io/n8n/issues/11952)) ([2b6a72f](https://github.com/n8n-io/n8n/commit/2b6a72f1289c01145edf2b88e5027d2b9b2ed624))
* **core:** Execute nodes after loops correctly with the new partial execution flow ([#11978](https://github.com/n8n-io/n8n/issues/11978)) ([891dd7f](https://github.com/n8n-io/n8n/commit/891dd7f995c78a2355a049b7ced981a5f6b1c40c))
* **core:** Fix support for multiple invocation of AI tools ([#12141](https://github.com/n8n-io/n8n/issues/12141)) ([c572c06](https://github.com/n8n-io/n8n/commit/c572c0648ca5b644b222157b3cabac9c05704a84))
* **core:** Make sure task runner exits ([#12123](https://github.com/n8n-io/n8n/issues/12123)) ([c5effca](https://github.com/n8n-io/n8n/commit/c5effca7d47a713f157eea21d7892002e9ab7283))
* **core:** Remove run data of nodes unrelated to the current partial execution ([#12099](https://github.com/n8n-io/n8n/issues/12099)) ([c4e4d37](https://github.com/n8n-io/n8n/commit/c4e4d37a8785d1a4bcd376cb1c49b82a80aa4391))
* **core:** Return homeProject when filtering workflows by project id ([#12077](https://github.com/n8n-io/n8n/issues/12077)) ([efafeed](https://github.com/n8n-io/n8n/commit/efafeed33482100a23fa0163a53b9ce93cd6b2c3))
* **editor:** Don't reset all Parameter Inputs when switched to read-only ([#12063](https://github.com/n8n-io/n8n/issues/12063)) ([706702d](https://github.com/n8n-io/n8n/commit/706702dff8da3c2e949e2c98dd5b34b299a1f17c))
* **editor:** Fix canvas panning using `Control` + `Left Mouse Button` on Windows ([#12104](https://github.com/n8n-io/n8n/issues/12104)) ([43009b6](https://github.com/n8n-io/n8n/commit/43009b6aa820f24b9e6f519e7a45592aa21db03e))
* **editor:** Fix Nodeview.v2 reinitialise based on route changes ([#12062](https://github.com/n8n-io/n8n/issues/12062)) ([b1f8663](https://github.com/n8n-io/n8n/commit/b1f866326574974eb2936e6b02771346e83e7137))
* **editor:** Fix svg background pattern rendering on safari ([#12079](https://github.com/n8n-io/n8n/issues/12079)) ([596f221](https://github.com/n8n-io/n8n/commit/596f22103c01e14063ebb2388c4dabf4714d37c6))
* **editor:** Fix switching from v2 to v1 ([#12050](https://github.com/n8n-io/n8n/issues/12050)) ([5c76de3](https://github.com/n8n-io/n8n/commit/5c76de324c2e25b0d8b74cdab79f04aa616d8c4f))
* **editor:** Improvements to the commit modal ([#12031](https://github.com/n8n-io/n8n/issues/12031)) ([4fe1952](https://github.com/n8n-io/n8n/commit/4fe1952e2fb3379d95da42a7bb531851af6d0094))
* **editor:** Load node types in demo and preview modes ([#12048](https://github.com/n8n-io/n8n/issues/12048)) ([4ac5f95](https://github.com/n8n-io/n8n/commit/4ac5f9527bbec382a65ed3f1d9c41d6948c154e3))
* **editor:** Polyfill crypto.randomUUID ([#12052](https://github.com/n8n-io/n8n/issues/12052)) ([0537524](https://github.com/n8n-io/n8n/commit/0537524c3e45d7633415c7a9175a3857ad52cd58))
* **editor:** Redirect Settings to the proper sub page depending on the instance type (cloud or not) ([#12053](https://github.com/n8n-io/n8n/issues/12053)) ([a16d006](https://github.com/n8n-io/n8n/commit/a16d006f893cac927d674fa447b08c1205b67c54))
* **editor:** Render sanitized HTML content in toast messages ([#12139](https://github.com/n8n-io/n8n/issues/12139)) ([0468945](https://github.com/n8n-io/n8n/commit/0468945c99f083577c4cc71f671b4b950f6aeb86))
* **editor:** Universal button snags ([#11974](https://github.com/n8n-io/n8n/issues/11974)) ([956b11a](https://github.com/n8n-io/n8n/commit/956b11a560528336a74be40f722fa05bf3cca94d))
* **editor:** Update concurrency UI considering different types of instances ([#12068](https://github.com/n8n-io/n8n/issues/12068)) ([fa572bb](https://github.com/n8n-io/n8n/commit/fa572bbca4397b1cc42668530497444630ed17eb))
* **FTP Node:** Fix issue with creating folders on rename ([#9340](https://github.com/n8n-io/n8n/issues/9340)) ([eb7d593](https://github.com/n8n-io/n8n/commit/eb7d5934ef8bc6e999d6de4c0b8025ce175df5dd))
* **n8n Form Node:** Completion page display if EXECUTIONS_DATA_SAVE_ON_SUCCESS=none ([#11869](https://github.com/n8n-io/n8n/issues/11869)) ([f4c2523](https://github.com/n8n-io/n8n/commit/f4c252341985fe03927a2fd5d60ba846ec3dfc77))
* **OpenAI Node:** Allow updating assistant files ([#12042](https://github.com/n8n-io/n8n/issues/12042)) ([7b20f8a](https://github.com/n8n-io/n8n/commit/7b20f8aaa8befd19dbad0af3bf1b881342c1fca5))
### Features
* **AI Transform Node:** Reduce payload size ([#11965](https://github.com/n8n-io/n8n/issues/11965)) ([d8ca8de](https://github.com/n8n-io/n8n/commit/d8ca8de13a4cbb856696873bdb56c66b12a5b027))
* **core:** Add option to filter for empty variables ([#12112](https://github.com/n8n-io/n8n/issues/12112)) ([a63f0e8](https://github.com/n8n-io/n8n/commit/a63f0e878e21da9924451e2679939209b34b6583))
* **core:** Cancel runner task on timeout in external mode ([#12101](https://github.com/n8n-io/n8n/issues/12101)) ([addb4fa](https://github.com/n8n-io/n8n/commit/addb4fa352c88d856e463bb2b7001173c4fd6a7d))
* **core:** Parent workflows should wait for sub-workflows to finish ([#11985](https://github.com/n8n-io/n8n/issues/11985)) ([60b3dcc](https://github.com/n8n-io/n8n/commit/60b3dccf9317da6f3013be35a78ce21d0416ad80))
* **editor:** Implementing the `Easy AI Workflow` experiment ([#12043](https://github.com/n8n-io/n8n/issues/12043)) ([67ed1d2](https://github.com/n8n-io/n8n/commit/67ed1d2c3c2e69d5a96daf7de2795c02f5d8f15b))
* **Redis Node:** Add support for continue on fail / error output branch ([#11714](https://github.com/n8n-io/n8n/issues/11714)) ([ed35958](https://github.com/n8n-io/n8n/commit/ed359586c88a7662f4d94d58c5a87cf91d027ab9))
# [1.71.0](https://github.com/n8n-io/n8n/compare/n8n@1.70.0...n8n@1.71.0) (2024-12-04)

127
README.md
View file

@ -1,104 +1,67 @@
![n8n.io - Workflow Automation](https://user-images.githubusercontent.com/65276001/173571060-9f2f6d7b-bac0-43b6-bdb2-001da9694058.png)
![Banner image](https://user-images.githubusercontent.com/10284570/173569848-c624317f-42b1-45a6-ab09-f0ea3c247648.png)
# n8n - Workflow automation tool
# n8n - Secure Workflow Automation for Technical Teams
n8n is an extendable workflow automation tool. With a [fair-code](https://faircode.io) distribution model, n8n
will always have visible source code, be available to self-host, and allow you to add your own custom
functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect
anything to everything.
n8n is a workflow automation platform that gives technical teams the flexibility of code with the speed of no-code. With 400+ integrations, native AI capabilities, and a fair-code license, n8n lets you build powerful automations while maintaining full control over your data and deployments.
![n8n.io - Screenshot](https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png)
![n8n.io - Screenshot](https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot-readme.png)
## Demo
## Key Capabilities
[:tv: A short video (< 5 min)](https://www.youtube.com/watch?v=1MwSoB0gnM4) that goes over key concepts of
creating workflows in n8n.
- **Code When You Need It**: Write JavaScript/Python, add npm packages, or use the visual interface
- **AI-Native Platform**: Build AI agent workflows based on LangChain with your own data and models
- **Full Control**: Self-host with our fair-code license or use our [cloud offering](https://app.n8n.cloud/login)
- **Enterprise-Ready**: Advanced permissions, SSO, and air-gapped deployments
- **Active Community**: 400+ integrations and 900+ ready-to-use [templates](https://n8n.io/workflows)
## Available integrations
## Quick Start
n8n has 200+ different nodes to automate workflows. The list can be found on:
[https://n8n.io/integrations](https://n8n.io/integrations)
## Documentation
The official n8n documentation can be found on our [documentation website](https://docs.n8n.io)
Additional information and example workflows on the [n8n.io website](https://n8n.io)
The release notes can be found [here](https://docs.n8n.io/release-notes/) and the list of breaking
changes [here](https://github.com/n8n-io/n8n/blob/master/packages/cli/BREAKING-CHANGES.md).
## Usage
- :books: Learn
[how to **use** it from the command line](https://docs.n8n.io/reference/cli-commands/)
- :whale: Learn
[how to run n8n in **Docker**](https://docs.n8n.io/hosting/installation/docker/)
## Start
You can try n8n without installing it using npx. You must have [Node.js](https://nodejs.org/en/) installed.
From the terminal, run:
Try n8n instantly with [npx](https://docs.n8n.io/hosting/installation/npm/) (requires [Node.js](https://nodejs.org/en/)):
`npx n8n`
This command will download everything that is needed to start n8n. You can then access n8n and start building workflows by opening [http://localhost:5678](http://localhost:5678).
Or deploy with [Docker](https://docs.n8n.io/hosting/installation/docker/):
## n8n cloud
`docker run -it --rm --name n8n -p 5678:5678 docker.n8n.io/n8n-io/n8n`
Sign-up for an [n8n cloud](https://www.n8n.io/cloud/) account.
Access the editor at http://localhost:5678
While n8n cloud and n8n are the same in terms of features, n8n cloud provides certain conveniences such as:
## Resources
- Not having to set up and maintain your n8n instance
- Managed OAuth for authentication
- Easily upgrading to the newer n8n versions
## Build with LangChain and AI in n8n (beta)
With n8n's LangChain nodes you can build AI-powered functionality within your workflows. The LangChain nodes are configurable, meaning you can choose your preferred agent, LLM, memory, and so on. Alongside the LangChain nodes, you can connect any n8n node as normal: this means you can integrate your LangChain logic with other data sources and services.
Learn more in the [documentation](https://docs.n8n.io/langchain/).
- [LangChain nodes package](https://www.npmjs.com/package/@n8n/n8n-nodes-langchain)
- [Chatbot package](https://www.npmjs.com/package/@n8n/chat)
- 📚 [Documentation](https://docs.n8n.io)
- 🔧 [400+ Integrations](https://n8n.io/integrations)
- 💡 [Example Workflows](https://n8n.io/workflows)
- 🤖 [AI & LangChain Guide](https://docs.n8n.io/langchain/)
- 👥 [Community Forum](https://community.n8n.io)
- 📖 [Community Tutorials](https://community.n8n.io/c/tutorials/28)
## Support
If you have problems or questions go to our forum, we will then try to help you asap:
[https://community.n8n.io](https://community.n8n.io)
## Jobs
If you are interested in working for n8n and so shape the future of the project check out our
[job posts](https://apply.workable.com/n8n/)
## What does n8n mean and how do you pronounce it?
**Short answer:** It means "nodemation" and it is pronounced as n-eight-n.
**Long answer:** "I get that question quite often (more often than I expected) so I decided it is probably
best to answer it here. While looking for a good name for the project with a free domain I realized very
quickly that all the good ones I could think of were already taken. So, in the end, I chose nodemation.
'node-' in the sense that it uses a Node-View and that it uses Node.js and '-mation' for 'automation' which is
what the project is supposed to help with. However, I did not like how long the name was and I could not
imagine writing something that long every time in the CLI. That is when I then ended up on 'n8n'." - **Jan
Oberhauser, Founder and CEO, n8n.io**
## Development setup
Have you found a bug :bug: ? Or maybe you have a nice feature :sparkles: to contribute ? The
[CONTRIBUTING guide](https://github.com/n8n-io/n8n/blob/master/CONTRIBUTING.md) will help you get your
development environment ready in minutes.
Need help? Our community forum is the place to get support and connect with other users:
[community.n8n.io](https://community.n8n.io)
## License
n8n is [fair-code](https://faircode.io) distributed under the
[**Sustainable Use License**](https://github.com/n8n-io/n8n/blob/master/LICENSE.md) and the
[**n8n Enterprise License**](https://github.com/n8n-io/n8n/blob/master/LICENSE_EE.md).
n8n is [fair-code](https://faircode.io) distributed under the [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md) and [n8n Enterprise License](https://github.com/n8n-io/n8n/blob/master/LICENSE_EE.md).
Proprietary licenses are available for enterprise customers. [Get in touch](mailto:license@n8n.io)
- **Source Available**: Always visible source code
- **Self-Hostable**: Deploy anywhere
- **Extensible**: Add your own nodes and functionality
Additional information about the license model can be found in the
[docs](https://docs.n8n.io/reference/license/).
[Enterprise licenses](mailto:license@n8n.io) available for additional features and support.
Additional information about the license model can be found in the [docs](https://docs.n8n.io/reference/license/).
## Contributing
Found a bug 🐛 or have a feature idea ✨? Check our [Contributing Guide](https://github.com/n8n-io/n8n/blob/master/CONTRIBUTING.md) to get started.
## Join the Team
Want to shape the future of automation? Check out our [job posts](https://n8n.io/careers) and join our team!
## What does n8n mean?
**Short answer:** It means "nodemation" and is pronounced as n-eight-n.
**Long answer:** "I get that question quite often (more often than I expected) so I decided it is probably best to answer it here. While looking for a good name for the project with a free domain I realized very quickly that all the good ones I could think of were already taken. So, in the end, I chose nodemation. 'node-' in the sense that it uses a Node-View and that it uses Node.js and '-mation' for 'automation' which is what the project is supposed to help with. However, I did not like how long the name was and I could not imagine writing something that long every time in the CLI. That is when I then ended up on 'n8n'." - **Jan Oberhauser, Founder and CEO, n8n.io**

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View file

@ -129,7 +129,7 @@ describe('Inline expression editor', () => {
// Run workflow
ndv.actions.close();
WorkflowPage.actions.executeNode('No Operation');
WorkflowPage.actions.executeNode('No Operation', { anchor: 'topLeft' });
WorkflowPage.actions.openNode('Hacker News');
WorkflowPage.actions.openInlineExpressionEditor();

View file

@ -112,7 +112,7 @@ describe('Data pinning', () => {
it('Should be able to pin data from canvas (context menu or shortcut)', () => {
workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger');
workflowPage.actions.addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME);
workflowPage.actions.openContextMenu(EDIT_FIELDS_SET_NODE_NAME, 'overflow-button');
workflowPage.actions.openContextMenu(EDIT_FIELDS_SET_NODE_NAME, { method: 'overflow-button' });
workflowPage.getters
.contextMenuAction('toggle_pin')
.parent()

View file

@ -185,7 +185,6 @@ describe('Data mapping', () => {
workflowPage.actions.openNode('Set1');
ndv.actions.executePrevious();
ndv.actions.expandSchemaViewNode(SCHEDULE_TRIGGER_NODE_NAME);
const dataPill = ndv.getters
.inputDataContainer()

View file

@ -148,24 +148,9 @@ describe('User Management', { disableAutoLogin: true }, () => {
personalSettingsPage.actions.changeTheme('Dark');
cy.get('body').should('have.attr', 'data-theme', 'dark');
settingsSidebar.actions.back();
mainSidebar.getters
.logo()
.should('have.attr', 'src')
.then((src) => {
expect(src).to.include('/static/logo/channel/dev-dark.svg');
});
cy.visit(personalSettingsPage.url);
personalSettingsPage.actions.changeTheme('Light');
cy.get('body').should('have.attr', 'data-theme', 'light');
settingsSidebar.actions.back();
mainSidebar.getters
.logo()
.should('have.attr', 'src')
.then((src) => {
expect(src).to.include('/static/logo/channel/dev.svg');
});
});
it('should delete user and their data', () => {

View file

@ -87,11 +87,28 @@ describe('Debug', () => {
confirmDialog.get('.btn--confirm').click();
cy.url().should('include', '/debug');
workflowPage.getters.canvasNodes().first().should('have.descendants', '.node-pin-data-icon');
workflowPage.getters
.canvasNodes()
.not(':first')
.should('not.have.descendants', '.node-pin-data-icon');
cy.ifCanvasVersion(
() => {
workflowPage.getters
.canvasNodes()
.first()
.should('have.descendants', '.node-pin-data-icon');
workflowPage.getters
.canvasNodes()
.not(':first')
.should('not.have.descendants', '.node-pin-data-icon');
},
() => {
workflowPage.getters
.canvasNodes()
.first()
.should('have.descendants', '[data-test-id="canvas-node-status-pinned"]');
workflowPage.getters
.canvasNodes()
.not(':first')
.should('not.have.descendants', '[data-test-id="canvas-node-status-pinned"]');
},
);
cy.reload(true);
cy.wait(['@getExecution']);
@ -114,7 +131,18 @@ describe('Debug', () => {
confirmDialog.get('.btn--confirm').click();
cy.url().should('include', '/debug');
workflowPage.getters.canvasNodes().last().find('.node-info-icon').should('be.empty');
cy.ifCanvasVersion(
() => {
workflowPage.getters.canvasNodes().last().find('.node-info-icon').should('be.empty');
},
() => {
workflowPage.getters
.canvasNodes()
.last()
.find('[class*="statusIcons"]')
.should('not.exist');
},
);
workflowPage.getters.canvasNodes().first().dblclick();
ndv.actions.unPinData();

View file

@ -98,6 +98,10 @@ describe('Workflow Selector Parameter', () => {
getVisiblePopper().findChildByTestId('rlc-item').eq(0).click();
cy.get('@windowOpen').should('be.calledWith', '/workflows/onboarding/0?sampleSubWorkflows=0');
const SAMPLE_SUBWORKFLOW_TEMPLATE_ID = 'VMiAxXa3lCAizGB5f7dVZQSFfg3FtHkdTKvLuupqBls=';
cy.get('@windowOpen').should(
'be.calledWith',
`/workflows/onboarding/${SAMPLE_SUBWORKFLOW_TEMPLATE_ID}?sampleSubWorkflows=0`,
);
});
});

View file

@ -77,7 +77,7 @@ describe('NDV', () => {
workflowPage.actions.openNode('Switch');
cy.get('.cm-line').realMouseMove(100, 100);
cy.get('.fa-angle-down').click();
cy.get('.fa-angle-down').first().click();
ndv.getters.backToCanvas().click();
workflowPage.actions.executeWorkflow();
workflowPage.actions.openNode('Merge');
@ -111,6 +111,7 @@ describe('NDV', () => {
cy.get('[class*=hasIssues]').should('have.length', 1);
});
// Correctly failing in V2 - node issues are only shows after execution
it('should show all validation errors when opening pasted node', () => {
cy.createFixtureWorkflow('Test_workflow_ndv_errors.json', 'Validation errors');
workflowPage.getters.canvasNodes().should('have.have.length', 1);
@ -204,7 +205,7 @@ describe('NDV', () => {
.contains(key)
.should('be.visible');
});
getObjectValueItem().find('label').click({ force: true });
getObjectValueItem().find('.toggle').click({ force: true });
expandedObjectProps.forEach((key) => {
ndv.getters
.outputPanel()
@ -213,9 +214,11 @@ describe('NDV', () => {
.should('not.be.visible');
});
});
it('should not display pagination for schema', () => {
setupSchemaWorkflow();
ndv.getters.backToCanvas().click();
workflowPage.actions.deselectAll();
workflowPage.getters.canvasNodeByName('Set').click();
workflowPage.actions.addNodeToCanvas(
'Customer Datastore (n8n training)',
@ -245,8 +248,8 @@ describe('NDV', () => {
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
ndv.getters
.outputPanel()
.find('[data-test-id=run-data-schema-item] [data-test-id=run-data-schema-item]')
.should('have.length', 20);
.find('[data-test-id=run-data-schema-item]')
.should('have.length.above', 10);
});
});
@ -407,8 +410,18 @@ describe('NDV', () => {
return cy.get(`[data-node-placement=${position}]`);
}
// Correctly failing in V2 - due to floating navigation not updating the selected node
it('should traverse floating nodes with mouse', () => {
cy.createFixtureWorkflow('Floating_Nodes.json', 'Floating Nodes');
cy.ifCanvasVersion(
() => {},
() => {
// Needed in V2 as all nodes remain selected when clicking on a selected node
workflowPage.actions.deselectAll();
},
);
workflowPage.getters.canvasNodes().first().dblclick();
getFloatingNodeByPosition('inputMain').should('not.exist');
getFloatingNodeByPosition('outputMain').should('exist');
@ -419,6 +432,7 @@ describe('NDV', () => {
getFloatingNodeByPosition('inputMain').should('exist');
getFloatingNodeByPosition('outputMain').should('exist');
ndv.actions.close();
// These two lines are broken in V2
workflowPage.getters.selectedNodes().should('have.length', 1);
workflowPage.getters
.selectedNodes()
@ -426,10 +440,8 @@ describe('NDV', () => {
.should('contain', `Node ${i + 1}`);
workflowPage.getters.selectedNodes().first().dblclick();
});
getFloatingNodeByPosition('outputMain').click({ force: true });
ndv.getters.nodeNameContainer().should('contain', 'Chain');
// Traverse 4 connected node backwards
Array.from(Array(4).keys()).forEach((i) => {
getFloatingNodeByPosition('inputMain').click({ force: true });
@ -453,8 +465,17 @@ describe('NDV', () => {
.should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME);
});
// Correctly failing in V2 - due to floating navigation not updating the selected node
it('should traverse floating nodes with keyboard', () => {
cy.createFixtureWorkflow('Floating_Nodes.json', 'Floating Nodes');
cy.ifCanvasVersion(
() => {},
() => {
// Needed in V2 as all nodes remain selected when clicking on a selected node
workflowPage.actions.deselectAll();
},
);
workflowPage.getters.canvasNodes().first().dblclick();
getFloatingNodeByPosition('inputMain').should('not.exist');
getFloatingNodeByPosition('outputMain').should('exist');
@ -465,6 +486,7 @@ describe('NDV', () => {
getFloatingNodeByPosition('inputMain').should('exist');
getFloatingNodeByPosition('outputMain').should('exist');
ndv.actions.close();
// These two lines are broken in V2
workflowPage.getters.selectedNodes().should('have.length', 1);
workflowPage.getters
.selectedNodes()
@ -492,6 +514,7 @@ describe('NDV', () => {
getFloatingNodeByPosition('inputSub').should('not.exist');
getFloatingNodeByPosition('outputSub').should('not.exist');
ndv.actions.close();
// These two lines are broken in V2
workflowPage.getters.selectedNodes().should('have.length', 1);
workflowPage.getters
.selectedNodes()
@ -717,6 +740,7 @@ describe('NDV', () => {
.should('have.value', 'Error fetching options from Notion');
});
// Correctly failing in V2 - NodeCreator is not opened after clicking on the link
it('Should open appropriate node creator after clicking on connection hint link', () => {
const nodeCreator = new NodeCreator();
const hintMapper = {
@ -734,6 +758,7 @@ describe('NDV', () => {
Object.entries(hintMapper).forEach(([node, group]) => {
workflowPage.actions.openNode(node);
// This fails to open the NodeCreator
cy.get('[data-action=openSelectiveNodeCreator]').contains('Insert one').click();
nodeCreator.getters.activeSubcategory().should('contain', group);
cy.realPress('Escape');

View file

@ -6,6 +6,7 @@
"cypress:install": "cypress install",
"test:e2e:ui": "scripts/run-e2e.js ui",
"test:e2e:dev": "scripts/run-e2e.js dev",
"test:e2e:dev:v2": "scripts/run-e2e.js dev:v2",
"test:e2e:all": "scripts/run-e2e.js all",
"format": "biome format --write .",
"format:check": "biome ci .",

View file

@ -6,48 +6,10 @@ export class CredentialsPage extends BasePage {
getters = {
emptyListCreateCredentialButton: () => cy.getByTestId('empty-resources-list').find('button'),
createCredentialButton: () => {
cy.getByTestId('resource-add').should('be.visible').click();
cy.getByTestId('resource-add')
.find('.el-sub-menu__title')
.as('menuitem')
.should('have.attr', 'aria-describedby');
cy.get('@menuitem')
.should('be.visible')
.invoke('attr', 'aria-describedby')
.then((el) => cy.get(`[id="${el}"]`))
.as('submenu');
cy.get('@submenu')
.should('be.visible')
.within((submenu) => {
// If submenu has another submenu
if (submenu.find('[data-test-id="navigation-submenu"]').length) {
cy.wrap(submenu)
.find('[data-test-id="navigation-submenu"]')
.should('be.visible')
.filter(':contains("Credential")')
.as('child')
.click();
cy.get('@child')
.should('be.visible')
.find('[data-test-id="navigation-submenu-item"]')
.should('be.visible')
.filter(':contains("Personal")')
.as('button');
} else {
cy.wrap(submenu)
.find('[data-test-id="navigation-menu-item"]')
.filter(':contains("Credential")')
.as('button');
}
});
return cy.get('@button').should('be.visible');
cy.getByTestId('add-resource').should('be.visible').click();
cy.getByTestId('add-resource').getByTestId('action-credential').should('be.visible');
return cy.getByTestId('add-resource').getByTestId('action-credential');
},
// cy.getByTestId('resources-list-add'),
searchInput: () => cy.getByTestId('resources-list-search'),
emptyList: () => cy.getByTestId('resources-list-empty'),
credentialCards: () => cy.getByTestId('resources-list-item'),

View file

@ -227,9 +227,6 @@ export class NDV extends BasePage {
this.getters.inputSelect().find('.el-select').click();
this.getters.inputOption().contains(nodeName).click();
},
expandSchemaViewNode: (nodeName: string) => {
this.getters.schemaViewNodeName().contains(nodeName).click();
},
addDefaultPinnedData: () => {
this.actions.editPinnedData();
this.actions.savePinnedData();

View file

@ -30,6 +30,12 @@ export class WorkflowExecutionsTab extends BasePage {
actions = {
toggleNodeEnabled: (nodeName: string) => {
cy.ifCanvasVersion(
() => {},
() => {
cy.get('body').click(); // Cancel selection if it exists
},
);
workflowPage.getters.canvasNodeByName(nodeName).click();
cy.get('body').type('d', { force: true });
},

View file

@ -1,6 +1,7 @@
import { BasePage } from './base';
import { NodeCreator } from './features/node-creator';
import { META_KEY } from '../constants';
import type { OpenContextMenuOptions } from '../types';
import { getVisibleSelect } from '../utils';
import { getUniqueWorkflowName, isCanvasV2 } from '../utils/workflowUtils';
@ -96,7 +97,7 @@ export class WorkflowPage extends BasePage {
disabledNodes: () =>
cy.ifCanvasVersion(
() => cy.get('.node-box.disabled'),
() => cy.get('[data-test-id="canvas-trigger-node"][class*="disabled"]'),
() => cy.get('[data-test-id*="node"][class*="disabled"]'),
),
selectedNodes: () =>
cy.ifCanvasVersion(
@ -272,14 +273,14 @@ export class WorkflowPage extends BasePage {
},
openContextMenu: (
nodeTypeName?: string,
method: 'right-click' | 'overflow-button' = 'right-click',
{ method = 'right-click', anchor = 'center' }: OpenContextMenuOptions = {},
) => {
const target = nodeTypeName
? this.getters.canvasNodeByName(nodeTypeName)
: this.getters.nodeViewBackground();
if (method === 'right-click') {
target.rightclick(nodeTypeName ? 'center' : 'topLeft', { force: true });
target.rightclick(nodeTypeName ? anchor : 'topLeft', { force: true });
} else {
target.realHover();
target.find('[data-test-id="overflow-node-button"]').click({ force: true });
@ -296,8 +297,8 @@ export class WorkflowPage extends BasePage {
this.actions.openContextMenu(nodeTypeName);
this.actions.contextMenuAction('delete');
},
executeNode: (nodeTypeName: string) => {
this.actions.openContextMenu(nodeTypeName);
executeNode: (nodeTypeName: string, options?: OpenContextMenuOptions) => {
this.actions.openContextMenu(nodeTypeName, options);
this.actions.contextMenuAction('execute');
},
addStickyFromContextMenu: () => {
@ -324,7 +325,7 @@ export class WorkflowPage extends BasePage {
this.actions.contextMenuAction('toggle_pin');
},
openNodeFromContextMenu: (nodeTypeName: string) => {
this.actions.openContextMenu(nodeTypeName, 'overflow-button');
this.actions.openContextMenu(nodeTypeName, { method: 'overflow-button' });
this.actions.contextMenuAction('open');
},
selectAllFromContextMenu: () => {
@ -332,8 +333,14 @@ export class WorkflowPage extends BasePage {
this.actions.contextMenuAction('select_all');
},
deselectAll: () => {
this.actions.openContextMenu();
this.actions.contextMenuAction('deselect_all');
cy.ifCanvasVersion(
() => {
this.actions.openContextMenu();
this.actions.contextMenuAction('deselect_all');
},
// rightclick doesn't work with vueFlow canvas
() => this.getters.nodeViewBackground().click('topLeft'),
);
},
openExpressionEditorModal: () => {
cy.contains('Expression').invoke('show').click();

View file

@ -8,45 +8,8 @@ export class WorkflowsPage extends BasePage {
newWorkflowTemplateCard: () => cy.getByTestId('new-workflow-template-card'),
searchBar: () => cy.getByTestId('resources-list-search'),
createWorkflowButton: () => {
cy.getByTestId('resource-add').should('be.visible').click();
cy.getByTestId('resource-add')
.find('.el-sub-menu__title')
.as('menuitem')
.should('have.attr', 'aria-describedby');
cy.get('@menuitem')
.should('be.visible')
.invoke('attr', 'aria-describedby')
.then((el) => cy.get(`[id="${el}"]`))
.as('submenu');
cy.get('@submenu')
.should('be.visible')
.within((submenu) => {
// If submenu has another submenu
if (submenu.find('[data-test-id="navigation-submenu"]').length) {
cy.wrap(submenu)
.find('[data-test-id="navigation-submenu"]')
.should('be.visible')
.filter(':contains("Workflow")')
.as('child')
.click();
cy.get('@child')
.should('be.visible')
.find('[data-test-id="navigation-submenu-item"]')
.should('be.visible')
.filter(':contains("Personal")')
.as('button');
} else {
cy.wrap(submenu)
.find('[data-test-id="navigation-menu-item"]')
.filter(':contains("Workflow")')
.as('button');
}
});
return cy.get('@button').should('be.visible');
cy.getByTestId('add-resource-workflow').should('be.visible');
return cy.getByTestId('add-resource-workflow');
},
workflowCards: () => cy.getByTestId('resources-list-item'),
workflowCard: (workflowName: string) =>

View file

@ -57,6 +57,17 @@ switch (scenario) {
},
});
break;
case 'dev:v2':
runTests({
startCommand: 'develop',
url: 'http://localhost:8080/favicon.ico',
testCommand: 'cypress open',
customEnv: {
CYPRESS_NODE_VIEW_VERSION: 2,
CYPRESS_BASE_URL: 'http://localhost:8080',
},
});
break;
case 'all':
const specSuiteFilter = process.argv[3];
const specParam = specSuiteFilter ? ` --spec **/*${specSuiteFilter}*` : '';

View file

@ -22,3 +22,8 @@ export interface ExecutionResponse {
results: Execution[];
};
}
export type OpenContextMenuOptions = {
method?: 'right-click' | 'overflow-button';
anchor?: 'topRight' | 'topLeft' | 'center' | 'bottomRight' | 'bottomLeft';
};

View file

@ -33,7 +33,7 @@ COPY docker/images/n8n/docker-entrypoint.sh /
# Setup the Task Runner Launcher
ARG TARGETPLATFORM
ARG LAUNCHER_VERSION=0.7.0-rc
ARG LAUNCHER_VERSION=1.0.0
COPY docker/images/n8n/n8n-task-runners.json /etc/n8n-task-runners.json
# Download, verify, then extract the launcher binary
RUN \

View file

@ -24,7 +24,7 @@ RUN set -eux; \
# Setup the Task Runner Launcher
ARG TARGETPLATFORM
ARG LAUNCHER_VERSION=0.7.0-rc
ARG LAUNCHER_VERSION=1.0.0
COPY n8n-task-runners.json /etc/n8n-task-runners.json
# Download, verify, then extract the launcher binary
RUN \

View file

@ -12,6 +12,7 @@
"N8N_RUNNERS_TASK_BROKER_URI",
"N8N_RUNNERS_MAX_PAYLOAD",
"N8N_RUNNERS_MAX_CONCURRENCY",
"N8N_RUNNERS_TASK_TIMEOUT",
"N8N_RUNNERS_HEALTH_CHECK_SERVER_ENABLED",
"N8N_RUNNERS_HEALTH_CHECK_SERVER_HOST",
"N8N_RUNNERS_HEALTH_CHECK_SERVER_PORT",

View file

@ -1,6 +1,6 @@
{
"name": "n8n-monorepo",
"version": "1.71.0",
"version": "1.72.0",
"private": true,
"engines": {
"node": ">=20.15",

View file

@ -1,6 +1,6 @@
{
"name": "@n8n/api-types",
"version": "0.9.0",
"version": "0.10.0",
"scripts": {
"clean": "rimraf dist .turbo",
"dev": "pnpm watch",

View file

@ -3,3 +3,4 @@ export { RoleChangeRequestDto } from './user/role-change-request.dto';
export { SettingsUpdateRequestDto } from './user/settings-update-request.dto';
export { UserUpdateRequestDto } from './user/user-update-request.dto';
export { CommunityRegisteredRequestDto } from './license/community-registered-request.dto';
export { VariableListRequestDto } from './variables/variables-list-request.dto';

View file

@ -4,4 +4,5 @@ import { Z } from 'zod-class';
export class SettingsUpdateRequestDto extends Z.class({
userActivated: z.boolean().optional(),
allowSSOManualLogin: z.boolean().optional(),
easyAIWorkflowOnboarded: z.boolean().optional(),
}) {}

View file

@ -0,0 +1,6 @@
import { z } from 'zod';
import { Z } from 'zod-class';
export class VariableListRequestDto extends Z.class({
state: z.literal('empty').optional(),
}) {}

View file

@ -163,7 +163,7 @@ export interface FrontendSettings {
pruneTime: number;
licensePruneTime: number;
};
pruning: {
pruning?: {
isEnabled: boolean;
maxAge: number;
maxCount: number;
@ -172,5 +172,5 @@ export interface FrontendSettings {
blockFileAccessToN8nFiles: boolean;
};
betaFeatures: FrontendBetaFeatures[];
virtualSchemaView: boolean;
easyAIWorkflowOnboarded: boolean;
}

View file

@ -1,6 +1,6 @@
{
"name": "@n8n/chat",
"version": "0.32.0",
"version": "0.33.0",
"scripts": {
"dev": "pnpm run storybook",
"build": "pnpm build:vite && pnpm build:bundle",

View file

@ -1,6 +1,6 @@
{
"name": "@n8n/config",
"version": "1.21.0",
"version": "1.22.0",
"scripts": {
"clean": "rimraf dist .turbo",
"dev": "pnpm watch",

View file

@ -43,11 +43,11 @@ export class TaskRunnersConfig {
@Env('N8N_RUNNERS_MAX_CONCURRENCY')
maxConcurrency: number = 5;
/** How long (in seconds) a task is allowed to take for completion, else the task will be aborted and the runner restarted. Must be greater than 0. */
/** How long (in seconds) a task is allowed to take for completion, else the task will be aborted. (In internal mode, the runner will also be restarted.) Must be greater than 0. */
@Env('N8N_RUNNERS_TASK_TIMEOUT')
taskTimeout: number = 60;
/** How often (in seconds) the runner must send a heartbeat to the broker, else the task will be aborted and the runner restarted. Must be greater than 0. */
/** How often (in seconds) the runner must send a heartbeat to the broker, else the task will be aborted. (In internal mode, the runner will also be restarted.) Must be greater than 0. */
@Env('N8N_RUNNERS_HEARTBEAT_INTERVAL')
heartbeatInterval: number = 30;
}

View file

@ -9,6 +9,8 @@ import type {
INodeProperties,
} from 'n8n-workflow';
import { promptTypeOptions, textFromPreviousNode, textInput } from '@utils/descriptions';
import { conversationalAgentProperties } from './agents/ConversationalAgent/description';
import { conversationalAgentExecute } from './agents/ConversationalAgent/execute';
import { openAiFunctionsAgentProperties } from './agents/OpenAiFunctionsAgent/description';
@ -21,7 +23,6 @@ import { sqlAgentAgentProperties } from './agents/SqlAgent/description';
import { sqlAgentAgentExecute } from './agents/SqlAgent/execute';
import { toolsAgentProperties } from './agents/ToolsAgent/description';
import { toolsAgentExecute } from './agents/ToolsAgent/execute';
import { promptTypeOptions, textFromPreviousNode, textInput } from '../../../utils/descriptions';
// Function used in the inputs expression to figure out which inputs to
// display based on the agent type

View file

@ -1,4 +1,5 @@
import type { INodeProperties } from 'n8n-workflow';
import { SYSTEM_MESSAGE, HUMAN_MESSAGE } from './prompt';
export const conversationalAgentProperties: INodeProperties[] = [

View file

@ -6,14 +6,11 @@ import { CombiningOutputParser } from 'langchain/output_parsers';
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import {
isChatInstance,
getPromptInputByType,
getConnectedTools,
} from '../../../../../utils/helpers';
import { getOptionalOutputParsers } from '../../../../../utils/output_parsers/N8nOutputParser';
import { throwIfToolSchema } from '../../../../../utils/schemaParsing';
import { getTracingConfig } from '../../../../../utils/tracing';
import { isChatInstance, getPromptInputByType, getConnectedTools } from '@utils/helpers';
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
import { throwIfToolSchema } from '@utils/schemaParsing';
import { getTracingConfig } from '@utils/tracing';
import { checkForStructuredTools, extractParsedOutput } from '../utils';
export async function conversationalAgentExecute(

View file

@ -1,4 +1,5 @@
import type { INodeProperties } from 'n8n-workflow';
import { SYSTEM_MESSAGE } from './prompt';
export const openAiFunctionsAgentProperties: INodeProperties[] = [

View file

@ -12,9 +12,10 @@ import {
NodeOperationError,
} from 'n8n-workflow';
import { getConnectedTools, getPromptInputByType } from '../../../../../utils/helpers';
import { getOptionalOutputParsers } from '../../../../../utils/output_parsers/N8nOutputParser';
import { getTracingConfig } from '../../../../../utils/tracing';
import { getConnectedTools, getPromptInputByType } from '@utils/helpers';
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
import { getTracingConfig } from '@utils/tracing';
import { extractParsedOutput } from '../utils';
export async function openAiFunctionsAgentExecute(

View file

@ -1,4 +1,5 @@
import type { INodeProperties } from 'n8n-workflow';
import { DEFAULT_STEP_EXECUTOR_HUMAN_CHAT_MESSAGE_TEMPLATE } from './prompt';
export const planAndExecuteAgentProperties: INodeProperties[] = [

View file

@ -10,10 +10,11 @@ import {
NodeOperationError,
} from 'n8n-workflow';
import { getConnectedTools, getPromptInputByType } from '../../../../../utils/helpers';
import { getOptionalOutputParsers } from '../../../../../utils/output_parsers/N8nOutputParser';
import { throwIfToolSchema } from '../../../../../utils/schemaParsing';
import { getTracingConfig } from '../../../../../utils/tracing';
import { getConnectedTools, getPromptInputByType } from '@utils/helpers';
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
import { throwIfToolSchema } from '@utils/schemaParsing';
import { getTracingConfig } from '@utils/tracing';
import { checkForStructuredTools, extractParsedOutput } from '../utils';
export async function planAndExecuteAgentExecute(

View file

@ -1,4 +1,5 @@
import type { INodeProperties } from 'n8n-workflow';
import { HUMAN_MESSAGE_TEMPLATE, PREFIX, SUFFIX, SUFFIX_CHAT } from './prompt';
export const reActAgentAgentProperties: INodeProperties[] = [

View file

@ -11,14 +11,11 @@ import {
NodeOperationError,
} from 'n8n-workflow';
import {
getConnectedTools,
getPromptInputByType,
isChatInstance,
} from '../../../../../utils/helpers';
import { getOptionalOutputParsers } from '../../../../../utils/output_parsers/N8nOutputParser';
import { throwIfToolSchema } from '../../../../../utils/schemaParsing';
import { getTracingConfig } from '../../../../../utils/tracing';
import { getConnectedTools, getPromptInputByType, isChatInstance } from '@utils/helpers';
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
import { throwIfToolSchema } from '@utils/schemaParsing';
import { getTracingConfig } from '@utils/tracing';
import { checkForStructuredTools, extractParsedOutput } from '../utils';
export async function reActAgentAgentExecute(

View file

@ -1,11 +1,8 @@
import type { INodeProperties } from 'n8n-workflow';
import { promptTypeOptions, textFromPreviousNode, textInput } from '@utils/descriptions';
import { SQL_PREFIX, SQL_SUFFIX } from './other/prompts';
import {
promptTypeOptions,
textFromPreviousNode,
textInput,
} from '../../../../../utils/descriptions';
const dataSourceOptions: INodeProperties = {
displayName: 'Data Source',

View file

@ -12,12 +12,13 @@ import {
type IDataObject,
} from 'n8n-workflow';
import { getPromptInputByType, serializeChatHistory } from '@utils/helpers';
import { getTracingConfig } from '@utils/tracing';
import { getMysqlDataSource } from './other/handlers/mysql';
import { getPostgresDataSource } from './other/handlers/postgres';
import { getSqliteDataSource } from './other/handlers/sqlite';
import { SQL_PREFIX, SQL_SUFFIX } from './other/prompts';
import { getPromptInputByType, serializeChatHistory } from '../../../../../utils/helpers';
import { getTracingConfig } from '../../../../../utils/tracing';
const parseTablesString = (tablesString: string) =>
tablesString

View file

@ -1,5 +1,5 @@
import { type IExecuteFunctions } from 'n8n-workflow';
import { DataSource } from '@n8n/typeorm';
import { type IExecuteFunctions } from 'n8n-workflow';
export async function getMysqlDataSource(this: IExecuteFunctions): Promise<DataSource> {
const credentials = await this.getCredentials('mySql');

View file

@ -1,5 +1,5 @@
import { type IExecuteFunctions } from 'n8n-workflow';
import { DataSource } from '@n8n/typeorm';
import { type IExecuteFunctions } from 'n8n-workflow';
export async function getPostgresDataSource(this: IExecuteFunctions): Promise<DataSource> {
const credentials = await this.getCredentials('postgres');

View file

@ -1,9 +1,9 @@
import { DataSource } from '@n8n/typeorm';
import * as fs from 'fs';
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { BINARY_ENCODING, NodeOperationError } from 'n8n-workflow';
import * as temp from 'temp';
import * as sqlite3 from 'sqlite3';
import { DataSource } from '@n8n/typeorm';
import * as temp from 'temp';
export async function getSqliteDataSource(
this: IExecuteFunctions,

View file

@ -1,4 +1,5 @@
import type { INodeProperties } from 'n8n-workflow';
import { SYSTEM_MESSAGE } from './prompt';
export const toolsAgentProperties: INodeProperties[] = [

View file

@ -14,16 +14,13 @@ import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import type { ZodObject } from 'zod';
import { z } from 'zod';
import { SYSTEM_MESSAGE } from './prompt';
import {
isChatInstance,
getPromptInputByType,
getConnectedTools,
} from '../../../../../utils/helpers';
import { isChatInstance, getPromptInputByType, getConnectedTools } from '@utils/helpers';
import {
getOptionalOutputParsers,
type N8nOutputParser,
} from '../../../../../utils/output_parsers/N8nOutputParser';
} from '@utils/output_parsers/N8nOutputParser';
import { SYSTEM_MESSAGE } from './prompt';
function getOutputParserSchema(outputParser: N8nOutputParser): ZodObject<any, any, any, any> {
const schema =
@ -33,7 +30,7 @@ function getOutputParserSchema(outputParser: N8nOutputParser): ZodObject<any, an
}
async function extractBinaryMessages(ctx: IExecuteFunctions) {
const binaryData = ctx.getInputData(0, 'main')?.[0]?.binary ?? {};
const binaryData = ctx.getInputData()?.[0]?.binary ?? {};
const binaryMessages = await Promise.all(
Object.values(binaryData)
.filter((data) => data.mimeType.startsWith('image/'))
@ -260,7 +257,7 @@ export async function toolsAgentExecute(this: IExecuteFunctions): Promise<INodeE
['human', '{input}'],
];
const hasBinaryData = this.getInputData(0, 'main')?.[0]?.binary !== undefined;
const hasBinaryData = this.getInputData()?.[0]?.binary !== undefined;
if (hasBinaryData && passthroughBinaryImages) {
const binaryMessage = await extractBinaryMessages(this);
messages.push(binaryMessage);

View file

@ -1,7 +1,7 @@
import type { z } from 'zod';
import type { BaseOutputParser } from '@langchain/core/output_parsers';
import type { DynamicStructuredTool, Tool } from 'langchain/tools';
import { NodeOperationError, type IExecuteFunctions, type INode } from 'n8n-workflow';
import type { z } from 'zod';
type ZodObjectAny = z.ZodObject<any, any, any, any>;

View file

@ -10,9 +10,10 @@ import type {
} from 'n8n-workflow';
import { OpenAI as OpenAIClient } from 'openai';
import { getConnectedTools } from '@utils/helpers';
import { getTracingConfig } from '@utils/tracing';
import { formatToOpenAIAssistantTool } from './utils';
import { getConnectedTools } from '../../../utils/helpers';
import { getTracingConfig } from '../../../utils/tracing';
export class OpenAiAssistant implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,6 +1,6 @@
import { zodToJsonSchema } from 'zod-to-json-schema';
import type { OpenAIClient } from '@langchain/openai';
import type { StructuredTool } from '@langchain/core/tools';
import type { OpenAIClient } from '@langchain/openai';
import { zodToJsonSchema } from 'zod-to-json-schema';
// Copied from langchain(`langchain/src/tools/convert_to_openai.ts`)
// since these functions are not exported

View file

@ -27,16 +27,17 @@ import {
NodeOperationError,
} from 'n8n-workflow';
import { getPromptInputByType, isChatInstance } from '../../../utils/helpers';
import type { N8nOutputParser } from '../../../utils/output_parsers/N8nOutputParser';
import { getOptionalOutputParsers } from '../../../utils/output_parsers/N8nOutputParser';
import { getTemplateNoticeField } from '../../../utils/sharedFields';
import { getTracingConfig } from '../../../utils/tracing';
import { promptTypeOptions, textFromPreviousNode } from '@utils/descriptions';
import { getPromptInputByType, isChatInstance } from '@utils/helpers';
import type { N8nOutputParser } from '@utils/output_parsers/N8nOutputParser';
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
import { getTemplateNoticeField } from '@utils/sharedFields';
import { getTracingConfig } from '@utils/tracing';
import {
getCustomErrorMessage as getCustomOpenAiErrorMessage,
isOpenAiError,
} from '../../vendors/OpenAi/helpers/error-handling';
import { promptTypeOptions, textFromPreviousNode } from '../../../utils/descriptions';
interface MessagesTemplate {
type: string;

View file

@ -16,10 +16,10 @@ import {
NodeOperationError,
} from 'n8n-workflow';
import { promptTypeOptions, textFromPreviousNode } from '../../../utils/descriptions';
import { getPromptInputByType, isChatInstance } from '../../../utils/helpers';
import { getTemplateNoticeField } from '../../../utils/sharedFields';
import { getTracingConfig } from '../../../utils/tracing';
import { promptTypeOptions, textFromPreviousNode } from '@utils/descriptions';
import { getPromptInputByType, isChatInstance } from '@utils/helpers';
import { getTemplateNoticeField } from '@utils/sharedFields';
import { getTracingConfig } from '@utils/tracing';
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.

View file

@ -1,3 +1,8 @@
import type { Document } from '@langchain/core/documents';
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import { PromptTemplate } from '@langchain/core/prompts';
import type { SummarizationChainParams } from 'langchain/chains';
import { loadSummarizationChain } from 'langchain/chains';
import {
NodeConnectionType,
type INodeTypeBaseDescription,
@ -7,14 +12,10 @@ import {
type INodeTypeDescription,
} from 'n8n-workflow';
import type { SummarizationChainParams } from 'langchain/chains';
import { loadSummarizationChain } from 'langchain/chains';
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import type { Document } from '@langchain/core/documents';
import { PromptTemplate } from '@langchain/core/prompts';
import { N8nJsonLoader } from '../../../../utils/N8nJsonLoader';
import { N8nBinaryLoader } from '../../../../utils/N8nBinaryLoader';
import { getTemplateNoticeField } from '../../../../utils/sharedFields';
import { N8nBinaryLoader } from '@utils/N8nBinaryLoader';
import { N8nJsonLoader } from '@utils/N8nJsonLoader';
import { getTemplateNoticeField } from '@utils/sharedFields';
import { REFINE_PROMPT_TEMPLATE, DEFAULT_PROMPT_TEMPLATE } from '../prompt';
export class ChainSummarizationV1 implements INodeType {

View file

@ -1,4 +1,8 @@
import { NodeConnectionType } from 'n8n-workflow';
import type { Document } from '@langchain/core/documents';
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import type { TextSplitter } from '@langchain/textsplitters';
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
import { loadSummarizationChain } from 'langchain/chains';
import type {
INodeTypeBaseDescription,
IExecuteFunctions,
@ -7,18 +11,15 @@ import type {
INodeTypeDescription,
IDataObject,
} from 'n8n-workflow';
import { NodeConnectionType } from 'n8n-workflow';
import { N8nBinaryLoader } from '@utils/N8nBinaryLoader';
import { N8nJsonLoader } from '@utils/N8nJsonLoader';
import { getTemplateNoticeField } from '@utils/sharedFields';
import { getTracingConfig } from '@utils/tracing';
import { loadSummarizationChain } from 'langchain/chains';
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import type { Document } from '@langchain/core/documents';
import type { TextSplitter } from '@langchain/textsplitters';
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
import { N8nJsonLoader } from '../../../../utils/N8nJsonLoader';
import { N8nBinaryLoader } from '../../../../utils/N8nBinaryLoader';
import { getTemplateNoticeField } from '../../../../utils/sharedFields';
import { REFINE_PROMPT_TEMPLATE, DEFAULT_PROMPT_TEMPLATE } from '../prompt';
import { getChainPromptsArgs } from '../helpers';
import { getTracingConfig } from '../../../../utils/tracing';
import { REFINE_PROMPT_TEMPLATE, DEFAULT_PROMPT_TEMPLATE } from '../prompt';
function getInputs(parameters: IDataObject) {
const chunkingMode = parameters?.chunkingMode;

View file

@ -1,5 +1,5 @@
import type { SummarizationChainParams } from 'langchain/chains';
import { PromptTemplate } from '@langchain/core/prompts';
import type { SummarizationChainParams } from 'langchain/chains';
interface ChainTypeOptions {
combineMapPrompt?: string;
prompt?: string;

View file

@ -13,15 +13,12 @@ import type {
} from 'n8n-workflow';
import type { z } from 'zod';
import { inputSchemaField, jsonSchemaExampleField, schemaTypeField } from '@utils/descriptions';
import { convertJsonSchemaToZod, generateSchema } from '@utils/schemaParsing';
import { getTracingConfig } from '@utils/tracing';
import { makeZodSchemaFromAttributes } from './helpers';
import type { AttributeDefinition } from './types';
import {
inputSchemaField,
jsonSchemaExampleField,
schemaTypeField,
} from '../../../utils/descriptions';
import { convertJsonSchemaToZod, generateSchema } from '../../../utils/schemaParsing';
import { getTracingConfig } from '../../../utils/tracing';
const SYSTEM_PROMPT_TEMPLATE = `You are an expert extraction algorithm.
Only extract relevant information from the text.

View file

@ -1,4 +1,5 @@
import { z } from 'zod';
import type { AttributeDefinition } from './types';
function makeAttributeSchema(attributeDefinition: AttributeDefinition, required: boolean = true) {

View file

@ -1,10 +1,10 @@
import type { IDataObject, IExecuteFunctions } from 'n8n-workflow/src';
import get from 'lodash/get';
import { FakeLLM, FakeListChatModel } from '@langchain/core/utils/testing';
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import { InformationExtractor } from '../InformationExtractor.node';
import { FakeLLM, FakeListChatModel } from '@langchain/core/utils/testing';
import get from 'lodash/get';
import type { IDataObject, IExecuteFunctions } from 'n8n-workflow/src';
import { makeZodSchemaFromAttributes } from '../helpers';
import { InformationExtractor } from '../InformationExtractor.node';
import type { AttributeDefinition } from '../types';
const mockPersonAttributes: AttributeDefinition[] = [

View file

@ -1,3 +1,8 @@
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import { HumanMessage } from '@langchain/core/messages';
import { SystemMessagePromptTemplate, ChatPromptTemplate } from '@langchain/core/prompts';
import { OutputFixingParser, StructuredOutputParser } from 'langchain/output_parsers';
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import type {
IDataObject,
IExecuteFunctions,
@ -6,15 +11,9 @@ import type {
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
import { HumanMessage } from '@langchain/core/messages';
import { SystemMessagePromptTemplate, ChatPromptTemplate } from '@langchain/core/prompts';
import { OutputFixingParser, StructuredOutputParser } from 'langchain/output_parsers';
import { z } from 'zod';
import { getTracingConfig } from '../../../utils/tracing';
import { getTracingConfig } from '@utils/tracing';
const DEFAULT_SYSTEM_PROMPT_TEMPLATE =
'You are highly intelligent and accurate sentiment analyzer. Analyze the sentiment of the provided text. Categorize it into one of the following: {categories}. Use the provided formatting instructions. Only output the JSON.';

View file

@ -13,7 +13,7 @@ import type {
} from 'n8n-workflow';
import { z } from 'zod';
import { getTracingConfig } from '../../../utils/tracing';
import { getTracingConfig } from '@utils/tracing';
const SYSTEM_PROMPT_TEMPLATE =
"Please classify the text provided by the user into one of the following categories: {categories}, and use the provided formatting instructions below. Don't explain, and only output the json.";

View file

@ -1,4 +1,9 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { Tool } from '@langchain/core/tools';
import { makeResolverFromLegacyOptions } from '@n8n/vm2';
import { JavaScriptSandbox } from 'n8n-nodes-base/dist/nodes/Code/JavaScriptSandbox';
import { getSandboxContext } from 'n8n-nodes-base/dist/nodes/Code/Sandbox';
import { standardizeOutput } from 'n8n-nodes-base/dist/nodes/Code/utils';
import { NodeOperationError, NodeConnectionType } from 'n8n-workflow';
import type {
IExecuteFunctions,
@ -12,12 +17,7 @@ import type {
// TODO: Add support for execute function. Got already started but got commented out
import { getSandboxContext } from 'n8n-nodes-base/dist/nodes/Code/Sandbox';
import { JavaScriptSandbox } from 'n8n-nodes-base/dist/nodes/Code/JavaScriptSandbox';
import { standardizeOutput } from 'n8n-nodes-base/dist/nodes/Code/utils';
import type { Tool } from '@langchain/core/tools';
import { makeResolverFromLegacyOptions } from '@n8n/vm2';
import { logWrapper } from '../../utils/logWrapper';
import { logWrapper } from '@utils/logWrapper';
const { NODE_FUNCTION_ALLOW_BUILTIN: builtIn, NODE_FUNCTION_ALLOW_EXTERNAL: external } =
process.env;

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { TextSplitter } from '@langchain/textsplitters';
import {
NodeConnectionType,
type INodeType,
@ -7,11 +8,9 @@ import {
type SupplyData,
} from 'n8n-workflow';
import type { TextSplitter } from '@langchain/textsplitters';
import { logWrapper } from '../../../utils/logWrapper';
import { N8nBinaryLoader } from '../../../utils/N8nBinaryLoader';
import { getConnectionHintNoticeField, metadataFilterField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { N8nBinaryLoader } from '@utils/N8nBinaryLoader';
import { getConnectionHintNoticeField, metadataFilterField } from '@utils/sharedFields';
// Dependencies needed underneath the hood for the loaders. We add them
// here only to track where what dependency is sued

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { TextSplitter } from '@langchain/textsplitters';
import {
NodeConnectionType,
type INodeType,
@ -7,10 +8,9 @@ import {
type SupplyData,
} from 'n8n-workflow';
import type { TextSplitter } from '@langchain/textsplitters';
import { logWrapper } from '../../../utils/logWrapper';
import { N8nBinaryLoader } from '../../../utils/N8nBinaryLoader';
import { metadataFilterField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { N8nBinaryLoader } from '@utils/N8nBinaryLoader';
import { metadataFilterField } from '@utils/sharedFields';
// Dependencies needed underneath the hood for the loaders. We add them
// here only to track where what dependency is sued
@ -18,7 +18,7 @@ import { metadataFilterField } from '../../../utils/sharedFields';
import 'mammoth'; // for docx
import 'epub2'; // for epub
import 'pdf-parse'; // for pdf
import { N8nJsonLoader } from '../../../utils/N8nJsonLoader';
import { N8nJsonLoader } from '@utils/N8nJsonLoader';
export class DocumentDefaultDataLoader implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,6 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { GithubRepoLoader } from '@langchain/community/document_loaders/web/github';
import type { CharacterTextSplitter } from '@langchain/textsplitters';
import {
NodeConnectionType,
type INodeType,
@ -6,10 +8,9 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { GithubRepoLoader } from '@langchain/community/document_loaders/web/github';
import type { CharacterTextSplitter } from '@langchain/textsplitters';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class DocumentGithubLoader implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { TextSplitter } from '@langchain/textsplitters';
import {
NodeConnectionType,
type INodeType,
@ -7,10 +8,9 @@ import {
type SupplyData,
} from 'n8n-workflow';
import type { TextSplitter } from '@langchain/textsplitters';
import { logWrapper } from '../../../utils/logWrapper';
import { N8nJsonLoader } from '../../../utils/N8nJsonLoader';
import { getConnectionHintNoticeField, metadataFilterField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { N8nJsonLoader } from '@utils/N8nJsonLoader';
import { getConnectionHintNoticeField, metadataFilterField } from '@utils/sharedFields';
export class DocumentJsonInputLoader implements INodeType {
description: INodeTypeDescription = {

View file

@ -8,8 +8,8 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class EmbeddingsAwsBedrock implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { OpenAIEmbeddings } from '@langchain/openai';
import {
NodeConnectionType,
type INodeType,
@ -7,9 +8,8 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { OpenAIEmbeddings } from '@langchain/openai';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class EmbeddingsAzureOpenAi implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { CohereEmbeddings } from '@langchain/cohere';
import {
NodeConnectionType,
type INodeType,
@ -6,9 +7,9 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { CohereEmbeddings } from '@langchain/cohere';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class EmbeddingsCohere implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { GoogleGenerativeAIEmbeddings } from '@langchain/google-genai';
import {
NodeConnectionType,
type INodeType,
@ -6,10 +7,9 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { GoogleGenerativeAIEmbeddings } from '@langchain/google-genai';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class EmbeddingsGoogleGemini implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { HuggingFaceInferenceEmbeddings } from '@langchain/community/embeddings/hf';
import {
NodeConnectionType,
type INodeType,
@ -6,9 +7,9 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { HuggingFaceInferenceEmbeddings } from '@langchain/community/embeddings/hf';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class EmbeddingsHuggingFaceInference implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,6 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { MistralAIEmbeddingsParams } from '@langchain/mistralai';
import { MistralAIEmbeddings } from '@langchain/mistralai';
import {
NodeConnectionType,
type INodeType,
@ -6,10 +8,9 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import type { MistralAIEmbeddingsParams } from '@langchain/mistralai';
import { MistralAIEmbeddings } from '@langchain/mistralai';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class EmbeddingsMistralCloud implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { OllamaEmbeddings } from '@langchain/ollama';
import {
NodeConnectionType,
type INodeType,
@ -6,9 +7,10 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { OllamaEmbeddings } from '@langchain/ollama';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { ollamaDescription, ollamaModel } from '../../llms/LMOllama/description';
export class EmbeddingsOllama implements INodeType {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { OpenAIEmbeddings } from '@langchain/openai';
import {
NodeConnectionType,
type INodeType,
@ -7,11 +8,10 @@ import {
type ISupplyDataFunctions,
type INodeProperties,
} from 'n8n-workflow';
import type { ClientOptions } from 'openai';
import { OpenAIEmbeddings } from '@langchain/openai';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
const modelParameter: INodeProperties = {
displayName: 'Model',

View file

@ -12,9 +12,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
const modelField: INodeProperties = {
displayName: 'Model',

View file

@ -1,4 +1,7 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { ChatOllamaInput } from '@langchain/ollama';
import { ChatOllama } from '@langchain/ollama';
import {
NodeConnectionType,
type INodeType,
@ -7,12 +10,11 @@ import {
type SupplyData,
} from 'n8n-workflow';
import type { ChatOllamaInput } from '@langchain/ollama';
import { ChatOllama } from '@langchain/ollama';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { ollamaModel, ollamaOptions, ollamaDescription } from '../LMOllama/description';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatOllama implements INodeType {
description: INodeTypeDescription = {

View file

@ -9,7 +9,8 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { openAiFailedAttemptHandler } from '../../vendors/OpenAi/helpers/error-handling';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { Cohere } from '@langchain/cohere';
import {
NodeConnectionType,
type INodeType,
@ -7,10 +8,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { Cohere } from '@langchain/cohere';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmCohere implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,6 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { Ollama } from '@langchain/community/llms/ollama';
import {
NodeConnectionType,
type INodeType,
@ -7,11 +9,11 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { Ollama } from '@langchain/community/llms/ollama';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { ollamaDescription, ollamaModel, ollamaOptions } from './description';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmOllama implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { OpenAI, type ClientOptions } from '@langchain/openai';
import { NodeConnectionType } from 'n8n-workflow';
import type {
INodeType,
@ -8,9 +9,8 @@ import type {
ILoadOptionsFunctions,
} from 'n8n-workflow';
import { OpenAI, type ClientOptions } from '@langchain/openai';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
type LmOpenAiOptions = {
baseURL?: string;

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { HuggingFaceInference } from '@langchain/community/llms/hf';
import {
NodeConnectionType,
type INodeType,
@ -7,10 +8,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { HuggingFaceInference } from '@langchain/community/llms/hf';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmOpenHuggingFaceInference implements INodeType {
description: INodeTypeDescription = {

View file

@ -8,9 +8,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatAwsBedrock implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { ChatOpenAI } from '@langchain/openai';
import {
NodeConnectionType,
type INodeType,
@ -7,10 +8,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { ChatOpenAI } from '@langchain/openai';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatAzureOpenAi implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,6 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { SafetySetting } from '@google/generative-ai';
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import {
NodeConnectionType,
type INodeType,
@ -6,12 +8,12 @@ import {
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import type { SafetySetting } from '@google/generative-ai';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { additionalOptions } from '../gemini-common/additional-options';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatGoogleGemini implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,8 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { SafetySetting } from '@google/generative-ai';
import { ProjectsClient } from '@google-cloud/resource-manager';
import { ChatVertexAI } from '@langchain/google-vertexai';
import { formatPrivateKey } from 'n8n-nodes-base/dist/utils/utilities';
import {
NodeConnectionType,
type INodeType,
@ -9,15 +13,13 @@ import {
type JsonObject,
NodeOperationError,
} from 'n8n-workflow';
import { ChatVertexAI } from '@langchain/google-vertexai';
import type { SafetySetting } from '@google/generative-ai';
import { ProjectsClient } from '@google-cloud/resource-manager';
import { formatPrivateKey } from 'n8n-nodes-base/dist/utils/utilities';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { additionalOptions } from '../gemini-common/additional-options';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeErrorFromStatus } from './error-handling';
import { additionalOptions } from '../gemini-common/additional-options';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatGoogleVertex implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,5 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import { ChatGroq } from '@langchain/groq';
import {
NodeConnectionType,
type INodeType,
@ -7,10 +8,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { ChatGroq } from '@langchain/groq';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatGroq implements INodeType {
description: INodeTypeDescription = {

View file

@ -1,4 +1,7 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { ChatMistralAIInput } from '@langchain/mistralai';
import { ChatMistralAI } from '@langchain/mistralai';
import {
NodeConnectionType,
type INodeType,
@ -7,11 +10,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import type { ChatMistralAIInput } from '@langchain/mistralai';
import { ChatMistralAI } from '@langchain/mistralai';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing';
export class LmChatMistralCloud implements INodeType {
description: INodeTypeDescription = {

View file

@ -9,11 +9,11 @@ import type {
import type { BaseMessage } from '@langchain/core/messages';
import type { LLMResult } from '@langchain/core/outputs';
import { encodingForModel } from '@langchain/core/utils/tiktoken';
import type { IDataObject, ISupplyDataFunctions, JsonObject } from 'n8n-workflow';
import { pick } from 'lodash';
import type { IDataObject, ISupplyDataFunctions, JsonObject } from 'n8n-workflow';
import { NodeConnectionType, NodeError, NodeOperationError } from 'n8n-workflow';
import { logAiEvent } from '../../utils/helpers';
import { logAiEvent } from '@utils/helpers';
type TokensUsageParser = (llmOutput: LLMResult['llmOutput']) => {
completionTokens: number;

View file

@ -1,5 +1,6 @@
import type { HarmBlockThreshold, HarmCategory } from '@google/generative-ai';
import type { INodeProperties } from 'n8n-workflow';
import { harmCategories, harmThresholds } from './safety-options';
export const additionalOptions: INodeProperties = {

View file

@ -9,9 +9,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { getSessionId } from '../../../utils/helpers';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getSessionId } from '@utils/helpers';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import {
sessionIdOption,
sessionKeyProperty,

View file

@ -1,4 +1,6 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
import type { BaseMessage } from '@langchain/core/messages';
import {
NodeConnectionType,
type IDataObject,
@ -7,8 +9,6 @@ import {
type INodeType,
type INodeTypeDescription,
} from 'n8n-workflow';
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
import type { BaseMessage } from '@langchain/core/messages';
function simplifyMessages(messages: BaseMessage[]) {
const chunkedMessages = [];

View file

@ -1,4 +1,6 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
import { AIMessage, SystemMessage, HumanMessage, type BaseMessage } from '@langchain/core/messages';
import { NodeConnectionType } from 'n8n-workflow';
import type {
IDataObject,
@ -7,8 +9,6 @@ import type {
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
import { AIMessage, SystemMessage, HumanMessage, type BaseMessage } from '@langchain/core/messages';
type MessageRole = 'ai' | 'system' | 'user';
interface MessageRecord {

View file

@ -8,9 +8,10 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { getSessionId } from '../../../utils/helpers';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getSessionId } from '@utils/helpers';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { expressionSessionKeyProperty, sessionIdOption, sessionKeyProperty } from '../descriptions';
export class MemoryMotorhead implements INodeType {

View file

@ -13,9 +13,10 @@ import type {
import { NodeConnectionType } from 'n8n-workflow';
import type pg from 'pg';
import { getSessionId } from '../../../utils/helpers';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getSessionId } from '@utils/helpers';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import {
sessionIdOption,
sessionKeyProperty,

View file

@ -13,9 +13,10 @@ import {
import type { RedisClientOptions } from 'redis';
import { createClient } from 'redis';
import { getSessionId } from '../../../utils/helpers';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getSessionId } from '@utils/helpers';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import {
sessionIdOption,
sessionKeyProperty,

View file

@ -10,9 +10,10 @@ import type {
SupplyData,
} from 'n8n-workflow';
import { getSessionId } from '../../../utils/helpers';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getSessionId } from '@utils/helpers';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import {
sessionIdOption,
sessionKeyProperty,

View file

@ -1,4 +1,9 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { BaseChatMemory } from '@langchain/community/dist/memory/chat_memory';
import { ZepMemory } from '@langchain/community/memory/zep';
import { ZepCloudMemory } from '@langchain/community/memory/zep_cloud';
import type { InputValues, MemoryVariables } from '@langchain/core/memory';
import type { BaseMessage } from '@langchain/core/messages';
import {
NodeConnectionType,
type ISupplyDataFunctions,
@ -7,16 +12,12 @@ import {
type SupplyData,
NodeOperationError,
} from 'n8n-workflow';
import { ZepMemory } from '@langchain/community/memory/zep';
import { ZepCloudMemory } from '@langchain/community/memory/zep_cloud';
import { logWrapper } from '../../../utils/logWrapper';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { getSessionId } from '@utils/helpers';
import { logWrapper } from '@utils/logWrapper';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { expressionSessionKeyProperty, sessionIdOption, sessionKeyProperty } from '../descriptions';
import { getSessionId } from '../../../utils/helpers';
import type { BaseChatMemory } from '@langchain/community/dist/memory/chat_memory';
import type { InputValues, MemoryVariables } from '@langchain/core/memory';
import type { BaseMessage } from '@langchain/core/messages';
// Extend ZepCloudMemory to trim white space in messages.
class WhiteSpaceTrimmedZepCloudMemory extends ZepCloudMemory {

View file

@ -6,10 +6,10 @@ export const sessionIdOption: INodeProperties = {
type: 'options',
options: [
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
name: 'Take from previous node automatically',
name: 'Connected Chat Trigger Node',
value: 'fromInput',
description: 'Looks for an input field called sessionId',
description:
"Looks for an input field called 'sessionId' that is coming from a directly connected Chat Trigger",
},
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased

View file

@ -8,12 +8,13 @@ import type {
SupplyData,
} from 'n8n-workflow';
import { NAIVE_FIX_PROMPT } from './prompt';
import {
N8nOutputFixingParser,
type N8nStructuredOutputParser,
} from '../../../utils/output_parsers/N8nOutputParser';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
} from '@utils/output_parsers/N8nOutputParser';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
import { NAIVE_FIX_PROMPT } from './prompt';
export class OutputParserAutofixing implements INodeType {
description: INodeTypeDescription = {

View file

@ -11,7 +11,8 @@ import { ApplicationError, NodeConnectionType, NodeOperationError } from 'n8n-wo
import type {
N8nOutputFixingParser,
N8nStructuredOutputParser,
} from '../../../../utils/output_parsers/N8nOutputParser';
} from '@utils/output_parsers/N8nOutputParser';
import { OutputParserAutofixing } from '../OutputParserAutofixing.node';
import { NAIVE_FIX_PROMPT } from '../prompt';

View file

@ -7,8 +7,8 @@ import {
type SupplyData,
} from 'n8n-workflow';
import { N8nItemListOutputParser } from '../../../utils/output_parsers/N8nItemListOutputParser';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nItemListOutputParser } from '@utils/output_parsers/N8nItemListOutputParser';
import { getConnectionHintNoticeField } from '@utils/sharedFields';
export class OutputParserItemList implements INodeType {
description: INodeTypeDescription = {

View file

@ -6,7 +6,8 @@ import {
type IWorkflowDataProxyData,
} from 'n8n-workflow';
import { N8nItemListOutputParser } from '../../../../utils/output_parsers/N8nItemListOutputParser';
import { N8nItemListOutputParser } from '@utils/output_parsers/N8nItemListOutputParser';
import { OutputParserItemList } from '../OutputParserItemList.node';
describe('OutputParserItemList', () => {

Some files were not shown because too many files have changed in this diff Show more