mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 08:34:07 -08:00
fix(editor): Ignore all node run messages after a success message is sent (no-changelog) (#11668)
This commit is contained in:
parent
b5cbf7566d
commit
7b20c1e93d
|
@ -224,6 +224,54 @@ describe('AI Assistant::enabled', () => {
|
||||||
.should('contain.text', 'item.json.myNewField = 1');
|
.should('contain.text', 'item.json.myNewField = 1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should ignore node execution success and error messages after the node run successfully once', () => {
|
||||||
|
const getParameter = () => ndv.getters.parameterInput('jsCode').should('be.visible');
|
||||||
|
|
||||||
|
const getEditor = () => getParameter().find('.cm-content').should('exist');
|
||||||
|
|
||||||
|
cy.intercept('POST', '/rest/ai/chat', {
|
||||||
|
statusCode: 200,
|
||||||
|
fixture: 'aiAssistant/responses/code_diff_suggestion_response.json',
|
||||||
|
}).as('chatRequest');
|
||||||
|
|
||||||
|
cy.createFixtureWorkflow('aiAssistant/workflows/test_workflow.json');
|
||||||
|
wf.actions.openNode('Code');
|
||||||
|
ndv.getters.nodeExecuteButton().click();
|
||||||
|
aiAssistant.getters.nodeErrorViewAssistantButton().click({ force: true });
|
||||||
|
cy.wait('@chatRequest');
|
||||||
|
|
||||||
|
cy.intercept('POST', '/rest/ai/chat', {
|
||||||
|
statusCode: 200,
|
||||||
|
fixture: 'aiAssistant/responses/node_execution_succeeded_response.json',
|
||||||
|
}).as('chatRequest2');
|
||||||
|
|
||||||
|
getEditor()
|
||||||
|
.type('{selectall}')
|
||||||
|
.paste(
|
||||||
|
'for (const item of $input.all()) {\n item.json.myNewField = 1;\n}\n\nreturn $input.all();',
|
||||||
|
);
|
||||||
|
|
||||||
|
ndv.getters.nodeExecuteButton().click();
|
||||||
|
|
||||||
|
getEditor()
|
||||||
|
.type('{selectall}')
|
||||||
|
.paste(
|
||||||
|
'for (const item of $input.all()) {\n item.json.myNewField = 1aaaa!;\n}\n\nreturn $input.all();',
|
||||||
|
);
|
||||||
|
|
||||||
|
ndv.getters.nodeExecuteButton().click();
|
||||||
|
|
||||||
|
aiAssistant.getters.chatMessagesAssistant().should('have.length', 3);
|
||||||
|
|
||||||
|
aiAssistant.getters
|
||||||
|
.chatMessagesAssistant()
|
||||||
|
.eq(2)
|
||||||
|
.should(
|
||||||
|
'contain.text',
|
||||||
|
'Code node ran successfully, did my solution help resolve your issue?\nQuick reply 👇Yes, thanksNo, I am still stuck',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should end chat session when `end_session` event is received', () => {
|
it('should end chat session when `end_session` event is received', () => {
|
||||||
cy.intercept('POST', '/rest/ai/chat', {
|
cy.intercept('POST', '/rest/ai/chat', {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"sessionId": "1",
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"type": "message",
|
||||||
|
"text": "**Code** node ran successfully, did my solution help resolve your issue?",
|
||||||
|
"quickReplies": [
|
||||||
|
{
|
||||||
|
"text": "Yes, thanks",
|
||||||
|
"type": "all-good",
|
||||||
|
"isFeedback": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "No, I am still stuck",
|
||||||
|
"type": "still-stuck",
|
||||||
|
"isFeedback": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -72,13 +72,15 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
|
||||||
};
|
};
|
||||||
}>({});
|
}>({});
|
||||||
|
|
||||||
|
type NodeExecutionStatus = 'error' | 'not_executed' | 'success';
|
||||||
|
|
||||||
const chatSessionCredType = ref<ICredentialType | undefined>();
|
const chatSessionCredType = ref<ICredentialType | undefined>();
|
||||||
const chatSessionError = ref<ChatRequest.ErrorContext | undefined>();
|
const chatSessionError = ref<ChatRequest.ErrorContext | undefined>();
|
||||||
const currentSessionId = ref<string | undefined>();
|
const currentSessionId = ref<string | undefined>();
|
||||||
const currentSessionActiveExecutionId = ref<string | undefined>();
|
const currentSessionActiveExecutionId = ref<string | undefined>();
|
||||||
const currentSessionWorkflowId = ref<string | undefined>();
|
const currentSessionWorkflowId = ref<string | undefined>();
|
||||||
const lastUnread = ref<ChatUI.AssistantMessage | undefined>();
|
const lastUnread = ref<ChatUI.AssistantMessage | undefined>();
|
||||||
const nodeExecutionStatus = ref<'not_executed' | 'success' | 'error'>('not_executed');
|
const nodeExecutionStatus = ref<NodeExecutionStatus>('not_executed');
|
||||||
// This is used to show a message when the assistant is performing intermediate steps
|
// This is used to show a message when the assistant is performing intermediate steps
|
||||||
// We use streaming for assistants that support it, and this for agents
|
// We use streaming for assistants that support it, and this for agents
|
||||||
const assistantThinkingMessage = ref<string | undefined>();
|
const assistantThinkingMessage = ref<string | undefined>();
|
||||||
|
@ -536,10 +538,16 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
|
||||||
(e) => handleServiceError(e, id, async () => await sendEvent(eventName, error)),
|
(e) => handleServiceError(e, id, async () => await sendEvent(eventName, error)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onNodeExecution(pushEvent: PushPayload<'nodeExecuteAfter'>) {
|
async function onNodeExecution(pushEvent: PushPayload<'nodeExecuteAfter'>) {
|
||||||
if (!chatSessionError.value || pushEvent.nodeName !== chatSessionError.value.node.name) {
|
if (!chatSessionError.value || pushEvent.nodeName !== chatSessionError.value.node.name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nodeExecutionStatus.value === 'success') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (pushEvent.data.error && nodeExecutionStatus.value !== 'error') {
|
if (pushEvent.data.error && nodeExecutionStatus.value !== 'error') {
|
||||||
await sendEvent('node-execution-errored', pushEvent.data.error);
|
await sendEvent('node-execution-errored', pushEvent.data.error);
|
||||||
nodeExecutionStatus.value = 'error';
|
nodeExecutionStatus.value = 'error';
|
||||||
|
@ -550,7 +558,7 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
pushEvent.data.executionStatus === 'success' &&
|
pushEvent.data.executionStatus === 'success' &&
|
||||||
nodeExecutionStatus.value !== 'success'
|
['error', 'not_executed'].includes(nodeExecutionStatus.value)
|
||||||
) {
|
) {
|
||||||
await sendEvent('node-execution-succeeded');
|
await sendEvent('node-execution-succeeded');
|
||||||
nodeExecutionStatus.value = 'success';
|
nodeExecutionStatus.value = 'success';
|
||||||
|
|
Loading…
Reference in a new issue