-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into ask-assistant
* master: refactor(core): Clean up event relays (no-changelog) (#10284) fix(editor): Fix execution retry button (#10275) feat(core): Show sub-node error on the logs pane. Open logs pane on sub-node error (#10248) refactor(core): Move instanceRole to InstanceSettings (no-changelog) (#10242) feat(core): Allow filtering executions and users by project in Public API (#10250) fix(core): Make execution and its data creation atomic (#10276) refactor(core): Mark schema env vars used by cloud hooks (no-changelog) (#10283) ci: Fix DB tests (no-changelog) (#10282) feat(core): Support create, delete, edit role for users in Public API (#10279) refactor(core): Decouple post workflow execute event from internal hooks (no-changelog) (#10280) feat(core): Allow transferring credentials in Public API (#10259) feat(core): Support create, read, update, delete projects in Public API (#10269) ci: Introduce lint rule `no-type-unsafe-event-emitter` (no-changelog) (#10254) fix(core): Surface enterprise trial error message (#10267) fix(editor): Enable moving resources only if team projects are available by the license (#10271) fix(core): Upgrade tournament to address some XSS vulnerabilities (#10277) # Conflicts: # packages/cli/src/Server.ts
- Loading branch information
Showing
118 changed files
with
2,734 additions
and
987 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
import type { ExecutionError } from 'n8n-workflow/src'; | ||
import { NDV, WorkflowPage as WorkflowPageClass } from '../pages'; | ||
import { | ||
addLanguageModelNodeToParent, | ||
addMemoryNodeToParent, | ||
addNodeToCanvas, | ||
addToolNodeToParent, | ||
navigateToNewWorkflowPage, | ||
openNode, | ||
} from '../composables/workflow'; | ||
import { | ||
AGENT_NODE_NAME, | ||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, | ||
AI_MEMORY_POSTGRES_NODE_NAME, | ||
AI_TOOL_CALCULATOR_NODE_NAME, | ||
MANUAL_CHAT_TRIGGER_NODE_DISPLAY_NAME, | ||
MANUAL_CHAT_TRIGGER_NODE_NAME, | ||
MANUAL_TRIGGER_NODE_DISPLAY_NAME, | ||
MANUAL_TRIGGER_NODE_NAME, | ||
} from '../constants'; | ||
import { | ||
clickCreateNewCredential, | ||
clickExecuteNode, | ||
clickGetBackToCanvas, | ||
} from '../composables/ndv'; | ||
import { setCredentialValues } from '../composables/modals/credential-modal'; | ||
import { | ||
closeManualChatModal, | ||
getManualChatMessages, | ||
getManualChatModalLogs, | ||
getManualChatModalLogsEntries, | ||
sendManualChatMessage, | ||
} from '../composables/modals/chat-modal'; | ||
import { createMockNodeExecutionData, getVisibleSelect, runMockWorkflowExecution } from '../utils'; | ||
|
||
const ndv = new NDV(); | ||
const WorkflowPage = new WorkflowPageClass(); | ||
|
||
function createRunDataWithError(inputMessage: string) { | ||
return [ | ||
createMockNodeExecutionData(MANUAL_CHAT_TRIGGER_NODE_NAME, { | ||
jsonData: { | ||
main: { input: inputMessage }, | ||
}, | ||
}), | ||
createMockNodeExecutionData(AI_MEMORY_POSTGRES_NODE_NAME, { | ||
jsonData: { | ||
ai_memory: { | ||
json: { | ||
action: 'loadMemoryVariables', | ||
values: { | ||
input: inputMessage, | ||
system_message: 'You are a helpful assistant', | ||
formatting_instructions: | ||
'IMPORTANT: Always call `format_final_response` to format your final response!', | ||
}, | ||
}, | ||
}, | ||
}, | ||
inputOverride: { | ||
ai_memory: [ | ||
[ | ||
{ | ||
json: { | ||
action: 'loadMemoryVariables', | ||
values: { | ||
input: inputMessage, | ||
system_message: 'You are a helpful assistant', | ||
formatting_instructions: | ||
'IMPORTANT: Always call `format_final_response` to format your final response!', | ||
}, | ||
}, | ||
}, | ||
], | ||
], | ||
}, | ||
error: { | ||
message: 'Internal error', | ||
timestamp: 1722591723244, | ||
name: 'NodeOperationError', | ||
description: 'Internal error', | ||
context: {}, | ||
cause: { | ||
name: 'error', | ||
severity: 'FATAL', | ||
code: '3D000', | ||
file: 'postinit.c', | ||
line: '885', | ||
routine: 'InitPostgres', | ||
} as unknown as Error, | ||
} as ExecutionError, | ||
}), | ||
createMockNodeExecutionData(AGENT_NODE_NAME, { | ||
executionStatus: 'error', | ||
error: { | ||
level: 'error', | ||
tags: { | ||
packageName: 'workflow', | ||
}, | ||
context: {}, | ||
functionality: 'configuration-node', | ||
name: 'NodeOperationError', | ||
timestamp: 1722591723244, | ||
node: { | ||
parameters: { | ||
notice: '', | ||
sessionIdType: 'fromInput', | ||
tableName: 'n8n_chat_histories', | ||
}, | ||
id: '6b9141da-0135-4e9d-94d1-2d658cbf48b5', | ||
name: 'Postgres Chat Memory', | ||
type: '@n8n/n8n-nodes-langchain.memoryPostgresChat', | ||
typeVersion: 1, | ||
position: [1140, 500], | ||
credentials: { | ||
postgres: { | ||
id: 'RkyZetVpGsSfEAhQ', | ||
name: 'Postgres account', | ||
}, | ||
}, | ||
}, | ||
messages: ['database "chat11" does not exist'], | ||
description: 'Internal error', | ||
message: 'Internal error', | ||
} as unknown as ExecutionError, | ||
metadata: { | ||
subRun: [ | ||
{ | ||
node: 'Postgres Chat Memory', | ||
runIndex: 0, | ||
}, | ||
], | ||
}, | ||
}), | ||
]; | ||
} | ||
|
||
function setupTestWorkflow(chatTrigger: boolean = false) { | ||
// Setup test workflow with AI Agent, Postgres Memory Node (source of error), Calculator Tool, and OpenAI Chat Model | ||
if (chatTrigger) { | ||
addNodeToCanvas(MANUAL_CHAT_TRIGGER_NODE_NAME, true); | ||
} else { | ||
addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME, true); | ||
} | ||
|
||
addNodeToCanvas(AGENT_NODE_NAME, true); | ||
|
||
if (!chatTrigger) { | ||
// Remove chat trigger | ||
WorkflowPage.getters | ||
.canvasNodeByName(MANUAL_CHAT_TRIGGER_NODE_DISPLAY_NAME) | ||
.find('[data-test-id="delete-node-button"]') | ||
.click({ force: true }); | ||
|
||
// Set manual trigger to output standard pinned data | ||
openNode(MANUAL_TRIGGER_NODE_DISPLAY_NAME); | ||
ndv.actions.editPinnedData(); | ||
ndv.actions.savePinnedData(); | ||
ndv.actions.close(); | ||
} | ||
|
||
// Calculator is added just to make OpenAI Chat Model work (tools can not be empty with OpenAI model) | ||
addToolNodeToParent(AI_TOOL_CALCULATOR_NODE_NAME, AGENT_NODE_NAME); | ||
clickGetBackToCanvas(); | ||
|
||
addMemoryNodeToParent(AI_MEMORY_POSTGRES_NODE_NAME, AGENT_NODE_NAME); | ||
|
||
clickCreateNewCredential(); | ||
setCredentialValues({ | ||
password: 'testtesttest', | ||
}); | ||
|
||
ndv.getters.parameterInput('sessionIdType').click(); | ||
getVisibleSelect().contains('Define below').click(); | ||
ndv.getters.parameterInput('sessionKey').type('asdasd'); | ||
|
||
clickGetBackToCanvas(); | ||
|
||
addLanguageModelNodeToParent( | ||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, | ||
AGENT_NODE_NAME, | ||
true, | ||
); | ||
|
||
clickCreateNewCredential(); | ||
setCredentialValues({ | ||
apiKey: 'sk_test_123', | ||
}); | ||
clickGetBackToCanvas(); | ||
|
||
WorkflowPage.actions.zoomToFit(); | ||
} | ||
|
||
function checkMessages(inputMessage: string, outputMessage: string) { | ||
const messages = getManualChatMessages(); | ||
messages.should('have.length', 2); | ||
messages.should('contain', inputMessage); | ||
messages.should('contain', outputMessage); | ||
|
||
getManualChatModalLogs().should('exist'); | ||
getManualChatModalLogsEntries() | ||
.should('have.length', 1) | ||
.should('contain', AI_MEMORY_POSTGRES_NODE_NAME); | ||
} | ||
|
||
describe("AI-233 Make root node's logs pane active in case of an error in sub-nodes", () => { | ||
beforeEach(() => { | ||
navigateToNewWorkflowPage(); | ||
}); | ||
|
||
it('should open logs tab by default when there was an error', () => { | ||
setupTestWorkflow(true); | ||
|
||
openNode(AGENT_NODE_NAME); | ||
|
||
const inputMessage = 'Test the code tool'; | ||
|
||
clickExecuteNode(); | ||
runMockWorkflowExecution({ | ||
trigger: () => sendManualChatMessage(inputMessage), | ||
runData: createRunDataWithError(inputMessage), | ||
lastNodeExecuted: AGENT_NODE_NAME, | ||
}); | ||
|
||
checkMessages(inputMessage, '[ERROR: Internal error]'); | ||
closeManualChatModal(); | ||
|
||
// Open the AI Agent node to see the logs | ||
openNode(AGENT_NODE_NAME); | ||
|
||
// Finally check that logs pane is opened by default | ||
ndv.getters.outputDataContainer().should('be.visible'); | ||
|
||
ndv.getters.aiOutputModeToggle().should('be.visible'); | ||
ndv.getters | ||
.aiOutputModeToggle() | ||
.find('[role="radio"]') | ||
.should('have.length', 2) | ||
.eq(1) | ||
.should('have.attr', 'aria-checked', 'true'); | ||
|
||
ndv.getters | ||
.outputPanel() | ||
.findChildByTestId('node-error-message') | ||
.should('be.visible') | ||
.should('contain', 'Error in sub-node'); | ||
}); | ||
|
||
it('should switch to logs tab on error, when NDV is already opened', () => { | ||
setupTestWorkflow(false); | ||
|
||
openNode(AGENT_NODE_NAME); | ||
|
||
const inputMessage = 'Test the code tool'; | ||
|
||
runMockWorkflowExecution({ | ||
trigger: () => clickExecuteNode(), | ||
runData: createRunDataWithError(inputMessage), | ||
lastNodeExecuted: AGENT_NODE_NAME, | ||
}); | ||
|
||
// Check that logs pane is opened by default | ||
ndv.getters.outputDataContainer().should('be.visible'); | ||
|
||
ndv.getters.aiOutputModeToggle().should('be.visible'); | ||
ndv.getters | ||
.aiOutputModeToggle() | ||
.find('[role="radio"]') | ||
.should('have.length', 2) | ||
.eq(1) | ||
.should('have.attr', 'aria-checked', 'true'); | ||
|
||
ndv.getters | ||
.outputPanel() | ||
.findChildByTestId('node-error-message') | ||
.should('be.visible') | ||
.should('contain', 'Error in sub-node'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.