/** * `client.interface` from `aaf_sdk.js` — `trigger` (host UI actions) and `open` (agent UI pages/forms). * Availability: all app locations (per product docs). */ export interface AafInterfaceApi { trigger: (operation: string, operationData: unknown) => Promise; /** * Opens a named form/page in the agent shell (e.g. `newTicketForm`). * Present on `application.ui` SDK builds; some older `ameyo.ui` bundles only ship `trigger`. */ open?: (contextName: string, contextData: unknown) => Promise; } export interface HasInterface { interface: AafInterfaceApi; } /** Documented `interface.trigger` operation names. */ export const GwtInterfaceTriggerOperation = { toastNotification: "toastNotification", desktopNotification: "desktopNotification", modalCloseConfirmation: "modalCloseConfirmation" } as const; export type GwtInterfaceTriggerOperationName = (typeof GwtInterfaceTriggerOperation)[keyof typeof GwtInterfaceTriggerOperation]; /** Documented `interface.open` context names. */ export const GwtInterfaceOpenContext = { newTicketForm: "newTicketForm", newCustomerForm: "newCustomerForm", openCustomerDetail: "openCustomerDetail" } as const; export type GwtInterfaceOpenContextName = (typeof GwtInterfaceOpenContext)[keyof typeof GwtInterfaceOpenContext]; // --- toastNotification --- export type ToastNotificationType = "success" | "alert" | "error"; export type ToastNotificationData = { type: ToastNotificationType; content: string; }; // --- desktopNotification --- export type DesktopNotificationClickAction = "focusWindow" | "noAction"; export type DesktopNotificationIcon = | "chat" | "call" | "wechat" | "messenger" | "twitter" | "line" | "viber" | "webchat" | "android" | "default"; export type DesktopNotificationData = { title: string; body?: string; tag?: string; imageUrl?: string; iconUrl?: string; clickAction?: DesktopNotificationClickAction; autoClose?: boolean; /** Ignored when `iconUrl` is set. */ notificationIcon?: DesktopNotificationIcon; showIfPageVisible?: boolean; }; // --- modalCloseConfirmation --- export type ModalCloseConfirmationData = { title?: string; message?: string; }; // --- open("newTicketForm", contextData) --- export type NewTicketMessageType = "MANUAL_MESSAGE" | "EMAIL" | "VOICE" | (string & {}); export type NewTicketMessageInfo = { /** Required when `messageInfo` is present. May be a single type or array (per docs). */ messageType: NewTicketMessageType | NewTicketMessageType[]; subject?: string; message?: string; target?: string | string[]; cc?: string | string[]; bcc?: string | string[]; }; export type NewTicketTicketInfo = { campaignId?: number; queueId?: number; priority?: string; externalState?: string; /** Custom field id → value (strings, numbers, arrays, objects per server). */ customFields?: Record; }; /** Payload for `interface.open("newTicketForm", contextData)`. */ export type NewTicketFormContextData = { customerId?: number; /** Pre-fill when `customerId` missing or unknown (shape is server-driven). */ customerInfo?: Record; ticketInfo?: NewTicketTicketInfo; messageInfo?: NewTicketMessageInfo; }; // --- open("newCustomerForm", contextData) --- /** * Customer field map for **newCustomerForm** (column name → value). * Common keys from docs: `name`, `phone1`, `email`; additional keys (e.g. `twitter`) are allowed. */ export type NewCustomerFormCustomerInfo = Record & { name?: string; phone1?: string; email?: string; }; /** Payload for `interface.open("newCustomerForm", contextData)`. */ export type NewCustomerFormContextData = { /** Campaign id the agent is logged into; used for column mapping (string per product docs). */ campaignId: string; customerInfo: NewCustomerFormCustomerInfo; }; function callInterfaceOpen( client: HasInterface, contextName: GwtInterfaceOpenContextName | (string & {}), contextData: unknown ): Promise { const open = client.interface.open; if (typeof open !== "function") { return Promise.reject( new Error("client.interface.open is missing — use an aaf_sdk.js build that includes `open` (e.g. application.ui).") ); } return open.call(client.interface, contextName, contextData); } export function triggerToastNotification( client: HasInterface, data: ToastNotificationData ): Promise { return client.interface.trigger(GwtInterfaceTriggerOperation.toastNotification, data); } export function triggerDesktopNotification( client: HasInterface, data: DesktopNotificationData ): Promise { return client.interface.trigger(GwtInterfaceTriggerOperation.desktopNotification, data); } export function triggerModalCloseConfirmation( client: HasInterface, data: ModalCloseConfirmationData ): Promise { return client.interface.trigger(GwtInterfaceTriggerOperation.modalCloseConfirmation, data); } export function openNewTicketForm( client: HasInterface, contextData: NewTicketFormContextData ): Promise { return callInterfaceOpen(client, GwtInterfaceOpenContext.newTicketForm, contextData); } export function openNewCustomerForm( client: HasInterface, contextData: NewCustomerFormContextData ): Promise { return callInterfaceOpen(client, GwtInterfaceOpenContext.newCustomerForm, contextData); } /** * Opens the **customer detail** page for an existing customer. * Second argument to `interface.open` is the **customer id string** (parsed to long server-side); not an object. */ export function openCustomerDetail(client: HasInterface, customerId: string | number): Promise { const id = typeof customerId === "number" ? String(customerId) : customerId.trim(); if (id === "") { return Promise.reject( new Error("customerId cannot be null or empty — host returns 101 (Customer id cannot be null).") ); } return callInterfaceOpen(client, GwtInterfaceOpenContext.openCustomerDetail, id); } /** Escape hatch for undocumented `trigger` operations. */ export function interfaceTrigger( client: HasInterface, operation: string, operationData: unknown ): Promise { return client.interface.trigger(operation, operationData); } /** Escape hatch for undocumented `open` targets. */ export function interfaceOpen(client: HasInterface, contextName: string, contextData: unknown): Promise { const open = client.interface.open; if (typeof open !== "function") { return Promise.reject(new Error("client.interface.open is not available in this SDK build.")); } return open.call(client.interface, contextName, contextData); }