@n8n/chat 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.eslintrc.cjs +0 -41
  2. package/README.md +27 -4
  3. package/build.config.js +21 -0
  4. package/package.json +8 -4
  5. package/resources/images/fullscreen.png +0 -0
  6. package/resources/images/windowed.png +0 -0
  7. package/resources/workflow-manual.json +238 -0
  8. package/resources/workflow.json +38 -212
  9. package/scripts/postbuild.js +20 -0
  10. package/src/App.vue +2 -2
  11. package/src/__stories__/App.stories.ts +3 -3
  12. package/src/__tests__/index.spec.ts +12 -17
  13. package/src/__tests__/utils/create.ts +1 -1
  14. package/src/__tests__/utils/fetch.ts +1 -1
  15. package/src/__tests__/utils/selectors.ts +1 -1
  16. package/src/api/generic.ts +5 -6
  17. package/src/api/message.ts +11 -5
  18. package/src/components/Chat.vue +19 -15
  19. package/src/components/ChatWindow.vue +3 -3
  20. package/src/components/GetStarted.vue +2 -2
  21. package/src/components/GetStartedFooter.vue +2 -2
  22. package/src/components/Input.vue +1 -1
  23. package/src/components/Layout.vue +2 -2
  24. package/src/components/Message.vue +6 -6
  25. package/src/components/MessageTyping.vue +2 -2
  26. package/src/components/MessagesList.vue +4 -4
  27. package/src/composables/useChat.ts +2 -2
  28. package/src/composables/useI18n.ts +1 -1
  29. package/src/composables/useOptions.ts +2 -2
  30. package/src/constants/defaults.ts +5 -1
  31. package/src/constants/symbols.ts +1 -1
  32. package/src/css/_tokens.scss +36 -0
  33. package/src/css/index.scss +1 -0
  34. package/src/event-buses/chatEventBus.ts +1 -1
  35. package/src/index.ts +4 -4
  36. package/src/main.scss +1 -36
  37. package/src/plugins/chat.ts +8 -4
  38. package/src/types/chat.ts +2 -2
  39. package/src/types/options.ts +5 -0
  40. package/tsconfig.json +1 -1
  41. package/vite.config.ts +3 -1
