@webex/contact-center 3.12.0-task-refactor.4 → 3.12.0-task-refactor.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/task/TaskManager.js +1 -0
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +8 -6
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/state-machine/TaskStateMachine.js +77 -14
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
- package/dist/services/task/state-machine/actions.js +85 -13
- package/dist/services/task/state-machine/actions.js.map +1 -1
- package/dist/services/task/state-machine/guards.js +35 -0
- package/dist/services/task/state-machine/guards.js.map +1 -1
- package/dist/services/task/state-machine/uiControlsComputer.js +76 -10
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
- package/dist/services/task/voice/Voice.js +10 -4
- package/dist/services/task/voice/Voice.js.map +1 -1
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +68 -8
- package/dist/types/services/task/state-machine/guards.d.ts +5 -0
- package/dist/types/services/task/voice/Voice.d.ts +18 -17
- package/dist/webex.js +1 -1
- package/package.json +1 -1
- package/src/services/task/TaskManager.ts +1 -1
- package/src/services/task/TaskUtils.ts +8 -6
- package/src/services/task/state-machine/TaskStateMachine.ts +101 -16
- package/src/services/task/state-machine/actions.ts +148 -24
- package/src/services/task/state-machine/guards.ts +46 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +158 -15
- package/src/services/task/voice/Voice.ts +12 -5
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- package/test/unit/spec/services/task/TaskManager.ts +26 -0
- package/test/unit/spec/services/task/TaskUtils.ts +16 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +573 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +88 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +1023 -46
- package/test/unit/spec/services/task/voice/Voice.ts +44 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -98,6 +98,17 @@ const guards = exports.guards = {
|
|
|
98
98
|
const taskData = getTaskDataFromEvent(event);
|
|
99
99
|
if (taskData?.interaction?.state === _constants.INTERACTION_STATE.CONSULTING) return true;
|
|
100
100
|
|
|
101
|
+
// Hydrate can report interaction as conference/hold while this agent is actively consulting.
|
|
102
|
+
// Detect consult by participant consultState + consult media, independent of top-level state.
|
|
103
|
+
const selfAgentId = getSelfAgentId(context, taskData);
|
|
104
|
+
const selfParticipant = selfAgentId ? taskData?.interaction?.participants?.[selfAgentId] : null;
|
|
105
|
+
const hasConsultMedia = Object.values(taskData?.interaction?.media ?? {}).some(media => media?.mType === _constants.MEDIA_TYPE_CONSULT);
|
|
106
|
+
const selfActiveConsult = selfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING;
|
|
107
|
+
const selfPendingConsultInitiated = selfParticipant?.consultState === 'consultInitiated' && taskData?.isConsulted === false;
|
|
108
|
+
if ((selfActiveConsult || selfPendingConsultInitiated) && hasConsultMedia) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
|
|
101
112
|
// EP_DN consulted agent: backend reports state as 'connected' but CPD indicates consult
|
|
102
113
|
const cpd = taskData?.interaction?.callProcessingDetails;
|
|
103
114
|
if (cpd?.relationshipType === 'consult' && taskData?.interaction?.state === _constants.INTERACTION_STATE.CONNECTED) {
|
|
@@ -109,6 +120,17 @@ const guards = exports.guards = {
|
|
|
109
120
|
if (hasActiveConsultInPostCall(taskData, getSelfAgentId(context, taskData))) {
|
|
110
121
|
return true;
|
|
111
122
|
}
|
|
123
|
+
|
|
124
|
+
// Customer left during consult: interaction state is "post_call" but consult
|
|
125
|
+
// between agents is still active. Detect via agent's consultState + consult media.
|
|
126
|
+
if (taskData?.interaction?.state === _constants.INTERACTION_STATE.POST_CALL) {
|
|
127
|
+
const postCallSelfAgentId = getSelfAgentId(context, taskData);
|
|
128
|
+
const postCallSelfParticipant = postCallSelfAgentId ? taskData?.interaction?.participants?.[postCallSelfAgentId] : null;
|
|
129
|
+
const hasPostCallConsultMedia = Object.values(taskData?.interaction?.media ?? {}).some(media => media?.mType === _constants.MEDIA_TYPE_CONSULT);
|
|
130
|
+
if (postCallSelfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING && hasPostCallConsultMedia) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
112
134
|
return false;
|
|
113
135
|
},
|
|
114
136
|
isInteractionHeld: ({
|
|
@@ -154,6 +176,19 @@ const guards = exports.guards = {
|
|
|
154
176
|
if (!taskData?.interaction) return false;
|
|
155
177
|
return (0, _TaskUtils.getIsConferenceInProgress)(taskData);
|
|
156
178
|
},
|
|
179
|
+
/**
|
|
180
|
+
* Conference hold signal for conference-downgraded consult-end transitions.
|
|
181
|
+
* Backend can report this as boolean or string.
|
|
182
|
+
*/
|
|
183
|
+
isConferenceHoldParticipantFromEvent: ({
|
|
184
|
+
context,
|
|
185
|
+
event
|
|
186
|
+
}) => {
|
|
187
|
+
const taskData = getTaskDataFromEvent(event) ?? context.taskData;
|
|
188
|
+
const callProcessingDetails = taskData?.interaction?.callProcessingDetails;
|
|
189
|
+
const conferenceHoldParticipant = callProcessingDetails?.conferenceHoldParticipant;
|
|
190
|
+
return conferenceHoldParticipant === true || conferenceHoldParticipant === 'true';
|
|
191
|
+
},
|
|
157
192
|
/**
|
|
158
193
|
* Conference downgrade check specifically for transitioning back to CONNECTED.
|
|
159
194
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_TaskUtils","require","_constants","getTaskDataFromEvent","event","taskData","undefined","exports","getSelfAgentId","context","uiControlConfig","agentId","isSelfConsultingAgent","selfAgentId","consultingAgentId","hasActiveConsultInPostCall","interaction","state","INTERACTION_STATE","POST_CALL","selfParticipant","participants","hasConsultMedia","Object","values","media","some","mType","MEDIA_TYPE_CONSULT","consultState","CONSULT_STATE","CONSULTING","shouldWrapUpForThisAgent","pending","agentsPendingWrapUp","Array","isArray","length","includes","participantWrapUp","isWrapUp","wrapUpRequired","owner","isConsulted","guards","isInteractionTerminated","isTerminated","isInteractionConsulting","cpd","callProcessingDetails","relationshipType","CONNECTED","isInteractionHeld","mainMediaId","mainInteractionId","interactionId","isHold","isInteractionConnected","isConferencingByParticipants","mainCallId","agentCount","pId","p","pType","hasLeft","conferenceInProgressFromEvent","getIsConferenceInProgress","shouldDowngradeConferenceToConnected","eventTaskData","CONFERENCE","agentParticipantsCount","getConferenceParticipantsCount","customerInCall","getIsCustomerInCall","selfInMainCall","Boolean","didInitiateConsult","consultInitiator","isConsultingAssignment","shouldWrapUp","type","TaskEvent","CONFERENCE_END","shouldWrapUpOrIsInitiator","didCurrentAgentLeaveConference","participantIdFromEvent","participantId","isPrimaryMediaOnHold","mediaId","mediaResourceId"],"sources":["guards.ts"],"sourcesContent":["/**\n * Task State Machine Guards\n *\n * Guard functions that determine if a state transition is allowed.\n * These functions validate the current context before allowing transitions.\n *\n * All guards are consolidated here for:\n * - Single source of truth\n * - Easy testing\n * - Reusability across state machine transitions\n *\n * Guards are organized by category:\n * 1. Helper Functions - Extract data from events/context\n * 2. Hydrate Guards - For state restoration on page refresh\n * 3. Conference Guards - Conference state checks\n * 4. Customer Guards - Customer presence checks\n * 5. Consult Guards - Consult flow checks\n * 6. Wrapup Guards - End-of-call flow checks\n * 7. Server State Guards - Check backend-reported state\n * 8. Recording Guards - Recording state checks\n */\n\nimport {TaskContext, TaskEventPayload} from './types';\nimport {TaskData} from '../types';\nimport {\n getIsCustomerInCall,\n getConferenceParticipantsCount,\n getIsConferenceInProgress,\n} from '../TaskUtils';\nimport {TaskEvent, INTERACTION_STATE, CONSULT_STATE, MEDIA_TYPE_CONSULT} from './constants';\n\nexport const getTaskDataFromEvent = (event?: TaskEventPayload): TaskData | undefined =>\n event && typeof event === 'object' && 'taskData' in event\n ? (event as {taskData?: TaskData}).taskData\n : undefined;\n\nexport const getSelfAgentId = (context: TaskContext, taskData?: TaskData): string | undefined =>\n context.uiControlConfig?.agentId ?? context.taskData?.agentId ?? taskData?.agentId;\n\nexport const isSelfConsultingAgent = (context: TaskContext, taskData?: TaskData): boolean => {\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n return taskData?.consultingAgentId === selfAgentId;\n};\n\n/**\n * Detects an active consult during post_call state (customer left but agents still consulting).\n * Shared by hydration guard (isInteractionConsulting) and action (deriveTaskDataUpdates).\n */\nexport const hasActiveConsultInPostCall = (\n taskData: TaskData | undefined,\n selfAgentId?: string\n): boolean => {\n if (taskData?.interaction?.state !== INTERACTION_STATE.POST_CALL || !selfAgentId) return false;\n\n const selfParticipant = taskData.interaction?.participants?.[selfAgentId];\n const hasConsultMedia = Object.values(taskData.interaction?.media ?? {}).some(\n (media) => (media as {mType?: string})?.mType === MEDIA_TYPE_CONSULT\n );\n\n return selfParticipant?.consultState === CONSULT_STATE.CONSULTING && hasConsultMedia;\n};\n\n/**\n * Determines if this agent should enter WRAPPING_UP state.\n * Priority: agentsPendingWrapUp > wrapUpRequired / participant.isWrapUp > ownership > !isConsulted\n */\nexport const shouldWrapUpForThisAgent = (context: TaskContext, taskData: TaskData): boolean => {\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const pending = taskData?.agentsPendingWrapUp;\n if (Array.isArray(pending) && pending.length > 0) {\n return pending.includes(selfAgentId);\n }\n\n const participantWrapUp = taskData?.interaction?.participants?.[selfAgentId]?.isWrapUp === true;\n const wrapUpRequired = taskData?.wrapUpRequired === true;\n if (wrapUpRequired || participantWrapUp) {\n return true;\n }\n\n const owner = taskData?.interaction?.owner;\n if (owner && owner === selfAgentId) {\n return true;\n }\n\n if (taskData?.isConsulted === false) {\n return true;\n }\n\n return false;\n};\n\nexport interface GuardParams {\n context: TaskContext;\n event?: TaskEventPayload;\n}\n\nexport type GuardFunction = (params: GuardParams) => boolean;\n\nexport const guards = {\n // Hydrate Guards\n isInteractionTerminated: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n if (taskData?.interaction?.isTerminated === true) return true;\n\n const selfAgentId = getSelfAgentId(context, taskData);\n if (selfAgentId && taskData?.interaction?.participants?.[selfAgentId]?.isWrapUp === true) {\n return true;\n }\n\n return false;\n },\n\n isInteractionConsulting: ({event, context}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n if (taskData?.interaction?.state === INTERACTION_STATE.CONSULTING) return true;\n\n // EP_DN consulted agent: backend reports state as 'connected' but CPD indicates consult\n const cpd = taskData?.interaction?.callProcessingDetails;\n if (\n cpd?.relationshipType === 'consult' &&\n taskData?.interaction?.state === INTERACTION_STATE.CONNECTED\n ) {\n return true;\n }\n\n // Customer left during consult: interaction state is \"post_call\" but consult\n // between agents is still active. Detect via agent's consultState + consult media.\n if (hasActiveConsultInPostCall(taskData, getSelfAgentId(context, taskData))) {\n return true;\n }\n\n return false;\n },\n\n isInteractionHeld: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n if (taskData?.interaction?.state === 'hold') return true;\n\n const mainMediaId = taskData?.interaction?.mainInteractionId || taskData?.interactionId;\n if (mainMediaId && taskData?.interaction?.media?.[mainMediaId]?.isHold === true) {\n return true;\n }\n\n return false;\n },\n\n isInteractionConnected: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n return taskData?.interaction?.state === INTERACTION_STATE.CONNECTED;\n },\n\n isConferencingByParticipants: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n const mainCallId = taskData.interaction?.mainInteractionId || taskData.interactionId;\n const media = taskData.interaction?.media?.[mainCallId];\n const participants = taskData.interaction?.participants;\n if (!media?.participants || !participants) return false;\n let agentCount = 0;\n for (const pId of media.participants) {\n const p = participants[pId];\n if (p && p.pType !== 'Customer' && p.pType !== 'Supervisor' && !p.hasLeft) {\n agentCount += 1;\n }\n }\n\n return agentCount >= 2;\n },\n\n // Conference Guards\n conferenceInProgressFromEvent: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData?.interaction) return false;\n\n return getIsConferenceInProgress(taskData);\n },\n\n /**\n * Conference downgrade check specifically for transitioning back to CONNECTED.\n *\n * Returns true only when:\n * - conference has downgraded (fewer than 2 active agent participants in main call)\n * - customer is still in the call\n * - current agent is still in the main call\n */\n shouldDowngradeConferenceToConnected: ({context, event}: GuardParams): boolean => {\n const eventTaskData = getTaskDataFromEvent(event);\n const taskData = eventTaskData ?? context.taskData;\n if (!taskData?.interaction) return false;\n\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const mainCallId = taskData.interaction.mainInteractionId || taskData.interactionId;\n if (!mainCallId) return false;\n\n // Don't downgrade while backend still reports conference.\n if (taskData.interaction.state === INTERACTION_STATE.CONFERENCE) return false;\n\n const agentParticipantsCount = getConferenceParticipantsCount(taskData.interaction, mainCallId);\n if (agentParticipantsCount >= 2) return false;\n\n const customerInCall = getIsCustomerInCall(taskData.interaction, mainCallId);\n if (!customerInCall) return false;\n\n const selfInMainCall = Boolean(\n taskData.interaction.media?.[mainCallId]?.participants?.includes(selfAgentId)\n );\n\n return selfInMainCall;\n },\n\n // Consult Guards\n /**\n * Check if this agent initiated the consult (using event data)\n * Handles both consultingAgentId and fallback to context flag\n */\n didInitiateConsult: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (taskData?.isConsulted === true) return false;\n\n return taskData?.consultingAgentId\n ? isSelfConsultingAgent(context, taskData)\n : context.consultInitiator === true;\n },\n\n /**\n * EP-DN / consulted consult legs can arrive as AGENT_CONTACT_ASSIGNED without a preceding\n * AgentConsulting event. When that happens, we should enter CONSULTING (not CONNECTED).\n */\n isConsultingAssignment: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n\n const relationshipType = taskData.interaction?.callProcessingDetails?.relationshipType;\n\n return (\n taskData.isConsulted === true ||\n relationshipType === 'consult' ||\n taskData.interaction?.state === INTERACTION_STATE.CONSULTING\n );\n },\n\n // Wrapup Guards\n shouldWrapUp: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n\n if (event?.type === TaskEvent.CONFERENCE_END) {\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const pending = taskData?.agentsPendingWrapUp;\n if (Array.isArray(pending) && pending.length > 0) {\n return pending.includes(selfAgentId);\n }\n\n const participantWrapUp =\n taskData?.interaction?.participants?.[selfAgentId]?.isWrapUp === true;\n const wrapUpRequired = taskData?.wrapUpRequired === true;\n\n return wrapUpRequired || participantWrapUp;\n }\n\n return shouldWrapUpForThisAgent(context, taskData);\n },\n\n /**\n * Check if wrapUpRequired in payload OR is consult initiator\n */\n shouldWrapUpOrIsInitiator: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n return Boolean(taskData?.wrapUpRequired || context.consultInitiator);\n },\n\n /**\n * True if PARTICIPANT_LEAVE indicates that *this* agent left the conference.\n *\n * Important: PARTICIPANT_LEAVE is broadcast to all agents in the conference.\n * Only the agent whose id matches the leaving participant should transition to\n * TERMINATED / WRAPPING_UP based on wrapup rules.\n */\n didCurrentAgentLeaveConference: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const participantIdFromEvent =\n event && typeof event === 'object' && 'participantId' in event\n ? (event as {participantId?: string}).participantId\n : undefined;\n const participantId = participantIdFromEvent ?? taskData?.participantId;\n\n if (Boolean(participantId) && participantId === selfAgentId) {\n return true;\n }\n\n // For EP-DN agents the backend removes the leaving participant entirely\n // from the participants map (rather than setting hasLeft). If this task\n // is in CONFERENCING (implied by the guard being evaluated here) but the\n // agent is absent from the updated participants, they have left.\n const participants = taskData?.interaction?.participants;\n if (participants && !(selfAgentId in participants)) {\n return true;\n }\n\n return false;\n },\n\n // Server State Guards\n isPrimaryMediaOnHold: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n const mediaId = taskData.mediaResourceId;\n if (!mediaId) return false;\n\n return taskData.interaction?.media?.[mediaId]?.isHold === true;\n },\n};\n\nexport type GuardName = keyof typeof guards;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_TaskUtils","require","_constants","getTaskDataFromEvent","event","taskData","undefined","exports","getSelfAgentId","context","uiControlConfig","agentId","isSelfConsultingAgent","selfAgentId","consultingAgentId","hasActiveConsultInPostCall","interaction","state","INTERACTION_STATE","POST_CALL","selfParticipant","participants","hasConsultMedia","Object","values","media","some","mType","MEDIA_TYPE_CONSULT","consultState","CONSULT_STATE","CONSULTING","shouldWrapUpForThisAgent","pending","agentsPendingWrapUp","Array","isArray","length","includes","participantWrapUp","isWrapUp","wrapUpRequired","owner","isConsulted","guards","isInteractionTerminated","isTerminated","isInteractionConsulting","selfActiveConsult","selfPendingConsultInitiated","cpd","callProcessingDetails","relationshipType","CONNECTED","postCallSelfAgentId","postCallSelfParticipant","hasPostCallConsultMedia","isInteractionHeld","mainMediaId","mainInteractionId","interactionId","isHold","isInteractionConnected","isConferencingByParticipants","mainCallId","agentCount","pId","p","pType","hasLeft","conferenceInProgressFromEvent","getIsConferenceInProgress","isConferenceHoldParticipantFromEvent","conferenceHoldParticipant","shouldDowngradeConferenceToConnected","eventTaskData","CONFERENCE","agentParticipantsCount","getConferenceParticipantsCount","customerInCall","getIsCustomerInCall","selfInMainCall","Boolean","didInitiateConsult","consultInitiator","isConsultingAssignment","shouldWrapUp","type","TaskEvent","CONFERENCE_END","shouldWrapUpOrIsInitiator","didCurrentAgentLeaveConference","participantIdFromEvent","participantId","isPrimaryMediaOnHold","mediaId","mediaResourceId"],"sources":["guards.ts"],"sourcesContent":["/**\n * Task State Machine Guards\n *\n * Guard functions that determine if a state transition is allowed.\n * These functions validate the current context before allowing transitions.\n *\n * All guards are consolidated here for:\n * - Single source of truth\n * - Easy testing\n * - Reusability across state machine transitions\n *\n * Guards are organized by category:\n * 1. Helper Functions - Extract data from events/context\n * 2. Hydrate Guards - For state restoration on page refresh\n * 3. Conference Guards - Conference state checks\n * 4. Customer Guards - Customer presence checks\n * 5. Consult Guards - Consult flow checks\n * 6. Wrapup Guards - End-of-call flow checks\n * 7. Server State Guards - Check backend-reported state\n * 8. Recording Guards - Recording state checks\n */\n\nimport {TaskContext, TaskEventPayload} from './types';\nimport {TaskData} from '../types';\nimport {\n getIsCustomerInCall,\n getConferenceParticipantsCount,\n getIsConferenceInProgress,\n} from '../TaskUtils';\nimport {TaskEvent, INTERACTION_STATE, CONSULT_STATE, MEDIA_TYPE_CONSULT} from './constants';\n\nexport const getTaskDataFromEvent = (event?: TaskEventPayload): TaskData | undefined =>\n event && typeof event === 'object' && 'taskData' in event\n ? (event as {taskData?: TaskData}).taskData\n : undefined;\n\nexport const getSelfAgentId = (context: TaskContext, taskData?: TaskData): string | undefined =>\n context.uiControlConfig?.agentId ?? context.taskData?.agentId ?? taskData?.agentId;\n\nexport const isSelfConsultingAgent = (context: TaskContext, taskData?: TaskData): boolean => {\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n return taskData?.consultingAgentId === selfAgentId;\n};\n\n/**\n * Detects an active consult during post_call state (customer left but agents still consulting).\n * Shared by hydration guard (isInteractionConsulting) and action (deriveTaskDataUpdates).\n */\nexport const hasActiveConsultInPostCall = (\n taskData: TaskData | undefined,\n selfAgentId?: string\n): boolean => {\n if (taskData?.interaction?.state !== INTERACTION_STATE.POST_CALL || !selfAgentId) return false;\n\n const selfParticipant = taskData.interaction?.participants?.[selfAgentId];\n const hasConsultMedia = Object.values(taskData.interaction?.media ?? {}).some(\n (media) => (media as {mType?: string})?.mType === MEDIA_TYPE_CONSULT\n );\n\n return selfParticipant?.consultState === CONSULT_STATE.CONSULTING && hasConsultMedia;\n};\n\n/**\n * Determines if this agent should enter WRAPPING_UP state.\n * Priority: agentsPendingWrapUp > wrapUpRequired / participant.isWrapUp > ownership > !isConsulted\n */\nexport const shouldWrapUpForThisAgent = (context: TaskContext, taskData: TaskData): boolean => {\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const pending = taskData?.agentsPendingWrapUp;\n if (Array.isArray(pending) && pending.length > 0) {\n return pending.includes(selfAgentId);\n }\n\n const participantWrapUp = taskData?.interaction?.participants?.[selfAgentId]?.isWrapUp === true;\n const wrapUpRequired = taskData?.wrapUpRequired === true;\n if (wrapUpRequired || participantWrapUp) {\n return true;\n }\n\n const owner = taskData?.interaction?.owner;\n if (owner && owner === selfAgentId) {\n return true;\n }\n\n if (taskData?.isConsulted === false) {\n return true;\n }\n\n return false;\n};\n\nexport interface GuardParams {\n context: TaskContext;\n event?: TaskEventPayload;\n}\n\nexport type GuardFunction = (params: GuardParams) => boolean;\n\nexport const guards = {\n // Hydrate Guards\n isInteractionTerminated: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n if (taskData?.interaction?.isTerminated === true) return true;\n\n const selfAgentId = getSelfAgentId(context, taskData);\n if (selfAgentId && taskData?.interaction?.participants?.[selfAgentId]?.isWrapUp === true) {\n return true;\n }\n\n return false;\n },\n\n isInteractionConsulting: ({event, context}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n if (taskData?.interaction?.state === INTERACTION_STATE.CONSULTING) return true;\n\n // Hydrate can report interaction as conference/hold while this agent is actively consulting.\n // Detect consult by participant consultState + consult media, independent of top-level state.\n const selfAgentId = getSelfAgentId(context, taskData);\n const selfParticipant = selfAgentId ? taskData?.interaction?.participants?.[selfAgentId] : null;\n const hasConsultMedia = Object.values(taskData?.interaction?.media ?? {}).some(\n (media: any) => media?.mType === MEDIA_TYPE_CONSULT\n );\n const selfActiveConsult = selfParticipant?.consultState === CONSULT_STATE.CONSULTING;\n const selfPendingConsultInitiated =\n selfParticipant?.consultState === 'consultInitiated' && taskData?.isConsulted === false;\n if ((selfActiveConsult || selfPendingConsultInitiated) && hasConsultMedia) {\n return true;\n }\n\n // EP_DN consulted agent: backend reports state as 'connected' but CPD indicates consult\n const cpd = taskData?.interaction?.callProcessingDetails;\n if (\n cpd?.relationshipType === 'consult' &&\n taskData?.interaction?.state === INTERACTION_STATE.CONNECTED\n ) {\n return true;\n }\n\n // Customer left during consult: interaction state is \"post_call\" but consult\n // between agents is still active. Detect via agent's consultState + consult media.\n if (hasActiveConsultInPostCall(taskData, getSelfAgentId(context, taskData))) {\n return true;\n }\n\n // Customer left during consult: interaction state is \"post_call\" but consult\n // between agents is still active. Detect via agent's consultState + consult media.\n if (taskData?.interaction?.state === INTERACTION_STATE.POST_CALL) {\n const postCallSelfAgentId = getSelfAgentId(context, taskData);\n const postCallSelfParticipant = postCallSelfAgentId\n ? taskData?.interaction?.participants?.[postCallSelfAgentId]\n : null;\n const hasPostCallConsultMedia = Object.values(taskData?.interaction?.media ?? {}).some(\n (media: any) => media?.mType === MEDIA_TYPE_CONSULT\n );\n if (\n postCallSelfParticipant?.consultState === CONSULT_STATE.CONSULTING &&\n hasPostCallConsultMedia\n ) {\n return true;\n }\n }\n\n return false;\n },\n\n isInteractionHeld: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n if (taskData?.interaction?.state === 'hold') return true;\n\n const mainMediaId = taskData?.interaction?.mainInteractionId || taskData?.interactionId;\n if (mainMediaId && taskData?.interaction?.media?.[mainMediaId]?.isHold === true) {\n return true;\n }\n\n return false;\n },\n\n isInteractionConnected: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n return taskData?.interaction?.state === INTERACTION_STATE.CONNECTED;\n },\n\n isConferencingByParticipants: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n const mainCallId = taskData.interaction?.mainInteractionId || taskData.interactionId;\n const media = taskData.interaction?.media?.[mainCallId];\n const participants = taskData.interaction?.participants;\n if (!media?.participants || !participants) return false;\n let agentCount = 0;\n for (const pId of media.participants) {\n const p = participants[pId];\n if (p && p.pType !== 'Customer' && p.pType !== 'Supervisor' && !p.hasLeft) {\n agentCount += 1;\n }\n }\n\n return agentCount >= 2;\n },\n\n // Conference Guards\n conferenceInProgressFromEvent: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData?.interaction) return false;\n\n return getIsConferenceInProgress(taskData);\n },\n\n /**\n * Conference hold signal for conference-downgraded consult-end transitions.\n * Backend can report this as boolean or string.\n */\n isConferenceHoldParticipantFromEvent: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event) ?? context.taskData;\n const callProcessingDetails = taskData?.interaction?.callProcessingDetails as\n | {conferenceHoldParticipant?: boolean | string}\n | undefined;\n const conferenceHoldParticipant = callProcessingDetails?.conferenceHoldParticipant;\n\n return conferenceHoldParticipant === true || conferenceHoldParticipant === 'true';\n },\n\n /**\n * Conference downgrade check specifically for transitioning back to CONNECTED.\n *\n * Returns true only when:\n * - conference has downgraded (fewer than 2 active agent participants in main call)\n * - customer is still in the call\n * - current agent is still in the main call\n */\n shouldDowngradeConferenceToConnected: ({context, event}: GuardParams): boolean => {\n const eventTaskData = getTaskDataFromEvent(event);\n const taskData = eventTaskData ?? context.taskData;\n if (!taskData?.interaction) return false;\n\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const mainCallId = taskData.interaction.mainInteractionId || taskData.interactionId;\n if (!mainCallId) return false;\n\n // Don't downgrade while backend still reports conference.\n if (taskData.interaction.state === INTERACTION_STATE.CONFERENCE) return false;\n\n const agentParticipantsCount = getConferenceParticipantsCount(taskData.interaction, mainCallId);\n if (agentParticipantsCount >= 2) return false;\n\n const customerInCall = getIsCustomerInCall(taskData.interaction, mainCallId);\n if (!customerInCall) return false;\n\n const selfInMainCall = Boolean(\n taskData.interaction.media?.[mainCallId]?.participants?.includes(selfAgentId)\n );\n\n return selfInMainCall;\n },\n\n // Consult Guards\n /**\n * Check if this agent initiated the consult (using event data)\n * Handles both consultingAgentId and fallback to context flag\n */\n didInitiateConsult: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (taskData?.isConsulted === true) return false;\n\n return taskData?.consultingAgentId\n ? isSelfConsultingAgent(context, taskData)\n : context.consultInitiator === true;\n },\n\n /**\n * EP-DN / consulted consult legs can arrive as AGENT_CONTACT_ASSIGNED without a preceding\n * AgentConsulting event. When that happens, we should enter CONSULTING (not CONNECTED).\n */\n isConsultingAssignment: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n\n const relationshipType = taskData.interaction?.callProcessingDetails?.relationshipType;\n\n return (\n taskData.isConsulted === true ||\n relationshipType === 'consult' ||\n taskData.interaction?.state === INTERACTION_STATE.CONSULTING\n );\n },\n\n // Wrapup Guards\n shouldWrapUp: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n\n if (event?.type === TaskEvent.CONFERENCE_END) {\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const pending = taskData?.agentsPendingWrapUp;\n if (Array.isArray(pending) && pending.length > 0) {\n return pending.includes(selfAgentId);\n }\n\n const participantWrapUp =\n taskData?.interaction?.participants?.[selfAgentId]?.isWrapUp === true;\n const wrapUpRequired = taskData?.wrapUpRequired === true;\n\n return wrapUpRequired || participantWrapUp;\n }\n\n return shouldWrapUpForThisAgent(context, taskData);\n },\n\n /**\n * Check if wrapUpRequired in payload OR is consult initiator\n */\n shouldWrapUpOrIsInitiator: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n\n return Boolean(taskData?.wrapUpRequired || context.consultInitiator);\n },\n\n /**\n * True if PARTICIPANT_LEAVE indicates that *this* agent left the conference.\n *\n * Important: PARTICIPANT_LEAVE is broadcast to all agents in the conference.\n * Only the agent whose id matches the leaving participant should transition to\n * TERMINATED / WRAPPING_UP based on wrapup rules.\n */\n didCurrentAgentLeaveConference: ({context, event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n const selfAgentId = getSelfAgentId(context, taskData);\n if (!selfAgentId) return false;\n\n const participantIdFromEvent =\n event && typeof event === 'object' && 'participantId' in event\n ? (event as {participantId?: string}).participantId\n : undefined;\n const participantId = participantIdFromEvent ?? taskData?.participantId;\n\n if (Boolean(participantId) && participantId === selfAgentId) {\n return true;\n }\n\n // For EP-DN agents the backend removes the leaving participant entirely\n // from the participants map (rather than setting hasLeft). If this task\n // is in CONFERENCING (implied by the guard being evaluated here) but the\n // agent is absent from the updated participants, they have left.\n const participants = taskData?.interaction?.participants;\n if (participants && !(selfAgentId in participants)) {\n return true;\n }\n\n return false;\n },\n\n // Server State Guards\n isPrimaryMediaOnHold: ({event}: GuardParams): boolean => {\n const taskData = getTaskDataFromEvent(event);\n if (!taskData) return false;\n const mediaId = taskData.mediaResourceId;\n if (!mediaId) return false;\n\n return taskData.interaction?.media?.[mediaId]?.isHold === true;\n },\n};\n\nexport type GuardName = keyof typeof guards;\n"],"mappings":";;;;;;AAwBA,IAAAA,UAAA,GAAAC,OAAA;AAKA,IAAAC,UAAA,GAAAD,OAAA;AA7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAWO,MAAME,oBAAoB,GAAIC,KAAwB,IAC3DA,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAI,UAAU,IAAIA,KAAK,GACpDA,KAAK,CAA2BC,QAAQ,GACzCC,SAAS;AAACC,OAAA,CAAAJ,oBAAA,GAAAA,oBAAA;AAET,MAAMK,cAAc,GAAGA,CAACC,OAAoB,EAAEJ,QAAmB,KACtEI,OAAO,CAACC,eAAe,EAAEC,OAAO,IAAIF,OAAO,CAACJ,QAAQ,EAAEM,OAAO,IAAIN,QAAQ,EAAEM,OAAO;AAACJ,OAAA,CAAAC,cAAA,GAAAA,cAAA;AAE9E,MAAMI,qBAAqB,GAAGA,CAACH,OAAoB,EAAEJ,QAAmB,KAAc;EAC3F,MAAMQ,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;EACrD,IAAI,CAACQ,WAAW,EAAE,OAAO,KAAK;EAE9B,OAAOR,QAAQ,EAAES,iBAAiB,KAAKD,WAAW;AACpD,CAAC;;AAED;AACA;AACA;AACA;AAHAN,OAAA,CAAAK,qBAAA,GAAAA,qBAAA;AAIO,MAAMG,0BAA0B,GAAGA,CACxCV,QAA8B,EAC9BQ,WAAoB,KACR;EACZ,IAAIR,QAAQ,EAAEW,WAAW,EAAEC,KAAK,KAAKC,4BAAiB,CAACC,SAAS,IAAI,CAACN,WAAW,EAAE,OAAO,KAAK;EAE9F,MAAMO,eAAe,GAAGf,QAAQ,CAACW,WAAW,EAAEK,YAAY,GAAGR,WAAW,CAAC;EACzE,MAAMS,eAAe,GAAGC,MAAM,CAACC,MAAM,CAACnB,QAAQ,CAACW,WAAW,EAAES,KAAK,IAAI,CAAC,CAAC,CAAC,CAACC,IAAI,CAC1ED,KAAK,IAAMA,KAAK,EAAuBE,KAAK,KAAKC,6BACpD,CAAC;EAED,OAAOR,eAAe,EAAES,YAAY,KAAKC,wBAAa,CAACC,UAAU,IAAIT,eAAe;AACtF,CAAC;;AAED;AACA;AACA;AACA;AAHAf,OAAA,CAAAQ,0BAAA,GAAAA,0BAAA;AAIO,MAAMiB,wBAAwB,GAAGA,CAACvB,OAAoB,EAAEJ,QAAkB,KAAc;EAC7F,MAAMQ,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;EACrD,IAAI,CAACQ,WAAW,EAAE,OAAO,KAAK;EAE9B,MAAMoB,OAAO,GAAG5B,QAAQ,EAAE6B,mBAAmB;EAC7C,IAAIC,KAAK,CAACC,OAAO,CAACH,OAAO,CAAC,IAAIA,OAAO,CAACI,MAAM,GAAG,CAAC,EAAE;IAChD,OAAOJ,OAAO,CAACK,QAAQ,CAACzB,WAAW,CAAC;EACtC;EAEA,MAAM0B,iBAAiB,GAAGlC,QAAQ,EAAEW,WAAW,EAAEK,YAAY,GAAGR,WAAW,CAAC,EAAE2B,QAAQ,KAAK,IAAI;EAC/F,MAAMC,cAAc,GAAGpC,QAAQ,EAAEoC,cAAc,KAAK,IAAI;EACxD,IAAIA,cAAc,IAAIF,iBAAiB,EAAE;IACvC,OAAO,IAAI;EACb;EAEA,MAAMG,KAAK,GAAGrC,QAAQ,EAAEW,WAAW,EAAE0B,KAAK;EAC1C,IAAIA,KAAK,IAAIA,KAAK,KAAK7B,WAAW,EAAE;IAClC,OAAO,IAAI;EACb;EAEA,IAAIR,QAAQ,EAAEsC,WAAW,KAAK,KAAK,EAAE;IACnC,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd,CAAC;AAACpC,OAAA,CAAAyB,wBAAA,GAAAA,wBAAA;AASK,MAAMY,MAAM,GAAArC,OAAA,CAAAqC,MAAA,GAAG;EACpB;EACAC,uBAAuB,EAAEA,CAAC;IAACpC,OAAO;IAAEL;EAAkB,CAAC,KAAc;IACnE,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAE5C,IAAIC,QAAQ,EAAEW,WAAW,EAAE8B,YAAY,KAAK,IAAI,EAAE,OAAO,IAAI;IAE7D,MAAMjC,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;IACrD,IAAIQ,WAAW,IAAIR,QAAQ,EAAEW,WAAW,EAAEK,YAAY,GAAGR,WAAW,CAAC,EAAE2B,QAAQ,KAAK,IAAI,EAAE;MACxF,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC;EAEDO,uBAAuB,EAAEA,CAAC;IAAC3C,KAAK;IAAEK;EAAoB,CAAC,KAAc;IACnE,MAAMJ,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAE5C,IAAIC,QAAQ,EAAEW,WAAW,EAAEC,KAAK,KAAKC,4BAAiB,CAACa,UAAU,EAAE,OAAO,IAAI;;IAE9E;IACA;IACA,MAAMlB,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;IACrD,MAAMe,eAAe,GAAGP,WAAW,GAAGR,QAAQ,EAAEW,WAAW,EAAEK,YAAY,GAAGR,WAAW,CAAC,GAAG,IAAI;IAC/F,MAAMS,eAAe,GAAGC,MAAM,CAACC,MAAM,CAACnB,QAAQ,EAAEW,WAAW,EAAES,KAAK,IAAI,CAAC,CAAC,CAAC,CAACC,IAAI,CAC3ED,KAAU,IAAKA,KAAK,EAAEE,KAAK,KAAKC,6BACnC,CAAC;IACD,MAAMoB,iBAAiB,GAAG5B,eAAe,EAAES,YAAY,KAAKC,wBAAa,CAACC,UAAU;IACpF,MAAMkB,2BAA2B,GAC/B7B,eAAe,EAAES,YAAY,KAAK,kBAAkB,IAAIxB,QAAQ,EAAEsC,WAAW,KAAK,KAAK;IACzF,IAAI,CAACK,iBAAiB,IAAIC,2BAA2B,KAAK3B,eAAe,EAAE;MACzE,OAAO,IAAI;IACb;;IAEA;IACA,MAAM4B,GAAG,GAAG7C,QAAQ,EAAEW,WAAW,EAAEmC,qBAAqB;IACxD,IACED,GAAG,EAAEE,gBAAgB,KAAK,SAAS,IACnC/C,QAAQ,EAAEW,WAAW,EAAEC,KAAK,KAAKC,4BAAiB,CAACmC,SAAS,EAC5D;MACA,OAAO,IAAI;IACb;;IAEA;IACA;IACA,IAAItC,0BAA0B,CAACV,QAAQ,EAAEG,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC,CAAC,EAAE;MAC3E,OAAO,IAAI;IACb;;IAEA;IACA;IACA,IAAIA,QAAQ,EAAEW,WAAW,EAAEC,KAAK,KAAKC,4BAAiB,CAACC,SAAS,EAAE;MAChE,MAAMmC,mBAAmB,GAAG9C,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;MAC7D,MAAMkD,uBAAuB,GAAGD,mBAAmB,GAC/CjD,QAAQ,EAAEW,WAAW,EAAEK,YAAY,GAAGiC,mBAAmB,CAAC,GAC1D,IAAI;MACR,MAAME,uBAAuB,GAAGjC,MAAM,CAACC,MAAM,CAACnB,QAAQ,EAAEW,WAAW,EAAES,KAAK,IAAI,CAAC,CAAC,CAAC,CAACC,IAAI,CACnFD,KAAU,IAAKA,KAAK,EAAEE,KAAK,KAAKC,6BACnC,CAAC;MACD,IACE2B,uBAAuB,EAAE1B,YAAY,KAAKC,wBAAa,CAACC,UAAU,IAClEyB,uBAAuB,EACvB;QACA,OAAO,IAAI;MACb;IACF;IAEA,OAAO,KAAK;EACd,CAAC;EAEDC,iBAAiB,EAAEA,CAAC;IAACrD;EAAkB,CAAC,KAAc;IACpD,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAE5C,IAAIC,QAAQ,EAAEW,WAAW,EAAEC,KAAK,KAAK,MAAM,EAAE,OAAO,IAAI;IAExD,MAAMyC,WAAW,GAAGrD,QAAQ,EAAEW,WAAW,EAAE2C,iBAAiB,IAAItD,QAAQ,EAAEuD,aAAa;IACvF,IAAIF,WAAW,IAAIrD,QAAQ,EAAEW,WAAW,EAAES,KAAK,GAAGiC,WAAW,CAAC,EAAEG,MAAM,KAAK,IAAI,EAAE;MAC/E,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC;EAEDC,sBAAsB,EAAEA,CAAC;IAAC1D;EAAkB,CAAC,KAAc;IACzD,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAE5C,OAAOC,QAAQ,EAAEW,WAAW,EAAEC,KAAK,KAAKC,4BAAiB,CAACmC,SAAS;EACrE,CAAC;EAEDU,4BAA4B,EAAEA,CAAC;IAAC3D;EAAkB,CAAC,KAAc;IAC/D,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,IAAI,CAACC,QAAQ,EAAE,OAAO,KAAK;IAC3B,MAAM2D,UAAU,GAAG3D,QAAQ,CAACW,WAAW,EAAE2C,iBAAiB,IAAItD,QAAQ,CAACuD,aAAa;IACpF,MAAMnC,KAAK,GAAGpB,QAAQ,CAACW,WAAW,EAAES,KAAK,GAAGuC,UAAU,CAAC;IACvD,MAAM3C,YAAY,GAAGhB,QAAQ,CAACW,WAAW,EAAEK,YAAY;IACvD,IAAI,CAACI,KAAK,EAAEJ,YAAY,IAAI,CAACA,YAAY,EAAE,OAAO,KAAK;IACvD,IAAI4C,UAAU,GAAG,CAAC;IAClB,KAAK,MAAMC,GAAG,IAAIzC,KAAK,CAACJ,YAAY,EAAE;MACpC,MAAM8C,CAAC,GAAG9C,YAAY,CAAC6C,GAAG,CAAC;MAC3B,IAAIC,CAAC,IAAIA,CAAC,CAACC,KAAK,KAAK,UAAU,IAAID,CAAC,CAACC,KAAK,KAAK,YAAY,IAAI,CAACD,CAAC,CAACE,OAAO,EAAE;QACzEJ,UAAU,IAAI,CAAC;MACjB;IACF;IAEA,OAAOA,UAAU,IAAI,CAAC;EACxB,CAAC;EAED;EACAK,6BAA6B,EAAEA,CAAC;IAAClE;EAAkB,CAAC,KAAc;IAChE,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,IAAI,CAACC,QAAQ,EAAEW,WAAW,EAAE,OAAO,KAAK;IAExC,OAAO,IAAAuD,oCAAyB,EAAClE,QAAQ,CAAC;EAC5C,CAAC;EAED;AACF;AACA;AACA;EACEmE,oCAAoC,EAAEA,CAAC;IAAC/D,OAAO;IAAEL;EAAkB,CAAC,KAAc;IAChF,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC,IAAIK,OAAO,CAACJ,QAAQ;IAChE,MAAM8C,qBAAqB,GAAG9C,QAAQ,EAAEW,WAAW,EAAEmC,qBAExC;IACb,MAAMsB,yBAAyB,GAAGtB,qBAAqB,EAAEsB,yBAAyB;IAElF,OAAOA,yBAAyB,KAAK,IAAI,IAAIA,yBAAyB,KAAK,MAAM;EACnF,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,oCAAoC,EAAEA,CAAC;IAACjE,OAAO;IAAEL;EAAkB,CAAC,KAAc;IAChF,MAAMuE,aAAa,GAAGxE,oBAAoB,CAACC,KAAK,CAAC;IACjD,MAAMC,QAAQ,GAAGsE,aAAa,IAAIlE,OAAO,CAACJ,QAAQ;IAClD,IAAI,CAACA,QAAQ,EAAEW,WAAW,EAAE,OAAO,KAAK;IAExC,MAAMH,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;IACrD,IAAI,CAACQ,WAAW,EAAE,OAAO,KAAK;IAE9B,MAAMmD,UAAU,GAAG3D,QAAQ,CAACW,WAAW,CAAC2C,iBAAiB,IAAItD,QAAQ,CAACuD,aAAa;IACnF,IAAI,CAACI,UAAU,EAAE,OAAO,KAAK;;IAE7B;IACA,IAAI3D,QAAQ,CAACW,WAAW,CAACC,KAAK,KAAKC,4BAAiB,CAAC0D,UAAU,EAAE,OAAO,KAAK;IAE7E,MAAMC,sBAAsB,GAAG,IAAAC,yCAA8B,EAACzE,QAAQ,CAACW,WAAW,EAAEgD,UAAU,CAAC;IAC/F,IAAIa,sBAAsB,IAAI,CAAC,EAAE,OAAO,KAAK;IAE7C,MAAME,cAAc,GAAG,IAAAC,8BAAmB,EAAC3E,QAAQ,CAACW,WAAW,EAAEgD,UAAU,CAAC;IAC5E,IAAI,CAACe,cAAc,EAAE,OAAO,KAAK;IAEjC,MAAME,cAAc,GAAGC,OAAO,CAC5B7E,QAAQ,CAACW,WAAW,CAACS,KAAK,GAAGuC,UAAU,CAAC,EAAE3C,YAAY,EAAEiB,QAAQ,CAACzB,WAAW,CAC9E,CAAC;IAED,OAAOoE,cAAc;EACvB,CAAC;EAED;EACA;AACF;AACA;AACA;EACEE,kBAAkB,EAAEA,CAAC;IAAC1E,OAAO;IAAEL;EAAkB,CAAC,KAAc;IAC9D,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,IAAIC,QAAQ,EAAEsC,WAAW,KAAK,IAAI,EAAE,OAAO,KAAK;IAEhD,OAAOtC,QAAQ,EAAES,iBAAiB,GAC9BF,qBAAqB,CAACH,OAAO,EAAEJ,QAAQ,CAAC,GACxCI,OAAO,CAAC2E,gBAAgB,KAAK,IAAI;EACvC,CAAC;EAED;AACF;AACA;AACA;EACEC,sBAAsB,EAAEA,CAAC;IAACjF;EAAkB,CAAC,KAAc;IACzD,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,IAAI,CAACC,QAAQ,EAAE,OAAO,KAAK;IAE3B,MAAM+C,gBAAgB,GAAG/C,QAAQ,CAACW,WAAW,EAAEmC,qBAAqB,EAAEC,gBAAgB;IAEtF,OACE/C,QAAQ,CAACsC,WAAW,KAAK,IAAI,IAC7BS,gBAAgB,KAAK,SAAS,IAC9B/C,QAAQ,CAACW,WAAW,EAAEC,KAAK,KAAKC,4BAAiB,CAACa,UAAU;EAEhE,CAAC;EAED;EACAuD,YAAY,EAAEA,CAAC;IAAC7E,OAAO;IAAEL;EAAkB,CAAC,KAAc;IACxD,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,IAAI,CAACC,QAAQ,EAAE,OAAO,KAAK;IAE3B,IAAID,KAAK,EAAEmF,IAAI,KAAKC,oBAAS,CAACC,cAAc,EAAE;MAC5C,MAAM5E,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;MACrD,IAAI,CAACQ,WAAW,EAAE,OAAO,KAAK;MAE9B,MAAMoB,OAAO,GAAG5B,QAAQ,EAAE6B,mBAAmB;MAC7C,IAAIC,KAAK,CAACC,OAAO,CAACH,OAAO,CAAC,IAAIA,OAAO,CAACI,MAAM,GAAG,CAAC,EAAE;QAChD,OAAOJ,OAAO,CAACK,QAAQ,CAACzB,WAAW,CAAC;MACtC;MAEA,MAAM0B,iBAAiB,GACrBlC,QAAQ,EAAEW,WAAW,EAAEK,YAAY,GAAGR,WAAW,CAAC,EAAE2B,QAAQ,KAAK,IAAI;MACvE,MAAMC,cAAc,GAAGpC,QAAQ,EAAEoC,cAAc,KAAK,IAAI;MAExD,OAAOA,cAAc,IAAIF,iBAAiB;IAC5C;IAEA,OAAOP,wBAAwB,CAACvB,OAAO,EAAEJ,QAAQ,CAAC;EACpD,CAAC;EAED;AACF;AACA;EACEqF,yBAAyB,EAAEA,CAAC;IAACjF,OAAO;IAAEL;EAAkB,CAAC,KAAc;IACrE,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAE5C,OAAO8E,OAAO,CAAC7E,QAAQ,EAAEoC,cAAc,IAAIhC,OAAO,CAAC2E,gBAAgB,CAAC;EACtE,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACEO,8BAA8B,EAAEA,CAAC;IAAClF,OAAO;IAAEL;EAAkB,CAAC,KAAc;IAC1E,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,MAAMS,WAAW,GAAGL,cAAc,CAACC,OAAO,EAAEJ,QAAQ,CAAC;IACrD,IAAI,CAACQ,WAAW,EAAE,OAAO,KAAK;IAE9B,MAAM+E,sBAAsB,GAC1BxF,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAI,eAAe,IAAIA,KAAK,GACzDA,KAAK,CAA8ByF,aAAa,GACjDvF,SAAS;IACf,MAAMuF,aAAa,GAAGD,sBAAsB,IAAIvF,QAAQ,EAAEwF,aAAa;IAEvE,IAAIX,OAAO,CAACW,aAAa,CAAC,IAAIA,aAAa,KAAKhF,WAAW,EAAE;MAC3D,OAAO,IAAI;IACb;;IAEA;IACA;IACA;IACA;IACA,MAAMQ,YAAY,GAAGhB,QAAQ,EAAEW,WAAW,EAAEK,YAAY;IACxD,IAAIA,YAAY,IAAI,EAAER,WAAW,IAAIQ,YAAY,CAAC,EAAE;MAClD,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC;EAED;EACAyE,oBAAoB,EAAEA,CAAC;IAAC1F;EAAkB,CAAC,KAAc;IACvD,MAAMC,QAAQ,GAAGF,oBAAoB,CAACC,KAAK,CAAC;IAC5C,IAAI,CAACC,QAAQ,EAAE,OAAO,KAAK;IAC3B,MAAM0F,OAAO,GAAG1F,QAAQ,CAAC2F,eAAe;IACxC,IAAI,CAACD,OAAO,EAAE,OAAO,KAAK;IAE1B,OAAO1F,QAAQ,CAACW,WAAW,EAAES,KAAK,GAAGsE,OAAO,CAAC,EAAElC,MAAM,KAAK,IAAI;EAChE;AACF,CAAC","ignoreList":[]}
|
|
@@ -106,13 +106,16 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
106
106
|
const isConferencing = state === _constants.TaskState.CONFERENCING;
|
|
107
107
|
const isWrappingUp = state === _constants.TaskState.WRAPPING_UP;
|
|
108
108
|
const selfInMainCall = Boolean(selfAgentId) && Boolean(mainCallId) && Boolean(interaction?.media?.[mainCallId]?.participants?.includes(selfAgentId));
|
|
109
|
+
const consultMedia = Object.values(interaction?.media ?? {}).find(media => media?.mediaResourceId === taskData?.consultMediaResourceId || media?.mType === 'consult');
|
|
110
|
+
const selfParticipant = selfAgentId ? interaction?.participants?.[selfAgentId] : null;
|
|
111
|
+
const selfInConsultCall = Boolean(selfAgentId) && Boolean(consultMedia?.participants?.includes(selfAgentId));
|
|
109
112
|
const conferenceActive = isConferencing || conferenceFromBackend || consultFromConference;
|
|
110
113
|
// Treat consult initiator as "in conference" even if mainCall participant list lags while consulting.
|
|
111
114
|
const inConference = conferenceActive && (isConferencing || selfInMainCall || consultInitiator);
|
|
112
115
|
|
|
113
116
|
// Check if this is a consulted agent (must be after isConsulting is computed).
|
|
114
|
-
const isSoleAgentOnCall = participantCount <= 1 && !isConsulting && !inConference;
|
|
115
|
-
const isConsulted = inConference || isSoleAgentOnCall ? false : (0, _TaskUtils.getIsConsultedAgentForControls)(taskData, context, isConsulting);
|
|
117
|
+
const isSoleAgentOnCall = participantCount <= 1 && selfInMainCall && !isConsulting && !inConference;
|
|
118
|
+
const isConsulted = inConference || isSoleAgentOnCall ? false : (0, _TaskUtils.getIsConsultedAgentForControls)(taskData, context, isConsulting) || !consultInitiator && (selfParticipant?.isConsulted === true || selfParticipant?.consultState === 'consulting');
|
|
116
119
|
|
|
117
120
|
// Active call = can perform call operations
|
|
118
121
|
const isActive = state === _constants.TaskState.CONNECTED || state === _constants.TaskState.HELD || state === _constants.TaskState.HOLD_INITIATING || state === _constants.TaskState.RESUME_INITIATING || isConsulting || isConferencing;
|
|
@@ -122,20 +125,49 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
122
125
|
const hasFullControls = !isConsulted || consultInitiator || inConference || isWrappingUp;
|
|
123
126
|
const consultOwnedBySelf = consultInitiator || Boolean(selfAgentId) && taskData?.consultingAgentId === selfAgentId;
|
|
124
127
|
const hasConsultMedia = Boolean(taskData?.consultMediaResourceId || Object.values(interaction?.media ?? {}).some(media => media?.mType === 'consult'));
|
|
128
|
+
const selfConsultPendingOnConsultMedia = selfParticipant?.consultState === 'consultInitiated' && !taskData?.isConsulted && hasConsultMedia;
|
|
129
|
+
const ownerParticipant = interaction?.owner ? interaction.participants?.[interaction.owner] : undefined;
|
|
130
|
+
const otherAgentConsultInProgress = Boolean(interaction?.participants && Object.values(interaction.participants).some(participant => {
|
|
131
|
+
if (!participant || participant.hasLeft) return false;
|
|
132
|
+
if (participant.id === selfAgentId) return false;
|
|
133
|
+
if (participant.pType !== 'AGENT') return false;
|
|
134
|
+
return participant.consultState === 'consultInitiated' || participant.consultState === 'consultReserved' || participant.consultState === 'consulting' || participant.currentState === 'consulting';
|
|
135
|
+
}));
|
|
136
|
+
const isHydratedConferenceConsultPending = inConference && selfConsultPendingOnConsultMedia && !consultDestinationAgentJoined;
|
|
125
137
|
const hasParallelConsultLeg = consultOwnedBySelf && !isConsulting && !isConsulted && (consultInProgress || consultCallHeld || hasConsultMedia);
|
|
138
|
+
const activeLegForConferenceConsult = consultCallHeld ? 'main' : 'consult';
|
|
139
|
+
const isCurrentLegActive = currentLeg === activeLegForConferenceConsult;
|
|
140
|
+
const isConferenceConsultTransferContext = inConference && consultInitiator && hasConsultMedia && isConsultDestinationReady;
|
|
126
141
|
const consultLegOnHold = isConsulting && consultCallHeld;
|
|
142
|
+
const callProcessingDetails = interaction?.callProcessingDetails;
|
|
143
|
+
const conferenceHoldParticipant = callProcessingDetails?.conferenceHoldParticipant === true || callProcessingDetails?.conferenceHoldParticipant === 'true';
|
|
144
|
+
const postDeclineHeldMainLeg = consultInitiator && !consultDestinationAgentJoined && isHeld && inConference && conferenceHoldParticipant;
|
|
145
|
+
const postConsultCompletedHeldMainLeg = selfParticipant?.consultState === 'consultCompleted' && isHeld && inConference && !isConsulting;
|
|
146
|
+
const nonOwnerPostConsultCompletedHeldMainLeg = isHeld && inConference && !isConsulting && !consultInitiator && Boolean(selfAgentId) && Boolean(interaction?.owner) && selfAgentId !== interaction?.owner && ownerParticipant?.consultState === 'consultCompleted';
|
|
147
|
+
const isConsultPendingBeforeJoin = selfParticipant?.consultState === 'consultInitiated' && !consultDestinationAgentJoined;
|
|
148
|
+
const hideExitConferenceWhileConsultPending = currentLeg === 'main' && inConference && isConsultPendingBeforeJoin && (consultFromConference || consultInitiator || taskData?.type === 'AgentConsultCreated' || consultInProgress || isConsulting);
|
|
149
|
+
const hideExitConferenceDuringActiveConsultFromConference = inConference && consultInitiator && consultDestinationAgentJoined && (isConsulting || taskData?.type === 'AgentConsulting' || selfParticipant?.consultState === 'consulting');
|
|
150
|
+
const forceHeldPostConsultControls = !hideExitConferenceWhileConsultPending && (postDeclineHeldMainLeg || postConsultCompletedHeldMainLeg);
|
|
151
|
+
const selfOnConsultLeg = selfParticipant?.consultState === 'consulting' || selfParticipant?.currentState === 'consulting';
|
|
152
|
+
const showMainLegConferenceControlsDuringConsult = currentLeg === 'main' && inConference && consultInProgress && !selfOnConsultLeg;
|
|
153
|
+
const allowHeldMainLegControlsForNonInitiator = showMainLegConferenceControlsDuringConsult && !isHydratedConferenceConsultPending;
|
|
127
154
|
return {
|
|
128
155
|
// Accept/Decline: Voice tasks in offered state
|
|
129
|
-
//
|
|
130
|
-
//
|
|
156
|
+
// Desktop/WebRTC + inbound: accept enabled (agent manually accepts)
|
|
157
|
+
// Desktop/WebRTC + outdial: accept disabled (auto-answer handles it; Widgets show "Accept" disabled)
|
|
158
|
+
// Extension mode (non-WebRTC): accept disabled (Widgets show "Ringing...")
|
|
131
159
|
accept: state === _constants.TaskState.OFFERED && !interaction?.isTerminated ? {
|
|
132
160
|
isVisible: true,
|
|
133
161
|
isEnabled: isWebrtc && !isOutdial
|
|
134
162
|
} : DISABLED,
|
|
135
|
-
decline:
|
|
163
|
+
decline: (() => {
|
|
164
|
+
if (!isWebrtc || state !== _constants.TaskState.OFFERED || interaction?.isTerminated) return DISABLED;
|
|
165
|
+
return isOutdial ? VISIBLE_DISABLED : VISIBLE_ENABLED;
|
|
166
|
+
})(),
|
|
136
167
|
// Hold: visible in connected/held/conference, disabled in conference/consulting
|
|
137
168
|
hold: (() => {
|
|
138
169
|
if (!hasFullControls) return DISABLED;
|
|
170
|
+
if (forceHeldPostConsultControls) return VISIBLE_ENABLED;
|
|
139
171
|
if (consultOwnedBySelf && (isConsulting || hasParallelConsultLeg || consultCallHeld)) {
|
|
140
172
|
return DISABLED;
|
|
141
173
|
}
|
|
@@ -152,6 +184,7 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
152
184
|
mute: (() => {
|
|
153
185
|
if (!isWebrtc) return DISABLED;
|
|
154
186
|
if (isWrappingUp) return DISABLED;
|
|
187
|
+
if (currentLeg === 'consult' && !selfInConsultCall) return DISABLED;
|
|
155
188
|
if (isConsulting) return VISIBLE_ENABLED;
|
|
156
189
|
if (isConnected || isHeld || isConferencing) {
|
|
157
190
|
if (inConference) return VISIBLE_ENABLED;
|
|
@@ -161,6 +194,9 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
161
194
|
})(),
|
|
162
195
|
// End: varies by state; during consulting only on main leg (consult held)
|
|
163
196
|
end: (() => {
|
|
197
|
+
if (allowHeldMainLegControlsForNonInitiator) return VISIBLE_ENABLED;
|
|
198
|
+
if (showMainLegConferenceControlsDuringConsult) return VISIBLE_DISABLED;
|
|
199
|
+
if (isHydratedConferenceConsultPending && currentLeg === 'main') return VISIBLE_DISABLED;
|
|
164
200
|
if (!config.isEndTaskEnabled) return DISABLED;
|
|
165
201
|
if (hasParallelConsultLeg) {
|
|
166
202
|
return isConnected && isEpDnConsult ? VISIBLE_ENABLED : VISIBLE_DISABLED;
|
|
@@ -171,6 +207,7 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
171
207
|
}
|
|
172
208
|
if (inConference) {
|
|
173
209
|
if (isConsulted) return DISABLED;
|
|
210
|
+
if (forceHeldPostConsultControls) return VISIBLE_DISABLED;
|
|
174
211
|
if (consultInProgress) return VISIBLE_DISABLED;
|
|
175
212
|
return isWrappingUp ? VISIBLE_DISABLED : VISIBLE_ENABLED;
|
|
176
213
|
}
|
|
@@ -180,6 +217,11 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
180
217
|
})(),
|
|
181
218
|
// Transfer: connected/held/conference
|
|
182
219
|
transfer: (() => {
|
|
220
|
+
if (isHydratedConferenceConsultPending) return VISIBLE_DISABLED;
|
|
221
|
+
if (isConferenceConsultTransferContext && currentLeg === 'main' && isCurrentLegActive) {
|
|
222
|
+
return DISABLED;
|
|
223
|
+
}
|
|
224
|
+
if (inConference && isConsulting && consultInitiator) return DISABLED;
|
|
183
225
|
if (hasParallelConsultLeg) {
|
|
184
226
|
if (!customerPresent) return DISABLED;
|
|
185
227
|
if (state === _constants.TaskState.CONNECTED) return VISIBLE_ENABLED;
|
|
@@ -203,6 +245,7 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
203
245
|
// Consult: connected/held/conference when conditions met
|
|
204
246
|
consult: (() => {
|
|
205
247
|
const isConnectedOrHeld = state === _constants.TaskState.CONNECTED || state === _constants.TaskState.HELD;
|
|
248
|
+
if (inConference && nonOwnerPostConsultCompletedHeldMainLeg) return VISIBLE_DISABLED;
|
|
206
249
|
if (hasParallelConsultLeg) return DISABLED;
|
|
207
250
|
if (!hasFullControls || !(isConnectedOrHeld || inConference)) {
|
|
208
251
|
return DISABLED;
|
|
@@ -213,7 +256,7 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
213
256
|
// Pending conference (only self agent): consult disabled
|
|
214
257
|
if (participantCount <= 1) return VISIBLE_DISABLED;
|
|
215
258
|
// Real conference: consult enabled if conditions met
|
|
216
|
-
const canFromConference = !maxParticipants && customerPresent && !consultInProgress && !isConsulting;
|
|
259
|
+
const canFromConference = !maxParticipants && customerPresent && !consultInProgress && !otherAgentConsultInProgress && !isConsulting;
|
|
217
260
|
return {
|
|
218
261
|
isVisible: true,
|
|
219
262
|
isEnabled: canFromConference
|
|
@@ -259,6 +302,7 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
259
302
|
// Conference: during consulting, enabled on both legs when agent joined
|
|
260
303
|
// Label changes based on leg: "Conference" on main leg, "Merge" on consult leg
|
|
261
304
|
conference: (() => {
|
|
305
|
+
if (isHydratedConferenceConsultPending && currentLeg === 'main') return VISIBLE_DISABLED;
|
|
262
306
|
if (hasParallelConsultLeg) {
|
|
263
307
|
if (!customerPresent) return DISABLED;
|
|
264
308
|
if (state === _constants.TaskState.CONNECTED) {
|
|
@@ -277,21 +321,33 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
277
321
|
wrapup: isWrappingUp ? VISIBLE_ENABLED : DISABLED,
|
|
278
322
|
// ExitConference: in conference with multiple agents in main call
|
|
279
323
|
exitConference: (() => {
|
|
324
|
+
if (hideExitConferenceWhileConsultPending) return DISABLED;
|
|
325
|
+
if (allowHeldMainLegControlsForNonInitiator) return VISIBLE_ENABLED;
|
|
326
|
+
if (showMainLegConferenceControlsDuringConsult) return VISIBLE_DISABLED;
|
|
327
|
+
if (hideExitConferenceDuringActiveConsultFromConference) return DISABLED;
|
|
328
|
+
if (forceHeldPostConsultControls) return VISIBLE_DISABLED;
|
|
280
329
|
if (isConsulted && !isConferencing) return DISABLED;
|
|
281
330
|
if (!inConference) return DISABLED;
|
|
282
331
|
if (participantCount <= 1) return DISABLED;
|
|
332
|
+
if (consultInProgress) return VISIBLE_DISABLED;
|
|
283
333
|
const consultingFromConference = consultInitiator && isConsulting && conferenceFromBackend;
|
|
284
334
|
return consultingFromConference ? VISIBLE_DISABLED : VISIBLE_ENABLED;
|
|
285
335
|
})(),
|
|
286
336
|
// TransferConference: in conference with active consult, owner consulting from conference
|
|
287
337
|
transferConference: (() => {
|
|
288
|
-
if (
|
|
289
|
-
|
|
338
|
+
if (isConferenceConsultTransferContext && !isCurrentLegActive) return VISIBLE_DISABLED;
|
|
339
|
+
const consultLegTransferAvailable = currentLeg === 'consult' && inConference && consultInitiator && hasConsultMedia;
|
|
340
|
+
const selfConsultingOnParticipantState = selfParticipant?.consultState === 'consulting';
|
|
341
|
+
const conferenceTransferAvailable = consultLegTransferAvailable || inConference && consultInitiator && hasConsultMedia && (isConsulting || consultInProgress || selfConsultingOnParticipantState);
|
|
342
|
+
if (consultLegOnHold) return DISABLED;
|
|
343
|
+
if (hasParallelConsultLeg && !conferenceTransferAvailable) return DISABLED;
|
|
344
|
+
if (!conferenceTransferAvailable && (!inConference || !isConsulting)) return DISABLED;
|
|
290
345
|
if (!consultInitiator || isConsulted) return DISABLED;
|
|
291
346
|
return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;
|
|
292
347
|
})(),
|
|
293
348
|
// MergeToConference: mirrors conference control, enabled on both legs
|
|
294
349
|
mergeToConference: (() => {
|
|
350
|
+
if (isHydratedConferenceConsultPending && currentLeg === 'consult') return VISIBLE_DISABLED;
|
|
295
351
|
if (!isConsulting || !consultInitiator) return DISABLED;
|
|
296
352
|
if (!customerPresent) return VISIBLE_DISABLED;
|
|
297
353
|
if (consultLegOnHold) return VISIBLE_DISABLED;
|
|
@@ -299,6 +355,7 @@ function computeVoiceInteractionUIControls(state, context, config, fallbackTaskD
|
|
|
299
355
|
})(),
|
|
300
356
|
// Switch: visible only on the currently active leg
|
|
301
357
|
switch: (() => {
|
|
358
|
+
if (isHydratedConferenceConsultPending && currentLeg === 'consult') return VISIBLE_DISABLED;
|
|
302
359
|
if (!customerPresent && hasParallelConsultLeg) return DISABLED;
|
|
303
360
|
if (currentLeg === 'consult') {
|
|
304
361
|
if (!isConsulting || !consultInitiator || consultCallHeld) return DISABLED;
|
|
@@ -353,7 +410,10 @@ function getVoiceLegState(currentState, context, config, fallbackTaskData) {
|
|
|
353
410
|
const isConsultingState = currentState === _constants.TaskState.CONSULTING || currentState === _constants.TaskState.CONSULT_INITIATING || currentState === _constants.TaskState.CONF_INITIATING;
|
|
354
411
|
const consultOwnedBySelf = context.consultInitiator || Boolean(selfAgentId) && taskData?.consultingAgentId === selfAgentId;
|
|
355
412
|
const hasConsultMedia = Boolean(taskData?.consultMediaResourceId || Object.values(interaction?.media ?? {}).some(media => media?.mType === 'consult'));
|
|
356
|
-
const
|
|
413
|
+
const selfParticipant = selfAgentId ? interaction?.participants?.[selfAgentId] : null;
|
|
414
|
+
const selfConsultPendingOnConsultMedia = selfParticipant?.consultState === 'consultInitiated' && !taskData?.isConsulted && hasConsultMedia;
|
|
415
|
+
const selfConsultingOnConsultMedia = selfParticipant?.consultState === 'consulting' && hasConsultMedia;
|
|
416
|
+
const hasConsultLeg = Boolean(!interaction?.isTerminated && (consultOwnedBySelf && !taskData?.isConsulted || selfConsultingOnConsultMedia || selfConsultPendingOnConsultMedia) && (consultInProgress || isConsultingState || context.consultCallHeld || hasConsultMedia));
|
|
357
417
|
if (!hasConsultLeg) {
|
|
358
418
|
return {
|
|
359
419
|
hasConsultLeg: false,
|
|
@@ -362,10 +422,16 @@ function getVoiceLegState(currentState, context, config, fallbackTaskData) {
|
|
|
362
422
|
consultState: _constants.TaskState.CONSULTING
|
|
363
423
|
};
|
|
364
424
|
}
|
|
425
|
+
let mainState = _constants.TaskState.HELD;
|
|
426
|
+
if (currentState === _constants.TaskState.CONFERENCING) {
|
|
427
|
+
mainState = _constants.TaskState.CONFERENCING;
|
|
428
|
+
} else if (context.consultCallHeld) {
|
|
429
|
+
mainState = _constants.TaskState.CONNECTED;
|
|
430
|
+
}
|
|
365
431
|
return {
|
|
366
432
|
hasConsultLeg: true,
|
|
367
433
|
activeLeg: context.consultCallHeld ? 'main' : 'consult',
|
|
368
|
-
mainState
|
|
434
|
+
mainState,
|
|
369
435
|
consultState: isConsultingState ? currentState : _constants.TaskState.CONSULTING
|
|
370
436
|
};
|
|
371
437
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_types","require","_constants","_TaskUtils","DISABLED","isVisible","isEnabled","VISIBLE_ENABLED","VISIBLE_DISABLED","getDefaultInteractionUIControls","accept","decline","hold","mute","end","transfer","consult","consultTransfer","endConsult","recording","conference","wrapup","exitConference","transferConference","mergeToConference","switch","createTaskUIControls","main","activeLeg","getDefaultUIControls","computeVoiceInteractionUIControls","state","context","config","fallbackTaskData","currentLeg","TaskState","IDLE","taskData","interaction","mainCallId","mainInteractionId","interactionId","isWebrtc","voiceVariant","VOICE_VARIANT","WEBRTC","isOutdial","outboundType","serverHold","getServerHoldStateForControls","customerInCall","getIsCustomerInCall","customerPresent","Boolean","participants","Object","values","some","p","pType","hasLeft","participantCount","getConferenceParticipantsCount","maxParticipants","MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE","selfAgentId","agentId","consultInProgress","getIsConsultInProgressForConferenceControls","conferenceFromBackend","getIsConferenceInProgress","consultInitiator","consultDestinationAgentJoined","consultDestinationType","consultCallHeld","consultFromConference","recordingControlsAvailable","isEpDnConsult","isConsultDestinationReady","stateImpliesHeld","HELD","RESUME_INITIATING","stateImpliesConnected","CONNECTED","HOLD_INITIATING","isHeld","isConnected","isConsulting","CONSULTING","CONSULT_INITIATING","CONF_INITIATING","isConferencing","CONFERENCING","isWrappingUp","WRAPPING_UP","selfInMainCall","media","includes","conferenceActive","inConference","isSoleAgentOnCall","isConsulted","getIsConsultedAgentForControls","isActive","hasFullControls","consultOwnedBySelf","consultingAgentId","hasConsultMedia","consultMediaResourceId","mType","hasParallelConsultLeg","consultLegOnHold","OFFERED","isTerminated","canHold","isEndTaskEnabled","isConnectedOrHeld","canFromConference","canFromConnected","isEndConsultEnabled","isRecordingEnabled","consultingFromConference","computeDigitalInteractionUIControls","getVoiceLegState","currentState","hasConsultLeg","mainState","consultState","isConsultingState","computeUIControls","TERMINATED","COMPLETED","uiControlConfig","channelType","TASK_CHANNEL_TYPE","VOICE","mainControls","consultControls","DIGITAL","haveInteractionUIControlsChanged","previous","next","keys","key","prev","curr","haveUIControlsChanged"],"sources":["uiControlsComputer.ts"],"sourcesContent":["/**\n * UI Controls Computer - Centralized logic for computing UI control states\n */\n\nimport {\n InteractionUIControls,\n TASK_CHANNEL_TYPE,\n TaskData,\n TaskUILeg,\n TaskUIControls,\n VOICE_VARIANT,\n} from '../types';\nimport {TaskContext, UIControlConfig} from './types';\nimport {TaskState, MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE} from './constants';\nimport {\n getIsCustomerInCall,\n getConferenceParticipantsCount,\n getIsConferenceInProgress,\n getIsConsultInProgressForConferenceControls,\n getIsConsultedAgentForControls,\n getServerHoldStateForControls,\n} from '../TaskUtils';\n\nconst DISABLED = {isVisible: false, isEnabled: false} as const;\nconst VISIBLE_ENABLED = {isVisible: true, isEnabled: true} as const;\nconst VISIBLE_DISABLED = {isVisible: true, isEnabled: false} as const;\n\nfunction getDefaultInteractionUIControls(): InteractionUIControls {\n return {\n accept: DISABLED,\n decline: DISABLED,\n hold: DISABLED,\n mute: DISABLED,\n end: DISABLED,\n transfer: DISABLED,\n consult: DISABLED,\n consultTransfer: DISABLED,\n endConsult: DISABLED,\n recording: DISABLED,\n conference: DISABLED,\n wrapup: DISABLED,\n exitConference: DISABLED,\n transferConference: DISABLED,\n mergeToConference: DISABLED,\n switch: DISABLED,\n };\n}\n\nfunction createTaskUIControls(\n main: InteractionUIControls,\n consult: InteractionUIControls,\n activeLeg: TaskUILeg\n): TaskUIControls {\n return {\n main,\n consult,\n activeLeg,\n };\n}\n\nexport function getDefaultUIControls(): TaskUIControls {\n return createTaskUIControls(\n getDefaultInteractionUIControls(),\n getDefaultInteractionUIControls(),\n 'main'\n );\n}\n\nfunction computeVoiceInteractionUIControls(\n state: TaskState,\n context: TaskContext,\n config: UIControlConfig,\n fallbackTaskData?: TaskData,\n currentLeg: TaskUILeg = 'main'\n): InteractionUIControls {\n // Early exit for idle\n if (state === TaskState.IDLE) {\n return getDefaultInteractionUIControls();\n }\n\n // Essential data\n const taskData = context.taskData ?? fallbackTaskData ?? null;\n const interaction = taskData?.interaction;\n const mainCallId = interaction?.mainInteractionId || taskData?.interactionId;\n const isWebrtc = config.voiceVariant === VOICE_VARIANT.WEBRTC;\n const isOutdial = interaction?.outboundType === 'OUTDIAL';\n const serverHold = getServerHoldStateForControls(context, mainCallId, fallbackTaskData);\n\n // Backend-derived checks\n const customerInCall =\n interaction && mainCallId ? getIsCustomerInCall(interaction, mainCallId) : false;\n // EP-DN/secondary legs can have incomplete media participant lists; fall back to participants map.\n const customerPresent =\n customerInCall ||\n Boolean(\n interaction &&\n interaction.participants &&\n Object.values(interaction.participants).some(\n (p: any) => p?.pType === 'Customer' && !p?.hasLeft\n )\n );\n const participantCount =\n interaction && mainCallId ? getConferenceParticipantsCount(interaction, mainCallId) : 0;\n const maxParticipants = participantCount >= MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE;\n const selfAgentId = config.agentId ?? taskData?.agentId;\n const consultInProgress = getIsConsultInProgressForConferenceControls(\n interaction,\n mainCallId,\n selfAgentId\n );\n const conferenceFromBackend = taskData ? getIsConferenceInProgress(taskData) : false;\n // Note: ownership is used by some controls; keep computations local to those controls\n\n // Context flags (set by state machine actions)\n const {\n consultInitiator,\n consultDestinationAgentJoined,\n consultDestinationType,\n consultCallHeld,\n consultFromConference,\n } = context;\n const {recordingControlsAvailable} = context;\n\n // EP_DN consults are \"ready\" as soon as the consult is created (EP accepts routing immediately).\n // Backend sends destinationType as 'EP-DN'; SDK method uses 'entryPoint' — check both.\n const isEpDnConsult =\n consultDestinationType === 'entryPoint' || consultDestinationType === ('EP-DN' as any);\n const isConsultDestinationReady = consultDestinationAgentJoined || isEpDnConsult;\n\n const stateImpliesHeld = state === TaskState.HELD || state === TaskState.RESUME_INITIATING;\n const stateImpliesConnected =\n state === TaskState.CONNECTED || state === TaskState.HOLD_INITIATING;\n const isHeld = stateImpliesHeld || serverHold === true;\n const isConnected = stateImpliesConnected || (!stateImpliesHeld && serverHold === false);\n\n // State categories for cleaner logic\n const isConsulting =\n state === TaskState.CONSULTING ||\n state === TaskState.CONSULT_INITIATING ||\n state === TaskState.CONF_INITIATING;\n const isConferencing = state === TaskState.CONFERENCING;\n const isWrappingUp = state === TaskState.WRAPPING_UP;\n const selfInMainCall =\n Boolean(selfAgentId) &&\n Boolean(mainCallId) &&\n Boolean(interaction?.media?.[mainCallId]?.participants?.includes(selfAgentId as string));\n const conferenceActive = isConferencing || conferenceFromBackend || consultFromConference;\n // Treat consult initiator as \"in conference\" even if mainCall participant list lags while consulting.\n const inConference = conferenceActive && (isConferencing || selfInMainCall || consultInitiator);\n\n // Check if this is a consulted agent (must be after isConsulting is computed).\n const isSoleAgentOnCall = participantCount <= 1 && !isConsulting && !inConference;\n const isConsulted =\n inConference || isSoleAgentOnCall\n ? false\n : getIsConsultedAgentForControls(taskData, context, isConsulting);\n\n // Active call = can perform call operations\n const isActive =\n state === TaskState.CONNECTED ||\n state === TaskState.HELD ||\n state === TaskState.HOLD_INITIATING ||\n state === TaskState.RESUME_INITIATING ||\n isConsulting ||\n isConferencing;\n\n // Consulted agents have limited controls until they're in conference or wrapup\n // Use inConference (not isConferencing) so controls remain enabled after state downgrade\n const hasFullControls = !isConsulted || consultInitiator || inConference || isWrappingUp;\n const consultOwnedBySelf =\n consultInitiator || (Boolean(selfAgentId) && taskData?.consultingAgentId === selfAgentId);\n const hasConsultMedia = Boolean(\n taskData?.consultMediaResourceId ||\n Object.values(interaction?.media ?? {}).some((media: any) => media?.mType === 'consult')\n );\n const hasParallelConsultLeg =\n consultOwnedBySelf &&\n !isConsulting &&\n !isConsulted &&\n (consultInProgress || consultCallHeld || hasConsultMedia);\n const consultLegOnHold = isConsulting && consultCallHeld;\n\n return {\n // Accept/Decline: Voice tasks in offered state\n // For outdial, accept is disabled (auto-answer handles it), decline remains enabled\n // For Extension mode (non-WebRTC), accept shows as disabled \"Ringing\" button\n accept:\n state === TaskState.OFFERED && !interaction?.isTerminated\n ? {isVisible: true, isEnabled: isWebrtc && !isOutdial}\n : DISABLED,\n decline:\n isWebrtc && state === TaskState.OFFERED && !interaction?.isTerminated\n ? VISIBLE_ENABLED\n : DISABLED,\n\n // Hold: visible in connected/held/conference, disabled in conference/consulting\n hold: (() => {\n if (!hasFullControls) return DISABLED;\n if (consultOwnedBySelf && (isConsulting || hasParallelConsultLeg || consultCallHeld)) {\n return DISABLED;\n }\n if (hasParallelConsultLeg) return DISABLED;\n if (state === TaskState.OFFERED) return DISABLED;\n if (isWrappingUp) return DISABLED;\n // Visibility: connected || held || inConference\n if (!(isConnected || isHeld || inConference)) return DISABLED;\n // Enabled: (connected || held) && !inConference && !isConsulting\n const canHold = (isConnected || isHeld) && !inConference && !isConsulting;\n\n return canHold ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // Mute: WebRTC only, active calls; hidden entirely during wrapup\n mute: (() => {\n if (!isWebrtc) return DISABLED;\n if (isWrappingUp) return DISABLED;\n if (isConsulting) return VISIBLE_ENABLED;\n\n if (isConnected || isHeld || isConferencing) {\n if (inConference) return VISIBLE_ENABLED;\n\n return isHeld ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n }\n\n return DISABLED;\n })(),\n\n // End: varies by state; during consulting only on main leg (consult held)\n end: (() => {\n if (!config.isEndTaskEnabled) return DISABLED;\n if (hasParallelConsultLeg) {\n return isConnected && isEpDnConsult ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n\n if (isConsulting) {\n if (currentLeg === 'consult' && consultCallHeld) return DISABLED;\n\n return consultInitiator && consultCallHeld ? VISIBLE_ENABLED : DISABLED;\n }\n\n if (inConference) {\n if (isConsulted) return DISABLED;\n\n if (consultInProgress) return VISIBLE_DISABLED;\n\n return isWrappingUp ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n }\n if (!hasFullControls) return DISABLED;\n if (isActive) return isHeld || isWrappingUp ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n\n return DISABLED;\n })(),\n\n // Transfer: connected/held/conference\n transfer: (() => {\n if (hasParallelConsultLeg) {\n if (!customerPresent) return DISABLED;\n if (state === TaskState.CONNECTED) return VISIBLE_ENABLED;\n if (state === TaskState.HELD) return VISIBLE_DISABLED;\n }\n if (isConsulting) {\n if (!consultInitiator) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n if (consultLegOnHold) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n if (!hasFullControls) return DISABLED;\n if (inConference) {\n // Real conference (multiple agents): transfer is hidden\n // Pending conference (only self agent): transfer remains available\n return participantCount > 1 ? DISABLED : VISIBLE_ENABLED;\n }\n if (state === TaskState.CONNECTED || state === TaskState.HELD) return VISIBLE_ENABLED;\n\n return DISABLED;\n })(),\n\n // Consult: connected/held/conference when conditions met\n consult: (() => {\n const isConnectedOrHeld = state === TaskState.CONNECTED || state === TaskState.HELD;\n\n if (hasParallelConsultLeg) return DISABLED;\n if (!hasFullControls || !(isConnectedOrHeld || inConference)) {\n return DISABLED;\n }\n\n // In conference: behavior depends on whether it's a real multi-agent conference\n if (inConference) {\n // Pending conference (only self agent): consult disabled\n if (participantCount <= 1) return VISIBLE_DISABLED;\n // Real conference: consult enabled if conditions met\n const canFromConference =\n !maxParticipants && customerPresent && !consultInProgress && !isConsulting;\n\n return {isVisible: true, isEnabled: canFromConference};\n }\n\n // Enabled conditions for connected/held\n const canFromConnected =\n !maxParticipants && customerPresent && !consultInProgress && !isConsulted;\n\n return {isVisible: true, isEnabled: canFromConnected};\n })(),\n\n // ConsultTransfer: always hidden (use transfer button)\n consultTransfer: DISABLED,\n\n // EndConsult: during consulting\n endConsult: (() => {\n if (!isConsulting) return DISABLED;\n if (isConsulted && isConferencing) return DISABLED;\n if (!isConsulted && isConferencing && !(consultInitiator && conferenceFromBackend)) {\n return DISABLED;\n }\n\n return {isVisible: true, isEnabled: consultInitiator || config.isEndConsultEnabled};\n })(),\n\n // Recording: connected/held, hidden in real conference, visible in pending conference\n recording: (() => {\n if (!recordingControlsAvailable || !config.isRecordingEnabled) return DISABLED;\n if (!hasFullControls || isConsulting) return DISABLED;\n if (inConference) {\n // Real conference (multiple agents): recording hidden\n // Pending conference (only self agent): recording available\n return participantCount > 1 ? DISABLED : VISIBLE_ENABLED;\n }\n if (hasParallelConsultLeg && !customerPresent) return DISABLED;\n if (state === TaskState.CONNECTED || state === TaskState.HELD) {\n return VISIBLE_ENABLED;\n }\n\n return DISABLED;\n })(),\n\n // Conference: during consulting, enabled on both legs when agent joined\n // Label changes based on leg: \"Conference\" on main leg, \"Merge\" on consult leg\n conference: (() => {\n if (hasParallelConsultLeg) {\n if (!customerPresent) return DISABLED;\n if (state === TaskState.CONNECTED) {\n return maxParticipants ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n }\n if (state === TaskState.HELD) return VISIBLE_DISABLED;\n\n return DISABLED;\n }\n if (!hasFullControls || !isConsulting) return DISABLED;\n if (!consultInitiator) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n if (consultLegOnHold) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady && !maxParticipants ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // Wrapup: wrapping up state\n wrapup: isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n\n // ExitConference: in conference with multiple agents in main call\n exitConference: (() => {\n if (isConsulted && !isConferencing) return DISABLED;\n if (!inConference) return DISABLED;\n if (participantCount <= 1) return DISABLED;\n const consultingFromConference = consultInitiator && isConsulting && conferenceFromBackend;\n\n return consultingFromConference ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n })(),\n\n // TransferConference: in conference with active consult, owner consulting from conference\n transferConference: (() => {\n if (hasParallelConsultLeg || consultLegOnHold) return DISABLED;\n if (!inConference || !isConsulting) return DISABLED;\n if (!consultInitiator || isConsulted) return DISABLED;\n\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // MergeToConference: mirrors conference control, enabled on both legs\n mergeToConference: (() => {\n if (!isConsulting || !consultInitiator) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n if (consultLegOnHold) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady && !maxParticipants ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // Switch: visible only on the currently active leg\n switch: (() => {\n if (!customerPresent && hasParallelConsultLeg) return DISABLED;\n if (currentLeg === 'consult') {\n if (!isConsulting || !consultInitiator || consultCallHeld) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n\n if (hasParallelConsultLeg && state === TaskState.CONNECTED) {\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n\n return DISABLED;\n })(),\n };\n}\n\nfunction computeDigitalInteractionUIControls(\n state: TaskState,\n context: TaskContext,\n fallbackTaskData?: TaskData\n): InteractionUIControls {\n const taskData = context.taskData ?? fallbackTaskData ?? null;\n const isTerminated = taskData?.interaction?.isTerminated ?? false;\n\n const isConnected = state === TaskState.CONNECTED;\n const isWrappingUp = state === TaskState.WRAPPING_UP;\n\n return {\n accept: state === TaskState.OFFERED ? VISIBLE_ENABLED : DISABLED,\n decline: DISABLED,\n hold: DISABLED,\n mute: DISABLED,\n end: isConnected && !isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n transfer: isConnected && !isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n consult: DISABLED,\n consultTransfer: DISABLED,\n endConsult: DISABLED,\n recording: DISABLED,\n conference: DISABLED,\n wrapup: isTerminated || isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n exitConference: DISABLED,\n transferConference: DISABLED,\n mergeToConference: DISABLED,\n switch: DISABLED,\n };\n}\n\nfunction getVoiceLegState(\n currentState: TaskState,\n context: TaskContext,\n config: UIControlConfig,\n fallbackTaskData?: TaskData\n): {hasConsultLeg: boolean; activeLeg: TaskUILeg; mainState: TaskState; consultState: TaskState} {\n if (currentState === TaskState.WRAPPING_UP) {\n return {\n hasConsultLeg: false,\n activeLeg: 'main',\n mainState: currentState,\n consultState: TaskState.CONSULTING,\n };\n }\n\n const taskData = context.taskData ?? fallbackTaskData ?? null;\n const interaction = taskData?.interaction;\n const mainCallId = interaction?.mainInteractionId || taskData?.interactionId;\n const selfAgentId = config.agentId ?? taskData?.agentId;\n const consultInProgress = getIsConsultInProgressForConferenceControls(\n interaction,\n mainCallId,\n selfAgentId\n );\n const isConsultingState =\n currentState === TaskState.CONSULTING ||\n currentState === TaskState.CONSULT_INITIATING ||\n currentState === TaskState.CONF_INITIATING;\n const consultOwnedBySelf =\n context.consultInitiator ||\n (Boolean(selfAgentId) && taskData?.consultingAgentId === selfAgentId);\n const hasConsultMedia = Boolean(\n taskData?.consultMediaResourceId ||\n Object.values(interaction?.media ?? {}).some((media: any) => media?.mType === 'consult')\n );\n const hasConsultLeg = Boolean(\n consultOwnedBySelf &&\n !taskData?.isConsulted &&\n !interaction?.isTerminated &&\n (consultInProgress || isConsultingState || context.consultCallHeld || hasConsultMedia)\n );\n\n if (!hasConsultLeg) {\n return {\n hasConsultLeg: false,\n activeLeg: 'main',\n mainState: currentState,\n consultState: TaskState.CONSULTING,\n };\n }\n\n return {\n hasConsultLeg: true,\n activeLeg: context.consultCallHeld ? 'main' : 'consult',\n mainState: context.consultCallHeld ? TaskState.CONNECTED : TaskState.HELD,\n consultState: isConsultingState ? currentState : TaskState.CONSULTING,\n };\n}\n\nexport function computeUIControls(\n currentState: TaskState,\n context: TaskContext,\n fallbackTaskData?: TaskData\n): TaskUIControls {\n if (currentState === TaskState.TERMINATED || currentState === TaskState.COMPLETED) {\n return getDefaultUIControls();\n }\n\n switch (context.uiControlConfig.channelType) {\n case TASK_CHANNEL_TYPE.VOICE: {\n const {hasConsultLeg, activeLeg, mainState, consultState} = getVoiceLegState(\n currentState,\n context,\n context.uiControlConfig,\n fallbackTaskData\n );\n\n const mainControls = computeVoiceInteractionUIControls(\n mainState,\n context,\n context.uiControlConfig,\n fallbackTaskData,\n 'main'\n );\n const consultControls = hasConsultLeg\n ? computeVoiceInteractionUIControls(\n consultState,\n context,\n context.uiControlConfig,\n fallbackTaskData,\n 'consult'\n )\n : getDefaultInteractionUIControls();\n\n return createTaskUIControls(mainControls, consultControls, activeLeg);\n }\n case TASK_CHANNEL_TYPE.DIGITAL:\n return createTaskUIControls(\n computeDigitalInteractionUIControls(currentState, context, fallbackTaskData),\n getDefaultInteractionUIControls(),\n 'main'\n );\n default:\n return getDefaultUIControls();\n }\n}\n\nfunction haveInteractionUIControlsChanged(\n previous: InteractionUIControls,\n next: InteractionUIControls\n): boolean {\n return (Object.keys(next) as (keyof InteractionUIControls)[]).some((key) => {\n const prev = previous[key];\n const curr = next[key];\n\n return prev.isVisible !== curr.isVisible || prev.isEnabled !== curr.isEnabled;\n });\n}\n\nexport function haveUIControlsChanged(\n previous: TaskUIControls | undefined,\n next: TaskUIControls\n): boolean {\n if (!previous) return true;\n\n return (\n previous.activeLeg !== next.activeLeg ||\n haveInteractionUIControlsChanged(previous.main, next.main) ||\n haveInteractionUIControlsChanged(previous.consult, next.consult)\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_types","require","_constants","_TaskUtils","DISABLED","isVisible","isEnabled","VISIBLE_ENABLED","VISIBLE_DISABLED","getDefaultInteractionUIControls","accept","decline","hold","mute","end","transfer","consult","consultTransfer","endConsult","recording","conference","wrapup","exitConference","transferConference","mergeToConference","switch","createTaskUIControls","main","activeLeg","getDefaultUIControls","computeVoiceInteractionUIControls","state","context","config","fallbackTaskData","currentLeg","TaskState","IDLE","taskData","interaction","mainCallId","mainInteractionId","interactionId","isWebrtc","voiceVariant","VOICE_VARIANT","WEBRTC","isOutdial","outboundType","serverHold","getServerHoldStateForControls","customerInCall","getIsCustomerInCall","customerPresent","Boolean","participants","Object","values","some","p","pType","hasLeft","participantCount","getConferenceParticipantsCount","maxParticipants","MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE","selfAgentId","agentId","consultInProgress","getIsConsultInProgressForConferenceControls","conferenceFromBackend","getIsConferenceInProgress","consultInitiator","consultDestinationAgentJoined","consultDestinationType","consultCallHeld","consultFromConference","recordingControlsAvailable","isEpDnConsult","isConsultDestinationReady","stateImpliesHeld","HELD","RESUME_INITIATING","stateImpliesConnected","CONNECTED","HOLD_INITIATING","isHeld","isConnected","isConsulting","CONSULTING","CONSULT_INITIATING","CONF_INITIATING","isConferencing","CONFERENCING","isWrappingUp","WRAPPING_UP","selfInMainCall","media","includes","consultMedia","find","mediaResourceId","consultMediaResourceId","mType","selfParticipant","selfInConsultCall","conferenceActive","inConference","isSoleAgentOnCall","isConsulted","getIsConsultedAgentForControls","consultState","isActive","hasFullControls","consultOwnedBySelf","consultingAgentId","hasConsultMedia","selfConsultPendingOnConsultMedia","ownerParticipant","owner","undefined","otherAgentConsultInProgress","participant","id","currentState","isHydratedConferenceConsultPending","hasParallelConsultLeg","activeLegForConferenceConsult","isCurrentLegActive","isConferenceConsultTransferContext","consultLegOnHold","callProcessingDetails","conferenceHoldParticipant","postDeclineHeldMainLeg","postConsultCompletedHeldMainLeg","nonOwnerPostConsultCompletedHeldMainLeg","isConsultPendingBeforeJoin","hideExitConferenceWhileConsultPending","type","hideExitConferenceDuringActiveConsultFromConference","forceHeldPostConsultControls","selfOnConsultLeg","showMainLegConferenceControlsDuringConsult","allowHeldMainLegControlsForNonInitiator","OFFERED","isTerminated","canHold","isEndTaskEnabled","isConnectedOrHeld","canFromConference","canFromConnected","isEndConsultEnabled","isRecordingEnabled","consultingFromConference","consultLegTransferAvailable","selfConsultingOnParticipantState","conferenceTransferAvailable","computeDigitalInteractionUIControls","getVoiceLegState","hasConsultLeg","mainState","isConsultingState","selfConsultingOnConsultMedia","computeUIControls","TERMINATED","COMPLETED","uiControlConfig","channelType","TASK_CHANNEL_TYPE","VOICE","mainControls","consultControls","DIGITAL","haveInteractionUIControlsChanged","previous","next","keys","key","prev","curr","haveUIControlsChanged"],"sources":["uiControlsComputer.ts"],"sourcesContent":["/**\n * UI Controls Computer - Centralized logic for computing UI control states\n */\n\nimport {\n InteractionUIControls,\n TASK_CHANNEL_TYPE,\n TaskData,\n TaskUILeg,\n TaskUIControls,\n VOICE_VARIANT,\n} from '../types';\nimport {TaskContext, UIControlConfig} from './types';\nimport {TaskState, MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE} from './constants';\nimport {\n getIsCustomerInCall,\n getConferenceParticipantsCount,\n getIsConferenceInProgress,\n getIsConsultInProgressForConferenceControls,\n getIsConsultedAgentForControls,\n getServerHoldStateForControls,\n} from '../TaskUtils';\n\nconst DISABLED = {isVisible: false, isEnabled: false} as const;\nconst VISIBLE_ENABLED = {isVisible: true, isEnabled: true} as const;\nconst VISIBLE_DISABLED = {isVisible: true, isEnabled: false} as const;\n\nfunction getDefaultInteractionUIControls(): InteractionUIControls {\n return {\n accept: DISABLED,\n decline: DISABLED,\n hold: DISABLED,\n mute: DISABLED,\n end: DISABLED,\n transfer: DISABLED,\n consult: DISABLED,\n consultTransfer: DISABLED,\n endConsult: DISABLED,\n recording: DISABLED,\n conference: DISABLED,\n wrapup: DISABLED,\n exitConference: DISABLED,\n transferConference: DISABLED,\n mergeToConference: DISABLED,\n switch: DISABLED,\n };\n}\n\nfunction createTaskUIControls(\n main: InteractionUIControls,\n consult: InteractionUIControls,\n activeLeg: TaskUILeg\n): TaskUIControls {\n return {\n main,\n consult,\n activeLeg,\n };\n}\n\nexport function getDefaultUIControls(): TaskUIControls {\n return createTaskUIControls(\n getDefaultInteractionUIControls(),\n getDefaultInteractionUIControls(),\n 'main'\n );\n}\n\nfunction computeVoiceInteractionUIControls(\n state: TaskState,\n context: TaskContext,\n config: UIControlConfig,\n fallbackTaskData?: TaskData,\n currentLeg: TaskUILeg = 'main'\n): InteractionUIControls {\n // Early exit for idle\n if (state === TaskState.IDLE) {\n return getDefaultInteractionUIControls();\n }\n\n // Essential data\n const taskData = context.taskData ?? fallbackTaskData ?? null;\n const interaction = taskData?.interaction;\n const mainCallId = interaction?.mainInteractionId || taskData?.interactionId;\n const isWebrtc = config.voiceVariant === VOICE_VARIANT.WEBRTC;\n const isOutdial = interaction?.outboundType === 'OUTDIAL';\n const serverHold = getServerHoldStateForControls(context, mainCallId, fallbackTaskData);\n\n // Backend-derived checks\n const customerInCall =\n interaction && mainCallId ? getIsCustomerInCall(interaction, mainCallId) : false;\n // EP-DN/secondary legs can have incomplete media participant lists; fall back to participants map.\n const customerPresent =\n customerInCall ||\n Boolean(\n interaction &&\n interaction.participants &&\n Object.values(interaction.participants).some(\n (p: any) => p?.pType === 'Customer' && !p?.hasLeft\n )\n );\n const participantCount =\n interaction && mainCallId ? getConferenceParticipantsCount(interaction, mainCallId) : 0;\n const maxParticipants = participantCount >= MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE;\n const selfAgentId = config.agentId ?? taskData?.agentId;\n const consultInProgress = getIsConsultInProgressForConferenceControls(\n interaction,\n mainCallId,\n selfAgentId\n );\n const conferenceFromBackend = taskData ? getIsConferenceInProgress(taskData) : false;\n // Note: ownership is used by some controls; keep computations local to those controls\n\n // Context flags (set by state machine actions)\n const {\n consultInitiator,\n consultDestinationAgentJoined,\n consultDestinationType,\n consultCallHeld,\n consultFromConference,\n } = context;\n const {recordingControlsAvailable} = context;\n\n // EP_DN consults are \"ready\" as soon as the consult is created (EP accepts routing immediately).\n // Backend sends destinationType as 'EP-DN'; SDK method uses 'entryPoint' — check both.\n const isEpDnConsult =\n consultDestinationType === 'entryPoint' || consultDestinationType === ('EP-DN' as any);\n const isConsultDestinationReady = consultDestinationAgentJoined || isEpDnConsult;\n\n const stateImpliesHeld = state === TaskState.HELD || state === TaskState.RESUME_INITIATING;\n const stateImpliesConnected =\n state === TaskState.CONNECTED || state === TaskState.HOLD_INITIATING;\n const isHeld = stateImpliesHeld || serverHold === true;\n const isConnected = stateImpliesConnected || (!stateImpliesHeld && serverHold === false);\n\n // State categories for cleaner logic\n const isConsulting =\n state === TaskState.CONSULTING ||\n state === TaskState.CONSULT_INITIATING ||\n state === TaskState.CONF_INITIATING;\n const isConferencing = state === TaskState.CONFERENCING;\n const isWrappingUp = state === TaskState.WRAPPING_UP;\n const selfInMainCall =\n Boolean(selfAgentId) &&\n Boolean(mainCallId) &&\n Boolean(interaction?.media?.[mainCallId]?.participants?.includes(selfAgentId as string));\n const consultMedia = Object.values(interaction?.media ?? {}).find(\n (media: any) =>\n media?.mediaResourceId === taskData?.consultMediaResourceId || media?.mType === 'consult'\n ) as {participants?: string[]} | undefined;\n const selfParticipant = selfAgentId ? interaction?.participants?.[selfAgentId] : null;\n const selfInConsultCall =\n Boolean(selfAgentId) && Boolean(consultMedia?.participants?.includes(selfAgentId as string));\n const conferenceActive = isConferencing || conferenceFromBackend || consultFromConference;\n // Treat consult initiator as \"in conference\" even if mainCall participant list lags while consulting.\n const inConference = conferenceActive && (isConferencing || selfInMainCall || consultInitiator);\n\n // Check if this is a consulted agent (must be after isConsulting is computed).\n const isSoleAgentOnCall =\n participantCount <= 1 && selfInMainCall && !isConsulting && !inConference;\n const isConsulted =\n inConference || isSoleAgentOnCall\n ? false\n : getIsConsultedAgentForControls(taskData, context, isConsulting) ||\n (!consultInitiator &&\n (selfParticipant?.isConsulted === true ||\n selfParticipant?.consultState === 'consulting'));\n\n // Active call = can perform call operations\n const isActive =\n state === TaskState.CONNECTED ||\n state === TaskState.HELD ||\n state === TaskState.HOLD_INITIATING ||\n state === TaskState.RESUME_INITIATING ||\n isConsulting ||\n isConferencing;\n\n // Consulted agents have limited controls until they're in conference or wrapup\n // Use inConference (not isConferencing) so controls remain enabled after state downgrade\n const hasFullControls = !isConsulted || consultInitiator || inConference || isWrappingUp;\n const consultOwnedBySelf =\n consultInitiator || (Boolean(selfAgentId) && taskData?.consultingAgentId === selfAgentId);\n const hasConsultMedia = Boolean(\n taskData?.consultMediaResourceId ||\n Object.values(interaction?.media ?? {}).some((media: any) => media?.mType === 'consult')\n );\n const selfConsultPendingOnConsultMedia =\n selfParticipant?.consultState === 'consultInitiated' &&\n !taskData?.isConsulted &&\n hasConsultMedia;\n const ownerParticipant = interaction?.owner\n ? interaction.participants?.[interaction.owner]\n : undefined;\n const otherAgentConsultInProgress = Boolean(\n interaction?.participants &&\n Object.values(interaction.participants).some((participant: any) => {\n if (!participant || participant.hasLeft) return false;\n if (participant.id === selfAgentId) return false;\n if (participant.pType !== 'AGENT') return false;\n\n return (\n participant.consultState === 'consultInitiated' ||\n participant.consultState === 'consultReserved' ||\n participant.consultState === 'consulting' ||\n participant.currentState === 'consulting'\n );\n })\n );\n const isHydratedConferenceConsultPending =\n inConference && selfConsultPendingOnConsultMedia && !consultDestinationAgentJoined;\n const hasParallelConsultLeg =\n consultOwnedBySelf &&\n !isConsulting &&\n !isConsulted &&\n (consultInProgress || consultCallHeld || hasConsultMedia);\n const activeLegForConferenceConsult = consultCallHeld ? 'main' : 'consult';\n const isCurrentLegActive = currentLeg === activeLegForConferenceConsult;\n const isConferenceConsultTransferContext =\n inConference && consultInitiator && hasConsultMedia && isConsultDestinationReady;\n const consultLegOnHold = isConsulting && consultCallHeld;\n const callProcessingDetails = interaction?.callProcessingDetails as\n | {conferenceHoldParticipant?: boolean | string}\n | undefined;\n const conferenceHoldParticipant =\n callProcessingDetails?.conferenceHoldParticipant === true ||\n callProcessingDetails?.conferenceHoldParticipant === 'true';\n const postDeclineHeldMainLeg =\n consultInitiator &&\n !consultDestinationAgentJoined &&\n isHeld &&\n inConference &&\n conferenceHoldParticipant;\n const postConsultCompletedHeldMainLeg =\n selfParticipant?.consultState === 'consultCompleted' && isHeld && inConference && !isConsulting;\n const nonOwnerPostConsultCompletedHeldMainLeg =\n isHeld &&\n inConference &&\n !isConsulting &&\n !consultInitiator &&\n Boolean(selfAgentId) &&\n Boolean(interaction?.owner) &&\n selfAgentId !== interaction?.owner &&\n ownerParticipant?.consultState === 'consultCompleted';\n const isConsultPendingBeforeJoin =\n selfParticipant?.consultState === 'consultInitiated' && !consultDestinationAgentJoined;\n const hideExitConferenceWhileConsultPending =\n currentLeg === 'main' &&\n inConference &&\n isConsultPendingBeforeJoin &&\n (consultFromConference ||\n consultInitiator ||\n taskData?.type === 'AgentConsultCreated' ||\n consultInProgress ||\n isConsulting);\n const hideExitConferenceDuringActiveConsultFromConference =\n inConference &&\n consultInitiator &&\n consultDestinationAgentJoined &&\n (isConsulting ||\n taskData?.type === 'AgentConsulting' ||\n selfParticipant?.consultState === 'consulting');\n const forceHeldPostConsultControls =\n !hideExitConferenceWhileConsultPending &&\n (postDeclineHeldMainLeg || postConsultCompletedHeldMainLeg);\n const selfOnConsultLeg =\n selfParticipant?.consultState === 'consulting' ||\n selfParticipant?.currentState === 'consulting';\n const showMainLegConferenceControlsDuringConsult =\n currentLeg === 'main' && inConference && consultInProgress && !selfOnConsultLeg;\n const allowHeldMainLegControlsForNonInitiator =\n showMainLegConferenceControlsDuringConsult && !isHydratedConferenceConsultPending;\n\n return {\n // Accept/Decline: Voice tasks in offered state\n // Desktop/WebRTC + inbound: accept enabled (agent manually accepts)\n // Desktop/WebRTC + outdial: accept disabled (auto-answer handles it; Widgets show \"Accept\" disabled)\n // Extension mode (non-WebRTC): accept disabled (Widgets show \"Ringing...\")\n accept:\n state === TaskState.OFFERED && !interaction?.isTerminated\n ? {isVisible: true, isEnabled: isWebrtc && !isOutdial}\n : DISABLED,\n decline: (() => {\n if (!isWebrtc || state !== TaskState.OFFERED || interaction?.isTerminated) return DISABLED;\n\n return isOutdial ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n })(),\n\n // Hold: visible in connected/held/conference, disabled in conference/consulting\n hold: (() => {\n if (!hasFullControls) return DISABLED;\n if (forceHeldPostConsultControls) return VISIBLE_ENABLED;\n if (consultOwnedBySelf && (isConsulting || hasParallelConsultLeg || consultCallHeld)) {\n return DISABLED;\n }\n if (hasParallelConsultLeg) return DISABLED;\n if (state === TaskState.OFFERED) return DISABLED;\n if (isWrappingUp) return DISABLED;\n // Visibility: connected || held || inConference\n if (!(isConnected || isHeld || inConference)) return DISABLED;\n // Enabled: (connected || held) && !inConference && !isConsulting\n const canHold = (isConnected || isHeld) && !inConference && !isConsulting;\n\n return canHold ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // Mute: WebRTC only, active calls; hidden entirely during wrapup\n mute: (() => {\n if (!isWebrtc) return DISABLED;\n if (isWrappingUp) return DISABLED;\n if (currentLeg === 'consult' && !selfInConsultCall) return DISABLED;\n if (isConsulting) return VISIBLE_ENABLED;\n\n if (isConnected || isHeld || isConferencing) {\n if (inConference) return VISIBLE_ENABLED;\n\n return isHeld ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n }\n\n return DISABLED;\n })(),\n\n // End: varies by state; during consulting only on main leg (consult held)\n end: (() => {\n if (allowHeldMainLegControlsForNonInitiator) return VISIBLE_ENABLED;\n if (showMainLegConferenceControlsDuringConsult) return VISIBLE_DISABLED;\n if (isHydratedConferenceConsultPending && currentLeg === 'main') return VISIBLE_DISABLED;\n if (!config.isEndTaskEnabled) return DISABLED;\n if (hasParallelConsultLeg) {\n return isConnected && isEpDnConsult ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n\n if (isConsulting) {\n if (currentLeg === 'consult' && consultCallHeld) return DISABLED;\n\n return consultInitiator && consultCallHeld ? VISIBLE_ENABLED : DISABLED;\n }\n\n if (inConference) {\n if (isConsulted) return DISABLED;\n if (forceHeldPostConsultControls) return VISIBLE_DISABLED;\n\n if (consultInProgress) return VISIBLE_DISABLED;\n\n return isWrappingUp ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n }\n if (!hasFullControls) return DISABLED;\n if (isActive) return isHeld || isWrappingUp ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n\n return DISABLED;\n })(),\n\n // Transfer: connected/held/conference\n transfer: (() => {\n if (isHydratedConferenceConsultPending) return VISIBLE_DISABLED;\n if (isConferenceConsultTransferContext && currentLeg === 'main' && isCurrentLegActive) {\n return DISABLED;\n }\n if (inConference && isConsulting && consultInitiator) return DISABLED;\n if (hasParallelConsultLeg) {\n if (!customerPresent) return DISABLED;\n if (state === TaskState.CONNECTED) return VISIBLE_ENABLED;\n if (state === TaskState.HELD) return VISIBLE_DISABLED;\n }\n if (isConsulting) {\n if (!consultInitiator) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n if (consultLegOnHold) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n if (!hasFullControls) return DISABLED;\n if (inConference) {\n // Real conference (multiple agents): transfer is hidden\n // Pending conference (only self agent): transfer remains available\n return participantCount > 1 ? DISABLED : VISIBLE_ENABLED;\n }\n if (state === TaskState.CONNECTED || state === TaskState.HELD) return VISIBLE_ENABLED;\n\n return DISABLED;\n })(),\n\n // Consult: connected/held/conference when conditions met\n consult: (() => {\n const isConnectedOrHeld = state === TaskState.CONNECTED || state === TaskState.HELD;\n\n if (inConference && nonOwnerPostConsultCompletedHeldMainLeg) return VISIBLE_DISABLED;\n if (hasParallelConsultLeg) return DISABLED;\n if (!hasFullControls || !(isConnectedOrHeld || inConference)) {\n return DISABLED;\n }\n\n // In conference: behavior depends on whether it's a real multi-agent conference\n if (inConference) {\n // Pending conference (only self agent): consult disabled\n if (participantCount <= 1) return VISIBLE_DISABLED;\n // Real conference: consult enabled if conditions met\n const canFromConference =\n !maxParticipants &&\n customerPresent &&\n !consultInProgress &&\n !otherAgentConsultInProgress &&\n !isConsulting;\n\n return {isVisible: true, isEnabled: canFromConference};\n }\n\n // Enabled conditions for connected/held\n const canFromConnected =\n !maxParticipants && customerPresent && !consultInProgress && !isConsulted;\n\n return {isVisible: true, isEnabled: canFromConnected};\n })(),\n\n // ConsultTransfer: always hidden (use transfer button)\n consultTransfer: DISABLED,\n\n // EndConsult: during consulting\n endConsult: (() => {\n if (!isConsulting) return DISABLED;\n if (isConsulted && isConferencing) return DISABLED;\n if (!isConsulted && isConferencing && !(consultInitiator && conferenceFromBackend)) {\n return DISABLED;\n }\n\n return {isVisible: true, isEnabled: consultInitiator || config.isEndConsultEnabled};\n })(),\n\n // Recording: connected/held, hidden in real conference, visible in pending conference\n recording: (() => {\n if (!recordingControlsAvailable || !config.isRecordingEnabled) return DISABLED;\n if (!hasFullControls || isConsulting) return DISABLED;\n if (inConference) {\n // Real conference (multiple agents): recording hidden\n // Pending conference (only self agent): recording available\n return participantCount > 1 ? DISABLED : VISIBLE_ENABLED;\n }\n if (hasParallelConsultLeg && !customerPresent) return DISABLED;\n if (state === TaskState.CONNECTED || state === TaskState.HELD) {\n return VISIBLE_ENABLED;\n }\n\n return DISABLED;\n })(),\n\n // Conference: during consulting, enabled on both legs when agent joined\n // Label changes based on leg: \"Conference\" on main leg, \"Merge\" on consult leg\n conference: (() => {\n if (isHydratedConferenceConsultPending && currentLeg === 'main') return VISIBLE_DISABLED;\n if (hasParallelConsultLeg) {\n if (!customerPresent) return DISABLED;\n if (state === TaskState.CONNECTED) {\n return maxParticipants ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n }\n if (state === TaskState.HELD) return VISIBLE_DISABLED;\n\n return DISABLED;\n }\n if (!hasFullControls || !isConsulting) return DISABLED;\n if (!consultInitiator) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n if (consultLegOnHold) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady && !maxParticipants ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // Wrapup: wrapping up state\n wrapup: isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n\n // ExitConference: in conference with multiple agents in main call\n exitConference: (() => {\n if (hideExitConferenceWhileConsultPending) return DISABLED;\n if (allowHeldMainLegControlsForNonInitiator) return VISIBLE_ENABLED;\n if (showMainLegConferenceControlsDuringConsult) return VISIBLE_DISABLED;\n if (hideExitConferenceDuringActiveConsultFromConference) return DISABLED;\n if (forceHeldPostConsultControls) return VISIBLE_DISABLED;\n if (isConsulted && !isConferencing) return DISABLED;\n if (!inConference) return DISABLED;\n if (participantCount <= 1) return DISABLED;\n if (consultInProgress) return VISIBLE_DISABLED;\n const consultingFromConference = consultInitiator && isConsulting && conferenceFromBackend;\n\n return consultingFromConference ? VISIBLE_DISABLED : VISIBLE_ENABLED;\n })(),\n\n // TransferConference: in conference with active consult, owner consulting from conference\n transferConference: (() => {\n if (isConferenceConsultTransferContext && !isCurrentLegActive) return VISIBLE_DISABLED;\n const consultLegTransferAvailable =\n currentLeg === 'consult' && inConference && consultInitiator && hasConsultMedia;\n const selfConsultingOnParticipantState = selfParticipant?.consultState === 'consulting';\n const conferenceTransferAvailable =\n consultLegTransferAvailable ||\n (inConference &&\n consultInitiator &&\n hasConsultMedia &&\n (isConsulting || consultInProgress || selfConsultingOnParticipantState));\n if (consultLegOnHold) return DISABLED;\n if (hasParallelConsultLeg && !conferenceTransferAvailable) return DISABLED;\n if (!conferenceTransferAvailable && (!inConference || !isConsulting)) return DISABLED;\n if (!consultInitiator || isConsulted) return DISABLED;\n\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // MergeToConference: mirrors conference control, enabled on both legs\n mergeToConference: (() => {\n if (isHydratedConferenceConsultPending && currentLeg === 'consult') return VISIBLE_DISABLED;\n if (!isConsulting || !consultInitiator) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n if (consultLegOnHold) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady && !maxParticipants ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n })(),\n\n // Switch: visible only on the currently active leg\n switch: (() => {\n if (isHydratedConferenceConsultPending && currentLeg === 'consult') return VISIBLE_DISABLED;\n if (!customerPresent && hasParallelConsultLeg) return DISABLED;\n if (currentLeg === 'consult') {\n if (!isConsulting || !consultInitiator || consultCallHeld) return DISABLED;\n if (!customerPresent) return VISIBLE_DISABLED;\n\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n\n if (hasParallelConsultLeg && state === TaskState.CONNECTED) {\n return isConsultDestinationReady ? VISIBLE_ENABLED : VISIBLE_DISABLED;\n }\n\n return DISABLED;\n })(),\n };\n}\n\nfunction computeDigitalInteractionUIControls(\n state: TaskState,\n context: TaskContext,\n fallbackTaskData?: TaskData\n): InteractionUIControls {\n const taskData = context.taskData ?? fallbackTaskData ?? null;\n const isTerminated = taskData?.interaction?.isTerminated ?? false;\n\n const isConnected = state === TaskState.CONNECTED;\n const isWrappingUp = state === TaskState.WRAPPING_UP;\n\n return {\n accept: state === TaskState.OFFERED ? VISIBLE_ENABLED : DISABLED,\n decline: DISABLED,\n hold: DISABLED,\n mute: DISABLED,\n end: isConnected && !isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n transfer: isConnected && !isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n consult: DISABLED,\n consultTransfer: DISABLED,\n endConsult: DISABLED,\n recording: DISABLED,\n conference: DISABLED,\n wrapup: isTerminated || isWrappingUp ? VISIBLE_ENABLED : DISABLED,\n exitConference: DISABLED,\n transferConference: DISABLED,\n mergeToConference: DISABLED,\n switch: DISABLED,\n };\n}\n\nfunction getVoiceLegState(\n currentState: TaskState,\n context: TaskContext,\n config: UIControlConfig,\n fallbackTaskData?: TaskData\n): {hasConsultLeg: boolean; activeLeg: TaskUILeg; mainState: TaskState; consultState: TaskState} {\n if (currentState === TaskState.WRAPPING_UP) {\n return {\n hasConsultLeg: false,\n activeLeg: 'main',\n mainState: currentState,\n consultState: TaskState.CONSULTING,\n };\n }\n\n const taskData = context.taskData ?? fallbackTaskData ?? null;\n const interaction = taskData?.interaction;\n const mainCallId = interaction?.mainInteractionId || taskData?.interactionId;\n const selfAgentId = config.agentId ?? taskData?.agentId;\n const consultInProgress = getIsConsultInProgressForConferenceControls(\n interaction,\n mainCallId,\n selfAgentId\n );\n const isConsultingState =\n currentState === TaskState.CONSULTING ||\n currentState === TaskState.CONSULT_INITIATING ||\n currentState === TaskState.CONF_INITIATING;\n const consultOwnedBySelf =\n context.consultInitiator ||\n (Boolean(selfAgentId) && taskData?.consultingAgentId === selfAgentId);\n const hasConsultMedia = Boolean(\n taskData?.consultMediaResourceId ||\n Object.values(interaction?.media ?? {}).some((media: any) => media?.mType === 'consult')\n );\n const selfParticipant = selfAgentId ? interaction?.participants?.[selfAgentId] : null;\n const selfConsultPendingOnConsultMedia =\n selfParticipant?.consultState === 'consultInitiated' &&\n !taskData?.isConsulted &&\n hasConsultMedia;\n const selfConsultingOnConsultMedia =\n selfParticipant?.consultState === 'consulting' && hasConsultMedia;\n const hasConsultLeg = Boolean(\n !interaction?.isTerminated &&\n ((consultOwnedBySelf && !taskData?.isConsulted) ||\n selfConsultingOnConsultMedia ||\n selfConsultPendingOnConsultMedia) &&\n (consultInProgress || isConsultingState || context.consultCallHeld || hasConsultMedia)\n );\n\n if (!hasConsultLeg) {\n return {\n hasConsultLeg: false,\n activeLeg: 'main',\n mainState: currentState,\n consultState: TaskState.CONSULTING,\n };\n }\n\n let mainState = TaskState.HELD;\n if (currentState === TaskState.CONFERENCING) {\n mainState = TaskState.CONFERENCING;\n } else if (context.consultCallHeld) {\n mainState = TaskState.CONNECTED;\n }\n\n return {\n hasConsultLeg: true,\n activeLeg: context.consultCallHeld ? 'main' : 'consult',\n mainState,\n consultState: isConsultingState ? currentState : TaskState.CONSULTING,\n };\n}\n\nexport function computeUIControls(\n currentState: TaskState,\n context: TaskContext,\n fallbackTaskData?: TaskData\n): TaskUIControls {\n if (currentState === TaskState.TERMINATED || currentState === TaskState.COMPLETED) {\n return getDefaultUIControls();\n }\n\n switch (context.uiControlConfig.channelType) {\n case TASK_CHANNEL_TYPE.VOICE: {\n const {hasConsultLeg, activeLeg, mainState, consultState} = getVoiceLegState(\n currentState,\n context,\n context.uiControlConfig,\n fallbackTaskData\n );\n\n const mainControls = computeVoiceInteractionUIControls(\n mainState,\n context,\n context.uiControlConfig,\n fallbackTaskData,\n 'main'\n );\n const consultControls = hasConsultLeg\n ? computeVoiceInteractionUIControls(\n consultState,\n context,\n context.uiControlConfig,\n fallbackTaskData,\n 'consult'\n )\n : getDefaultInteractionUIControls();\n\n return createTaskUIControls(mainControls, consultControls, activeLeg);\n }\n case TASK_CHANNEL_TYPE.DIGITAL:\n return createTaskUIControls(\n computeDigitalInteractionUIControls(currentState, context, fallbackTaskData),\n getDefaultInteractionUIControls(),\n 'main'\n );\n default:\n return getDefaultUIControls();\n }\n}\n\nfunction haveInteractionUIControlsChanged(\n previous: InteractionUIControls,\n next: InteractionUIControls\n): boolean {\n return (Object.keys(next) as (keyof InteractionUIControls)[]).some((key) => {\n const prev = previous[key];\n const curr = next[key];\n\n return prev.isVisible !== curr.isVisible || prev.isEnabled !== curr.isEnabled;\n });\n}\n\nexport function haveUIControlsChanged(\n previous: TaskUIControls | undefined,\n next: TaskUIControls\n): boolean {\n if (!previous) return true;\n\n return (\n previous.activeLeg !== next.activeLeg ||\n haveInteractionUIControlsChanged(previous.main, next.main) ||\n haveInteractionUIControlsChanged(previous.consult, next.consult)\n );\n}\n"],"mappings":"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","ignoreList":[]}
|