Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/@n8n/api-types/src/chat-hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,6 @@ export interface EnrichedStructuredChunk extends StructuredChunk {
messageId: ChatMessageId;
previousMessageId: ChatMessageId | null;
retryOfMessageId: ChatMessageId | null;
executionId: number | null;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has no effect in this PR, but along with changes in #21393 this makes it possible to show the link to execution in the chat message action without refreshing the browser.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On base llm models the execution gets deleted right after the streaming is done, we should make sure we don't show those execution links as user won't be able to follow them 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we'll show it for n8n workflow agent only.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(when the execution gets deleted the column also gets set to NULL on the db)

};
}
1 change: 1 addition & 0 deletions packages/cli/src/modules/chat-hub/chat-hub.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,7 @@ export class ChatHubService {
messageId: message.id,
previousMessageId: message.previousMessageId,
retryOfMessageId: message.retryOfMessageId,
executionId: executionId ? +executionId : null,
},
};

Expand Down
56 changes: 28 additions & 28 deletions packages/frontend/editor-ui/src/features/ai/chatHub/ChatView.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<script setup lang="ts">
import { useToast } from '@/composables/useToast';
import { LOCAL_STORAGE_CHAT_HUB_SELECTED_MODEL } from '@/constants';
import {
findOneFromModelsResponse,
restoreConversationModelFromMessageOrSession,
} from '@/features/ai/chatHub/chat.utils';
import { findOneFromModelsResponse, unflattenModel } from '@/features/ai/chatHub/chat.utils';
import ChatConversationHeader from '@/features/ai/chatHub/components/ChatConversationHeader.vue';
import ChatMessage from '@/features/ai/chatHub/components/ChatMessage.vue';
import ChatPrompt from '@/features/ai/chatHub/components/ChatPrompt.vue';
Expand All @@ -29,7 +26,7 @@ import {
import { N8nIconButton, N8nScrollArea } from '@n8n/design-system';
import { useLocalStorage, useMediaQuery, useScroll } from '@vueuse/core';
import { v4 as uuidv4 } from 'uuid';
import { computed, ref, useTemplateRef, watch } from 'vue';
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useChatStore } from './chat.store';
import { useDocumentTitle } from '@/composables/useDocumentTitle';
Expand Down Expand Up @@ -60,9 +57,12 @@ const currentConversation = computed(() =>
: undefined,
);
const currentConversationTitle = computed(() => currentConversation.value?.title);
const readyToShowMessages = computed(() => chatStore.agentsReady);

const { arrivedState } = useScroll(scrollContainerRef, { throttle: 100, offset: { bottom: 100 } });

const { arrivedState, measure } = useScroll(scrollContainerRef, {
throttle: 100,
offset: { bottom: 100 },
});
const defaultModel = useLocalStorage<ChatHubConversationModel | null>(
LOCAL_STORAGE_CHAT_HUB_SELECTED_MODEL(usersStore.currentUserId ?? 'anonymous'),
null,
Expand Down Expand Up @@ -109,13 +109,17 @@ const selectedModel = computed<ChatModelDto | undefined>(() => {
return modelFromQuery.value;
}

if (!currentConversation.value?.provider) {
return defaultModel.value ? chatStore.getAgent(defaultModel.value) : undefined;
if (currentConversation.value?.provider) {
const model = unflattenModel(currentConversation.value);

return model ? chatStore.getAgent(model) : undefined;
}

const model = restoreConversationModelFromMessageOrSession(currentConversation.value);
if (chatStore.streaming?.sessionId === sessionId.value) {
return chatStore.getAgent(chatStore.streaming.model);
}

return model ? chatStore.getAgent(model) : undefined;
return defaultModel.value ? chatStore.getAgent(defaultModel.value) : undefined;
});

const { credentialsByProvider, selectCredential } = useChatCredentials(
Expand Down Expand Up @@ -170,26 +174,22 @@ function scrollToMessage(messageId: ChatMessageId) {

// Scroll to the bottom when a new message is added
watch(
() => chatMessages.value[chatMessages.value.length - 1]?.id,
(lastMessageId) => {
if (!lastMessageId) {
return;
}

const currentMessage = chatStore.lastMessage(sessionId.value);
if (lastMessageId !== currentMessage?.id) {
scrollToBottom(currentMessage !== null);
[readyToShowMessages, () => chatMessages.value[chatMessages.value.length - 1]?.id],
([ready, lastMessageId]) => {
if (!ready || !lastMessageId) {
return;
}

const message = chatStore
.getActiveMessages(sessionId.value)
.find((m) => m.id === lastMessageId);
// Prevent "scroll to bottom" button from appearing when not necessary
void nextTick(measure);

if (message?.previousMessageId) {
if (chatStore.streaming) {
// Scroll to user's prompt when the message is being generated
scrollToMessage(message.previousMessageId);
scrollToMessage(chatStore.streaming.promptId);
return;
}

scrollToBottom(false);
},
{ immediate: true, flush: 'post' },
);
Expand Down Expand Up @@ -286,7 +286,7 @@ function handleCancelEditMessage() {

function handleEditMessage(message: ChatHubMessageDto) {
if (
chatStore.isResponding(message.sessionId) ||
isResponding.value ||
!['human', 'ai'].includes(message.type) ||
!selectedModel.value ||
!credentialsForSelectedProvider.value
Expand All @@ -308,7 +308,7 @@ function handleEditMessage(message: ChatHubMessageDto) {

function handleRegenerateMessage(message: ChatHubMessageDto) {
if (
chatStore.isResponding(message.sessionId) ||
isResponding.value ||
message.type !== 'ai' ||
!selectedModel.value ||
!credentialsForSelectedProvider.value
Expand Down Expand Up @@ -400,7 +400,7 @@ function closeAgentEditor() {
/>

<N8nScrollArea
v-if="chatStore.agentsReady"
v-if="readyToShowMessages"
type="scroll"
:enable-vertical-scroll="true"
:enable-horizontal-scroll="false"
Expand Down
Loading
Loading