@babelbeez/sdk 0.1.1

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 ADDED
@@ -0,0 +1,208 @@
1
+ # Babelbeez Headless SDK (`@babelbeez/sdk`)
2
+
3
+ The **Babelbeez Headless SDK** provides raw, programmatic access to the Babelbeez Voice Agent protocol.
4
+
5
+ It’s ideal if you want to:
6
+
7
+ - Integrate Babelbeez voice agents into an existing app (web, dashboards, custom UIs)
8
+ - Build completely custom button/widget designs instead of using the standard embed
9
+ - Create hybrid **text + voice** interfaces while Babelbeez handles:
10
+ - Low-latency audio processing
11
+ - WebRTC connections
12
+ - AI orchestration and session management
13
+
14
+ > If you just want a drop-in widget for your website, you probably want the standard Babelbeez embed instead of this SDK.
15
+
16
+ ---
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @babelbeez/sdk
22
+ ```
23
+
24
+ The SDK is designed for modern browsers that support WebRTC and access to the microphone.
25
+
26
+ ---
27
+
28
+ ## Quick Start
29
+
30
+ To use the SDK, you will need the **Public Chatbot ID** of your configured Voice Agent. You can find this in the Babelbeez Dashboard under **Voice Agent Settings**.
31
+
32
+ ```ts
33
+ import { BabelbeezClient } from '@babelbeez/sdk';
34
+
35
+ // 1. Initialize the client
36
+ const client = new BabelbeezClient({
37
+ publicChatbotId: 'YOUR_UUID_HERE',
38
+ });
39
+
40
+ // 2. Listen for state changes (e.g., loading, listening, speaking)
41
+ client.on('buttonState', (state) => {
42
+ console.log('Agent State:', state); // 'loading' | 'active' | 'speaking' | 'idle'
43
+ });
44
+
45
+ // 3. Listen for live transcripts
46
+ client.on('transcript', ({ role, text, isFinal }) => {
47
+ console.log(`${role}: ${text}`);
48
+ });
49
+
50
+ // 4. Connect (browser will request microphone permissions)
51
+ document.getElementById('start-btn')!.addEventListener('click', async () => {
52
+ try {
53
+ await client.connect();
54
+ } catch (err) {
55
+ console.error('Failed to connect:', err);
56
+ }
57
+ });
58
+ ```
59
+
60
+ ---
61
+
62
+ ## API Reference
63
+
64
+ ### `new BabelbeezClient(config)`
65
+
66
+ Creates a new instance of the Babelbeez client.
67
+
68
+ **Config object**
69
+
70
+ - `publicChatbotId` **(string, required)** – The unique UUID of your Voice Agent.
71
+
72
+ ```ts
73
+ const client = new BabelbeezClient({
74
+ publicChatbotId: 'YOUR_UUID_HERE',
75
+ });
76
+ ```
77
+
78
+ ---
79
+
80
+ ### Methods
81
+
82
+ #### `connect()`
83
+
84
+ Initializes the session, requests microphone access from the user, and establishes a realtime WebRTC connection with the Babelbeez infrastructure.
85
+
86
+ ```ts
87
+ await client.connect();
88
+ ```
89
+
90
+ If the user denies microphone permissions, or the connection fails, an `error` event will be emitted and the promise will reject.
91
+
92
+ ---
93
+
94
+ #### `disconnect(reason?)`
95
+
96
+ Gracefully terminates the voice session.
97
+
98
+ ```ts
99
+ client.disconnect('user_button_click');
100
+ ```
101
+
102
+ **Parameters**
103
+
104
+ - `reason` **(string, optional)** – A descriptive reason for the disconnection. Defaults to `'client_disconnect'`.
105
+
106
+ Special handling:
107
+
108
+ - Passing `'user_button_click'` specifically triggers the agent to play its configured **“Goodbye”** message **before** disconnecting.
109
+ - Other reasons generally terminate the session immediately.
110
+
111
+ ---
112
+
113
+ #### `sendUserText(text)`
114
+
115
+ Sends a text message to the agent. This enables hybrid interfaces where a user can **speak or type** to the same agent within the same session.
116
+
117
+ ```ts
118
+ client.sendUserText('Hello, I would like to book an appointment.');
119
+ ```
120
+
121
+ **Parameters**
122
+
123
+ - `text` **(string)** – The message to send.
124
+
125
+ ---
126
+
127
+ #### `handleHandoffSubmit({ email, consent })`
128
+
129
+ Submits user contact details in response to a **“Request Human Handoff”** event.
130
+
131
+ ```ts
132
+ client.handleHandoffSubmit({
133
+ email: 'user@example.com',
134
+ consent: true,
135
+ });
136
+ ```
137
+
138
+ **Parameters**
139
+
140
+ - `email` **(string)** – The user’s email address.
141
+ - `consent` **(boolean)** – Whether the user consented to be contacted.
142
+
143
+ ---
144
+
145
+ #### `handleHandoffCancel({ viaWhatsapp })`
146
+
147
+ Cancels a pending handoff request.
148
+
149
+ ```ts
150
+ client.handleHandoffCancel({
151
+ viaWhatsapp: true,
152
+ });
153
+ ```
154
+
155
+ **Parameters**
156
+
157
+ - `viaWhatsapp` **(boolean, optional)** – Set to `true` if the cancellation occurred because the user chose to continue the conversation on WhatsApp via a deep link.
158
+
159
+ ---
160
+
161
+ ## Events
162
+
163
+ The client extends an `EventEmitter`. You can subscribe to events using `client.on(event, callback)`.
164
+
165
+ ```ts
166
+ client.on('event-name', (payload) => {
167
+ // handle event
168
+ });
169
+ ```
170
+
171
+ ### Core Events
172
+
173
+ | Event | Payload | Description |
174
+ |-----------------|----------------------------|-------------|
175
+ | `buttonState` | `string` | Current status of the agent. One of: `'idle'`, `'loading'`, `'active'` (listening), `'speaking'`, `'rag-retrieval'`, `'error'`. |
176
+ | `transcript` | `{ role, text, isFinal }` | Realtime transcript updates. `role` is `'user'` or `'agent'`. `isFinal` indicates that the utterance/response is complete. |
177
+ | `session:start` | `{ chatbotId, config }` | Fired when the WebRTC connection is fully established and the session is active. |
178
+ | `session:end` | `{ reason }` | Fired when the session terminates (user disconnect, timeout, error, etc.). |
179
+ | `handoff:show` | `{ summaryText, waLink }` | Fired when the AI determines a human is needed. Render a UI form to collect user details. `waLink` contains a WhatsApp deep link if configured. |
180
+ | `handoff:hide` | `{ outcome }` | Fired when the handoff flow is completed or cancelled. |
181
+ | `error` | `{ code, message, fatal }` | Emitted when an error occurs. If `fatal` is `true`, the session has been terminated. |
182
+
183
+ Example:
184
+
185
+ ```ts
186
+ client.on('error', ({ code, message, fatal }) => {
187
+ console.error(`[Babelbeez] Error (${code}): ${message}`);
188
+
189
+ if (fatal) {
190
+ // e.g. update UI, disable button, prompt user to refresh
191
+ }
192
+ });
193
+ ```
194
+
195
+ ---
196
+
197
+ ## Usage Notes
198
+
199
+ - The SDK is **browser-first** and assumes access to `navigator.mediaDevices` for microphone input.
200
+ - Make sure your site is served over **HTTPS**, or from `localhost`, otherwise the browser may block microphone access.
201
+ - You should always provide clear UI affordances (e.g. a “Start call” / “End call” button) that map to `connect()` and `disconnect()` calls.
202
+
203
+ ---
204
+
205
+ ## License
206
+
207
+ ISC
208
+
@@ -0,0 +1,167 @@
1
+ export type BabelbeezButtonState =
2
+ | 'idle'
3
+ | 'loading'
4
+ | 'active'
5
+ | 'speaking'
6
+ | 'error'
7
+ | 'rag-retrieval';
8
+
9
+ export interface BabelbeezTranscriptEvent {
10
+ role: 'user' | 'agent';
11
+ text: string;
12
+ isFinal: boolean;
13
+ }
14
+
15
+ export interface BabelbeezSessionStartEvent {
16
+ chatbotId: string;
17
+ // Chatbot configuration snapshot returned from /initialize-chat.
18
+ // The exact shape is backend-defined, so we leave it open.
19
+ config: unknown;
20
+ }
21
+
22
+ export interface BabelbeezSessionEndEvent {
23
+ reason: string;
24
+ }
25
+
26
+ export type BabelbeezErrorSeverity = 'info' | 'warning' | 'error';
27
+
28
+ export interface BabelbeezErrorEvent {
29
+ code: string;
30
+ message: string;
31
+ severity: BabelbeezErrorSeverity;
32
+ fatal?: boolean;
33
+ }
34
+
35
+ export interface BabelbeezHandoffShowEvent {
36
+ summaryText: string;
37
+ /** WhatsApp deep-link if configured, otherwise null. */
38
+ waLink: string | null;
39
+ }
40
+
41
+ export type BabelbeezHandoffHideOutcome =
42
+ | 'email_submitted'
43
+ | 'whatsapp_submitted'
44
+ | 'cancelled';
45
+
46
+ export interface BabelbeezHandoffHideEvent {
47
+ outcome: BabelbeezHandoffHideOutcome;
48
+ }
49
+
50
+ export interface BabelbeezClientEventMap {
51
+ /**
52
+ * Voice button / widget state changes.
53
+ */
54
+ buttonState: BabelbeezButtonState;
55
+
56
+ /**
57
+ * Fired once a Realtime session has successfully started.
58
+ */
59
+ 'session:start': BabelbeezSessionStartEvent;
60
+
61
+ /**
62
+ * Fired when the session has fully ended and resources are cleaned up.
63
+ */
64
+ 'session:end': BabelbeezSessionEndEvent;
65
+
66
+ /**
67
+ * Non-fatal and fatal errors surfaced to the host UI.
68
+ */
69
+ error: BabelbeezErrorEvent;
70
+
71
+ /**
72
+ * Streaming user/agent transcripts suitable for rendering a chat-like UI.
73
+ *
74
+ * - For role "user": multiple events per utterance; the last has
75
+ * isFinal = true once speech transcription completes.
76
+ * - For role "agent": multiple events per spoken response; a final event
77
+ * with isFinal = true is emitted when the assistant has finished
78
+ * speaking for that turn.
79
+ */
80
+ transcript: BabelbeezTranscriptEvent;
81
+
82
+ /**
83
+ * Request to show the human handoff form.
84
+ */
85
+ 'handoff:show': BabelbeezHandoffShowEvent;
86
+
87
+ /**
88
+ * Notification that the handoff form has been closed.
89
+ */
90
+ 'handoff:hide': BabelbeezHandoffHideEvent;
91
+ }
92
+
93
+ export interface BabelbeezHandoffSubmitPayload {
94
+ email: string;
95
+ consent: boolean;
96
+ }
97
+
98
+ export interface BabelbeezHandoffCancelOptions {
99
+ viaWhatsapp?: boolean;
100
+ }
101
+
102
+ export interface BabelbeezClientConfig {
103
+ publicChatbotId: string;
104
+ }
105
+
106
+ /**
107
+ * Headless Babelbeez voice client.
108
+ *
109
+ * Manages the OpenAI Realtime session lifecycle and exposes a small
110
+ * event-driven API for building custom UIs.
111
+ */
112
+ export class BabelbeezClient {
113
+ constructor(config: BabelbeezClientConfig);
114
+
115
+ /**
116
+ * Initialize the session via /initialize-chat and connect to the
117
+ * OpenAI Realtime API. Safe to call once per session.
118
+ */
119
+ connect(): Promise<void>;
120
+
121
+ /**
122
+ * Gracefully end the session and send /end-chat to the backend.
123
+ * The optional reason is included in the payload.
124
+ */
125
+ disconnect(reason?: string): Promise<void>;
126
+
127
+ /**
128
+ * Optional helper to unlock the AudioContext (e.g. in response to a
129
+ * user gesture) when running in a browser environment.
130
+ */
131
+ initializeAudio(): void;
132
+
133
+ /**
134
+ * Send a text message from the user to the agent. Useful for hybrid
135
+ * text/voice interfaces.
136
+ */
137
+ sendUserText(text: string): Promise<void>;
138
+
139
+ /**
140
+ * Called when the user submits the handoff form in your UI.
141
+ */
142
+ handleHandoffSubmit(payload: BabelbeezHandoffSubmitPayload): Promise<void>;
143
+
144
+ /**
145
+ * Called when the user cancels the handoff form or chooses WhatsApp.
146
+ */
147
+ handleHandoffCancel(options?: BabelbeezHandoffCancelOptions): Promise<void>;
148
+
149
+ /**
150
+ * Subscribe to SDK events. Unknown event names are allowed but will be
151
+ * typed as `any` payloads.
152
+ */
153
+ on<E extends keyof BabelbeezClientEventMap>(
154
+ event: E,
155
+ listener: (payload: BabelbeezClientEventMap[E]) => void,
156
+ ): this;
157
+ on(event: string, listener: (...args: any[]) => void): this;
158
+
159
+ /**
160
+ * Unsubscribe an event listener.
161
+ */
162
+ off<E extends keyof BabelbeezClientEventMap>(
163
+ event: E,
164
+ listener: (payload: BabelbeezClientEventMap[E]) => void,
165
+ ): this;
166
+ off(event: string, listener: (...args: any[]) => void): this;
167
+ }