+
+
+
;
currentSessionId: Ref;
waitingForResponse: Ref;
- loadPreviousSession: () => Promise;
- startNewSession: () => Promise;
+ loadPreviousSession?: () => Promise;
+ startNewSession?: () => Promise;
sendMessage: (text: string) => Promise;
}
diff --git a/packages/@n8n/chat/src/types/messages.ts b/packages/@n8n/chat/src/types/messages.ts
index 6c73936a52..982c12b3bd 100644
--- a/packages/@n8n/chat/src/types/messages.ts
+++ b/packages/@n8n/chat/src/types/messages.ts
@@ -1,6 +1,19 @@
-export interface ChatMessage {
- id: string;
+export type ChatMessage> = ChatMessageComponent | ChatMessageText;
+
+export interface ChatMessageComponent> extends ChatMessageBase {
+ type: 'component';
+ key: string;
+ arguments: T;
+}
+
+export interface ChatMessageText extends ChatMessageBase {
+ type?: 'text';
text: string;
+}
+
+interface ChatMessageBase {
+ id: string;
createdAt: string;
+ transparent?: boolean;
sender: 'user' | 'bot';
}
diff --git a/packages/@n8n/chat/src/types/options.ts b/packages/@n8n/chat/src/types/options.ts
index 85648a66f6..6cc7b302bb 100644
--- a/packages/@n8n/chat/src/types/options.ts
+++ b/packages/@n8n/chat/src/types/options.ts
@@ -1,3 +1,4 @@
+import type { Component, Ref } from 'vue';
export interface ChatOptions {
webhookUrl: string;
webhookConfig?: {
@@ -6,6 +7,7 @@ export interface ChatOptions {
};
target?: string | Element;
mode?: 'window' | 'fullscreen';
+ showWindowCloseButton?: boolean;
showWelcomeScreen?: boolean;
loadPreviousSession?: boolean;
chatInputKey?: string;
@@ -21,8 +23,11 @@ export interface ChatOptions {
footer: string;
getStarted: string;
inputPlaceholder: string;
+ closeButtonTooltip: string;
[message: string]: string;
}
>;
theme?: {};
+ messageComponents?: Record;
+ disabled?: Ref;
}
diff --git a/packages/editor-ui/src/App.vue b/packages/editor-ui/src/App.vue
index ef2a3738ea..4df18d2573 100644
--- a/packages/editor-ui/src/App.vue
+++ b/packages/editor-ui/src/App.vue
@@ -26,6 +26,9 @@
+
@@ -59,6 +62,8 @@ import { useUsersStore } from '@/stores/users.store';
import { useHistoryHelper } from '@/composables/useHistoryHelper';
import { useRoute } from 'vue-router';
import { initializeAuthenticatedFeatures } from '@/init';
+import { useAIStore } from './stores/ai.store';
+import AIAssistantChat from './components/AIAssistantChat/AIAssistantChat.vue';
export default defineComponent({
name: 'App',
@@ -67,6 +72,7 @@ export default defineComponent({
LoadingView,
Telemetry,
Modals,
+ AIAssistantChat,
},
mixins: [userHelpers],
setup() {
@@ -88,6 +94,7 @@ export default defineComponent({
useSourceControlStore,
useCloudPlanStore,
useUsageStore,
+ useAIStore,
),
defaultLocale(): string {
return this.rootStore.defaultLocale;
@@ -140,10 +147,10 @@ export default defineComponent({
.container {
display: grid;
grid-template-areas:
- 'banners banners'
- 'sidebar header'
- 'sidebar content';
- grid-auto-columns: fit-content($sidebar-expanded-width) 1fr;
+ 'banners banners banners'
+ 'sidebar header chat'
+ 'sidebar content chat';
+ grid-auto-columns: fit-content($sidebar-expanded-width) 1fr fit-content($chat-width);
grid-template-rows: auto fit-content($header-height) 1fr;
height: 100vh;
}
@@ -177,4 +184,15 @@ export default defineComponent({
height: 100%;
z-index: 999;
}
+.chat {
+ grid-area: chat;
+ z-index: 999;
+ height: 100%;
+ width: 0;
+ transition: all 0.2s ease-in-out;
+
+ &.open {
+ width: $chat-width;
+ }
+}
diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts
index 67a4053308..f1c0a688a2 100644
--- a/packages/editor-ui/src/Interface.ts
+++ b/packages/editor-ui/src/Interface.ts
@@ -55,6 +55,7 @@ import type { PartialBy, TupleToUnion } from '@/utils/typeHelpers';
import type { Component } from 'vue';
import type { Scope } from '@n8n/permissions';
import type { NotificationOptions as ElementNotificationOptions } from 'element-plus';
+import type { Connection } from '@jsplumb/core';
export * from 'n8n-design-system/types';
@@ -1894,3 +1895,17 @@ export type SuggestedTemplatesWorkflowPreview = {
preview: IWorkflowData;
nodes: Array>;
};
+
+export type NewConnectionInfo = {
+ sourceId: string;
+ index: number;
+ eventSource: NodeCreatorOpenSource;
+ connection?: Connection;
+ nodeCreatorView?: string;
+ outputType?: NodeConnectionType;
+ endpointUuid?: string;
+};
+
+export type AIAssistantConnectionInfo = NewConnectionInfo & {
+ stepName: string;
+};
diff --git a/packages/editor-ui/src/components/AIAssistantChat/AIAssistantChat.vue b/packages/editor-ui/src/components/AIAssistantChat/AIAssistantChat.vue
new file mode 100644
index 0000000000..484ce7474e
--- /dev/null
+++ b/packages/editor-ui/src/components/AIAssistantChat/AIAssistantChat.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/editor-ui/src/components/AIAssistantChat/NextStepPopup.vue b/packages/editor-ui/src/components/AIAssistantChat/NextStepPopup.vue
new file mode 100644
index 0000000000..1b5c921217
--- /dev/null
+++ b/packages/editor-ui/src/components/AIAssistantChat/NextStepPopup.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
{{ title }}
+
+ -
+
+ {{ option.icon }}
+
+
+ {{ option.label }}
+
+
+
+
+
+
+
diff --git a/packages/editor-ui/src/components/AIAssistantChat/QuickReplies.vue b/packages/editor-ui/src/components/AIAssistantChat/QuickReplies.vue
new file mode 100644
index 0000000000..1a43f625d7
--- /dev/null
+++ b/packages/editor-ui/src/components/AIAssistantChat/QuickReplies.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
{{ locale.baseText('aiAssistantChat.quickReply.title') }}
+
+
+
+
+
+
+
diff --git a/packages/editor-ui/src/components/CanvasControls.vue b/packages/editor-ui/src/components/CanvasControls.vue
index b5677e54f3..de0ff8eb7c 100644
--- a/packages/editor-ui/src/components/CanvasControls.vue
+++ b/packages/editor-ui/src/components/CanvasControls.vue
@@ -94,7 +94,6 @@ onBeforeUnmount(() => {