@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,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { onBeforeUnmount, onMounted, ref } from 'vue';
3
- import { chatEventBus } from '@/event-buses';
3
+ import { chatEventBus } from '@n8n/chat/event-buses';
4
4
 
5
5
  const chatBodyRef = ref<HTMLElement | null>(null);
6
6
 
@@ -26,7 +26,7 @@ onBeforeUnmount(() => {
26
26
  <div v-if="$slots.header" class="chat-header">
27
27
  <slot name="header" />
28
28
  </div>
29
- <div v-if="$slots.default" class="chat-body" ref="chatBodyRef">
29
+ <div v-if="$slots.default" ref="chatBodyRef" class="chat-body">
30
30
  <slot />
31
31
  </div>
32
32
  <div v-if="$slots.footer" class="chat-footer">
@@ -1,10 +1,10 @@
1
1
  <script lang="ts" setup>
2
2
  /* eslint-disable @typescript-eslint/naming-convention */
3
- import type { ChatMessage } from '@/types';
4
3
  import type { PropType } from 'vue';
5
4
  import { computed, toRefs } from 'vue';
6
5
  import VueMarkdown from 'vue-markdown-render';
7
6
  import hljs from 'highlight.js/lib/core';
7
+ import type { ChatMessage } from '@n8n/chat/types';
8
8
 
9
9
  const props = defineProps({
10
10
  message: {
@@ -15,6 +15,10 @@ const props = defineProps({
15
15
 
16
16
  const { message } = toRefs(props);
17
17
 
18
+ const messageText = computed(() => {
19
+ return message.value.text || '&lt;Empty response&gt;';
20
+ });
21
+
18
22
  const classes = computed(() => {
19
23
  return {
20
24
  'chat-message-from-user': message.value.sender === 'user',
@@ -37,11 +41,7 @@ const markdownOptions = {
37
41
  <template>
38
42
  <div class="chat-message" :class="classes">
39
43
  <slot>
40
- <vue-markdown
41
- class="chat-message-markdown"
42
- :source="message.text"
43
- :options="markdownOptions"
44
- />
44
+ <VueMarkdown class="chat-message-markdown" :source="messageText" :options="markdownOptions" />
45
45
  </slot>
46
46
  </div>
47
47
  </template>
@@ -1,8 +1,8 @@
1
1
  <script lang="ts" setup>
2
- import type { ChatMessage } from '@/types';
3
- import { Message } from './index';
4
2
  import type { PropType } from 'vue';
5
3
  import { computed } from 'vue';
4
+ import { Message } from './index';
5
+ import type { ChatMessage } from '@n8n/chat/types';
6
6
 
7
7
  const props = defineProps({
8
8
  animation: {
@@ -1,9 +1,9 @@
1
1
  <script lang="ts" setup>
2
2
  import type { PropType } from 'vue';
3
- import Message from '@/components/Message.vue';
4
- import type { ChatMessage } from '@/types';
5
- import MessageTyping from '@/components/MessageTyping.vue';
6
- import { useChat } from '@/composables';
3
+ import Message from '@n8n/chat/components/Message.vue';
4
+ import type { ChatMessage } from '@n8n/chat/types';
5
+ import MessageTyping from '@n8n/chat/components/MessageTyping.vue';
6
+ import { useChat } from '@n8n/chat/composables';
7
7
 
8
8
  defineProps({
9
9
  messages: {
@@ -1,6 +1,6 @@
1
1
  import { inject } from 'vue';
2
- import { ChatSymbol } from '@/constants';
3
- import type { Chat } from '@/types';
2
+ import { ChatSymbol } from '@n8n/chat/constants';
3
+ import type { Chat } from '@n8n/chat/types';
4
4
 
5
5
  export function useChat() {
6
6
  return inject(ChatSymbol) as Chat;
@@ -1,4 +1,4 @@
1
- import { useOptions } from '@/composables/useOptions';
1
+ import { useOptions } from '@n8n/chat/composables/useOptions';
2
2
 
3
3
  export function useI18n() {
4
4
  const { options } = useOptions();
@@ -1,6 +1,6 @@
1
1
  import { inject } from 'vue';
2
- import { ChatOptionsSymbol } from '@/constants';
3
- import type { ChatOptions } from '@/types';
2
+ import { ChatOptionsSymbol } from '@n8n/chat/constants';
3
+ import type { ChatOptions } from '@n8n/chat/types';
4
4
 
5
5
  export function useOptions() {
6
6
  const options = inject(ChatOptionsSymbol) as ChatOptions;
@@ -1,4 +1,4 @@
1
- import type { ChatOptions } from '@/types';
1
+ import type { ChatOptions } from '@n8n/chat/types';
2
2
 
3
3
  export const defaultOptions: ChatOptions = {
4
4
  webhookUrl: 'http://localhost:5678',
@@ -8,7 +8,11 @@ export const defaultOptions: ChatOptions = {
8
8
  },
9
9
  target: '#n8n-chat',
10
10
  mode: 'window',
11
+ loadPreviousSession: true,
12
+ chatInputKey: 'chatInput',
13
+ chatSessionKey: 'sessionId',
11
14
  defaultLanguage: 'en',
15
+ showWelcomeScreen: false,
12
16
  initialMessages: ['Hi there! 👋', 'My name is Nathan. How can I assist you today?'],
13
17
  i18n: {
14
18
  en: {
@@ -1,5 +1,5 @@
1
1
  import type { InjectionKey } from 'vue';
2
- import type { Chat, ChatOptions } from '@/types';
2
+ import type { Chat, ChatOptions } from '@n8n/chat/types';
3
3
 
4
4
  // eslint-disable-next-line @typescript-eslint/naming-convention
5
5
  export const ChatSymbol = 'Chat' as unknown as InjectionKey<Chat>;
@@ -0,0 +1,36 @@
1
+ :root {
2
+ --chat--color-primary: #e74266;
3
+ --chat--color-primary-shade-50: #db4061;
4
+ --chat--color-primary-shade-100: #cf3c5c;
5
+ --chat--color-secondary: #20b69e;
6
+ --chat--color-secondary-shade-50: #1ca08a;
7
+ --chat--color-white: #ffffff;
8
+ --chat--color-light: #f2f4f8;
9
+ --chat--color-light-shade-50: #e6e9f1;
10
+ --chat--color-light-shade-100: #c2c5cc;
11
+ --chat--color-medium: #d2d4d9;
12
+ --chat--color-dark: #101330;
13
+ --chat--color-disabled: #777980;
14
+ --chat--color-typing: #404040;
15
+
16
+ --chat--spacing: 1rem;
17
+ --chat--border-radius: 0.25rem;
18
+ --chat--transition-duration: 0.15s;
19
+
20
+ --chat--window--width: 400px;
21
+ --chat--window--height: 600px;
22
+
23
+ --chat--textarea--height: 50px;
24
+
25
+ --chat--message--bot--background: var(--chat--color-white);
26
+ --chat--message--bot--color: var(--chat--color-dark);
27
+ --chat--message--user--background: var(--chat--color-secondary);
28
+ --chat--message--user--color: var(--chat--color-white);
29
+ --chat--message--pre--background: rgba(0, 0, 0, 0.05);
30
+
31
+ --chat--toggle--background: var(--chat--color-primary);
32
+ --chat--toggle--hover--background: var(--chat--color-primary-shade-50);
33
+ --chat--toggle--active--background: var(--chat--color-primary-shade-100);
34
+ --chat--toggle--color: var(--chat--color-white);
35
+ --chat--toggle--size: 64px;
36
+ }
@@ -0,0 +1 @@
1
+ @import 'tokens';
@@ -1,3 +1,3 @@
1
- import { createEventBus } from '@/utils';
1
+ import { createEventBus } from '@n8n/chat/utils';
2
2
 
3
3
  export const chatEventBus = createEventBus();
package/src/index.ts CHANGED
@@ -2,10 +2,10 @@ import './main.scss';
2
2
 
3
3
  import { createApp } from 'vue';
4
4
  import App from './App.vue';
5
- import type { ChatOptions } from '@/types';
6
- import { defaultMountingTarget, defaultOptions } from '@/constants';
7
- import { createDefaultMountingTarget } from '@/utils';
8
- import { ChatPlugin } from '@/plugins';
5
+ import type { ChatOptions } from '@n8n/chat/types';
6
+ import { defaultMountingTarget, defaultOptions } from '@n8n/chat/constants';
7
+ import { createDefaultMountingTarget } from '@n8n/chat/utils';
8
+ import { ChatPlugin } from '@n8n/chat/plugins';
9
9
 
10
10
  export function createChat(options?: Partial<ChatOptions>) {
11
11
  const resolvedOptions: ChatOptions = {
package/src/main.scss CHANGED
@@ -2,39 +2,4 @@
2
2
  @import 'highlight.js/styles/github';
3
3
  }
4
4
 
5
- :root {
6
- --chat--color-primary: #e74266;
7
- --chat--color-primary-shade-50: #db4061;
8
- --chat--color-primary-shade-100: #cf3c5c;
9
- --chat--color-secondary: #20b69e;
10
- --chat--color-secondary-shade-50: #1ca08a;
11
- --chat--color-white: #ffffff;
12
- --chat--color-light: #f2f4f8;
13
- --chat--color-light-shade-50: #e6e9f1;
14
- --chat--color-light-shade-100: #c2c5cc;
15
- --chat--color-medium: #d2d4d9;
16
- --chat--color-dark: #101330;
17
- --chat--color-disabled: #777980;
18
- --chat--color-typing: #404040;
19
-
20
- --chat--spacing: 1rem;
21
- --chat--border-radius: 0.25rem;
22
- --chat--transition-duration: 0.15s;
23
-
24
- --chat--window--width: 400px;
25
- --chat--window--height: 600px;
26
-
27
- --chat--textarea--height: 50px;
28
-
29
- --chat--message--bot--background: var(--chat--color-white);
30
- --chat--message--bot--color: var(--chat--color-dark);
31
- --chat--message--user--background: var(--chat--color-secondary);
32
- --chat--message--user--color: var(--chat--color-white);
33
- --chat--message--pre--background: rgba(0, 0, 0, 0.05);
34
-
35
- --chat--toggle--background: var(--chat--color-primary);
36
- --chat--toggle--hover--background: var(--chat--color-primary-shade-50);
37
- --chat--toggle--active--background: var(--chat--color-primary-shade-100);
38
- --chat--toggle--color: var(--chat--color-white);
39
- --chat--toggle--size: 64px;
40
- }
5
+ @import 'css';
@@ -1,10 +1,10 @@
1
1
  import type { Plugin } from 'vue';
2
2
  import { computed, nextTick, ref } from 'vue';
3
- import type { ChatMessage, ChatOptions } from '@/types';
4
3
  import { v4 as uuidv4 } from 'uuid';
5
- import { chatEventBus } from '@/event-buses';
6
- import * as api from '@/api';
7
- import { ChatOptionsSymbol, ChatSymbol, localStorageSessionIdKey } from '@/constants';
4
+ import type { ChatMessage, ChatOptions } from '@n8n/chat/types';
5
+ import { chatEventBus } from '@n8n/chat/event-buses';
6
+ import * as api from '@n8n/chat/api';
7
+ import { ChatOptionsSymbol, ChatSymbol, localStorageSessionIdKey } from '@n8n/chat/constants';
8
8
 
9
9
  // eslint-disable-next-line @typescript-eslint/naming-convention
10
10
  export const ChatPlugin: Plugin<ChatOptions> = {
@@ -61,6 +61,10 @@ export const ChatPlugin: Plugin<ChatOptions> = {
61
61
  }
62
62
 
63
63
  async function loadPreviousSession() {
64
+ if (!options.loadPreviousSession) {
65
+ return;
66
+ }
67
+
64
68
  const sessionId = localStorage.getItem(localStorageSessionIdKey) ?? uuidv4();
65
69
  const previousMessagesResponse = await api.loadPreviousSession(sessionId, options);
66
70
  const timestamp = new Date().toISOString();
package/src/types/chat.ts CHANGED
@@ -1,12 +1,12 @@
1
- import type { ChatMessage } from '@/types/messages';
2
1
  import type { Ref } from 'vue';
2
+ import type { ChatMessage } from '@n8n/chat/types/messages';
3
3
 
4
4
  export interface Chat {
5
5
  initialMessages: Ref<ChatMessage[]>;
6
6
  messages: Ref<ChatMessage[]>;
7
7
  currentSessionId: Ref<string | null>;
8
8
  waitingForResponse: Ref<boolean>;
9
- loadPreviousSession: () => Promise<string>;
9
+ loadPreviousSession: () => Promise<string | undefined>;
10
10
  startNewSession: () => Promise<void>;
11
11
  sendMessage: (text: string) => Promise<void>;
12
12
  }
@@ -6,8 +6,13 @@ export interface ChatOptions {
6
6
  };
7
7
  target?: string | Element;
8
8
  mode?: 'window' | 'fullscreen';
9
+ showWelcomeScreen?: boolean;
10
+ loadPreviousSession?: boolean;
11
+ chatInputKey?: string;
12
+ chatSessionKey?: string;
9
13
  defaultLanguage?: 'en';
10
14
  initialMessages?: string[];
15
+ metadata?: Record<string, unknown>;
11
16
  i18n: Record<
12
17
  string,
13
18
  {
package/tsconfig.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "types": ["vitest/globals", "unplugin-icons/types/vue"],
15
15
  "paths": {
16
16
  "@/*": ["src/*"],
17
- "n8n-design-system/*": ["../design-system/src/*"]
17
+ "@n8n/chat/*": ["src/*"]
18
18
  },
19
19
  "lib": ["esnext", "dom", "dom.iterable", "scripthost"],
20
20
  // TODO: remove all options below this line
package/vite.config.ts CHANGED
@@ -7,6 +7,7 @@ import icons from 'unplugin-icons/vite';
7
7
  import dts from 'vite-plugin-dts';
8
8
 
9
9
  const includeVue = process.env.INCLUDE_VUE === 'true';
10
+ const srcPath = fileURLToPath(new URL('./src', import.meta.url));
10
11
 
11
12
  // https://vitejs.dev/config/
12
13
  export default defineConfig({
@@ -19,7 +20,8 @@ export default defineConfig({
19
20
  ],
20
21
  resolve: {
21
22
  alias: {
22
- '@': fileURLToPath(new URL('./src', import.meta.url)),
23
+ '@': srcPath,
24
+ '@n8n/chat': srcPath,
23
25
  },
24
26
  },
25
27
  define: {