Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions packages/@webex/contact-center/src/cc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
throw error;
});
} catch (error) {
LoggerProxy.error(`Error during register: ${error}`, {
LoggerProxy.error(`Error during register: ${(error as any)?.message || error}`, {
module: CC_FILE,
method: METHODS.CONNECT_WEBSOCKET,
});
Expand Down Expand Up @@ -1213,10 +1213,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
try {
await this.webCallingService.registerWebCallingLine();
} catch (error) {
LoggerProxy.error(`Error registering web calling line: ${error}`, {
module: CC_FILE,
method: METHODS.HANDLE_DEVICE_TYPE,
});
LoggerProxy.error(
`Error registering web calling line: ${(error as any)?.message || error}`,
{
module: CC_FILE,
method: METHODS.HANDLE_DEVICE_TYPE,
}
);
throw error;
}
break;
Expand Down
10 changes: 10 additions & 0 deletions packages/@webex/contact-center/src/logger-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ export default class LoggerProxy {
}
}

// Minimal error summary helper retained for future use if needed
public static formatError(err: unknown): string {
// Keep simple; prefer caller to pass message directly
if (!err) return 'Unknown error';
if (typeof err === 'string') return err;
const anyErr: any = err as any;

return String(err) || anyErr?.message;
}

/**
* Formats a log message with timestamp, log level, and context details.
*
Expand Down
16 changes: 16 additions & 0 deletions packages/@webex/contact-center/src/services/core/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {LoginOption, WebexRequestPayload} from '../../types';
import {Failure} from './GlobalTypes';
import LoggerProxy from '../../logger-proxy';
import WebexRequest from './WebexRequest';
import {TaskData, ConsultTransferPayLoad, CONSULT_TRANSFER_DESTINATION_TYPE} from '../task/types';

/**
* Extracts common error details from a Webex request payload.
Expand Down Expand Up @@ -130,3 +131,18 @@ export const createErrDetailsObject = (errObj: WebexRequestPayload) => {

return new Err.Details('Service.reqs.generic.failure', details);
};

// Task destination utilities (shared across services)
export const isEntryPointOrEpdn = (destAgentType?: string): boolean => {
return destAgentType === 'EPDN' || destAgentType === 'ENTRYPOINT';
};

export const getAgentActionTypeFromTask = (taskData?: TaskData): 'DIAL_NUMBER' | '' => {
const destAgentType = (taskData as any)?.destAgentType;

return destAgentType === 'DN' || isEntryPointOrEpdn(destAgentType) ? 'DIAL_NUMBER' : '';
};

export const getDestAgentTypeForEporEpdn = (): ConsultTransferPayLoad['destinationType'] => {
return CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT;
};
44 changes: 32 additions & 12 deletions packages/@webex/contact-center/src/services/task/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import EventEmitter from 'events';
import {CALL_EVENT_KEYS, LocalMicrophoneStream} from '@webex/calling';
import {CallId} from '@webex/calling/dist/types/common/types';
import {getErrorDetails} from '../core/Utils';
import {
getErrorDetails,
isEntryPointOrEpdn,
getAgentActionTypeFromTask,
getDestAgentTypeForEporEpdn,
} from '../core/Utils';
import {LoginOption} from '../../types';
import {TASK_FILE} from '../../constants';
import {METHODS} from './constants';
Expand Down Expand Up @@ -1317,30 +1322,45 @@ export default class Task extends EventEmitter implements ITask {
interactionId: this.data.interactionId,
});

// For queue destinations, use the destAgentId from task data
// Normalize payload based on desktop logic using TaskData
const agentActionType = getAgentActionTypeFromTask(this.data);

let finalDestinationType: ConsultTransferPayLoad['destinationType'];
if (agentActionType === 'DIAL_NUMBER') {
if (isEntryPointOrEpdn((this.data as any)?.destAgentType)) {
finalDestinationType = getDestAgentTypeForEporEpdn();
} else {
finalDestinationType = CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER;
}
} else {
finalDestinationType = CONSULT_TRANSFER_DESTINATION_TYPE.AGENT;
}

// Resolve the target id (queue consult transfers go to the accepted agent)
let targetId = consultTransferPayload.to;
if (consultTransferPayload.destinationType === CONSULT_TRANSFER_DESTINATION_TYPE.QUEUE) {
if (!this.data.destAgentId) {
if (!this.data?.destAgentId) {
throw new Error('No agent has accepted this queue consult yet');
}

// Override the destination with the agent who accepted the queue consult
consultTransferPayload = {
to: this.data.destAgentId,
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
};
targetId = this.data.destAgentId;
}

const consultTransferRequest: ConsultTransferPayLoad = {
to: targetId,
destinationType: finalDestinationType,
};

const result = await this.contact.consultTransfer({
interactionId: this.data.interactionId,
data: consultTransferPayload,
data: consultTransferRequest,
});

this.metricsManager.trackEvent(
METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS,
{
taskId: this.data.interactionId,
destination: consultTransferPayload.to,
destinationType: consultTransferPayload.destinationType,
destination: consultTransferRequest.to,
destinationType: consultTransferRequest.destinationType,
isConsultTransfer: true,
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
},
Expand Down
Loading