@webex/contact-center 3.12.0-next.7 → 3.12.0-next.71

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.
Files changed (63) hide show
  1. package/dist/cc.js +212 -23
  2. package/dist/cc.js.map +1 -1
  3. package/dist/constants.js +2 -0
  4. package/dist/constants.js.map +1 -1
  5. package/dist/metrics/behavioral-events.js +26 -0
  6. package/dist/metrics/behavioral-events.js.map +1 -1
  7. package/dist/metrics/constants.js +4 -0
  8. package/dist/metrics/constants.js.map +1 -1
  9. package/dist/services/config/Util.js +1 -1
  10. package/dist/services/config/Util.js.map +1 -1
  11. package/dist/services/config/constants.js +1 -1
  12. package/dist/services/config/constants.js.map +1 -1
  13. package/dist/services/config/types.js +4 -0
  14. package/dist/services/config/types.js.map +1 -1
  15. package/dist/services/core/Err.js.map +1 -1
  16. package/dist/services/core/Utils.js +37 -9
  17. package/dist/services/core/Utils.js.map +1 -1
  18. package/dist/services/task/TaskManager.js +94 -8
  19. package/dist/services/task/TaskManager.js.map +1 -1
  20. package/dist/services/task/constants.js +3 -1
  21. package/dist/services/task/constants.js.map +1 -1
  22. package/dist/services/task/dialer.js +78 -0
  23. package/dist/services/task/dialer.js.map +1 -1
  24. package/dist/services/task/index.js +7 -2
  25. package/dist/services/task/index.js.map +1 -1
  26. package/dist/services/task/types.js +56 -0
  27. package/dist/services/task/types.js.map +1 -1
  28. package/dist/types/cc.d.ts +61 -0
  29. package/dist/types/constants.d.ts +2 -0
  30. package/dist/types/metrics/constants.d.ts +4 -0
  31. package/dist/types/services/config/types.d.ts +10 -1
  32. package/dist/types/services/core/Err.d.ts +4 -0
  33. package/dist/types/services/core/Utils.d.ts +10 -3
  34. package/dist/types/services/task/constants.d.ts +2 -0
  35. package/dist/types/services/task/dialer.d.ts +30 -0
  36. package/dist/types/services/task/types.d.ts +65 -1
  37. package/dist/types/types.d.ts +2 -0
  38. package/dist/types.js.map +1 -1
  39. package/dist/webex.js +1 -1
  40. package/package.json +9 -9
  41. package/src/cc.ts +270 -24
  42. package/src/constants.ts +2 -0
  43. package/src/metrics/behavioral-events.ts +28 -0
  44. package/src/metrics/constants.ts +4 -0
  45. package/src/services/config/Util.ts +1 -1
  46. package/src/services/config/constants.ts +1 -1
  47. package/src/services/config/types.ts +6 -1
  48. package/src/services/core/Err.ts +2 -0
  49. package/src/services/core/Utils.ts +43 -8
  50. package/src/services/task/TaskManager.ts +106 -22
  51. package/src/services/task/constants.ts +2 -0
  52. package/src/services/task/dialer.ts +80 -0
  53. package/src/services/task/index.ts +7 -2
  54. package/src/services/task/types.ts +70 -0
  55. package/src/types.ts +2 -0
  56. package/test/unit/spec/cc.ts +210 -20
  57. package/test/unit/spec/services/config/index.ts +3 -3
  58. package/test/unit/spec/services/core/Utils.ts +90 -7
  59. package/test/unit/spec/services/task/TaskManager.ts +252 -7
  60. package/test/unit/spec/services/task/dialer.ts +190 -0
  61. package/test/unit/spec/services/task/index.ts +21 -0
  62. package/umd/contact-center.min.js +2 -2
  63. package/umd/contact-center.min.js.map +1 -1
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["HTTP_METHODS","exports","GET","POST","PATCH","PUT","DELETE","LOGGING_LEVEL","LoginOption","AGENT_DN","EXTENSION","BROWSER","AIAssistantEventType","CUSTOM_EVENT","CTI_EVENT","AIAssistantEventName","GET_TRANSCRIPTS","GET_MID_CALL_SUMMARY","GET_POST_CALL_SUMMARY","MID_CALL_SUMMARY_RESPONSE","POST_CALL_SUMMARY_RESPONSE","SUGGESTED_RESPONSES_DIGITAL"],"sources":["types.ts"],"sourcesContent":["import {CallingClientConfig} from '@webex/calling';\nimport {\n SubmitBehavioralEvent,\n SubmitOperationalEvent,\n SubmitBusinessEvent,\n} from '@webex/internal-plugin-metrics/src/metrics.types';\nimport * as Agent from './services/agent/types';\nimport * as Contact from './services/task/types';\nimport {Profile} from './services/config/types';\nimport {PaginatedResponse, BaseSearchParams} from './utils/PageCache';\n\n/**\n * Generic type for converting a const enum object into a union type of its values.\n * @template T The enum object type\n * @internal\n * @ignore\n */\ntype Enum<T extends Record<string, unknown>> = T[keyof T];\n\n/**\n * HTTP methods supported by WebexRequest.\n * @enum {string}\n * @public\n * @example\n * const method: HTTP_METHODS = HTTP_METHODS.GET;\n * @ignore\n */\nexport const HTTP_METHODS = {\n /** HTTP GET method for retrieving data */\n GET: 'GET',\n /** HTTP POST method for creating resources */\n POST: 'POST',\n /** HTTP PATCH method for partial updates */\n PATCH: 'PATCH',\n /** HTTP PUT method for complete updates */\n PUT: 'PUT',\n /** HTTP DELETE method for removing resources */\n DELETE: 'DELETE',\n} as const;\n\n/**\n * Union type of HTTP methods.\n * @public\n * @example\n * function makeRequest(method: HTTP_METHODS) { ... }\n * @ignore\n */\nexport type HTTP_METHODS = Enum<typeof HTTP_METHODS>;\n\n/**\n * Payload for making requests to Webex APIs.\n * @public\n * @example\n * const payload: WebexRequestPayload = {\n * service: 'identity',\n * resource: '/users',\n * method: HTTP_METHODS.GET\n * };\n * @ignore\n */\nexport type WebexRequestPayload = {\n /** Service name to target */\n service?: string;\n /** Resource path within the service */\n resource?: string;\n /** HTTP method to use */\n method?: HTTP_METHODS;\n /** Full URI if not using service/resource pattern */\n uri?: string;\n /** Whether to add authorization header */\n addAuthHeader?: boolean;\n /** Custom headers to include in request */\n headers?: {\n [key: string]: string | null;\n };\n /** Request body data */\n body?: object;\n /** Expected response status code */\n statusCode?: number;\n /** Whether to parse response as JSON */\n json?: boolean;\n};\n\n/**\n * Event listener function type.\n * @internal\n * @ignore\n */\ntype Listener = (e: string, data?: unknown) => void;\n\n/**\n * Event listener removal function type.\n * @internal\n * @ignore\n */\ntype ListenerOff = (e: string) => void;\n\n/**\n * Service host configuration.\n * @internal\n * @ignore\n */\ntype ServiceHost = {\n /** Host URL/domain for the service */\n host: string;\n /** Time-to-live in seconds */\n ttl: number;\n /** Priority level for load balancing (lower is higher priority) */\n priority: number;\n /** Unique identifier for this host */\n id: string;\n /** Whether this is the home cluster for the user */\n homeCluster?: boolean;\n};\n\n/**\n * Configuration options for the Contact Center Plugin.\n * @interface CCPluginConfig\n * @public\n * @example\n * const config: CCPluginConfig = {\n * allowMultiLogin: true,\n * allowAutomatedRelogin: false,\n * clientType: 'browser',\n * isKeepAliveEnabled: true,\n * force: false,\n * metrics: { clientName: 'myClient', clientType: 'browser' },\n * logging: { enable: true, verboseEvents: false },\n * callingClientConfig: { ... }\n * };\n */\nexport interface CCPluginConfig {\n /** Whether to allow multiple logins from different devices */\n allowMultiLogin: boolean;\n /** Whether to automatically attempt relogin on connection loss */\n allowAutomatedRelogin: boolean;\n /** The type of client making the connection */\n clientType: string;\n /** Whether to enable keep-alive messages */\n isKeepAliveEnabled: boolean;\n /** Whether to force registration */\n force: boolean;\n /** Metrics configuration */\n metrics: {\n /** Name of the client for metrics */\n clientName: string;\n /** Type of client for metrics */\n clientType: string;\n };\n /** Logging configuration */\n logging: {\n /** Whether to enable logging */\n enable: boolean;\n /** Whether to log verbose events */\n verboseEvents: boolean;\n };\n /** Configuration for the calling client */\n callingClientConfig: CallingClientConfig;\n}\n\n/**\n * Logger interface for standardized logging throughout the plugin.\n * @public\n * @example\n * logger.log('This is a log message');\n * logger.error('This is an error message');\n * @ignore\n */\nexport type Logger = {\n /** Log general messages */\n log: (payload: string) => void;\n /** Log error messages */\n error: (payload: string) => void;\n /** Log warning messages */\n warn: (payload: string) => void;\n /** Log informational messages */\n info: (payload: string) => void;\n /** Log detailed trace messages */\n trace: (payload: string) => void;\n /** Log debug messages */\n debug: (payload: string) => void;\n};\n\n/**\n * Contextual information for log entries.\n * @public\n * @ignore\n */\nexport interface LogContext {\n /** Module name where the log originated */\n module?: string;\n /** Method name where the log originated */\n method?: string;\n interactionId?: string;\n trackingId?: string;\n /** Additional structured data to include in logs */\n data?: Record<string, any>;\n /** Error object to include in logs */\n error?: Error | unknown;\n}\n\n/**\n * Available logging severity levels.\n * @enum {string}\n * @public\n * @example\n * const level: LOGGING_LEVEL = LOGGING_LEVEL.error;\n * @ignore\n */\nexport enum LOGGING_LEVEL {\n /** Critical failures that require immediate attention */\n error = 'ERROR',\n /** Important issues that don't prevent the system from working */\n warn = 'WARN',\n /** General informational logs */\n log = 'LOG',\n /** Detailed information about system operation */\n info = 'INFO',\n /** Highly detailed diagnostic information */\n trace = 'TRACE',\n}\n\n/**\n * Metadata for log uploads.\n * @public\n * @example\n * const meta: LogsMetaData = { feedbackId: 'fb123', correlationId: 'corr456' };\n * @ignore\n */\nexport type LogsMetaData = {\n /** Optional feedback ID to associate with logs */\n feedbackId?: string;\n /** Optional correlation ID to track related operations */\n correlationId?: string;\n};\n\n/**\n * Response from uploading logs to the server.\n * @public\n * @example\n * const response: UploadLogsResponse = { trackingid: 'track123', url: 'https://...', userId: 'user1' };\n */\nexport type UploadLogsResponse = {\n /** Tracking ID for the upload request */\n trackingid?: string;\n /** URL where the logs can be accessed */\n url?: string;\n /** ID of the user who uploaded logs */\n userId?: string;\n /** Feedback ID associated with the logs */\n feedbackId?: string;\n /** Correlation ID for tracking related operations */\n correlationId?: string;\n};\n\n/**\n * Internal Webex SDK interfaces needed for plugin integration.\n * @internal\n * @ignore\n */\ninterface IWebexInternal {\n /** Mercury service for real-time messaging */\n mercury: {\n /** Register an event listener */\n on: Listener;\n /** Remove an event listener */\n off: ListenerOff;\n /** Establish a connection to the Mercury service */\n connect: () => Promise<void>;\n /** Disconnect from the Mercury service */\n disconnect: () => Promise<void>;\n /** Whether Mercury is currently connected */\n connected: boolean;\n /** Whether Mercury is in the process of connecting */\n connecting: boolean;\n };\n /** Device information */\n device: {\n /** Current WDM URL */\n url: string;\n /** Current user's ID */\n userId: string;\n /** Current organization ID */\n orgId: string;\n /** Device version */\n version: string;\n /** Calling behavior configuration */\n callingBehavior: string;\n };\n /** Presence service */\n presence: unknown;\n /** Services discovery and management */\n services: {\n /** Get a service URL by name */\n get: (service: string) => string;\n /** Wait for service catalog to be loaded */\n waitForCatalog: (service: string) => Promise<void>;\n /** Check if current environment is INT (integration) */\n isIntegrationEnvironment: () => boolean;\n /** Host catalog for service discovery */\n _hostCatalog: Record<string, ServiceHost[]>;\n /** Service URLs cache */\n _serviceUrls: {\n /** Mobius calling service */\n mobius: string;\n /** Identity service */\n identity: string;\n /** Janus media server */\n janus: string;\n /** WDM (WebEx Device Management) service */\n wdm: string;\n /** BroadWorks IDP proxy service */\n broadworksIdpProxy: string;\n /** Hydra API service */\n hydra: string;\n /** Mercury API service */\n mercuryApi: string;\n /** UC Management gateway service */\n 'ucmgmt-gateway': string;\n /** Contacts service */\n contactsService: string;\n };\n };\n /** Metrics collection services */\n newMetrics: {\n /** Submit behavioral events (user actions) */\n submitBehavioralEvent: SubmitBehavioralEvent;\n /** Submit operational events (system operations) */\n submitOperationalEvent: SubmitOperationalEvent;\n /** Submit business events (business outcomes) */\n submitBusinessEvent: SubmitBusinessEvent;\n };\n /** Support functionality */\n support: {\n /** Submit logs to server */\n submitLogs: (\n metaData: LogsMetaData,\n logs: string,\n options: {\n /** Whether to submit full logs or just differences */\n type: 'diff' | 'full';\n }\n ) => Promise<UploadLogsResponse>;\n };\n}\n\n/**\n * Interface representing the WebexSDK core functionality.\n * @interface WebexSDK\n * @public\n * @example\n * const sdk: WebexSDK = ...;\n * sdk.request({ service: 'identity', resource: '/users', method: HTTP_METHODS.GET });\n * @ignore\n */\nexport interface WebexSDK {\n /** Version of the WebexSDK */\n version: string;\n /** Whether the SDK can authorize requests */\n canAuthorize: boolean;\n /** Credentials management */\n credentials: {\n /** Get the user token for authentication */\n getUserToken: () => Promise<string>;\n /** Get the organization ID */\n getOrgId: () => string;\n };\n /** Whether the SDK is ready for use */\n ready: boolean;\n /** Make a request to the Webex APIs */\n request: <T>(payload: WebexRequestPayload) => Promise<T>;\n /** Register a one-time event handler */\n once: (event: string, callBack: () => void) => void;\n /** Internal plugins and services */\n internal: IWebexInternal;\n /** Logger instance */\n logger: Logger;\n}\n\n/**\n * An interface for the `ContactCenter` class.\n * The `ContactCenter` package is designed to provide a set of APIs to perform various operations for the Agent flow within Webex Contact Center.\n * @public\n * @example\n * const cc: IContactCenter = ...;\n * cc.register().then(profile => { ... });\n * @ignore\n */\nexport interface IContactCenter {\n /**\n * Initialize the CC SDK by setting up the contact center mercury connection.\n * This establishes WebSocket connectivity for real-time communication.\n *\n * @returns A Promise that resolves to the agent's profile upon successful registration\n * @public\n * @example\n * cc.register().then(profile => { ... });\n */\n register(): Promise<Profile>;\n}\n\n/**\n * Generic HTTP response structure.\n * @public\n * @example\n * const response: IHttpResponse = { body: {}, statusCode: 200, method: 'GET', headers: {}, url: '...' };\n * @ignore\n */\nexport interface IHttpResponse {\n /** Response body content */\n body: any;\n /** HTTP status code */\n statusCode: number;\n /** HTTP method used for the request */\n method: string;\n /** Response headers */\n headers: Headers;\n /** Request URL */\n url: string;\n}\n\n/**\n * Supported login options for agent authentication.\n * @public\n * @example\n * const option: LoginOption = LoginOption.AGENT_DN;\n * @ignore\n */\nexport const LoginOption = {\n /** Login using agent's direct number */\n AGENT_DN: 'AGENT_DN',\n /** Login using an extension number */\n EXTENSION: 'EXTENSION',\n /** Login using browser WebRTC capabilities */\n BROWSER: 'BROWSER',\n} as const;\n\n/**\n * Union type of login options.\n * @public\n * @example\n * function login(option: LoginOption) { ... }\n * @ignore\n */\nexport type LoginOption = Enum<typeof LoginOption>;\n\n/**\n * Request payload for subscribing to the contact center websocket.\n * @public\n * @example\n * const req: SubscribeRequest = { force: true, isKeepAliveEnabled: true, clientType: 'browser', allowMultiLogin: false };\n * @ignore\n */\nexport type SubscribeRequest = {\n /** Whether to force connection even if another exists */\n force: boolean;\n /** Whether to send keepalive messages */\n isKeepAliveEnabled: boolean;\n /** Type of client connecting */\n clientType: string;\n /** Whether to allow login from multiple devices */\n allowMultiLogin: boolean;\n};\n\n/**\n * Represents the response from getListOfTeams method.\n * Teams are groups of agents that can be managed together.\n * @public\n * @example\n * const team: Team = { id: 'team1', name: 'Support', desktopLayoutId: 'layout1' };\n * @ignore\n */\nexport type Team = {\n /**\n * Unique identifier of the team.\n */\n id: string;\n\n /**\n * Display name of the team.\n */\n name: string;\n\n /**\n * Associated desktop layout ID for the team.\n * Controls how the agent desktop is displayed for team members.\n */\n desktopLayoutId?: string;\n};\n\n/**\n * Represents the request to perform agent login.\n * @public\n * @example\n * const login: AgentLogin = { dialNumber: '1234', teamId: 'team1', loginOption: LoginOption.AGENT_DN };\n */\nexport type AgentLogin = {\n /**\n * A dialNumber field contains the number to dial such as a route point or extension.\n * Required for AGENT_DN and EXTENSION login options.\n */\n dialNumber?: string;\n\n /**\n * The unique ID representing a team of users.\n * The agent must belong to this team.\n */\n teamId: string;\n\n /**\n * The loginOption field specifies the type of login method.\n * Controls how calls are delivered to the agent.\n */\n loginOption: LoginOption;\n};\n\n/**\n * Represents the request to update agent profile settings.\n * @public\n * @example\n * const update: AgentProfileUpdate = { loginOption: LoginOption.BROWSER, dialNumber: '5678' };\n */\nexport type AgentProfileUpdate = Pick<AgentLogin, 'loginOption' | 'dialNumber' | 'teamId'>;\n\n/**\n * Union type for all possible request body types.\n * @internal\n * @ignore\n */\nexport type RequestBody =\n | SubscribeRequest\n | Agent.Logout\n | Agent.UserStationLogin\n | Agent.StateChange\n | Agent.BuddyAgents\n | Contact.HoldResumePayload\n | Contact.ResumeRecordingPayload\n | Contact.ConsultPayload\n | Contact.ConsultEndAPIPayload // API Payload accepts only QueueId wheres SDK API allows more params\n | Contact.TransferPayLoad\n | Contact.ConsultTransferPayLoad\n | Contact.cancelCtq\n | Contact.WrapupPayLoad\n | Contact.DialerPayload\n | Contact.PreviewContactPayload;\n\n/**\n * Represents the options to fetch buddy agents for the logged in agent.\n * Buddy agents are other agents who can be consulted or transfered to.\n * @public\n * @example\n * const opts: BuddyAgents = { mediaType: 'telephony', state: 'Available' };\n * @ignore\n */\nexport type BuddyAgents = {\n /**\n * The media type channel to filter buddy agents.\n * Determines which channel capability the returned agents must have.\n */\n mediaType: 'telephony' | 'chat' | 'social' | 'email';\n\n /**\n * Optional filter for agent state.\n * If specified, returns only agents in that state.\n * If omitted, returns both available and idle agents.\n */\n state?: 'Available' | 'Idle';\n};\n\n/**\n * Generic error structure for Contact Center SDK errors.\n * Contains detailed information about the error context.\n * @public\n * @example\n * const err: GenericError = new Error('Failed');\n * err.details = { type: 'ERR', orgId: 'org1', trackingId: 'track1', data: {} };\n * @ignore\n */\nexport interface GenericError extends Error {\n /** Structured details about the error */\n details: {\n /** Error type identifier */\n type: string;\n /** Organization ID where the error occurred */\n orgId: string;\n /** Unique tracking ID for the error */\n trackingId: string;\n /** Additional error context data */\n data: Record<string, any>;\n };\n}\n\n/**\n * Response type for station login operations.\n * Either a success response with agent details or an error.\n * @public\n * @example\n * function handleLogin(resp: StationLoginResponse) { ... }\n */\nexport type StationLoginResponse = Agent.StationLoginSuccessResponse | Error;\n\n/**\n * Response type for station logout operations.\n * Either a success response with logout details or an error.\n * @public\n * @example\n * function handleLogout(resp: StationLogoutResponse) { ... }\n */\nexport type StationLogoutResponse = Agent.LogoutSuccess | Error;\n\n/**\n * Response type for station relogin operations.\n * Either a success response with relogin details or an error.\n * @public\n * @example\n * function handleReLogin(resp: StationReLoginResponse) { ... }\n * @ignore\n */\nexport type StationReLoginResponse = Agent.ReloginSuccess | Error;\n\n/**\n * Response type for agent state change operations.\n * Either a success response with state change details or an error.\n * @public\n * @example\n * function handleStateChange(resp: SetStateResponse) { ... }\n * @ignore\n */\nexport type SetStateResponse = Agent.StateChangeSuccess | Error;\n\n/**\n * AddressBook types\n */\nexport interface AddressBookEntry {\n id: string;\n organizationId?: string;\n version?: number;\n name: string;\n number: string;\n createdTime?: number;\n lastUpdatedTime?: number;\n}\n\nexport type AddressBookEntriesResponse = PaginatedResponse<AddressBookEntry>;\n\nexport interface AddressBookEntrySearchParams extends BaseSearchParams {\n addressBookId?: string;\n}\n\n/**\n * EntryPointRecord types\n */\nexport interface EntryPointRecord {\n id: string;\n name: string;\n description?: string;\n type: string;\n isActive: boolean;\n orgId: string;\n createdAt?: string;\n updatedAt?: string;\n settings?: Record<string, any>;\n}\n\nexport type EntryPointListResponse = PaginatedResponse<EntryPointRecord>;\nexport type EntryPointSearchParams = BaseSearchParams;\n\n/**\n * Queue types\n */\nexport interface QueueSkillRequirement {\n organizationId?: string;\n id?: string;\n version?: number;\n skillId: string;\n skillName?: string;\n skillType?: string;\n condition: string;\n skillValue: string;\n createdTime?: number;\n lastUpdatedTime?: number;\n}\n\nexport interface QueueAgent {\n id: string;\n ciUserId?: string;\n}\n\nexport interface AgentGroup {\n teamId: string;\n}\n\nexport interface CallDistributionGroup {\n agentGroups: AgentGroup[];\n order: number;\n duration?: number;\n}\n\nexport interface AssistantSkillMapping {\n assistantSkillId?: string;\n assistantSkillUpdatedTime?: number;\n}\n\n/**\n * Configuration for a contact service queue\n * @public\n */\nexport interface ContactServiceQueue {\n /** Organization ID */\n organizationId?: string;\n /** Unique identifier for the queue */\n id?: string;\n /** Version of the queue */\n version?: number;\n /** Name of the Contact Service Queue */\n name: string;\n /** Description of the queue */\n description?: string;\n /** Queue type (INBOUND, OUTBOUND) */\n queueType: 'INBOUND' | 'OUTBOUND';\n /** Whether to check agent availability */\n checkAgentAvailability: boolean;\n /** Channel type (TELEPHONY, EMAIL, SOCIAL_CHANNEL, CHAT, etc.) */\n channelType: 'TELEPHONY' | 'EMAIL' | 'FAX' | 'CHAT' | 'VIDEO' | 'OTHERS' | 'SOCIAL_CHANNEL';\n /** Social channel type for SOCIAL_CHANNEL channelType */\n socialChannelType?:\n | 'MESSAGEBIRD'\n | 'MESSENGER'\n | 'WHATSAPP'\n | 'APPLE_BUSINESS_CHAT'\n | 'GOOGLE_BUSINESS_MESSAGES';\n /** Service level threshold in seconds */\n serviceLevelThreshold: number;\n /** Maximum number of simultaneous contacts */\n maxActiveContacts: number;\n /** Maximum time in queue in seconds */\n maxTimeInQueue: number;\n /** Default music in queue media file ID */\n defaultMusicInQueueMediaFileId: string;\n /** Timezone for routing strategies */\n timezone?: string;\n /** Whether the queue is active */\n active: boolean;\n /** Whether outdial campaign is enabled */\n outdialCampaignEnabled?: boolean;\n /** Whether monitoring is permitted */\n monitoringPermitted: boolean;\n /** Whether parking is permitted */\n parkingPermitted: boolean;\n /** Whether recording is permitted */\n recordingPermitted: boolean;\n /** Whether recording all calls is permitted */\n recordingAllCallsPermitted: boolean;\n /** Whether pausing recording is permitted */\n pauseRecordingPermitted: boolean;\n /** Recording pause duration in seconds */\n recordingPauseDuration?: number;\n /** Control flow script URL */\n controlFlowScriptUrl: string;\n /** IVR requeue URL */\n ivrRequeueUrl: string;\n /** Overflow number for telephony */\n overflowNumber?: string;\n /** Vendor ID */\n vendorId?: string;\n /** Routing type */\n routingType: 'LONGEST_AVAILABLE_AGENT' | 'SKILLS_BASED' | 'CIRCULAR' | 'LINEAR';\n /** Skills-based routing type */\n skillBasedRoutingType?: 'LONGEST_AVAILABLE_AGENT' | 'BEST_AVAILABLE_AGENT';\n /** Queue routing type */\n queueRoutingType: 'TEAM_BASED' | 'SKILL_BASED' | 'AGENT_BASED';\n /** Queue skill requirements */\n queueSkillRequirements?: QueueSkillRequirement[];\n /** List of agents for agent-based queue */\n agents?: QueueAgent[];\n /** Call distribution groups */\n callDistributionGroups: CallDistributionGroup[];\n /** XSP version */\n xspVersion?: string;\n /** Subscription ID */\n subscriptionId?: string;\n /** Assistant skill mapping */\n assistantSkill?: AssistantSkillMapping;\n /** Whether this is a system default queue */\n systemDefault?: boolean;\n /** User who last updated agents list */\n agentsLastUpdatedByUserName?: string;\n /** Email of user who last updated agents list */\n agentsLastUpdatedByUserEmailPrefix?: string;\n /** When agents list was last updated */\n agentsLastUpdatedTime?: number;\n /** Creation timestamp in epoch millis */\n createdTime?: number;\n /** Last updated timestamp in epoch millis */\n lastUpdatedTime?: number;\n}\n\nexport type ContactServiceQueuesResponse = PaginatedResponse<ContactServiceQueue>;\n\nexport interface ContactServiceQueueSearchParams extends BaseSearchParams {\n desktopProfileFilter?: boolean;\n provisioningView?: boolean;\n singleObjectResponse?: boolean;\n}\n\n/**\n * Response type for buddy agents query operations.\n * Either a success response with list of buddy agents or an error.\n * @public\n * @example\n * function handleBuddyAgents(resp: BuddyAgentsResponse) { ... }\n */\nexport type BuddyAgentsResponse = Agent.BuddyAgentsSuccess | Error;\n\n/**\n * Response type for device type update operations.\n * Either a success response with update confirmation or an error.\n * @public\n * @example\n * function handleUpdateDeviceType(resp: UpdateDeviceTypeResponse) { ... }\n */\nexport type UpdateDeviceTypeResponse = Agent.DeviceTypeUpdateSuccess | Error;\n\nexport type TranscriptAction = 'START' | 'STOP';\n\nexport const AIAssistantEventType = {\n CUSTOM_EVENT: 'CUSTOM_EVENT',\n CTI_EVENT: 'CTI_EVENT',\n} as const;\n\nexport type AIAssistantEventType = Enum<typeof AIAssistantEventType>;\n\nexport const AIAssistantEventName = {\n GET_TRANSCRIPTS: 'GET_TRANSCRIPTS',\n GET_MID_CALL_SUMMARY: 'GET_MID_CALL_SUMMARY',\n GET_POST_CALL_SUMMARY: 'GET_POST_CALL_SUMMARY',\n MID_CALL_SUMMARY_RESPONSE: 'MID_CALL_SUMMARY_RESPONSE',\n POST_CALL_SUMMARY_RESPONSE: 'POST_CALL_SUMMARY_RESPONSE',\n SUGGESTED_RESPONSES_DIGITAL: 'SUGGESTED_RESPONSES_DIGITAL',\n} as const;\n\nexport type AIAssistantEventName = Enum<typeof AIAssistantEventName>;\n\nexport type TranscriptMessage = {\n role: string;\n content: string;\n messageId: string;\n publishTimestamp: number;\n};\n\nexport type HistoricTranscriptsResponse = {\n orgId: string;\n agentId: string;\n conversationId: string | null;\n interactionId: string;\n source: string;\n data: TranscriptMessage[];\n};\n"],"mappings":";;;;;;AAWA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG;EAC1B;EACAE,GAAG,EAAE,KAAK;EACV;EACAC,IAAI,EAAE,MAAM;EACZ;EACAC,KAAK,EAAE,OAAO;EACd;EACAC,GAAG,EAAE,KAAK;EACV;EACAC,MAAM,EAAE;AACV,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAwBA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA8BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA,IAQYC,aAAa,GAAAN,OAAA,CAAAM,aAAA,0BAAbA,aAAa;EACvB;EADUA,aAAa;EAGvB;EAHUA,aAAa;EAKvB;EALUA,aAAa;EAOvB;EAPUA,aAAa;EASvB;EATUA,aAAa;EAAA,OAAbA,aAAa;AAAA;AAazB;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AAuFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAyBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,WAAW,GAAAP,OAAA,CAAAO,WAAA,GAAG;EACzB;EACAC,QAAQ,EAAE,UAAU;EACpB;EACAC,SAAS,EAAE,WAAW;EACtB;EACAC,OAAO,EAAE;AACX,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAmBA;AACA;AACA;AACA;AACA;AACA;;AAqBA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAkBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAeA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAiBA;AACA;AACA;;AAgBA;AACA;AACA;;AAkCA;AACA;AACA;AACA;;AAmGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAKO,MAAMC,oBAAoB,GAAAX,OAAA,CAAAW,oBAAA,GAAG;EAClCC,YAAY,EAAE,cAAc;EAC5BC,SAAS,EAAE;AACb,CAAU;AAIH,MAAMC,oBAAoB,GAAAd,OAAA,CAAAc,oBAAA,GAAG;EAClCC,eAAe,EAAE,iBAAiB;EAClCC,oBAAoB,EAAE,sBAAsB;EAC5CC,qBAAqB,EAAE,uBAAuB;EAC9CC,yBAAyB,EAAE,2BAA2B;EACtDC,0BAA0B,EAAE,4BAA4B;EACxDC,2BAA2B,EAAE;AAC/B,CAAU","ignoreList":[]}
1
+ {"version":3,"names":["HTTP_METHODS","exports","GET","POST","PATCH","PUT","DELETE","LOGGING_LEVEL","LoginOption","AGENT_DN","EXTENSION","BROWSER","AIAssistantEventType","CUSTOM_EVENT","CTI_EVENT","AIAssistantEventName","GET_TRANSCRIPTS","GET_MID_CALL_SUMMARY","GET_POST_CALL_SUMMARY","MID_CALL_SUMMARY_RESPONSE","POST_CALL_SUMMARY_RESPONSE","SUGGESTED_RESPONSES_DIGITAL"],"sources":["types.ts"],"sourcesContent":["import {CallingClientConfig} from '@webex/calling';\nimport {\n SubmitBehavioralEvent,\n SubmitOperationalEvent,\n SubmitBusinessEvent,\n} from '@webex/internal-plugin-metrics/src/metrics.types';\nimport * as Agent from './services/agent/types';\nimport * as Contact from './services/task/types';\nimport {Profile} from './services/config/types';\nimport {PaginatedResponse, BaseSearchParams} from './utils/PageCache';\n\n/**\n * Generic type for converting a const enum object into a union type of its values.\n * @template T The enum object type\n * @internal\n * @ignore\n */\ntype Enum<T extends Record<string, unknown>> = T[keyof T];\n\n/**\n * HTTP methods supported by WebexRequest.\n * @enum {string}\n * @public\n * @example\n * const method: HTTP_METHODS = HTTP_METHODS.GET;\n * @ignore\n */\nexport const HTTP_METHODS = {\n /** HTTP GET method for retrieving data */\n GET: 'GET',\n /** HTTP POST method for creating resources */\n POST: 'POST',\n /** HTTP PATCH method for partial updates */\n PATCH: 'PATCH',\n /** HTTP PUT method for complete updates */\n PUT: 'PUT',\n /** HTTP DELETE method for removing resources */\n DELETE: 'DELETE',\n} as const;\n\n/**\n * Union type of HTTP methods.\n * @public\n * @example\n * function makeRequest(method: HTTP_METHODS) { ... }\n * @ignore\n */\nexport type HTTP_METHODS = Enum<typeof HTTP_METHODS>;\n\n/**\n * Payload for making requests to Webex APIs.\n * @public\n * @example\n * const payload: WebexRequestPayload = {\n * service: 'identity',\n * resource: '/users',\n * method: HTTP_METHODS.GET\n * };\n * @ignore\n */\nexport type WebexRequestPayload = {\n /** Service name to target */\n service?: string;\n /** Resource path within the service */\n resource?: string;\n /** HTTP method to use */\n method?: HTTP_METHODS;\n /** Full URI if not using service/resource pattern */\n uri?: string;\n /** Whether to add authorization header */\n addAuthHeader?: boolean;\n /** Custom headers to include in request */\n headers?: {\n [key: string]: string | null;\n };\n /** Request body data */\n body?: object;\n /** Expected response status code */\n statusCode?: number;\n /** Whether to parse response as JSON */\n json?: boolean;\n};\n\n/**\n * Event listener function type.\n * @internal\n * @ignore\n */\ntype Listener = (e: string, data?: unknown) => void;\n\n/**\n * Event listener removal function type.\n * @internal\n * @ignore\n */\ntype ListenerOff = (e: string) => void;\n\n/**\n * Service host configuration.\n * @internal\n * @ignore\n */\ntype ServiceHost = {\n /** Host URL/domain for the service */\n host: string;\n /** Time-to-live in seconds */\n ttl: number;\n /** Priority level for load balancing (lower is higher priority) */\n priority: number;\n /** Unique identifier for this host */\n id: string;\n /** Whether this is the home cluster for the user */\n homeCluster?: boolean;\n};\n\n/**\n * Configuration options for the Contact Center Plugin.\n * @interface CCPluginConfig\n * @public\n * @example\n * const config: CCPluginConfig = {\n * allowMultiLogin: true,\n * allowAutomatedRelogin: false,\n * clientType: 'browser',\n * isKeepAliveEnabled: true,\n * force: false,\n * metrics: { clientName: 'myClient', clientType: 'browser' },\n * logging: { enable: true, verboseEvents: false },\n * callingClientConfig: { ... }\n * };\n */\nexport interface CCPluginConfig {\n /** Whether to allow multiple logins from different devices */\n allowMultiLogin: boolean;\n /** Whether to automatically attempt relogin on connection loss */\n allowAutomatedRelogin: boolean;\n /** The type of client making the connection */\n clientType: string;\n /** Whether to enable keep-alive messages */\n isKeepAliveEnabled: boolean;\n /** Whether to force registration */\n force: boolean;\n /** Metrics configuration */\n metrics: {\n /** Name of the client for metrics */\n clientName: string;\n /** Type of client for metrics */\n clientType: string;\n };\n /** Logging configuration */\n logging: {\n /** Whether to enable logging */\n enable: boolean;\n /** Whether to log verbose events */\n verboseEvents: boolean;\n };\n /** Configuration for the calling client */\n callingClientConfig: CallingClientConfig;\n /** Whether to skip Mobius/WebRTC registration for browser login flows */\n disableWebRTCRegistration?: boolean;\n}\n\n/**\n * Logger interface for standardized logging throughout the plugin.\n * @public\n * @example\n * logger.log('This is a log message');\n * logger.error('This is an error message');\n * @ignore\n */\nexport type Logger = {\n /** Log general messages */\n log: (payload: string) => void;\n /** Log error messages */\n error: (payload: string) => void;\n /** Log warning messages */\n warn: (payload: string) => void;\n /** Log informational messages */\n info: (payload: string) => void;\n /** Log detailed trace messages */\n trace: (payload: string) => void;\n /** Log debug messages */\n debug: (payload: string) => void;\n};\n\n/**\n * Contextual information for log entries.\n * @public\n * @ignore\n */\nexport interface LogContext {\n /** Module name where the log originated */\n module?: string;\n /** Method name where the log originated */\n method?: string;\n interactionId?: string;\n trackingId?: string;\n /** Additional structured data to include in logs */\n data?: Record<string, any>;\n /** Error object to include in logs */\n error?: Error | unknown;\n}\n\n/**\n * Available logging severity levels.\n * @enum {string}\n * @public\n * @example\n * const level: LOGGING_LEVEL = LOGGING_LEVEL.error;\n * @ignore\n */\nexport enum LOGGING_LEVEL {\n /** Critical failures that require immediate attention */\n error = 'ERROR',\n /** Important issues that don't prevent the system from working */\n warn = 'WARN',\n /** General informational logs */\n log = 'LOG',\n /** Detailed information about system operation */\n info = 'INFO',\n /** Highly detailed diagnostic information */\n trace = 'TRACE',\n}\n\n/**\n * Metadata for log uploads.\n * @public\n * @example\n * const meta: LogsMetaData = { feedbackId: 'fb123', correlationId: 'corr456' };\n * @ignore\n */\nexport type LogsMetaData = {\n /** Optional feedback ID to associate with logs */\n feedbackId?: string;\n /** Optional correlation ID to track related operations */\n correlationId?: string;\n};\n\n/**\n * Response from uploading logs to the server.\n * @public\n * @example\n * const response: UploadLogsResponse = { trackingid: 'track123', url: 'https://...', userId: 'user1' };\n */\nexport type UploadLogsResponse = {\n /** Tracking ID for the upload request */\n trackingid?: string;\n /** URL where the logs can be accessed */\n url?: string;\n /** ID of the user who uploaded logs */\n userId?: string;\n /** Feedback ID associated with the logs */\n feedbackId?: string;\n /** Correlation ID for tracking related operations */\n correlationId?: string;\n};\n\n/**\n * Internal Webex SDK interfaces needed for plugin integration.\n * @internal\n * @ignore\n */\ninterface IWebexInternal {\n /** Mercury service for real-time messaging */\n mercury: {\n /** Register an event listener */\n on: Listener;\n /** Remove an event listener */\n off: ListenerOff;\n /** Establish a connection to the Mercury service */\n connect: () => Promise<void>;\n /** Disconnect from the Mercury service */\n disconnect: () => Promise<void>;\n /** Whether Mercury is currently connected */\n connected: boolean;\n /** Whether Mercury is in the process of connecting */\n connecting: boolean;\n };\n /** Device information */\n device: {\n /** Current WDM URL */\n url: string;\n /** Current user's ID */\n userId: string;\n /** Current organization ID */\n orgId: string;\n /** Device version */\n version: string;\n /** Calling behavior configuration */\n callingBehavior: string;\n };\n /** Presence service */\n presence: unknown;\n /** Services discovery and management */\n services: {\n /** Get a service URL by name */\n get: (service: string) => string;\n /** Wait for service catalog to be loaded */\n waitForCatalog: (service: string) => Promise<void>;\n /** Check if current environment is INT (integration) */\n isIntegrationEnvironment: () => boolean;\n /** Host catalog for service discovery */\n _hostCatalog: Record<string, ServiceHost[]>;\n /** Service URLs cache */\n _serviceUrls: {\n /** Mobius calling service */\n mobius: string;\n /** Identity service */\n identity: string;\n /** Janus media server */\n janus: string;\n /** WDM (WebEx Device Management) service */\n wdm: string;\n /** BroadWorks IDP proxy service */\n broadworksIdpProxy: string;\n /** Hydra API service */\n hydra: string;\n /** Mercury API service */\n mercuryApi: string;\n /** UC Management gateway service */\n 'ucmgmt-gateway': string;\n /** Contacts service */\n contactsService: string;\n };\n };\n /** Metrics collection services */\n newMetrics: {\n /** Submit behavioral events (user actions) */\n submitBehavioralEvent: SubmitBehavioralEvent;\n /** Submit operational events (system operations) */\n submitOperationalEvent: SubmitOperationalEvent;\n /** Submit business events (business outcomes) */\n submitBusinessEvent: SubmitBusinessEvent;\n };\n /** Support functionality */\n support: {\n /** Submit logs to server */\n submitLogs: (\n metaData: LogsMetaData,\n logs: string,\n options: {\n /** Whether to submit full logs or just differences */\n type: 'diff' | 'full';\n }\n ) => Promise<UploadLogsResponse>;\n };\n}\n\n/**\n * Interface representing the WebexSDK core functionality.\n * @interface WebexSDK\n * @public\n * @example\n * const sdk: WebexSDK = ...;\n * sdk.request({ service: 'identity', resource: '/users', method: HTTP_METHODS.GET });\n * @ignore\n */\nexport interface WebexSDK {\n /** Version of the WebexSDK */\n version: string;\n /** Whether the SDK can authorize requests */\n canAuthorize: boolean;\n /** Credentials management */\n credentials: {\n /** Get the user token for authentication */\n getUserToken: () => Promise<string>;\n /** Get the organization ID */\n getOrgId: () => string;\n };\n /** Whether the SDK is ready for use */\n ready: boolean;\n /** Make a request to the Webex APIs */\n request: <T>(payload: WebexRequestPayload) => Promise<T>;\n /** Register a one-time event handler */\n once: (event: string, callBack: () => void) => void;\n /** Internal plugins and services */\n internal: IWebexInternal;\n /** Logger instance */\n logger: Logger;\n}\n\n/**\n * An interface for the `ContactCenter` class.\n * The `ContactCenter` package is designed to provide a set of APIs to perform various operations for the Agent flow within Webex Contact Center.\n * @public\n * @example\n * const cc: IContactCenter = ...;\n * cc.register().then(profile => { ... });\n * @ignore\n */\nexport interface IContactCenter {\n /**\n * Initialize the CC SDK by setting up the contact center mercury connection.\n * This establishes WebSocket connectivity for real-time communication.\n *\n * @returns A Promise that resolves to the agent's profile upon successful registration\n * @public\n * @example\n * cc.register().then(profile => { ... });\n */\n register(): Promise<Profile>;\n}\n\n/**\n * Generic HTTP response structure.\n * @public\n * @example\n * const response: IHttpResponse = { body: {}, statusCode: 200, method: 'GET', headers: {}, url: '...' };\n * @ignore\n */\nexport interface IHttpResponse {\n /** Response body content */\n body: any;\n /** HTTP status code */\n statusCode: number;\n /** HTTP method used for the request */\n method: string;\n /** Response headers */\n headers: Headers;\n /** Request URL */\n url: string;\n}\n\n/**\n * Supported login options for agent authentication.\n * @public\n * @example\n * const option: LoginOption = LoginOption.AGENT_DN;\n * @ignore\n */\nexport const LoginOption = {\n /** Login using agent's direct number */\n AGENT_DN: 'AGENT_DN',\n /** Login using an extension number */\n EXTENSION: 'EXTENSION',\n /** Login using browser WebRTC capabilities */\n BROWSER: 'BROWSER',\n} as const;\n\n/**\n * Union type of login options.\n * @public\n * @example\n * function login(option: LoginOption) { ... }\n * @ignore\n */\nexport type LoginOption = Enum<typeof LoginOption>;\n\n/**\n * Request payload for subscribing to the contact center websocket.\n * @public\n * @example\n * const req: SubscribeRequest = { force: true, isKeepAliveEnabled: true, clientType: 'browser', allowMultiLogin: false };\n * @ignore\n */\nexport type SubscribeRequest = {\n /** Whether to force connection even if another exists */\n force: boolean;\n /** Whether to send keepalive messages */\n isKeepAliveEnabled: boolean;\n /** Type of client connecting */\n clientType: string;\n /** Whether to allow login from multiple devices */\n allowMultiLogin: boolean;\n};\n\n/**\n * Represents the response from getListOfTeams method.\n * Teams are groups of agents that can be managed together.\n * @public\n * @example\n * const team: Team = { id: 'team1', name: 'Support', desktopLayoutId: 'layout1' };\n * @ignore\n */\nexport type Team = {\n /**\n * Unique identifier of the team.\n */\n id: string;\n\n /**\n * Display name of the team.\n */\n name: string;\n\n /**\n * Associated desktop layout ID for the team.\n * Controls how the agent desktop is displayed for team members.\n */\n desktopLayoutId?: string;\n};\n\n/**\n * Represents the request to perform agent login.\n * @public\n * @example\n * const login: AgentLogin = { dialNumber: '1234', teamId: 'team1', loginOption: LoginOption.AGENT_DN };\n */\nexport type AgentLogin = {\n /**\n * A dialNumber field contains the number to dial such as a route point or extension.\n * Required for AGENT_DN and EXTENSION login options.\n */\n dialNumber?: string;\n\n /**\n * The unique ID representing a team of users.\n * The agent must belong to this team.\n */\n teamId: string;\n\n /**\n * The loginOption field specifies the type of login method.\n * Controls how calls are delivered to the agent.\n */\n loginOption: LoginOption;\n};\n\n/**\n * Represents the request to update agent profile settings.\n * @public\n * @example\n * const update: AgentProfileUpdate = { loginOption: LoginOption.BROWSER, dialNumber: '5678' };\n */\nexport type AgentProfileUpdate = Pick<AgentLogin, 'loginOption' | 'dialNumber' | 'teamId'>;\n\n/**\n * Union type for all possible request body types.\n * @internal\n * @ignore\n */\nexport type RequestBody =\n | SubscribeRequest\n | Agent.Logout\n | Agent.UserStationLogin\n | Agent.StateChange\n | Agent.BuddyAgents\n | Contact.HoldResumePayload\n | Contact.ResumeRecordingPayload\n | Contact.ConsultPayload\n | Contact.ConsultEndAPIPayload // API Payload accepts only QueueId wheres SDK API allows more params\n | Contact.TransferPayLoad\n | Contact.ConsultTransferPayLoad\n | Contact.cancelCtq\n | Contact.WrapupPayLoad\n | Contact.DialerPayload\n | Contact.PreviewContactPayload;\n\n/**\n * Represents the options to fetch buddy agents for the logged in agent.\n * Buddy agents are other agents who can be consulted or transfered to.\n * @public\n * @example\n * const opts: BuddyAgents = { mediaType: 'telephony', state: 'Available' };\n * @ignore\n */\nexport type BuddyAgents = {\n /**\n * The media type channel to filter buddy agents.\n * Determines which channel capability the returned agents must have.\n */\n mediaType: 'telephony' | 'chat' | 'social' | 'email';\n\n /**\n * Optional filter for agent state.\n * If specified, returns only agents in that state.\n * If omitted, returns both available and idle agents.\n */\n state?: 'Available' | 'Idle';\n};\n\n/**\n * Generic error structure for Contact Center SDK errors.\n * Contains detailed information about the error context.\n * @public\n * @example\n * const err: GenericError = new Error('Failed');\n * err.details = { type: 'ERR', orgId: 'org1', trackingId: 'track1', data: {} };\n * @ignore\n */\nexport interface GenericError extends Error {\n /** Structured details about the error */\n details: {\n /** Error type identifier */\n type: string;\n /** Organization ID where the error occurred */\n orgId: string;\n /** Unique tracking ID for the error */\n trackingId: string;\n /** Additional error context data */\n data: Record<string, any>;\n };\n}\n\n/**\n * Response type for station login operations.\n * Either a success response with agent details or an error.\n * @public\n * @example\n * function handleLogin(resp: StationLoginResponse) { ... }\n */\nexport type StationLoginResponse = Agent.StationLoginSuccessResponse | Error;\n\n/**\n * Response type for station logout operations.\n * Either a success response with logout details or an error.\n * @public\n * @example\n * function handleLogout(resp: StationLogoutResponse) { ... }\n */\nexport type StationLogoutResponse = Agent.LogoutSuccess | Error;\n\n/**\n * Response type for station relogin operations.\n * Either a success response with relogin details or an error.\n * @public\n * @example\n * function handleReLogin(resp: StationReLoginResponse) { ... }\n * @ignore\n */\nexport type StationReLoginResponse = Agent.ReloginSuccess | Error;\n\n/**\n * Response type for agent state change operations.\n * Either a success response with state change details or an error.\n * @public\n * @example\n * function handleStateChange(resp: SetStateResponse) { ... }\n * @ignore\n */\nexport type SetStateResponse = Agent.StateChangeSuccess | Error;\n\n/**\n * AddressBook types\n */\nexport interface AddressBookEntry {\n id: string;\n organizationId?: string;\n version?: number;\n name: string;\n number: string;\n createdTime?: number;\n lastUpdatedTime?: number;\n}\n\nexport type AddressBookEntriesResponse = PaginatedResponse<AddressBookEntry>;\n\nexport interface AddressBookEntrySearchParams extends BaseSearchParams {\n addressBookId?: string;\n}\n\n/**\n * EntryPointRecord types\n */\nexport interface EntryPointRecord {\n id: string;\n name: string;\n description?: string;\n type: string;\n isActive: boolean;\n orgId: string;\n createdAt?: string;\n updatedAt?: string;\n settings?: Record<string, any>;\n}\n\nexport type EntryPointListResponse = PaginatedResponse<EntryPointRecord>;\nexport type EntryPointSearchParams = BaseSearchParams;\n\n/**\n * Queue types\n */\nexport interface QueueSkillRequirement {\n organizationId?: string;\n id?: string;\n version?: number;\n skillId: string;\n skillName?: string;\n skillType?: string;\n condition: string;\n skillValue: string;\n createdTime?: number;\n lastUpdatedTime?: number;\n}\n\nexport interface QueueAgent {\n id: string;\n ciUserId?: string;\n}\n\nexport interface AgentGroup {\n teamId: string;\n}\n\nexport interface CallDistributionGroup {\n agentGroups: AgentGroup[];\n order: number;\n duration?: number;\n}\n\nexport interface AssistantSkillMapping {\n assistantSkillId?: string;\n assistantSkillUpdatedTime?: number;\n}\n\n/**\n * Configuration for a contact service queue\n * @public\n */\nexport interface ContactServiceQueue {\n /** Organization ID */\n organizationId?: string;\n /** Unique identifier for the queue */\n id?: string;\n /** Version of the queue */\n version?: number;\n /** Name of the Contact Service Queue */\n name: string;\n /** Description of the queue */\n description?: string;\n /** Queue type (INBOUND, OUTBOUND) */\n queueType: 'INBOUND' | 'OUTBOUND';\n /** Whether to check agent availability */\n checkAgentAvailability: boolean;\n /** Channel type (TELEPHONY, EMAIL, SOCIAL_CHANNEL, CHAT, etc.) */\n channelType: 'TELEPHONY' | 'EMAIL' | 'FAX' | 'CHAT' | 'VIDEO' | 'OTHERS' | 'SOCIAL_CHANNEL';\n /** Social channel type for SOCIAL_CHANNEL channelType */\n socialChannelType?:\n | 'MESSAGEBIRD'\n | 'MESSENGER'\n | 'WHATSAPP'\n | 'APPLE_BUSINESS_CHAT'\n | 'GOOGLE_BUSINESS_MESSAGES';\n /** Service level threshold in seconds */\n serviceLevelThreshold: number;\n /** Maximum number of simultaneous contacts */\n maxActiveContacts: number;\n /** Maximum time in queue in seconds */\n maxTimeInQueue: number;\n /** Default music in queue media file ID */\n defaultMusicInQueueMediaFileId: string;\n /** Timezone for routing strategies */\n timezone?: string;\n /** Whether the queue is active */\n active: boolean;\n /** Whether outdial campaign is enabled */\n outdialCampaignEnabled?: boolean;\n /** Whether monitoring is permitted */\n monitoringPermitted: boolean;\n /** Whether parking is permitted */\n parkingPermitted: boolean;\n /** Whether recording is permitted */\n recordingPermitted: boolean;\n /** Whether recording all calls is permitted */\n recordingAllCallsPermitted: boolean;\n /** Whether pausing recording is permitted */\n pauseRecordingPermitted: boolean;\n /** Recording pause duration in seconds */\n recordingPauseDuration?: number;\n /** Control flow script URL */\n controlFlowScriptUrl: string;\n /** IVR requeue URL */\n ivrRequeueUrl: string;\n /** Overflow number for telephony */\n overflowNumber?: string;\n /** Vendor ID */\n vendorId?: string;\n /** Routing type */\n routingType: 'LONGEST_AVAILABLE_AGENT' | 'SKILLS_BASED' | 'CIRCULAR' | 'LINEAR';\n /** Skills-based routing type */\n skillBasedRoutingType?: 'LONGEST_AVAILABLE_AGENT' | 'BEST_AVAILABLE_AGENT';\n /** Queue routing type */\n queueRoutingType: 'TEAM_BASED' | 'SKILL_BASED' | 'AGENT_BASED';\n /** Queue skill requirements */\n queueSkillRequirements?: QueueSkillRequirement[];\n /** List of agents for agent-based queue */\n agents?: QueueAgent[];\n /** Call distribution groups */\n callDistributionGroups: CallDistributionGroup[];\n /** XSP version */\n xspVersion?: string;\n /** Subscription ID */\n subscriptionId?: string;\n /** Assistant skill mapping */\n assistantSkill?: AssistantSkillMapping;\n /** Whether this is a system default queue */\n systemDefault?: boolean;\n /** User who last updated agents list */\n agentsLastUpdatedByUserName?: string;\n /** Email of user who last updated agents list */\n agentsLastUpdatedByUserEmailPrefix?: string;\n /** When agents list was last updated */\n agentsLastUpdatedTime?: number;\n /** Creation timestamp in epoch millis */\n createdTime?: number;\n /** Last updated timestamp in epoch millis */\n lastUpdatedTime?: number;\n}\n\nexport type ContactServiceQueuesResponse = PaginatedResponse<ContactServiceQueue>;\n\nexport interface ContactServiceQueueSearchParams extends BaseSearchParams {\n desktopProfileFilter?: boolean;\n provisioningView?: boolean;\n singleObjectResponse?: boolean;\n}\n\n/**\n * Response type for buddy agents query operations.\n * Either a success response with list of buddy agents or an error.\n * @public\n * @example\n * function handleBuddyAgents(resp: BuddyAgentsResponse) { ... }\n */\nexport type BuddyAgentsResponse = Agent.BuddyAgentsSuccess | Error;\n\n/**\n * Response type for device type update operations.\n * Either a success response with update confirmation or an error.\n * @public\n * @example\n * function handleUpdateDeviceType(resp: UpdateDeviceTypeResponse) { ... }\n */\nexport type UpdateDeviceTypeResponse = Agent.DeviceTypeUpdateSuccess | Error;\n\nexport type TranscriptAction = 'START' | 'STOP';\n\nexport const AIAssistantEventType = {\n CUSTOM_EVENT: 'CUSTOM_EVENT',\n CTI_EVENT: 'CTI_EVENT',\n} as const;\n\nexport type AIAssistantEventType = Enum<typeof AIAssistantEventType>;\n\nexport const AIAssistantEventName = {\n GET_TRANSCRIPTS: 'GET_TRANSCRIPTS',\n GET_MID_CALL_SUMMARY: 'GET_MID_CALL_SUMMARY',\n GET_POST_CALL_SUMMARY: 'GET_POST_CALL_SUMMARY',\n MID_CALL_SUMMARY_RESPONSE: 'MID_CALL_SUMMARY_RESPONSE',\n POST_CALL_SUMMARY_RESPONSE: 'POST_CALL_SUMMARY_RESPONSE',\n SUGGESTED_RESPONSES_DIGITAL: 'SUGGESTED_RESPONSES_DIGITAL',\n} as const;\n\nexport type AIAssistantEventName = Enum<typeof AIAssistantEventName>;\n\nexport type TranscriptMessage = {\n role: string;\n content: string;\n messageId: string;\n publishTimestamp: number;\n};\n\nexport type HistoricTranscriptsResponse = {\n orgId: string;\n agentId: string;\n conversationId: string | null;\n interactionId: string;\n source: string;\n data: TranscriptMessage[];\n};\n"],"mappings":";;;;;;AAWA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG;EAC1B;EACAE,GAAG,EAAE,KAAK;EACV;EACAC,IAAI,EAAE,MAAM;EACZ;EACAC,KAAK,EAAE,OAAO;EACd;EACAC,GAAG,EAAE,KAAK;EACV;EACAC,MAAM,EAAE;AACV,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAwBA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA,IAQYC,aAAa,GAAAN,OAAA,CAAAM,aAAA,0BAAbA,aAAa;EACvB;EADUA,aAAa;EAGvB;EAHUA,aAAa;EAKvB;EALUA,aAAa;EAOvB;EAPUA,aAAa;EASvB;EATUA,aAAa;EAAA,OAAbA,aAAa;AAAA;AAazB;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AAuFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAyBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,WAAW,GAAAP,OAAA,CAAAO,WAAA,GAAG;EACzB;EACAC,QAAQ,EAAE,UAAU;EACpB;EACAC,SAAS,EAAE,WAAW;EACtB;EACAC,OAAO,EAAE;AACX,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAmBA;AACA;AACA;AACA;AACA;AACA;;AAqBA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAkBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAeA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAiBA;AACA;AACA;;AAgBA;AACA;AACA;;AAkCA;AACA;AACA;AACA;;AAmGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAKO,MAAMC,oBAAoB,GAAAX,OAAA,CAAAW,oBAAA,GAAG;EAClCC,YAAY,EAAE,cAAc;EAC5BC,SAAS,EAAE;AACb,CAAU;AAIH,MAAMC,oBAAoB,GAAAd,OAAA,CAAAc,oBAAA,GAAG;EAClCC,eAAe,EAAE,iBAAiB;EAClCC,oBAAoB,EAAE,sBAAsB;EAC5CC,qBAAqB,EAAE,uBAAuB;EAC9CC,yBAAyB,EAAE,2BAA2B;EACtDC,0BAA0B,EAAE,4BAA4B;EACxDC,2BAA2B,EAAE;AAC/B,CAAU","ignoreList":[]}
package/dist/webex.js CHANGED
@@ -29,7 +29,7 @@ if (!global.Buffer) {
29
29
  */
30
30
  const Webex = _webexCore.default.extend({
31
31
  webex: true,
32
- version: `3.12.0-next.7`
32
+ version: `3.12.0-next.71`
33
33
  });
34
34
 
35
35
  /**
package/package.json CHANGED
@@ -45,13 +45,13 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@types/platform": "1.3.4",
48
- "@webex/calling": "3.12.0-next.6",
49
- "@webex/internal-plugin-mercury": "3.12.0-next.2",
50
- "@webex/internal-plugin-metrics": "3.12.0-next.2",
51
- "@webex/internal-plugin-support": "3.12.0-next.2",
52
- "@webex/plugin-authorization": "3.12.0-next.2",
53
- "@webex/plugin-logger": "3.12.0-next.2",
54
- "@webex/webex-core": "3.12.0-next.2",
48
+ "@webex/calling": "3.12.0-next.62",
49
+ "@webex/internal-plugin-mercury": "3.12.0-next.25",
50
+ "@webex/internal-plugin-metrics": "3.12.0-next.24",
51
+ "@webex/internal-plugin-support": "3.12.0-next.26",
52
+ "@webex/plugin-authorization": "3.12.0-next.24",
53
+ "@webex/plugin-logger": "3.12.0-next.24",
54
+ "@webex/webex-core": "3.12.0-next.24",
55
55
  "jest-html-reporters": "3.0.11",
56
56
  "lodash": "^4.17.21"
57
57
  },
@@ -65,7 +65,7 @@
65
65
  "@webex/eslint-config-legacy": "0.0.0",
66
66
  "@webex/jest-config-legacy": "0.0.0",
67
67
  "@webex/legacy-tools": "0.0.0",
68
- "@webex/test-helper-mock-webex": "3.11.0-next.1",
68
+ "@webex/test-helper-mock-webex": "3.12.0-next.4",
69
69
  "eslint": "^8.24.0",
70
70
  "eslint-config-airbnb-base": "15.0.0",
71
71
  "eslint-config-prettier": "8.3.0",
@@ -80,5 +80,5 @@
80
80
  "typedoc": "^0.25.0",
81
81
  "typescript": "4.9.5"
82
82
  },
83
- "version": "3.12.0-next.7"
83
+ "version": "3.12.0-next.71"
84
84
  }
package/src/cc.ts CHANGED
@@ -357,6 +357,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
357
357
  this.$webex.once(READY, () => {
358
358
  // @ts-ignore
359
359
  this.$config = this.config;
360
+ this.validatePluginConfig();
360
361
 
361
362
  /**
362
363
  * This is used for handling the async requests by sending webex.request and wait for corresponding websocket event.
@@ -369,7 +370,6 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
369
370
  webex: this.$webex,
370
371
  connectionConfig: this.getConnectionConfig(),
371
372
  });
372
- this.services.webSocketManager.on('message', this.handleWebsocketMessage);
373
373
 
374
374
  this.webCallingService = new WebCallingService(this.$webex);
375
375
  this.apiAIAssistant = new ApiAIAssistant(this.$webex);
@@ -431,6 +431,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
431
431
  this.trigger(TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, task);
432
432
  };
433
433
 
434
+ /**
435
+ * Handles multi-login hydrate events emitted when browser login accepts an incoming call.
436
+ * @private
437
+ * @param {ITask} task The task object associated with multi-login hydrate
438
+ */
439
+ private handleTaskMultiLoginHydrate = (task: ITask) => {
440
+ // @ts-ignore
441
+ this.trigger(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, task);
442
+ };
443
+
434
444
  private handleRTDWebsocketMessage = (payload: string) => {
435
445
  this.taskManager.handleRealtimeWebsocketEvent(payload);
436
446
  };
@@ -444,6 +454,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
444
454
  this.taskManager.on(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
445
455
  this.taskManager.on(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
446
456
  this.taskManager.on(TASK_EVENTS.TASK_MERGED, this.handleTaskMerged);
457
+ this.taskManager.on(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
447
458
  this.taskManager.on(
448
459
  TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
449
460
  this.handleCampaignPreviewReservation
@@ -487,7 +498,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
487
498
  * ```
488
499
  */
489
500
  public async register(): Promise<Profile> {
490
- LoggerProxy.info('Starting CC SDK registration', {
501
+ LoggerProxy.log('Starting CC SDK registration', {
491
502
  module: CC_FILE,
492
503
  method: METHODS.REGISTER,
493
504
  });
@@ -497,6 +508,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
497
508
  METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED,
498
509
  ]);
499
510
  this.setupEventListeners();
511
+ this.services.webSocketManager.on('message', this.handleWebsocketMessage);
500
512
 
501
513
  const resp = await this.connectWebsocket();
502
514
  // Ensure 'dn' is always populated from 'defaultDn'
@@ -576,6 +588,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
576
588
 
577
589
  this.taskManager.off(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
578
590
  this.taskManager.off(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
591
+ this.taskManager.off(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
579
592
  this.taskManager.off(
580
593
  TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
581
594
  this.handleCampaignPreviewReservation
@@ -724,6 +737,30 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
724
737
  }
725
738
  }
726
739
 
740
+ /**
741
+ * Checks whether WebRTC registration should be skipped by config.
742
+ * @returns {boolean}
743
+ * @private
744
+ */
745
+ private isWebRTCRegistrationDisabled(): boolean {
746
+ return this.$config?.disableWebRTCRegistration === true;
747
+ }
748
+
749
+ /**
750
+ * Validates contact-center plugin configuration before service initialization
751
+ * @private
752
+ */
753
+ private validatePluginConfig(): void {
754
+ if (
755
+ this.$config?.disableWebRTCRegistration === true &&
756
+ this.$config?.allowMultiLogin === false
757
+ ) {
758
+ throw new Error(
759
+ 'Invalid Contact Center configuration: disableWebRTCRegistration cannot be true when allowMultiLogin is false. Enable allowMultiLogin or allow WebRTC registration so an SDK instance can receive Mobius/WebRTC task events.'
760
+ );
761
+ }
762
+ }
763
+
727
764
  /**
728
765
  * Connects to the websocket and fetches the agent profile
729
766
  * @returns {Promise<Profile>} Agent profile information
@@ -731,7 +768,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
731
768
  * @private
732
769
  */
733
770
  private async connectWebsocket() {
734
- LoggerProxy.info('Connecting to websocket', {
771
+ LoggerProxy.log('Connecting to websocket', {
735
772
  module: CC_FILE,
736
773
  method: METHODS.CONNECT_WEBSOCKET,
737
774
  });
@@ -758,7 +795,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
758
795
  this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
759
796
 
760
797
  if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable) {
761
- LoggerProxy.info('Connecting to RTD websocket', {
798
+ LoggerProxy.log('Connecting to RTD websocket', {
762
799
  module: CC_FILE,
763
800
  method: METHODS.CONNECT_WEBSOCKET,
764
801
  });
@@ -785,7 +822,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
785
822
 
786
823
  if (
787
824
  this.agentConfig.webRtcEnabled &&
788
- this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER)
825
+ this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER) &&
826
+ !this.isWebRTCRegistrationDisabled()
789
827
  ) {
790
828
  try {
791
829
  await this.$webex.internal.mercury.connect();
@@ -799,10 +837,23 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
799
837
  method: METHODS.CONNECT_WEBSOCKET,
800
838
  });
801
839
  }
840
+ } else if (this.isWebRTCRegistrationDisabled()) {
841
+ LoggerProxy.info(
842
+ 'Skipping Mobius registration because disableWebRTCRegistration is enabled',
843
+ {
844
+ module: CC_FILE,
845
+ method: METHODS.CONNECT_WEBSOCKET,
846
+ }
847
+ );
802
848
  }
803
849
 
804
850
  if (this.$config && this.$config.allowAutomatedRelogin) {
805
851
  await this.silentRelogin();
852
+ } else {
853
+ LoggerProxy.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
854
+ module: CC_FILE,
855
+ method: METHODS.CONNECT_WEBSOCKET,
856
+ });
806
857
  }
807
858
 
808
859
  return this.agentConfig;
@@ -845,26 +896,37 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
845
896
  * ```
846
897
  */
847
898
  public async stationLogin(data: AgentLogin): Promise<StationLoginResponse> {
848
- LoggerProxy.info('Starting agent station login', {
849
- module: CC_FILE,
850
- method: METHODS.STATION_LOGIN,
851
- });
899
+ const loggerContext = {module: CC_FILE, method: METHODS.STATION_LOGIN};
900
+
852
901
  try {
902
+ LoggerProxy.log(
903
+ `Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`,
904
+ loggerContext
905
+ );
853
906
  this.metricsManager.timeEvent([
854
907
  METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
855
908
  METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
856
909
  ]);
857
910
 
858
911
  const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
859
- if (
860
- data.loginOption === LoginOption.AGENT_DN &&
861
- !isValidDialNumber(data.dialNumber, dialPlanEntries)
862
- ) {
863
- const error = new Error('INVALID_DIAL_NUMBER');
864
- // @ts-ignore - adding custom key to the error object
865
- error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
912
+ if (data.loginOption === LoginOption.AGENT_DN) {
913
+ LoggerProxy.log(
914
+ `Validating dial number | dialPlanEnabled: ${!!this.agentConfig
915
+ ?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`,
916
+ loggerContext
917
+ );
918
+
919
+ if (!isValidDialNumber(data.dialNumber, dialPlanEntries)) {
920
+ LoggerProxy.log(
921
+ `Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`,
922
+ loggerContext
923
+ );
924
+ const error = new Error('INVALID_DIAL_NUMBER');
925
+ // @ts-ignore - adding custom key to the error object
926
+ error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
866
927
 
867
- throw error;
928
+ throw error;
929
+ }
868
930
  }
869
931
 
870
932
  const loginResponse = await this.services.agent.stationLogin({
@@ -883,8 +945,24 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
883
945
  },
884
946
  });
885
947
 
886
- if (this.agentConfig.webRtcEnabled && data.loginOption === LoginOption.BROWSER) {
948
+ if (
949
+ this.agentConfig.webRtcEnabled &&
950
+ data.loginOption === LoginOption.BROWSER &&
951
+ !this.isWebRTCRegistrationDisabled()
952
+ ) {
887
953
  await this.webCallingService.registerWebCallingLine();
954
+ } else if (
955
+ this.agentConfig.webRtcEnabled &&
956
+ data.loginOption === LoginOption.BROWSER &&
957
+ this.isWebRTCRegistrationDisabled()
958
+ ) {
959
+ LoggerProxy.info(
960
+ 'Skipping web calling line registration because disableWebRTCRegistration is enabled',
961
+ {
962
+ module: CC_FILE,
963
+ method: METHODS.STATION_LOGIN,
964
+ }
965
+ );
888
966
  }
889
967
 
890
968
  const resp = await loginResponse;
@@ -1277,13 +1355,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1277
1355
  private async handleConnectionLost(msg: ConnectionLostDetails): Promise<void> {
1278
1356
  if (msg.isConnectionLost) {
1279
1357
  // TODO: Emit an event saying connection is lost
1280
- LoggerProxy.info('event=handleConnectionLost | Connection lost', {
1358
+ LoggerProxy.log('event=handleConnectionLost | Connection lost', {
1281
1359
  module: CC_FILE,
1282
1360
  method: METHODS.HANDLE_CONNECTION_LOST,
1283
1361
  });
1284
1362
  } else if (msg.isSocketReconnected) {
1285
1363
  // TODO: Emit an event saying connection is re-estabilished
1286
- LoggerProxy.info(
1364
+ LoggerProxy.log(
1287
1365
  'event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin',
1288
1366
  {module: CC_FILE, method: METHODS.HANDLE_CONNECTION_LOST}
1289
1367
  );
@@ -1298,7 +1376,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1298
1376
  * @private
1299
1377
  */
1300
1378
  private async silentRelogin(): Promise<void> {
1301
- LoggerProxy.info('Starting silent relogin process', {
1379
+ LoggerProxy.log('Starting silent relogin process', {
1302
1380
  module: CC_FILE,
1303
1381
  method: METHODS.SILENT_RELOGIN,
1304
1382
  });
@@ -1320,7 +1398,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1320
1398
  await this.handleDeviceType(deviceType as LoginOption, dn);
1321
1399
 
1322
1400
  if (lastStateChangeReason === 'agent-wss-disconnect') {
1323
- LoggerProxy.info(
1401
+ LoggerProxy.log(
1324
1402
  'event=requestAutoStateChange | Requesting state change to available on socket reconnect',
1325
1403
  {module: CC_FILE, method: METHODS.SILENT_RELOGIN}
1326
1404
  );
@@ -1349,8 +1427,6 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1349
1427
  }
1350
1428
  this.agentConfig.lastStateAuxCodeId = auxCodeId;
1351
1429
  this.agentConfig.isAgentLoggedIn = true;
1352
- // TODO: https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-626777 Implement the de-register method and close the listener there
1353
- this.services.webSocketManager.on('message', this.handleWebsocketMessage);
1354
1430
 
1355
1431
  LoggerProxy.log(
1356
1432
  `Silent relogin process completed successfully with login Option: ${reLoginResponse.data.deviceType} teamId: ${reLoginResponse.data.teamId}`,
@@ -1391,6 +1467,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1391
1467
  this.agentConfig.deviceType = deviceType;
1392
1468
  switch (deviceType) {
1393
1469
  case LoginOption.BROWSER:
1470
+ if (this.isWebRTCRegistrationDisabled()) {
1471
+ LoggerProxy.info(
1472
+ 'Skipping web calling line registration because disableWebRTCRegistration is enabled',
1473
+ {
1474
+ module: CC_FILE,
1475
+ method: METHODS.HANDLE_DEVICE_TYPE,
1476
+ }
1477
+ );
1478
+ break;
1479
+ }
1394
1480
  try {
1395
1481
  await this.webCallingService.registerWebCallingLine();
1396
1482
  } catch (error) {
@@ -1656,6 +1742,166 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1656
1742
  }
1657
1743
  }
1658
1744
 
1745
+ /**
1746
+ * Skips a campaign preview contact, requesting the next contact from the campaign.
1747
+ *
1748
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1749
+ * `AgentOfferCampaignReservation` event. Instead of accepting, the agent can skip the
1750
+ * preview contact to move to the next contact in the campaign.
1751
+ *
1752
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1753
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1754
+ * @throws {Error} If the operation fails (network error, etc.)
1755
+ *
1756
+ * @example
1757
+ * ```typescript
1758
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1759
+ * const { interactionId } = task.data;
1760
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1761
+ *
1762
+ * const result = await webex.cc.skipPreviewContact({ interactionId, campaignId });
1763
+ * });
1764
+ * ```
1765
+ */
1766
+ public async skipPreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
1767
+ const task = this.taskManager.getTask(payload.interactionId);
1768
+ if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewSkipDisabled === 'true') {
1769
+ LoggerProxy.warn('Skip action is disabled for this campaign preview contact', {
1770
+ module: CC_FILE,
1771
+ method: METHODS.SKIP_PREVIEW_CONTACT,
1772
+ interactionId: payload.interactionId,
1773
+ });
1774
+ throw new Error('Skip action is disabled for this campaign preview contact');
1775
+ }
1776
+
1777
+ LoggerProxy.info('Skipping campaign preview contact', {
1778
+ module: CC_FILE,
1779
+ method: METHODS.SKIP_PREVIEW_CONTACT,
1780
+ });
1781
+ try {
1782
+ this.metricsManager.timeEvent([
1783
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS,
1784
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED,
1785
+ ]);
1786
+
1787
+ const result = await this.services.dialer.skipPreviewContact({data: payload});
1788
+
1789
+ this.metricsManager.trackEvent(
1790
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS,
1791
+ {
1792
+ ...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
1793
+ interactionId: payload.interactionId,
1794
+ campaignId: payload.campaignId,
1795
+ },
1796
+ ['behavioral', 'business', 'operational']
1797
+ );
1798
+
1799
+ LoggerProxy.log('Campaign preview contact skipped successfully', {
1800
+ module: CC_FILE,
1801
+ method: METHODS.SKIP_PREVIEW_CONTACT,
1802
+ trackingId: result.trackingId,
1803
+ interactionId: payload.interactionId,
1804
+ });
1805
+
1806
+ return result;
1807
+ } catch (error) {
1808
+ const failure = error.details as Failure;
1809
+ this.metricsManager.trackEvent(
1810
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED,
1811
+ {
1812
+ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
1813
+ interactionId: payload.interactionId,
1814
+ campaignId: payload.campaignId,
1815
+ },
1816
+ ['behavioral', 'business', 'operational']
1817
+ );
1818
+ const {error: detailedError} = getErrorDetails(error, METHODS.SKIP_PREVIEW_CONTACT, CC_FILE);
1819
+ throw detailedError;
1820
+ }
1821
+ }
1822
+
1823
+ /**
1824
+ * Removes a campaign preview contact from the campaign list entirely.
1825
+ *
1826
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1827
+ * `AgentOfferCampaignReservation` event. Instead of accepting or skipping, the agent can
1828
+ * remove the preview contact to permanently take it out of the campaign contact list.
1829
+ *
1830
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1831
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1832
+ * @throws {Error} If the operation fails (network error, etc.)
1833
+ *
1834
+ * @example
1835
+ * ```typescript
1836
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1837
+ * const { interactionId } = task.data;
1838
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1839
+ *
1840
+ * const result = await webex.cc.removePreviewContact({ interactionId, campaignId });
1841
+ * });
1842
+ * ```
1843
+ */
1844
+ public async removePreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
1845
+ const task = this.taskManager.getTask(payload.interactionId);
1846
+ if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewRemoveDisabled === 'true') {
1847
+ LoggerProxy.warn('Remove action is disabled for this campaign preview contact', {
1848
+ module: CC_FILE,
1849
+ method: METHODS.REMOVE_PREVIEW_CONTACT,
1850
+ interactionId: payload.interactionId,
1851
+ });
1852
+ throw new Error('Remove action is disabled for this campaign preview contact');
1853
+ }
1854
+
1855
+ LoggerProxy.info('Removing campaign preview contact', {
1856
+ module: CC_FILE,
1857
+ method: METHODS.REMOVE_PREVIEW_CONTACT,
1858
+ });
1859
+ try {
1860
+ this.metricsManager.timeEvent([
1861
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS,
1862
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED,
1863
+ ]);
1864
+
1865
+ const result = await this.services.dialer.removePreviewContact({data: payload});
1866
+
1867
+ this.metricsManager.trackEvent(
1868
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS,
1869
+ {
1870
+ ...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
1871
+ interactionId: payload.interactionId,
1872
+ campaignId: payload.campaignId,
1873
+ },
1874
+ ['behavioral', 'business', 'operational']
1875
+ );
1876
+
1877
+ LoggerProxy.log('Campaign preview contact removed successfully', {
1878
+ module: CC_FILE,
1879
+ method: METHODS.REMOVE_PREVIEW_CONTACT,
1880
+ trackingId: result.trackingId,
1881
+ interactionId: payload.interactionId,
1882
+ });
1883
+
1884
+ return result;
1885
+ } catch (error) {
1886
+ const failure = error.details as Failure;
1887
+ this.metricsManager.trackEvent(
1888
+ METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED,
1889
+ {
1890
+ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
1891
+ interactionId: payload.interactionId,
1892
+ campaignId: payload.campaignId,
1893
+ },
1894
+ ['behavioral', 'business', 'operational']
1895
+ );
1896
+ const {error: detailedError} = getErrorDetails(
1897
+ error,
1898
+ METHODS.REMOVE_PREVIEW_CONTACT,
1899
+ CC_FILE
1900
+ );
1901
+ throw detailedError;
1902
+ }
1903
+ }
1904
+
1659
1905
  /**
1660
1906
  * Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
1661
1907
  *
package/src/constants.ts CHANGED
@@ -50,6 +50,8 @@ export const METHODS = {
50
50
  HANDLE_TASK_HYDRATE: 'handleTaskHydrate',
51
51
  INCOMING_TASK_LISTENER: 'incomingTaskListener',
52
52
  ACCEPT_PREVIEW_CONTACT: 'acceptPreviewContact',
53
+ SKIP_PREVIEW_CONTACT: 'skipPreviewContact',
54
+ REMOVE_PREVIEW_CONTACT: 'removePreviewContact',
53
55
  GET_BASE_URL: 'getBaseUrl',
54
56
  SEND_EVENT: 'sendEvent',
55
57
  FETCH_HISTORIC_TRANSCRIPTS: 'fetchHistoricTranscripts',