DIAL Overlay
Dial Overlay is a library for using AI DIAL Chat in overlay. You can configure and communicate with chat using iframe event based protocol.
Public classes to use
ChatOverlay
- class which creates iframe with DIAL, allows to interact with it (send/receive messages). Types for configuration options is ChatOverlayOptions
.
ChatOverlayManager
- class which provides overlay factory, different styles and animation for overlay (for example: opening animation, auto placement, fullscreen button, etc.). Types for configuration options is ChatOverlayManagerOptions
.
If you need only 1 iframe and API to interact and nothing more - use ChatOverlay
If you need several iframes with API and you want that it should be placed with pre-prepared styles options - use ChatOverlayManager
Prerequisites
Your Dial Chat application should configure host where you are using this library with ALLOWED_IFRAME_ORIGINS
env variable
_Note: For development purposes you can set *
_
ALLOWED_IFRAME_ORIGINS=http://localhost:8000
For integration with DIAL CHAT you should do these steps:
- Install library
npm i @epam/ai-dial-overlay
- Add file to serving folder in your application or just import it in code
import { ChatOverlay, ChatOverlayManager, ChatOverlayOptions } from '@epam/ai-dial-overlay';
- Create an instance of
ChatOverlay
(to just overlay and nothing more) or ChatOverlayManager
(if you want create more than 1 ChatOverlay, or additional style options, like positions, animations, etc.)
ChatOverlay:
const container = document.create('div');
document.body.appendChild(container);
const run = async () => {
const overlay: ChatOverlayOptions = new ChatOverlay(container, {
hostDomain: window.location.origin,
domain: 'https://chat-overlay.staging.deltixhub.io',
theme: 'light',
modelId: 'gpt-4',
requestTimeout: 20000,
enabledFeatures: ['conversations-section', 'prompts-section', 'top-settings', 'top-clear-conversation', 'top-chat-info', 'top-chat-model-settings', 'empty-chat-settings', 'header', 'footer', 'request-api-key', 'report-an-issue', 'likes'],
loaderStyles: {
background: 'black',
},
loaderClass: 'overlay__loader',
});
await overlay.ready();
const { messages } = await overlay.getMessages();
await overlay.sendMessage('Hello chat!');
await overlay.setSystemPrompt('Be patient and supportive!');
await overlay.setOverlayOptions({
hostDomain: window.location.origin,
domain: 'https://chat-overlay.staging.deltixhub.io',
theme: 'dark',
modelId: 'statgpt',
requestTimeout: 11111,
});
const unsubscribe = overlay.subscribe('@DIAL_OVERLAY/GPT_START_GENERATING', () => console.log('Starting...'));
unsubscribe();
};
ChatOverlayManager:
For manager the same as for ChatOverlay
but with some minor changes. You should specify overlay displaying options and id for new instance.
ChatOverlayManager.createOverlay({
id: 'test',
position: 'left-bottom',
width: 300,
height: 300,
zIndex: 6,
...ChatOverlayOptions
});
ChatOverlayManager.removeOverlay('test');
ChatOverlayManager.hideOverlay('test');
ChatOverlayManager.showOverlay('test');
...
ChatOverlayManager.getMessages('test');
ChatOverlayManager.sendMessage('test', 'Hi chat!');
...
Internal structure
That part would be useful for overlay developers or people who might be interested in tech implementation.
Overlay communication, as all iframe communication, implemented using javascript post message.
There is 2 parts of implementation:
- ChatOverlay library
- DIAL post message listeners
ChatOverlay
Main methods and practices that allow us to communicate with DIAL:
ChatOverlay
is the class which in constructor is creating iframe and set origin of deployed version of DIAL.
That how it should work for end user
const overlay = new ChatOverlay({domain: "https://overlay-domain.com", ...});
overlay.getSomething().then(...);
Overlay
uses Task
, it's a class which contain Promise
with external function resolve. It's needed for cases when you want resolve promise not only in this way Promise((resolve) => resolve(...))
, you want to do something like this: currentPromise.complete()
Main logic that used there:
let complete;
const promise = new Promise((resolve) => {
complete = resolve;
});
complete();
Overlay
uses DeferredRequest
, it's the same as Task
by conception, but contains more business specific logic. For example: timeout for completing task, generating uuid of request, payload of request, matching request algorithm, etc.- Chat overlay contains
Task
which called this.iframeInteraction
. When this.iframeInteraction
is complete, that's mean we can receive and send messages. There is method ready()
, it's displaying this.iframeInteraction.ready()
- For communication ChatOverlay uses the method
send()
. There are parts that you should know about this method:
- It's creating the new
DeferredRequest
, setting necessary info and putting to this.requests
, and sending post message. - That's totally depends
this.ready()
. No requests would be processed until this.ready()
...send method...
await send() {
await this.ready();
...
this.requests.push(new DeferredRequest(...));
}
window.addEventListener('message', this.process)
, this.process
is checking that some message contains payload that we can match with some request in this.requests
or just event. Before them all is checking that application send us @DIAL_OVERLAY/READY
and we can complete this.iframeInteraction
.
...handle post message...
if (event.data.type === "@DIAL_OVERLAY/READY") {
this.iframeInteraction.complete();
return;
}
- In constructor we're sending configuration to application (it's handshake, we will get ready event, after we will say our domain and additional information),
this.send()
depends from this.iframeInteraction
. Until we don't get the '@DIAL_OVERLAY/READY'
we don't send something, don't worry.
constructor() {
...
this.setOverlayOptions({...});
}
- Method
subscribe
just add callback to this.subscriptions
. In this.process
we call this.processEvent
if we don't have requestId
. Returns the callback which removes callback
from this.subscriptions
subscribe(eventType: string, callback: () => void) {
this.subscriptions.push({ callback, eventType });
}
- We're showing loader until DIAL Chat notify that OverlayOptions is installed.
DIAL Chat side
Main methods and practices that allow us to communicate with host.
Business logic which related to overlays are located in overlay.epics.ts, overlay.reducers.ts
and has own slice.
postMessageMapperEpic
, main epic that parse post message and dispatch necessary action to other internal epics to separate business logic.notifyHostAboutReadyEpic
, send to host '@DIAL_OVERLAY/READY'
setOverlayConfigEpic
, listens when host send configuration (incl. hostDomain, to not broadcast information to other participants of host page).
Other epics self described.
Flow to add some new method:
- Add action to overlay slice
- Add dispatch action to postMessageMapper
- Add epic which get all needed information from common store and send result using
sendPMResponse
.
Flow to add some new event:
- Add epic which get necessary information
- Send result to host using
sendPMEvent