@sippet-ai/operator-widget 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -88
- package/custom-elements.json +165 -179
- package/dist/components/voip-widget/voip-widget-settings-tab.d.ts +0 -1
- package/dist/components/voip-widget/voip-widget-settings-tab.js +0 -16
- package/dist/components/voip-widget/voip-widget.d.ts +28 -18
- package/dist/components/voip-widget/voip-widget.js +493 -305
- package/dist/lib/realtime.d.ts +1 -1
- package/dist/lib/realtime.js +1 -1
- package/dist/lib/sippet.d.ts +5 -2
- package/dist/lib/sippet.js +77 -38
- package/dist/styles/tailwind.global.css +1 -1
- package/dist/styles/tailwind.global.css.js +1 -1
- package/package.json +2 -2
- package/react/SippetAIVoipWidget.d.ts +9 -31
- package/react/SippetAIVoipWidget.js +6 -18
- package/react/SippetAIVoipWidgetSettingsTab.d.ts +0 -4
- package/react/SippetAIVoipWidgetSettingsTab.js +0 -2
- package/types/custom-element-jsx.d.ts +34 -64
- package/types/custom-element-svelte.d.ts +8 -19
- package/types/custom-element-vuejs.d.ts +8 -19
package/README.md
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
# Sippet AI Operator Widget
|
|
2
2
|
|
|
3
|
-
A web component (with React wrappers) for embedding Sippet AI telephony controls
|
|
4
|
-
It provides a floating softphone UI, SIP/WebRTC call controls, queue handling, and light helpers
|
|
5
|
-
built on `@sippet-ai/sdk-js`.
|
|
6
|
-
|
|
7
|
-
## What it does
|
|
8
|
-
|
|
9
|
-
- Renders a floating VoIP widget with phone, queue, contacts, history, and settings tabs.
|
|
10
|
-
- Connects to SIP and WebRTC (mic/speaker selection and permissions).
|
|
11
|
-
- Listens to queue entries and call history.
|
|
12
|
-
- Exposes a small JS API (`sippet`) to trigger calls and query queues/history.
|
|
3
|
+
A web component (with React wrappers) for embedding Sippet AI operator telephony controls.
|
|
13
4
|
|
|
14
5
|
## Install
|
|
15
6
|
|
|
@@ -17,9 +8,64 @@ built on `@sippet-ai/sdk-js`.
|
|
|
17
8
|
npm install @sippet-ai/operator-widget
|
|
18
9
|
```
|
|
19
10
|
|
|
20
|
-
|
|
11
|
+
## Auth flow
|
|
12
|
+
|
|
13
|
+
1. Ensure your operator exists in Sippet's 'Team members' section in the settings
|
|
14
|
+
2. Operator logs in to your frontend.
|
|
15
|
+
3. Your frontend calls your backend (never call Sippet mint endpoint directly from browser).
|
|
16
|
+
4. Your backend validates the operator session and extracts the user's email.
|
|
17
|
+
5. Your backend mints the operator token using one of these methods:
|
|
18
|
+
- SDK server RPC call (recommended): `issueOperatorAccessToken` via `createServerClient` from `@sippet-ai/sdk-js/server`
|
|
19
|
+
- REST endpoint: `POST /api/operator/access`
|
|
20
|
+
6. Sippet finds the operator by email in the workspace tied to that secret key and returns an access token.
|
|
21
|
+
7. Your backend returns that token to frontend.
|
|
22
|
+
8. Frontend passes token to widget via `access-token` or `getAccessToken`.
|
|
23
|
+
|
|
24
|
+
## Minting options on your backend
|
|
25
|
+
|
|
26
|
+
### Option A: SDK server RPC call (recommended)
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createServerClient } from '@sippet-ai/sdk-js/server';
|
|
30
|
+
|
|
31
|
+
const sippet = createServerClient({
|
|
32
|
+
apiKey: process.env.SIPPET_SECRET_API_KEY!,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const result = await sippet.issueOperatorAccessToken({
|
|
36
|
+
input: { operatorEmail: operator.email },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (!result.success) {
|
|
40
|
+
throw new Error(result.errors.map(error => error.message).join(', '));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return result.data.token;
|
|
44
|
+
```
|
|
21
45
|
|
|
22
|
-
|
|
46
|
+
### Option B: Raw REST endpoint
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const response = await fetch('https://api.sippet.ai/api/operator/access', {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers: {
|
|
52
|
+
'content-type': 'application/json',
|
|
53
|
+
'x-api-key': process.env.SIPPET_SECRET_API_KEY!,
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({ operator_email: operator.email }),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (!response.ok) throw new Error('Failed to mint operator access token');
|
|
59
|
+
const body = await response.json();
|
|
60
|
+
return body.token;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Important requirement: operator email must exist in Sippet
|
|
64
|
+
|
|
65
|
+
The `operator_email` must map to an existing invited/created user in your Sippet workspace (team members).
|
|
66
|
+
If the email is not present in that workspace, token minting fails.
|
|
67
|
+
|
|
68
|
+
## Quick start (Web Component, token auth)
|
|
23
69
|
|
|
24
70
|
```html
|
|
25
71
|
<script type="module">
|
|
@@ -27,19 +73,12 @@ npm install @sippet-ai/operator-widget
|
|
|
27
73
|
</script>
|
|
28
74
|
|
|
29
75
|
<sippetai-voip-widget
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
sip-user="1001"
|
|
33
|
-
sip-password="1234"
|
|
34
|
-
sip-web-socket-url="wss://sip.sippet.ai:7443"
|
|
35
|
-
user-name="Agent"
|
|
36
|
-
user-email="agent@example.com"
|
|
76
|
+
access-token="YOUR_OPERATOR_ACCESS_TOKEN"
|
|
77
|
+
api-origin="https://api.sippet.ai"
|
|
37
78
|
></sippetai-voip-widget>
|
|
38
79
|
```
|
|
39
80
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
## React usage
|
|
81
|
+
## React usage (token auth)
|
|
43
82
|
|
|
44
83
|
```tsx
|
|
45
84
|
import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
|
|
@@ -47,89 +86,84 @@ import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
|
|
|
47
86
|
export function SupportWidget() {
|
|
48
87
|
return (
|
|
49
88
|
<SippetAIVoipWidget
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
sipUser="1001"
|
|
53
|
-
sipPassword="1234"
|
|
54
|
-
sipWebSocketUrl="wss://sip.sippet.ai:7443"
|
|
55
|
-
userName="Agent"
|
|
56
|
-
userEmail="agent@example.com"
|
|
89
|
+
accessToken="YOUR_OPERATOR_ACCESS_TOKEN"
|
|
90
|
+
apiOrigin="https://api.sippet.ai"
|
|
57
91
|
/>
|
|
58
92
|
);
|
|
59
93
|
}
|
|
60
94
|
```
|
|
61
95
|
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
- `api-key` (attribute) / `apiKey` (property). Required for contacts, history, queue polling, and realtime events.
|
|
65
|
-
- `api-origin` (attribute) / `apiOrigin` (property). Optional override for a self-hosted or local API origin.
|
|
66
|
-
- `sip-url`, `sip-user`, `sip-password`, `sip-web-socket-url`. Required for SIP calling.
|
|
67
|
-
- `user-name`, `user-email`. Displayed in the widget.
|
|
96
|
+
## Shared SDK + widget state
|
|
68
97
|
|
|
69
|
-
|
|
98
|
+
If your app already uses `@sippet-ai/sdk-js/client`, pass that same client object
|
|
99
|
+
to the widget as a property. This keeps SIP session/call state in one place, so
|
|
100
|
+
SDK actions (for example joining a call) are reflected in the widget UI.
|
|
70
101
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
import { sippet } from '@sippet-ai/operator-widget';
|
|
75
|
-
|
|
76
|
-
sippet.setApiKey('YOUR_PUBLISHABLE_API_KEY');
|
|
77
|
-
sippet.setApiOrigin('https://api.sippet.ai');
|
|
78
|
-
|
|
79
|
-
await sippet.call('+15551234567');
|
|
80
|
-
await sippet.answer();
|
|
81
|
-
await sippet.decline();
|
|
82
|
-
await sippet.hold();
|
|
102
|
+
```tsx
|
|
103
|
+
import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
|
|
104
|
+
import * as sdkClient from '@sippet-ai/sdk-js/client';
|
|
83
105
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
export function SupportWidget({ isWidgetOpen }: { isWidgetOpen: boolean }) {
|
|
107
|
+
return (
|
|
108
|
+
<SippetAIVoipWidget
|
|
109
|
+
client={sdkClient}
|
|
110
|
+
openWidget={isWidgetOpen}
|
|
111
|
+
getAccessToken={async () => {
|
|
112
|
+
const response = await fetch('/api/your-backend/operator-token', {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) throw new Error('Failed to mint operator token');
|
|
116
|
+
const body = await response.json();
|
|
117
|
+
return body.token;
|
|
118
|
+
}}
|
|
119
|
+
apiOrigin="https://api.sippet.ai"
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
87
123
|
```
|
|
88
124
|
|
|
89
|
-
|
|
125
|
+
## Token rotation with backend endpoint
|
|
90
126
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
import { initSocket, joinEventsChannel } from '@sippet-ai/operator-widget';
|
|
95
|
-
|
|
96
|
-
initSocket({ publishableKey: 'YOUR_PUBLISHABLE_API_KEY' });
|
|
97
|
-
|
|
98
|
-
const channel = joinEventsChannel();
|
|
127
|
+
```tsx
|
|
128
|
+
import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
|
|
99
129
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
130
|
+
export function SupportWidget() {
|
|
131
|
+
return (
|
|
132
|
+
<SippetAIVoipWidget
|
|
133
|
+
apiOrigin="https://api.sippet.ai"
|
|
134
|
+
getAccessToken={async () => {
|
|
135
|
+
const response = await fetch('/api/your-backend/operator-token', {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
});
|
|
138
|
+
if (!response.ok) throw new Error('Failed to mint operator token');
|
|
139
|
+
const body = await response.json();
|
|
140
|
+
return body.token;
|
|
141
|
+
}}
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
103
145
|
```
|
|
104
146
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
- `incoming_call`
|
|
108
|
-
- `call_answered`
|
|
109
|
-
- `call_ended`
|
|
110
|
-
- `operator_status_change`
|
|
111
|
-
- `call_queue_entry_updated`
|
|
112
|
-
- `call_queue_entry_deleted`
|
|
113
|
-
- `call_participant_joined`
|
|
114
|
-
- `call_participant_left`
|
|
115
|
-
- `call_transcript_delta`
|
|
116
|
-
- `call_transcript_completed`
|
|
117
|
-
|
|
118
|
-
## Permissions and runtime behavior
|
|
119
|
-
|
|
120
|
-
- Microphone access is required for calling; the widget prompts for audio permissions when opened.
|
|
121
|
-
- Speaker selection uses `setSinkId` when supported by the browser; some browsers require a user gesture.
|
|
122
|
-
- Queue entries are refreshed on realtime socket events and when the queue tab is opened (no polling loop).
|
|
147
|
+
## Configuration
|
|
123
148
|
|
|
124
|
-
|
|
149
|
+
- `access-token` / `accessToken`: operator bearer token.
|
|
150
|
+
- `getAccessToken` (property only): async token resolver.
|
|
151
|
+
- `api-origin` / `apiOrigin`: API origin override.
|
|
152
|
+
- `client` (property only): shared SDK client instance from `@sippet-ai/sdk-js/client`.
|
|
153
|
+
- `open-widget` / `openWidget`: controls whether the panel is open.
|
|
125
154
|
|
|
126
|
-
|
|
155
|
+
## Helper API
|
|
127
156
|
|
|
128
157
|
```ts
|
|
129
|
-
import {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
158
|
+
import { sippet } from '@sippet-ai/operator-widget';
|
|
159
|
+
import * as sdkClient from '@sippet-ai/sdk-js/client';
|
|
160
|
+
|
|
161
|
+
sippet.setClient(sdkClient);
|
|
162
|
+
sippet.setGetAccessToken(async () => {
|
|
163
|
+
const response = await fetch('/api/your-backend/operator-token', {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
});
|
|
166
|
+
const body = await response.json();
|
|
167
|
+
return body.token;
|
|
134
168
|
});
|
|
135
169
|
```
|