feat: Add AI tool building capabilities (#7336)

Github issue / Community forum post (link here to close automatically):
https://community.n8n.io/t/langchain-memory-chat/23733

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Val <68596159+valya@users.noreply.github.com>
Co-authored-by: Alex Grozav <alex@grozav.com>
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
Co-authored-by: Deborah <deborah@starfallprojects.co.uk>
Co-authored-by: Jesper Bylund <mail@jesperbylund.com>
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
Co-authored-by: Giulio Andreini <andreini@netseven.it>
Co-authored-by: Mason Geloso <Mason.geloso@gmail.com>
Co-authored-by: Mason Geloso <hone@Masons-Mac-mini.local>
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
Jan Oberhauser
2023-11-29 12:13:55 +01:00
committed by GitHub
parent dbfd617ace
commit 87def60979
243 changed files with 21526 additions and 321 deletions

View File

@@ -0,0 +1,164 @@
import WorkflowLMChatModal from '@/components/WorkflowLMChat.vue';
import {
AGENT_NODE_TYPE,
MANUAL_CHAT_TRIGGER_NODE_TYPE,
WORKFLOW_LM_CHAT_MODAL_KEY,
} from '@/constants';
import { createComponentRenderer } from '@/__tests__/render';
import { fireEvent, waitFor } from '@testing-library/vue';
import { uuid } from '@jsplumb/util';
import { createTestNode, createTestWorkflow } from '@/__tests__/mocks';
import { createPinia, setActivePinia } from 'pinia';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useUIStore } from '@/stores/ui.store';
import { useUsersStore } from '@/stores/users.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { testingNodeTypes, mockNodeTypesToArray } from '@/__tests__/defaults';
import { setupServer } from '@/__tests__/server';
const renderComponent = createComponentRenderer(WorkflowLMChatModal, {
props: {
teleported: false,
appendToBody: false,
},
});
async function createPiniaWithAINodes(options = { withConnections: true, withAgentNode: true }) {
const { withConnections, withAgentNode } = options;
const workflowId = uuid();
const workflow = createTestWorkflow({
id: workflowId,
name: 'Test Workflow',
connections: withConnections
? {
'On new manual Chat Message': {
main: [
[
{
node: 'Agent',
type: 'main',
index: 0,
},
],
],
},
}
: {},
active: true,
nodes: [
createTestNode({
name: 'On new manual Chat Message',
type: MANUAL_CHAT_TRIGGER_NODE_TYPE,
}),
...(withAgentNode
? [
createTestNode({
name: 'Agent',
type: AGENT_NODE_TYPE,
}),
]
: []),
],
});
const pinia = createPinia();
setActivePinia(pinia);
const workflowsStore = useWorkflowsStore();
const nodeTypesStore = useNodeTypesStore();
const uiStore = useUIStore();
nodeTypesStore.setNodeTypes(
mockNodeTypesToArray({
[MANUAL_CHAT_TRIGGER_NODE_TYPE]: testingNodeTypes[MANUAL_CHAT_TRIGGER_NODE_TYPE],
[AGENT_NODE_TYPE]: testingNodeTypes[AGENT_NODE_TYPE],
}),
);
workflowsStore.workflow = workflow;
await useSettingsStore().getSettings();
await useUsersStore().loginWithCookie();
uiStore.openModal(WORKFLOW_LM_CHAT_MODAL_KEY);
return pinia;
}
describe('WorkflowLMChatModal', () => {
let server: ReturnType<typeof setupServer>;
beforeAll(() => {
server = setupServer();
});
afterEach(() => {
vi.clearAllMocks();
});
afterAll(() => {
server.shutdown();
});
it('should render correctly when Agent Node not present', async () => {
renderComponent({
pinia: await createPiniaWithAINodes({
withConnections: false,
withAgentNode: false,
}),
});
await waitFor(() =>
expect(document.querySelectorAll('.el-notification')[0]).toHaveTextContent(
'Missing AI node Chat only works when an AI agent or chain is connected to the chat trigger node',
),
);
});
it('should render correctly when Agent Node present but not connected to Manual Chat Node', async () => {
renderComponent({
pinia: await createPiniaWithAINodes({
withConnections: false,
withAgentNode: true,
}),
});
await waitFor(() =>
expect(document.querySelectorAll('.el-notification')[1]).toHaveTextContent(
'Missing AI node Chat only works when an AI agent or chain is connected to the chat trigger node',
),
);
});
it('should render correctly', async () => {
const wrapper = renderComponent({
pinia: await createPiniaWithAINodes(),
});
await waitFor(() =>
expect(wrapper.container.querySelector('.modal-content')).toBeInTheDocument(),
);
expect(wrapper.getByTestId('workflow-lm-chat-dialog')).toBeInTheDocument();
});
it('should send and display chat message', async () => {
const wrapper = renderComponent({
pinia: await createPiniaWithAINodes(),
});
await waitFor(() =>
expect(wrapper.container.querySelector('.modal-content')).toBeInTheDocument(),
);
const chatDialog = wrapper.getByTestId('workflow-lm-chat-dialog');
const chatSendButton = wrapper.getByTestId('workflow-chat-send-button');
const chatInput = wrapper.getByTestId('workflow-chat-input');
await fireEvent.update(chatInput, 'Hello!');
await fireEvent.click(chatSendButton);
await waitFor(() => expect(chatDialog.querySelectorAll('.message')).toHaveLength(1));
expect(chatDialog.querySelector('.message')).toHaveTextContent('Hello!');
});
});