Refactor message post-processing logic to improve handling of workflow outputs and assumptions. Updated test cases to reflect changes in message structure and added type definitions for flagChat results. Enhanced error handling for scenarios with minimal workflow output.

This commit is contained in:
dal 2025-08-18 23:42:27 -06:00
parent 1d3146e35b
commit f0796b35af
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
4 changed files with 25 additions and 46 deletions

View File

@ -190,12 +190,8 @@ describe('data-transformers', () => {
expect(result).toEqual({ expect(result).toEqual({
conversationHistory: [{ role: 'user', content: 'Hello' }], conversationHistory: [{ role: 'user', content: 'Hello' }],
userName: 'John Doe', userName: 'John Doe',
messageId: 'msg-123',
userId: 'user-123',
chatId: 'chat-123',
isFollowUp: false, isFollowUp: false,
isSlackFollowUp: false, isSlackFollowUp: false,
previousMessages: [],
datasets: 'yaml content', datasets: 'yaml content',
}); });
}); });
@ -212,8 +208,6 @@ describe('data-transformers', () => {
expect(result.isFollowUp).toBe(true); expect(result.isFollowUp).toBe(true);
expect(result.isSlackFollowUp).toBe(true); expect(result.isSlackFollowUp).toBe(true);
expect(result.previousMessages).toHaveLength(1);
expect(result.previousMessages[0]).toContain('Previous assumption');
}); });
it('should handle null userName', () => { it('should handle null userName', () => {

View File

@ -1,6 +1,6 @@
import type { PermissionedDataset } from '@buster/access-controls'; import type { PermissionedDataset } from '@buster/access-controls';
import type { MessageHistory } from '@buster/ai/utils/memory/types'; import type { MessageHistory } from '@buster/ai/utils/memory/types';
import type { PostProcessingWorkflowInput } from '@buster/ai/workflows/post-processing-workflow'; import type { PostProcessingWorkflowInput } from '@buster/ai/workflows/message-post-processing-workflow/message-post-processing-workflow';
import type { MessageContext, PostProcessingResult } from '../types'; import type { MessageContext, PostProcessingResult } from '../types';
/** /**
@ -56,21 +56,14 @@ export function buildWorkflowInput(
// Determine if this is a Slack follow-up (both follow-up AND Slack message exists) // Determine if this is a Slack follow-up (both follow-up AND Slack message exists)
const isSlackFollowUp = isFollowUp && slackMessageExists; const isSlackFollowUp = isFollowUp && slackMessageExists;
// Format previous messages
const previousMessages = formatPreviousMessages(previousPostProcessingResults);
// Concatenate datasets // Concatenate datasets
const datasetsYaml = concatenateDatasets(datasets); const datasetsYaml = concatenateDatasets(datasets);
return { return {
conversationHistory, conversationHistory,
userName: messageContext.userName || 'Unknown User', userName: messageContext.userName || 'Unknown User',
messageId: messageContext.id,
userId: messageContext.createdBy,
chatId: messageContext.chatId,
isFollowUp, isFollowUp,
isSlackFollowUp, isSlackFollowUp,
previousMessages,
datasets: datasetsYaml, datasets: datasetsYaml,
}; };
} }

View File

@ -124,12 +124,13 @@ describe('messagePostProcessingTask', () => {
descriptiveTitle: 'Test assumption', descriptiveTitle: 'Test assumption',
classification: 'business_rules', classification: 'business_rules',
explanation: 'Test explanation', explanation: 'Test explanation',
label: 'important', label: 'major' as const,
}, },
], ],
toolCalled: 'analyze', toolCalled: 'analyze',
}, },
flagChatResult: { flagChatResult: {
type: 'flagChat' as const,
summaryTitle: 'Test Summary', summaryTitle: 'Test Summary',
summaryMessage: 'Test summary message', summaryMessage: 'Test summary message',
message: 'Test message', message: 'Test message',
@ -156,12 +157,8 @@ describe('messagePostProcessingTask', () => {
vi.mocked(helpers.buildWorkflowInput).mockReturnValue({ vi.mocked(helpers.buildWorkflowInput).mockReturnValue({
conversationHistory: [{ role: 'user', content: 'Hello' }], conversationHistory: [{ role: 'user', content: 'Hello' }],
userName: 'John Doe', userName: 'John Doe',
messageId,
userId: 'user-123',
chatId: 'chat-123',
isFollowUp: false, isFollowUp: false,
isSlackFollowUp: false, isSlackFollowUp: false,
previousMessages: [],
datasets: '', datasets: '',
}); });
vi.mocked(postProcessingWorkflow).mockResolvedValue(workflowOutput); vi.mocked(postProcessingWorkflow).mockResolvedValue(workflowOutput);
@ -190,15 +187,15 @@ describe('messagePostProcessingTask', () => {
expect(mockDb.update).toHaveBeenCalledWith(database.messages); expect(mockDb.update).toHaveBeenCalledWith(database.messages);
expect(mockDb.set).toHaveBeenCalledWith({ expect(mockDb.set).toHaveBeenCalledWith({
postProcessingMessage: { postProcessingMessage: {
summary_message: 'Test message', summary_message: 'Test summary message',
summary_title: 'No Major Assumptions Identified', summary_title: 'Test Summary',
confidence_score: 'high', confidence_score: 'low',
assumptions: [ assumptions: [
{ {
descriptive_title: 'Test assumption', descriptive_title: 'Test assumption',
classification: 'business_rules', classification: 'business_rules',
explanation: 'Test explanation', explanation: 'Test explanation',
label: 'important', label: 'major' as const,
}, },
], ],
tool_called: 'analyze', tool_called: 'analyze',
@ -223,6 +220,7 @@ describe('messagePostProcessingTask', () => {
toolCalled: 'analyze', toolCalled: 'analyze',
}, },
flagChatResult: { flagChatResult: {
type: 'noIssuesFound' as const,
summaryTitle: 'Follow-up Analysis', summaryTitle: 'Follow-up Analysis',
summaryMessage: 'Based on previous conversation...', summaryMessage: 'Based on previous conversation...',
message: 'Follow-up message', message: 'Follow-up message',
@ -264,12 +262,8 @@ describe('messagePostProcessingTask', () => {
vi.mocked(helpers.buildWorkflowInput).mockReturnValue({ vi.mocked(helpers.buildWorkflowInput).mockReturnValue({
conversationHistory: undefined, conversationHistory: undefined,
userName: 'John Doe', userName: 'John Doe',
messageId,
userId: 'user-123',
chatId: 'chat-123',
isFollowUp: true, isFollowUp: true,
isSlackFollowUp: true, isSlackFollowUp: true,
previousMessages: ['{"assumptions":["Previous assumption"]}'],
datasets: '', datasets: '',
}); });
vi.mocked(postProcessingWorkflow).mockResolvedValue(workflowOutput); vi.mocked(postProcessingWorkflow).mockResolvedValue(workflowOutput);
@ -294,7 +288,7 @@ describe('messagePostProcessingTask', () => {
); );
}); });
it('should return error result when workflow returns no output', async () => { it('should handle workflow with minimal output', async () => {
const messageId = '123e4567-e89b-12d3-a456-426614174000'; const messageId = '123e4567-e89b-12d3-a456-426614174000';
vi.mocked(helpers.fetchMessageWithContext).mockResolvedValue({ vi.mocked(helpers.fetchMessageWithContext).mockResolvedValue({
@ -324,28 +318,29 @@ describe('messagePostProcessingTask', () => {
vi.mocked(helpers.buildWorkflowInput).mockReturnValue({ vi.mocked(helpers.buildWorkflowInput).mockReturnValue({
conversationHistory: undefined, conversationHistory: undefined,
userName: 'John Doe', userName: 'John Doe',
messageId,
userId: 'user-123',
chatId: 'chat-123',
isFollowUp: false, isFollowUp: false,
isSlackFollowUp: false, isSlackFollowUp: false,
previousMessages: [],
datasets: '', datasets: '',
}); });
vi.mocked(postProcessingWorkflow).mockResolvedValue(null); vi.mocked(postProcessingWorkflow).mockResolvedValue({
flagChatResult: {
type: 'noIssuesFound' as const,
},
assumptionsResult: {
toolCalled: 'none',
},
});
const result = await runTask({ messageId }); const result = await runTask({ messageId });
expect(result).toEqual({ expect(result).toEqual({
success: false, success: true,
messageId, messageId,
error: { result: {
code: 'WORKFLOW_EXECUTION_ERROR', success: true,
message: 'Post-processing workflow returned no output',
details: {
operation: 'message_post_processing_task_execution',
messageId, messageId,
}, executionTimeMs: expect.any(Number),
workflowCompleted: true,
}, },
}); });
}); });
@ -403,12 +398,8 @@ describe('messagePostProcessingTask', () => {
vi.mocked(helpers.buildWorkflowInput).mockReturnValue({ vi.mocked(helpers.buildWorkflowInput).mockReturnValue({
conversationHistory: undefined, conversationHistory: undefined,
userName: 'John Doe', userName: 'John Doe',
messageId,
userId: 'user-123',
chatId: 'chat-123',
isFollowUp: false, isFollowUp: false,
isSlackFollowUp: false, isSlackFollowUp: false,
previousMessages: [],
datasets: '', datasets: '',
}); });
vi.mocked(postProcessingWorkflow).mockResolvedValue({ vi.mocked(postProcessingWorkflow).mockResolvedValue({
@ -417,6 +408,7 @@ describe('messagePostProcessingTask', () => {
toolCalled: 'analyze', toolCalled: 'analyze',
}, },
flagChatResult: { flagChatResult: {
type: 'flagChat' as const,
summaryTitle: 'Summary', summaryTitle: 'Summary',
summaryMessage: 'Summary message', summaryMessage: 'Summary message',
message: 'Summary message', message: 'Summary message',

View File

@ -153,7 +153,7 @@ export const messagePostProcessingTask: ReturnType<
messageId: payload.messageId, messageId: payload.messageId,
isFollowUp: workflowInput.isFollowUp, isFollowUp: workflowInput.isFollowUp,
isSlackFollowUp: workflowInput.isSlackFollowUp, isSlackFollowUp: workflowInput.isSlackFollowUp,
previousMessagesCount: workflowInput.previousMessages.length, previousMessagesCount: previousPostProcessingResults.length,
hasConversationHistory: !!workflowInput.conversationHistory, hasConversationHistory: !!workflowInput.conversationHistory,
datasetsLength: workflowInput.datasets.length, datasetsLength: workflowInput.datasets.length,
}); });