@@ -1,245 +1,77 @@
1
1
  {
2
- "name": "AI Webhook Chat",
2
+ "name": "Hosted n8n AI Chat",
3
3
  "nodes": [
4
- {
5
- "parameters": {
6
- "httpMethod": "POST",
7
- "path": "513107b3-6f3a-4a1e-af21-659f0ed14183",
8
- "responseMode": "responseNode",
9
- "options": {
10
- "domainAllowlist": "*.localhost"
11
- }
12
- },
13
- "id": "51ab2689-647d-4cff-9d6f-0ba4df45e904",
14
- "name": "Webhook",
15
- "type": "n8n-nodes-base.webhook",
16
- "typeVersion": 1,
17
- "position": [
18
- 900,
19
- 200
20
- ],
21
- "webhookId": "513107b3-6f3a-4a1e-af21-659f0ed14183"
22
- },
23
4
  {
24
5
  "parameters": {
25
6
  "options": {}
26
7
  },
27
- "id": "3c7fd563-f610-41fa-b198-7fcf100e2815",
28
- "name": "Chat OpenAI",
8
+ "id": "4c109d13-62a2-4e23-9979-e50201db743d",
9
+ "name": "OpenAI Chat Model",
29
10
  "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
30
11
  "typeVersion": 1,
31
12
  "position": [
32
- 1720,
33
- 620
13
+ 640,
14
+ 540
34
15
  ],
35
16
  "credentials": {
36
17
  "openAiApi": {
37
- "id": "B5Fiv70Adfg6htxn",
38
- "name": "Alex's OpenAI Account"
18
+ "id": "cIIkOhl7tUX1KsL6",
19
+ "name": "OpenAi account"
39
20
  }
40
21
  }
41
22
  },
42
23
  {
43
24
  "parameters": {
44
- "sessionKey": "={{ $json.body.sessionId }}"
25
+ "sessionKey": "={{ $json.sessionId }}"
45
26
  },
46
- "id": "ebc23ffa-3bcf-494f-bcb8-51a5fff91885",
27
+ "id": "b416df7b-4802-462f-8f74-f0a71dc4c0be",
47
28
  "name": "Window Buffer Memory",
48
29
  "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
49
30
  "typeVersion": 1,
50
31
  "position": [
51
- 1920,
52
- 620
53
- ]
54
- },
55
- {
56
- "parameters": {
57
- "simplifyOutput": false
58
- },
59
- "id": "d6721a60-159b-4a93-ac6b-b81e16d9f16f",
60
- "name": "Memory Chat Retriever",
61
- "type": "@n8n/n8n-nodes-langchain.memoryChatRetriever",
62
- "typeVersion": 1,
63
- "position": [
64
- 1780,
65
- -40
32
+ 340,
33
+ 540
66
34
  ]
67
35
  },
68
36
  {
69
37
  "parameters": {
70
- "sessionKey": "={{ $json.body.sessionId }}"
38
+ "text": "={{ $json.chatInput }}",
39
+ "options": {}
71
40
  },
72
- "id": "347edc3a-1dda-4996-b778-dcdc447ecfd8",
73
- "name": "Memory Chat Retriever Window Buffer Memory",
74
- "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
75
- "typeVersion": 1,
41
+ "id": "4de25807-a2ef-4453-900e-e00e0021ecdc",
42
+ "name": "AI Agent",
43
+ "type": "@n8n/n8n-nodes-langchain.agent",
44
+ "typeVersion": 1.1,
76
45
  "position": [
77
- 1800,
78
- 160
46
+ 620,
47
+ 300
79
48
  ]
80
49
  },
81
50
  {
82
51
  "parameters": {
52
+ "public": true,
83
53
  "options": {
84
- "responseCode": 200,
85
- "responseHeaders": {
86
- "entries": [
87
- {
88
- "name": "sessionId",
89
- "value": "={{ $json.body.sessionId }}"
90
- },
91
- {
92
- "name": "Access-Control-Allow-Headers",
93
- "value": "*"
94
- }
95
- ]
96
- }
54
+ "loadPreviousSession": "memory"
97
55
  }
98
56
  },
99
- "id": "d229963e-e2f1-4381-87d2-47043bd6ccc7",
100
- "name": "Respond to Webhook",
101
- "type": "n8n-nodes-base.respondToWebhook",
57
+ "id": "5a9612ae-51c1-4be2-bd8b-8556872d1149",
58
+ "name": "Chat Trigger",
59
+ "type": "@n8n/n8n-nodes-langchain.chatTrigger",
102
60
  "typeVersion": 1,
103
61
  "position": [
104
- 2460,
105
- 220
106
- ]
107
- },
108
- {
109
- "parameters": {
110
- "dataType": "string",
111
- "value1": "={{ $json.body.action }}",
112
- "rules": {
113
- "rules": [
114
- {
115
- "value2": "loadPreviousSession"
116
- },
117
- {
118
- "value2": "sendMessage",
119
- "output": 1
120
- }
121
- ]
122
- }
123
- },
124
- "id": "fc4ad994-5f38-4dce-b1e5-397acc512687",
125
- "name": "Chatbot Action",
126
- "type": "n8n-nodes-base.switch",
127
- "typeVersion": 1,
128
- "position": [
129
- 1320,
130
- 200
131
- ]
132
- },
133
- {
134
- "parameters": {
135
- "jsCode": "const response = { data: [] };\n\nfor (const item of $input.all()) {\n response.data.push(item.json);\n}\n\nreturn {\n json: response,\n pairedItem: 0\n};"
136
- },
137
- "id": "e1a80bdc-411a-42df-88dd-36915b1ae8f4",
138
- "name": "Code",
139
- "type": "n8n-nodes-base.code",
140
- "typeVersion": 2,
141
- "position": [
142
- 2160,
143
- -40
144
- ]
145
- },
146
- {
147
- "parameters": {
148
- "text": "={{ $json.body.message }}",
149
- "options": {}
150
- },
151
- "id": "f28f5c00-c742-41d5-8ddb-f0f59ab111a3",
152
- "name": "Agent",
153
- "type": "@n8n/n8n-nodes-langchain.agent",
154
- "typeVersion": 1,
155
- "position": [
156
- 1780,
157
- 340
158
- ]
159
- },
160
- {
161
- "parameters": {
162
- "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.body = JSON.parse(item.json.body);\n}\n\nreturn $input.all();"
163
- },
164
- "id": "415c071b-18b2-4ac5-8634-e3d939bf36ac",
165
- "name": "Transform request body",
166
- "type": "n8n-nodes-base.code",
167
- "typeVersion": 2,
168
- "position": [
169
- 1120,
170
- 200
171
- ]
62
+ 340,
63
+ 300
64
+ ],
65
+ "webhookId": "f406671e-c954-4691-b39a-66c90aa2f103"
172
66
  }
173
67
  ],
