Merge branch 'master' of github.com:n8n-io/n8n into ado-2808-1

This commit is contained in:
Mutasem Aldmour 2024-11-12 13:14:37 +01:00
commit 020d860360
No known key found for this signature in database
GPG key ID: 3DFA8122BB7FD6B8
4 changed files with 81 additions and 2 deletions

View file

@ -224,6 +224,54 @@ describe('AI Assistant::enabled', () => {
.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', () => {
cy.intercept('POST', '/rest/ai/chat', {
statusCode: 200,

View file

@ -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
}
]
}
]
}

View file

@ -127,6 +127,7 @@ export class MemoryRedisChat implements INodeType {
socket: {
host: credentials.host as string,
port: credentials.port as number,
tls: credentials.ssl === true,
},
database: credentials.database as number,
};

View file

@ -72,13 +72,15 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
};
}>({});
type NodeExecutionStatus = 'error' | 'not_executed' | 'success';
const chatSessionCredType = ref<ICredentialType | undefined>();
const chatSessionError = ref<ChatRequest.ErrorContext | undefined>();
const currentSessionId = ref<string | undefined>();
const currentSessionActiveExecutionId = ref<string | undefined>();
const currentSessionWorkflowId = ref<string | 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
// We use streaming for assistants that support it, and this for agents
const assistantThinkingMessage = ref<string | undefined>();
@ -536,10 +538,16 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
(e) => handleServiceError(e, id, async () => await sendEvent(eventName, error)),
);
}
async function onNodeExecution(pushEvent: PushPayload<'nodeExecuteAfter'>) {
if (!chatSessionError.value || pushEvent.nodeName !== chatSessionError.value.node.name) {
return;
}
if (nodeExecutionStatus.value === 'success') {
return;
}
if (pushEvent.data.error && nodeExecutionStatus.value !== 'error') {
await sendEvent('node-execution-errored', pushEvent.data.error);
nodeExecutionStatus.value = 'error';
@ -550,7 +558,7 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
});
} else if (
pushEvent.data.executionStatus === 'success' &&
nodeExecutionStatus.value !== 'success'
['error', 'not_executed'].includes(nodeExecutionStatus.value)
) {
await sendEvent('node-execution-succeeded');
nodeExecutionStatus.value = 'success';