diff --git a/src/modules/temporal/activities/nodes/add-label.node.ts b/src/modules/temporal/activities/nodes/add-label.node.ts index 89301de..71dcc5c 100644 --- a/src/modules/temporal/activities/nodes/add-label.node.ts +++ b/src/modules/temporal/activities/nodes/add-label.node.ts @@ -7,6 +7,9 @@ export interface AddLabelNodeInput { labelId: string; labelName?: string; sessionId: string; + // EVO-1917: journeyId lets interpolateNodeData load journey-level variable + // defaults so {{variables}} resolve in this node (mirrors send-webhook). + journeyId?: string; nodeData: { labelId: string; nextNodeId?: string; diff --git a/src/modules/temporal/activities/nodes/base.node.spec.ts b/src/modules/temporal/activities/nodes/base.node.spec.ts index 4f249eb..c486c4a 100644 --- a/src/modules/temporal/activities/nodes/base.node.spec.ts +++ b/src/modules/temporal/activities/nodes/base.node.spec.ts @@ -75,6 +75,31 @@ describe('BaseNode.interpolateNodeData — journeyId fallback (EVO-1885)', () => expect(findOne).toHaveBeenCalledWith({ where: { id: 'journey-from-input' } }); }); + // EVO-1917: the dispatch sweep threads input.journeyId to every interpolating + // executor. This proves that thread is load-bearing: when the cached session + // carries no journeyId (e.g. a lean cache shape), the explicitly-dispatched + // input.journeyId is what resolves journey-default {{variables}}. + it('EVO-1917: resolves journey defaults from input.journeyId when session has none', async () => { + mockGetSessionFromCache.mockResolvedValue({ + id: 's1', + // no journeyId on the session — only the dispatched input carries it + variables: {}, + }); + findOne.mockResolvedValue({ + variables: [{ name: 'greeting', defaultValue: 'Olá' }], + }); + + const result = await node.interpolate( + { sessionId: 's1', journeyId: 'journey-from-dispatch' }, + { message: '{{greeting}}' }, + ); + + expect(findOne).toHaveBeenCalledWith({ + where: { id: 'journey-from-dispatch' }, + }); + expect(result.message).toBe('Olá'); + }); + it('AC3: skips the journey query when no id resolves, leaving journey-default tokens literal', async () => { mockGetSessionFromCache.mockResolvedValue({ id: 's1', diff --git a/src/modules/temporal/activities/nodes/conditional.node.ts b/src/modules/temporal/activities/nodes/conditional.node.ts index 4f1b0fd..c105272 100644 --- a/src/modules/temporal/activities/nodes/conditional.node.ts +++ b/src/modules/temporal/activities/nodes/conditional.node.ts @@ -17,6 +17,7 @@ export interface ConditionalNodeInput { contactId: string; conversationId?: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} in condition values via interpolateNodeData nodeData: { paths: Array<{ id: string; diff --git a/src/modules/temporal/activities/nodes/evoai/assignment/assign-agent.node.ts b/src/modules/temporal/activities/nodes/evoai/assignment/assign-agent.node.ts index 7f7bdb4..add17b5 100644 --- a/src/modules/temporal/activities/nodes/evoai/assignment/assign-agent.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/assignment/assign-agent.node.ts @@ -5,6 +5,7 @@ export interface AssignAgentNodeInput { nodeId: string; conversationId: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { agent_id?: string; agent_name?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/assignment/assign-bot.node.ts b/src/modules/temporal/activities/nodes/evoai/assignment/assign-bot.node.ts index 1783799..b63413f 100644 --- a/src/modules/temporal/activities/nodes/evoai/assignment/assign-bot.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/assignment/assign-bot.node.ts @@ -5,6 +5,7 @@ export interface AssignBotNodeInput { nodeId: string; conversationId: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { bot_id?: string; bot_name?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/assignment/assign-team.node.ts b/src/modules/temporal/activities/nodes/evoai/assignment/assign-team.node.ts index 482540b..30959a1 100644 --- a/src/modules/temporal/activities/nodes/evoai/assignment/assign-team.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/assignment/assign-team.node.ts @@ -5,6 +5,7 @@ export interface AssignTeamNodeInput { nodeId: string; conversationId: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { team_id?: string; team_name?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/communication/send-canned-response.node.ts b/src/modules/temporal/activities/nodes/evoai/communication/send-canned-response.node.ts index 91c6011..b6225a1 100644 --- a/src/modules/temporal/activities/nodes/evoai/communication/send-canned-response.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/communication/send-canned-response.node.ts @@ -6,6 +6,7 @@ export interface SendCannedResponseNodeInput { conversationId?: string; sessionId: string; contactId?: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { canned_response_id?: string; cannedResponseId?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/communication/send-email-team.node.ts b/src/modules/temporal/activities/nodes/evoai/communication/send-email-team.node.ts index 6b7ca87..c784b59 100644 --- a/src/modules/temporal/activities/nodes/evoai/communication/send-email-team.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/communication/send-email-team.node.ts @@ -5,6 +5,7 @@ export interface SendEmailTeamNodeInput { nodeId: string; conversationId?: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { team_ids?: string[]; teamIds?: string[]; diff --git a/src/modules/temporal/activities/nodes/evoai/communication/send-message.node.ts b/src/modules/temporal/activities/nodes/evoai/communication/send-message.node.ts index 510606d..079a187 100644 --- a/src/modules/temporal/activities/nodes/evoai/communication/send-message.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/communication/send-message.node.ts @@ -31,6 +31,7 @@ export interface SendMessageNodeInput { conversationId?: string; // Optional - will create new conversation if not provided sessionId: string; contactId?: string; // Add contactId for creating new conversations + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} in the message body via interpolateNodeData nodeData: { message?: string; message_content?: string; // Alternative field name from frontend diff --git a/src/modules/temporal/activities/nodes/evoai/communication/send-transcript.node.ts b/src/modules/temporal/activities/nodes/evoai/communication/send-transcript.node.ts index 00e31f9..c0a7c25 100644 --- a/src/modules/temporal/activities/nodes/evoai/communication/send-transcript.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/communication/send-transcript.node.ts @@ -5,6 +5,7 @@ export interface SendTranscriptNodeInput { nodeId: string; conversationId: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { email?: string; recipient_email?: string; // Alternative field name from frontend diff --git a/src/modules/temporal/activities/nodes/evoai/conversation/change-priority.node.ts b/src/modules/temporal/activities/nodes/evoai/conversation/change-priority.node.ts index a37b297..36bd873 100644 --- a/src/modules/temporal/activities/nodes/evoai/conversation/change-priority.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/conversation/change-priority.node.ts @@ -5,6 +5,7 @@ export interface ChangePriorityNodeInput { nodeId: string; conversationId: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { priority?: 'low' | 'medium' | 'high' | 'urgent' | null; nextNodeId?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/pipeline/assign-to-pipeline.node.ts b/src/modules/temporal/activities/nodes/evoai/pipeline/assign-to-pipeline.node.ts index 8e4206e..c402000 100644 --- a/src/modules/temporal/activities/nodes/evoai/pipeline/assign-to-pipeline.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/pipeline/assign-to-pipeline.node.ts @@ -5,6 +5,7 @@ export interface AssignToPipelineNodeInput { nodeId: string; conversationId?: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { pipeline_id?: string; pipelineId?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/pipeline/create-pipeline-task.node.ts b/src/modules/temporal/activities/nodes/evoai/pipeline/create-pipeline-task.node.ts index 68403d4..c0bcff2 100644 --- a/src/modules/temporal/activities/nodes/evoai/pipeline/create-pipeline-task.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/pipeline/create-pipeline-task.node.ts @@ -12,6 +12,7 @@ export interface CreatePipelineTaskNodeInput { nodeId: string; conversationId?: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { title?: string; description?: string; diff --git a/src/modules/temporal/activities/nodes/evoai/pipeline/move-to-pipeline-stage.node.ts b/src/modules/temporal/activities/nodes/evoai/pipeline/move-to-pipeline-stage.node.ts index e929f01..3da6757 100644 --- a/src/modules/temporal/activities/nodes/evoai/pipeline/move-to-pipeline-stage.node.ts +++ b/src/modules/temporal/activities/nodes/evoai/pipeline/move-to-pipeline-stage.node.ts @@ -12,6 +12,7 @@ export interface MoveToPipelineStageNodeInput { nodeId: string; conversationId?: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { pipeline_id?: string; pipelineId?: string; diff --git a/src/modules/temporal/activities/nodes/remove-label.node.ts b/src/modules/temporal/activities/nodes/remove-label.node.ts index fbfaf8d..39bc381 100644 --- a/src/modules/temporal/activities/nodes/remove-label.node.ts +++ b/src/modules/temporal/activities/nodes/remove-label.node.ts @@ -7,6 +7,7 @@ export interface RemoveLabelNodeInput { labelId: string; labelName?: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { labelId: string; nextNodeId?: string; diff --git a/src/modules/temporal/activities/nodes/update-contact.node.ts b/src/modules/temporal/activities/nodes/update-contact.node.ts index 4b04c26..e497502 100644 --- a/src/modules/temporal/activities/nodes/update-contact.node.ts +++ b/src/modules/temporal/activities/nodes/update-contact.node.ts @@ -4,6 +4,7 @@ export interface UpdateContactNodeInput { nodeId: string; contactId: string; sessionId: string; + journeyId?: string; // EVO-1917: resolve journey-default {{variables}} via interpolateNodeData nodeData: { fieldToUpdate?: string; newValue?: any; diff --git a/src/modules/temporal/workflows/journey-execution.workflow.ts b/src/modules/temporal/workflows/journey-execution.workflow.ts index 126877f..4e993d5 100644 --- a/src/modules/temporal/workflows/journey-execution.workflow.ts +++ b/src/modules/temporal/workflows/journey-execution.workflow.ts @@ -669,6 +669,9 @@ export async function JourneyExecutionWorkflow( labelId: currentNode.data.labelId, labelName: currentNode.data.labelName, sessionId: input.sessionId, + // EVO-1917: thread journeyId so interpolateNodeData resolves + // journey-default {{variables}} (mirrors send-webhook/scheduled-action). + journeyId: input.journeyId, nodeData: currentNode.data, }); break; @@ -681,6 +684,7 @@ export async function JourneyExecutionWorkflow( labelId: currentNode.data.labelId, labelName: currentNode.data.labelName, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -691,6 +695,7 @@ export async function JourneyExecutionWorkflow( nodeId: currentNode.id, contactId: input.contactId, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -778,6 +783,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || undefined, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917: resolve journey-default {{var}} in condition values nodeData: currentNode.data, }); break; @@ -797,6 +803,7 @@ export async function JourneyExecutionWorkflow( conversationId: conversationId || undefined, sessionId: input.sessionId, contactId: input.contactId, // Pass contactId for creating new conversations + journeyId: input.journeyId, // EVO-1917: resolve journey-default {{var}} in message body nodeData: currentNode.data, }); @@ -817,6 +824,7 @@ export async function JourneyExecutionWorkflow( input.triggerEvent?.properties?.conversation_id || undefined, sessionId: input.sessionId, contactId: input.contactId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -827,6 +835,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || undefined, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -838,6 +847,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || undefined, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -849,6 +859,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || undefined, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -860,6 +871,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || undefined, sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -870,6 +882,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || '', sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -880,6 +893,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || '', sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -890,6 +904,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || '', sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -901,6 +916,7 @@ export async function JourneyExecutionWorkflow( input.triggerEvent?.properties?.conversation_id || 'inbox-level', // Bot assignment can work without specific conversation sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break; @@ -957,6 +973,7 @@ export async function JourneyExecutionWorkflow( conversationId: input.triggerEvent?.properties?.conversation_id || '', sessionId: input.sessionId, + journeyId: input.journeyId, // EVO-1917 nodeData: currentNode.data, }); break;