174
68
  "pinData": {},
175
69
  "connections": {
176
- "Webhook": {
177
- "main": [
178
- [
179
- {
180
- "node": "Transform request body",
181
- "type": "main",
182
- "index": 0
183
- }
184
- ]
185
- ]
186
- },
187
- "Memory Chat Retriever": {
188
- "main": [
189
- [
190
- {
191
- "node": "Code",
192
- "type": "main",
193
- "index": 0
194
- }
195
- ]
196
- ]
197
- },
198
- "Memory Chat Retriever Window Buffer Memory": {
199
- "ai_memory": [
200
- [
201
- {
202
- "node": "Memory Chat Retriever",
203
- "type": "ai_memory",
204
- "index": 0
205
- }
206
- ]
207
- ]
208
- },
209
- "Chatbot Action": {
210
- "main": [
211
- [
212
- {
213
- "node": "Memory Chat Retriever",
214
- "type": "main",
215
- "index": 0
216
- }
217
- ],
218
- [
219
- {
220
- "node": "Agent",
221
- "type": "main",
222
- "index": 0
223
- }
224
- ]
225
- ]
226
- },
227
- "Code": {
228
- "main": [
229
- [
230
- {
231
- "node": "Respond to Webhook",
232
- "type": "main",
233
- "index": 0
234
- }
235
- ]
236
- ]
237
- },
238
- "Chat OpenAI": {
70
+ "OpenAI Chat Model": {
239
71
  "ai_languageModel": [
240
72
  [
241
73
  {
242
- "node": "Agent",
74
+ "node": "AI Agent",
243
75
  "type": "ai_languageModel",
244
76
  "index": 0
245
77
  }
@@ -250,29 +82,23 @@
250
82
  "ai_memory": [
251
83
  [
252
84
  {
253
- "node": "Agent",
85
+ "node": "AI Agent",
254
86
  "type": "ai_memory",
255
87
  "index": 0
256
- }
257
- ]
258
- ]
259
- },
260
- "Agent": {
261
- "main": [
262
- [
88
+ },
263
89
  {
264
- "node": "Respond to Webhook",
265
- "type": "main",
90
+ "node": "Chat Trigger",
91
+ "type": "ai_memory",
266
92
  "index": 0
267
93
  }
268
94
  ]
269
95
  ]
270
96
  },
271
- "Transform request body": {
97
+ "Chat Trigger": {
272
98
  "main": [
273
99
  [
274
100
  {
275
- "node": "Chatbot Action",
101
+ "node": "AI Agent",
276
102
  "type": "main",
277
103
  "index": 0
278
104
  }
@@ -284,8 +110,8 @@
284
110
  "settings": {
285
111
  "executionOrder": "v1"
286
112
  },
287
- "versionId": "12c145a2-74bf-48b5-a87a-ba707949eaed",
288
- "id": "L3FlJuFOxZcHtoFT",
113
+ "versionId": "6076136f-fdb4-48d9-b483-d1c24c95ef9e",
114
+ "id": "zaBHnDtj22BzEQ6K",
289
115
  "meta": {
290
116
  "instanceId": "374b43d8b8d6299cc777811a4ad220fc688ee2d54a308cfb0de4450a5233ca9e"
291
117
  },
@@ -1,9 +1,13 @@
1
1
  const path = require('path');
2
2
  const shelljs = require('shelljs');
3
+ const glob = require('fast-glob');
3
4
 
4
5
  const rootDirPath = path.resolve(__dirname, '..');
5
6
  const n8nRootDirPath = path.resolve(rootDirPath, '..', '..', '..');
6
7
  const distDirPath = path.resolve(rootDirPath, 'dist');
8
+ const srcDirPath = path.resolve(rootDirPath, 'src');
9
+ const libDirPath = path.resolve(rootDirPath, 'tmp', 'lib');
10
+ const cjsDirPath = path.resolve(rootDirPath, 'tmp', 'cjs');
7
11
 
8
12
  const packageJsonFilePath = path.resolve(rootDirPath, 'package.json');
9
13
  const readmeFilePath = path.resolve(rootDirPath, 'README.md');
@@ -14,3 +18,19 @@ shelljs.cp(readmeFilePath, distDirPath);
14
18
  shelljs.cp(licenseFilePath, distDirPath);
15
19
 
16
20
  shelljs.mv(path.resolve(distDirPath, 'src'), path.resolve(distDirPath, 'types'));
21
+
22
+ function moveFiles(files, from, to) {
23
+ files.forEach((file) => {
24
+ const toFile = file.replace(from, to);
25
+ shelljs.mkdir('-p', path.dirname(toFile));
26
+ shelljs.mv(file, toFile);
27
+ });
28
+ }
29
+
30
+ const cjsFiles = glob.sync(path.resolve(cjsDirPath, '**', '*'));
31
+ moveFiles(cjsFiles, 'tmp/cjs', 'dist');
32
+ shelljs.rm('-rf', cjsDirPath);
33
+
34
+ const libFiles = glob.sync(path.resolve(libDirPath, '**/*'));
35
+ moveFiles(libFiles, 'tmp/lib', 'dist');
36
+ shelljs.rm('-rf', libDirPath);
package/src/App.vue CHANGED
@@ -1,10 +1,10 @@
1
1
  <script lang="ts" setup>
2
- import { Chat, ChatWindow } from '@/components';
3
2
  import { computed, onMounted } from 'vue';
4
3
  import hljs from 'highlight.js/lib/core';
5
4
  import hljsXML from 'highlight.js/lib/languages/xml';
6
5
  import hljsJavascript from 'highlight.js/lib/languages/javascript';
7
- import { useOptions } from '@/composables';
6
+ import { Chat, ChatWindow } from '@n8n/chat/components';
7
+ import { useOptions } from '@n8n/chat/composables';
8
8
 
9
9
  defineProps({});
10
10
 
@@ -1,10 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/naming-convention */
2
2
  import type { StoryObj } from '@storybook/vue3';
3
- import type { ChatOptions } from '@/types';
4
- import { createChat } from '@/index';
5
3
  import { onMounted } from 'vue';
4
+ import type { ChatOptions } from '@n8n/chat/types';
5
+ import { createChat } from '@n8n/chat/index';
6
6
 
7
- const webhookUrl = 'http://localhost:5678/webhook/513107b3-6f3a-4a1e-af21-659f0ed14183';
7
+ const webhookUrl = 'http://localhost:5678/webhook/f406671e-c954-4691-b39a-66c90aa2f103/chat';
8
8
 
9
9
  const meta = {
10
10
  title: 'Chat',
@@ -14,9 +14,8 @@ import {
14
14
  getChatWrapper,
15
15
  getGetStartedButton,
16
16
  getMountingTarget,
17
- } from '@/__tests__/utils';
18
- import { createChat } from '@/index';
19
- import { useChat } from '@/composables';
17
+ } from '@n8n/chat/__tests__/utils';
18
+ import { createChat } from '@n8n/chat/index';
20
19
 
21
20
  describe('createChat()', () => {
22
21
  let app: ReturnType<typeof createChat>;
@@ -77,6 +76,7 @@ describe('createChat()', () => {
77
76
 
78
77
  app = createChat({
79
78
  mode: 'fullscreen',
79
+ showWelcomeScreen: true,
80
80
  });
81
81
 
82
82
  const getStartedButton = getGetStartedButton();
@@ -85,7 +85,9 @@ describe('createChat()', () => {
85
85
  expect(fetchSpy.mock.calls[0][1]).toEqual(
86
86
  expect.objectContaining({
87
87
  method: 'POST',
88
- headers: {},
88
+ headers: {
89
+ 'Content-Type': 'application/json',
90
+ },
89
91
  body: expect.stringContaining('"action":"loadPreviousSession"') as unknown,
90
92
  mode: 'cors',
91
93
  cache: 'no-cache',
@@ -112,9 +114,6 @@ describe('createChat()', () => {
112
114
  await fireEvent.click(trigger as HTMLElement);
113
115
  }
114
116
 
115
- const getStartedButton = getGetStartedButton();
116
- await fireEvent.click(getStartedButton as HTMLElement);
117
-
118
117
  expect(getChatMessages().length).toBe(initialMessages.length);
119
118
  expect(getChatMessageByText(initialMessages[0])).toBeInTheDocument();
120
119
  expect(getChatMessageByText(initialMessages[1])).toBeInTheDocument();
@@ -144,12 +143,10 @@ describe('createChat()', () => {
144
143
  }
145
144
 
146
145
  expect(getChatMessageTyping()).not.toBeInTheDocument();
147
-
148
- const getStartedButton = getGetStartedButton();
149
- await fireEvent.click(getStartedButton as HTMLElement);
150
-
151
146
  expect(getChatMessages().length).toBe(2);
152
147
 
148
+ await waitFor(() => expect(getChatInputTextarea()).toBeInTheDocument());
149
+
153
150
  const textarea = getChatInputTextarea();
154
151
  const sendButton = getChatInputSendButton();
155
152
  await fireEvent.update(textarea as HTMLElement, input);
@@ -159,7 +156,9 @@ describe('createChat()', () => {
159
156
  expect(fetchSpy.mock.calls[1][1]).toEqual(
160
157
  expect.objectContaining({
161
158
  method: 'POST',
162
- headers: {},
159
+ headers: {
160
+ 'Content-Type': 'application/json',
161
+ },
163
162
  body: expect.stringMatching(/"action":"sendMessage"/) as unknown,
164
163
  mode: 'cors',
165
164
  cache: 'no-cache',
@@ -182,9 +181,6 @@ describe('createChat()', () => {
182
181
  const input = 'Teach me javascript!';
183
182
  const output = '# Code\n```js\nconsole.log("Hello World!");\n```';
184
183
 
185
- const chatStore = useChat();
186
- console.log(chatStore);
187
-
188
184
  const fetchSpy = vi.spyOn(window, 'fetch');
189
185
  fetchSpy
190
186
  .mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse))
@@ -199,8 +195,7 @@ describe('createChat()', () => {
199
195
  await fireEvent.click(trigger as HTMLElement);
200
196
  }
201
197
 
202
- const getStartedButton = getGetStartedButton();
203
- await fireEvent.click(getStartedButton as HTMLElement);
198
+ await waitFor(() => expect(getChatInputTextarea()).toBeInTheDocument());
204
199
 
205
200
  const textarea = getChatInputTextarea();
206
201
  const sendButton = getChatInputSendButton();
@@ -1,4 +1,4 @@
1
- import { createChat } from '@/index';
1
+ import { createChat } from '@n8n/chat/index';
2
2
 
3
3
  export function createTestChat(options: Parameters<typeof createChat>[0] = {}): {
4
4
  unmount: () => void;
@@ -1,4 +1,4 @@
1
- import type { LoadPreviousSessionResponse, SendMessageResponse } from '@/types';
1
+ import type { LoadPreviousSessionResponse, SendMessageResponse } from '@n8n/chat/types';
2
2
 
3
3
  export function createFetchResponse<T>(data: T) {
4
4
  return async () =>
@@ -1,5 +1,5 @@
1
1
  import { screen } from '@testing-library/vue';
2
- import { defaultMountingTarget } from '@/constants';
2
+ import { defaultMountingTarget } from '@n8n/chat/constants';
3
3
 
4
4
  export function getMountingTarget(target = defaultMountingTarget) {
5
5
  return document.querySelector(target);
@@ -10,6 +10,7 @@ export async function authenticatedFetch<T>(...args: Parameters<typeof fetch>):
10
10
  mode: 'cors',
11
11
  cache: 'no-cache',
12
12
  headers: {
13
+ 'Content-Type': 'application/json',
13
14
  ...(accessToken ? { authorization: `Bearer ${accessToken}` } : {}),
14
15
  ...args[1]?.headers,
15
16
  },
@@ -18,14 +19,12 @@ export async function authenticatedFetch<T>(...args: Parameters<typeof fetch>):
18
19
  return (await response.json()) as Promise<T>;
19
20
  }
20
21
 
21
- export async function get<T>(
22
- url: string,
23
- query: Record<string, string> = {},
24
- options: RequestInit = {},
25
- ) {
22
+ export async function get<T>(url: string, query: object = {}, options: RequestInit = {}) {
26
23
  let resolvedUrl = url;
27
24
  if (Object.keys(query).length > 0) {
28
- resolvedUrl = `${resolvedUrl}?${new URLSearchParams(query).toString()}`;
25
+ resolvedUrl = `${resolvedUrl}?${new URLSearchParams(
26
+ query as Record<string, string>,
27
+ ).toString()}`;
29
28
  }
30
29
 
31
30
  return authenticatedFetch<T>(resolvedUrl, { ...options, method: 'GET' });
@@ -1,5 +1,9 @@
1
- import { get, post } from '@/api/generic';
2
- import type { ChatOptions, LoadPreviousSessionResponse, SendMessageResponse } from '@/types';
1
+ import { get, post } from '@n8n/chat/api/generic';
2
+ import type {
3
+ ChatOptions,
4
+ LoadPreviousSessionResponse,
5
+ SendMessageResponse,
6
+ } from '@n8n/chat/types';
3
7
 
4
8
  export async function loadPreviousSession(sessionId: string, options: ChatOptions) {
5
9
  const method = options.webhookConfig?.method === 'POST' ? post : get;
@@ -7,7 +11,8 @@ export async function loadPreviousSession(sessionId: string, options: ChatOption
7
11
  `${options.webhookUrl}`,
8
12
  {
9
13
  action: 'loadPreviousSession',
10
- sessionId,
14
+ [options.chatSessionKey as string]: sessionId,
15
+ ...(options.metadata ? { metadata: options.metadata } : {}),
11
16
  },
12
17
  {
13
18
  headers: options.webhookConfig?.headers,
@@ -21,8 +26,9 @@ export async function sendMessage(message: string, sessionId: string, options: C
21
26
  `${options.webhookUrl}`,
22
27
  {
23
28
  action: 'sendMessage',
24
- sessionId,
25
- message,
29
+ [options.chatSessionKey as string]: sessionId,
30
+ [options.chatInputKey as string]: message,
31
+ ...(options.metadata ? { metadata: options.metadata } : {}),
26
32
  },
27
33
  {
28
34
  headers: options.webhookConfig?.headers,
@@ -1,44 +1,48 @@
1
1
  <script setup lang="ts">
2
- import Layout from '@/components/Layout.vue';
3
- import GetStarted from '@/components/GetStarted.vue';
4
- import GetStartedFooter from '@/components/GetStartedFooter.vue';
5
- import MessagesList from '@/components/MessagesList.vue';
6
- import Input from '@/components/Input.vue';
7
2
  import { nextTick, onMounted } from 'vue';
8
- import { useI18n, useChat } from '@/composables';
9
- import { chatEventBus } from '@/event-buses';
3
+ import Layout from '@n8n/chat/components/Layout.vue';
4
+ import GetStarted from '@n8n/chat/components/GetStarted.vue';
5
+ import GetStartedFooter from '@n8n/chat/components/GetStartedFooter.vue';
6
+ import MessagesList from '@n8n/chat/components/MessagesList.vue';
7
+ import Input from '@n8n/chat/components/Input.vue';
8
+ import { useI18n, useChat, useOptions } from '@n8n/chat/composables';
9
+ import { chatEventBus } from '@n8n/chat/event-buses';
10
10
 
11
11
  const { t } = useI18n();
12
12
  const chatStore = useChat();
13
13
 
14
14
  const { messages, currentSessionId } = chatStore;
15
+ const { options } = useOptions();
15
16
 
16
- async function initialize() {
17
- await chatStore.loadPreviousSession();
17
+ async function getStarted() {
18
+ void chatStore.startNewSession();
18
19
  void nextTick(() => {
19
20
  chatEventBus.emit('scrollToBottom');
20
21
  });
21
22
  }
22
23
 
23
- async function getStarted() {
24
- void chatStore.startNewSession();
24
+ async function initialize() {
25
+ await chatStore.loadPreviousSession();
25
26
  void nextTick(() => {
26
27
  chatEventBus.emit('scrollToBottom');
27
28
  });
28
29
  }
29
30
 
30
- onMounted(() => {
31
- void initialize();
31
+ onMounted(async () => {
32
+ await initialize();
33
+ if (!options.showWelcomeScreen && !currentSessionId.value) {
34
+ await getStarted();
35
+ }
32
36
  });
33
37
  </script>
34
38
 
35
39
  <template>
36
40
  <Layout class="chat-wrapper">
37
- <template #header v-if="!currentSessionId">
41
+ <template #header>
38
42
  <h1>{{ t('title') }}</h1>
39
43
  <p>{{ t('subtitle') }}</p>
40
44
  </template>
41
- <GetStarted v-if="!currentSessionId" @click:button="getStarted" />
45
+ <GetStarted v-if="!currentSessionId && options.showWelcomeScreen" @click:button="getStarted" />
42
46
  <MessagesList v-else :messages="messages" />
43
47
  <template #footer>
44
48
  <Input v-if="currentSessionId" />
@@ -3,9 +3,9 @@
3
3
  import IconChat from 'virtual:icons/mdi/chat';
4
4
  // eslint-disable-next-line import/no-unresolved
5
5
  import IconChevronDown from 'virtual:icons/mdi/chevron-down';
6
- import Chat from '@/components/Chat.vue';
7
6
  import { nextTick, ref } from 'vue';
8
- import { chatEventBus } from '@/event-buses';
7
+ import Chat from '@n8n/chat/components/Chat.vue';
8
+ import { chatEventBus } from '@n8n/chat/event-buses';
9
9
 
10
10
  const isOpen = ref(false);
11
11
 
@@ -23,7 +23,7 @@ function toggle() {
23
23
  <template>
24
24
  <div class="chat-window-wrapper">
25
25
  <Transition name="chat-window-transition">
26
- <div class="chat-window" v-show="isOpen">
26
+ <div v-show="isOpen" class="chat-window">
27
27
  <Chat />
28
28
  </div>
29
29
  </Transition>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
- import Button from '@/components/Button.vue';
3
- import { useI18n } from '@/composables';
2
+ import Button from '@n8n/chat/components/Button.vue';
3
+ import { useI18n } from '@n8n/chat/composables';
4
4
 
5
5
  const { t } = useI18n();
6
6
  </script>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
- import { useI18n } from '@/composables';
3
- import PoweredBy from '@/components/PoweredBy.vue';
2
+ import { useI18n } from '@n8n/chat/composables';
3
+ import PoweredBy from '@n8n/chat/components/PoweredBy.vue';
4
4
 
5
5
  const { t, te } = useI18n();
6
6
  </script>
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  // eslint-disable-next-line import/no-unresolved
3
3
  import IconSend from 'virtual:icons/mdi/send';
4
- import { useI18n, useChat } from '@/composables';
5
4
  import { computed, ref } from 'vue';
5
+ import { useI18n, useChat } from '@n8n/chat/composables';
6
6
 
7
7
  const chatStore = useChat();
8
8
  const { waitingForResponse } = chatStore;