mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-22 12:19:09 +00:00
feat: Add planning step to AI workflow builder (no-changelog) (#18737)
Co-authored-by: Eugene Molodkin <eugene@n8n.io>
This commit is contained in:
@@ -24,6 +24,7 @@ interface Props {
|
||||
};
|
||||
messages?: ChatUI.AssistantMessage[];
|
||||
streaming?: boolean;
|
||||
disabled?: boolean;
|
||||
loadingMessage?: string;
|
||||
sessionId?: string;
|
||||
title?: string;
|
||||
@@ -66,7 +67,9 @@ function normalizeMessages(messages: ChatUI.AssistantMessage[]): ChatUI.Assistan
|
||||
|
||||
// filter out these messages so that tool collapsing works correctly
|
||||
function filterOutHiddenMessages(messages: ChatUI.AssistantMessage[]): ChatUI.AssistantMessage[] {
|
||||
return messages.filter((message) => Boolean(getSupportedMessageComponent(message.type)));
|
||||
return messages.filter(
|
||||
(message) => Boolean(getSupportedMessageComponent(message.type)) || message.type === 'custom',
|
||||
);
|
||||
}
|
||||
|
||||
function collapseToolMessages(messages: ChatUI.AssistantMessage[]): ChatUI.AssistantMessage[] {
|
||||
@@ -165,7 +168,7 @@ const sessionEnded = computed(() => {
|
||||
});
|
||||
|
||||
const sendDisabled = computed(() => {
|
||||
return !textInputValue.value || props.streaming || sessionEnded.value;
|
||||
return !textInputValue.value || props.streaming || sessionEnded.value || props.disabled;
|
||||
});
|
||||
|
||||
const showPlaceholder = computed(() => {
|
||||
@@ -226,6 +229,13 @@ watch(
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
// Expose focusInput method to parent components
|
||||
defineExpose({
|
||||
focusInput: () => {
|
||||
chatInput.value?.focus();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -265,7 +275,11 @@ watch(
|
||||
@code-replace="() => emit('codeReplace', i)"
|
||||
@code-undo="() => emit('codeUndo', i)"
|
||||
@feedback="onRateMessage"
|
||||
/>
|
||||
>
|
||||
<template v-if="$slots['custom-message']" #custom-message="customMessageProps">
|
||||
<slot name="custom-message" v-bind="customMessageProps" />
|
||||
</template>
|
||||
</MessageWrapper>
|
||||
|
||||
<div
|
||||
v-if="lastMessageQuickReplies.length && i === normalizedMessages.length - 1"
|
||||
@@ -336,8 +350,8 @@ watch(
|
||||
ref="chatInput"
|
||||
v-model="textInputValue"
|
||||
class="ignore-key-press-node-creator ignore-key-press-canvas"
|
||||
:class="{ [$style.disabled]: sessionEnded || streaming }"
|
||||
:disabled="sessionEnded || streaming"
|
||||
:class="{ [$style.disabled]: sessionEnded || streaming || disabled }"
|
||||
:disabled="sessionEnded || streaming || disabled"
|
||||
:placeholder="placeholder ?? t('assistantChat.inputPlaceholder')"
|
||||
rows="1"
|
||||
wrap="hard"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,16 +31,27 @@ const messageComponent = computed<Component | null>(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="messageComponent"
|
||||
v-if="messageComponent"
|
||||
:message="message"
|
||||
:is-first-of-role="isFirstOfRole"
|
||||
:user="user"
|
||||
:streaming="streaming"
|
||||
:is-last-message="isLastMessage"
|
||||
@code-replace="emit('codeReplace')"
|
||||
@code-undo="emit('codeUndo')"
|
||||
@feedback="(feedback: RatingFeedback) => emit('feedback', feedback)"
|
||||
/>
|
||||
<div>
|
||||
<component
|
||||
:is="messageComponent"
|
||||
v-if="messageComponent"
|
||||
:message="message"
|
||||
:is-first-of-role="isFirstOfRole"
|
||||
:user="user"
|
||||
:streaming="streaming"
|
||||
:is-last-message="isLastMessage"
|
||||
@code-replace="emit('codeReplace')"
|
||||
@code-undo="emit('codeUndo')"
|
||||
@feedback="(feedback: RatingFeedback) => emit('feedback', feedback)"
|
||||
/>
|
||||
<slot
|
||||
v-else-if="message.type === 'custom'"
|
||||
name="custom-message"
|
||||
:message="message"
|
||||
:is-first-of-role="isFirstOfRole"
|
||||
:user="user"
|
||||
:streaming="streaming"
|
||||
:is-last-message="isLastMessage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -23,6 +23,7 @@ export function getSupportedMessageComponent(type: ChatUI.AssistantMessage['type
|
||||
return ToolMessage;
|
||||
case 'agent-suggestion':
|
||||
case 'workflow-updated':
|
||||
case 'custom':
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -87,6 +87,15 @@ export namespace ChatUI {
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface CustomMessage {
|
||||
id?: string;
|
||||
role: 'assistant' | 'user';
|
||||
type: 'custom';
|
||||
message?: string;
|
||||
customType: string;
|
||||
data: unknown;
|
||||
}
|
||||
|
||||
type MessagesWithReplies = (
|
||||
| TextMessage
|
||||
| CodeDiffMessage
|
||||
@@ -106,6 +115,7 @@ export namespace ChatUI {
|
||||
| AgentSuggestionMessage
|
||||
| WorkflowUpdatedMessage
|
||||
| ToolMessage
|
||||
| CustomMessage
|
||||
) & {
|
||||
id?: string;
|
||||
read?: boolean;
|
||||
@@ -186,6 +196,12 @@ export function isToolMessage(
|
||||
return msg.type === 'tool';
|
||||
}
|
||||
|
||||
export function isCustomMessage(
|
||||
msg: ChatUI.AssistantMessage,
|
||||
): msg is ChatUI.CustomMessage & { id?: string; read?: boolean } {
|
||||
return msg.type === 'custom';
|
||||
}
|
||||
|
||||
// Helper to ensure message has required id and read properties
|
||||
export function hasRequiredProps<T extends ChatUI.AssistantMessage>(
|
||||
msg: T,
|
||||
|
||||
Reference in New Issue
Block a user