@sippet-ai/operator-widget 0.0.14 → 0.0.15

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 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 in any app.
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
- `@sippet-ai/sdk-js` is a dependency of the widget, so it will be installed automatically.
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
+ });
21
38
 
22
- ## Quick start (Web Component)
39
+ if (!result.success) {
40
+ throw new Error(result.errors.map(error => error.message).join(', '));
41
+ }
42
+
43
+ return result.data.token;
44
+ ```
45
+
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
- api-key="YOUR_PUBLISHABLE_API_KEY"
31
- sip-url="sip.sippet.ai"
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
- The widget renders a launcher button at the bottom-right of the page. Clicking it opens the panel.
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,51 @@ import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
47
86
  export function SupportWidget() {
48
87
  return (
49
88
  <SippetAIVoipWidget
50
- apiKey="YOUR_PUBLISHABLE_API_KEY"
51
- sipUrl="sip.sippet.ai"
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
- ## Configuration
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.
68
-
69
- ## Methods & events
70
-
71
- Methods are available on the DOM element instance via the `sippet` helper.
72
-
73
- ```ts
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();
83
-
84
- const queue = await sippet.getQueue();
85
- const activeCalls = await sippet.getActiveCalls();
86
- const callDetails = await sippet.callDetails('CALL_UUID');
87
- ```
88
-
89
- If the widget element already has `api-key`, you can omit `sippet.setApiKey`.
96
+ ## Token rotation with backend endpoint
90
97
 
91
- ## Realtime events
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();
98
+ ```tsx
99
+ import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
99
100
 
100
- channel.on('incoming_call', payload => {
101
- console.log('incoming_call', payload);
102
- });
101
+ export function SupportWidget() {
102
+ return (
103
+ <SippetAIVoipWidget
104
+ apiOrigin="https://api.sippet.ai"
105
+ getAccessToken={async () => {
106
+ const response = await fetch('/api/your-backend/operator-token', {
107
+ method: 'POST',
108
+ });
109
+ if (!response.ok) throw new Error('Failed to mint operator token');
110
+ const body = await response.json();
111
+ return body.token;
112
+ }}
113
+ />
114
+ );
115
+ }
103
116
  ```
104
117
 
105
- Known event names:
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).
118
+ ## Configuration
123
119
 
124
- ## Using `@sippet-ai/sdk-js/client` directly
120
+ - `access-token` / `accessToken`: operator bearer token.
121
+ - `getAccessToken` (property only): async token resolver.
122
+ - `api-origin` / `apiOrigin`: API origin override.
125
123
 
126
- If you need RPC calls outside the widget, use the SDK client directly:
124
+ ## Helper API
127
125
 
128
126
  ```ts
129
- import { listCalls } from '@sippet-ai/sdk-js/client';
127
+ import { sippet } from '@sippet-ai/operator-widget';
130
128
 
131
- const calls = await listCalls({
132
- headers: { 'x-api-key': 'YOUR_PUBLISHABLE_API_KEY' },
133
- fields: ['id', 'callUuid', 'status'],
129
+ sippet.setGetAccessToken(async () => {
130
+ const response = await fetch('/api/your-backend/operator-token', {
131
+ method: 'POST',
132
+ });
133
+ const body = await response.json();
134
+ return body.token;
134
135
  });
135
136
  ```