@floe-ai/sdk 0.1.0-dev.10

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.
@@ -0,0 +1,561 @@
1
+ declare interface ContextData {
2
+ screenshot?: string;
3
+ url: string;
4
+ structure: PageStructure;
5
+ timestamp: number;
6
+ userProfile?: any;
7
+ }
8
+
9
+ declare interface ElementInfo {
10
+ selector: string;
11
+ type: string;
12
+ text?: string;
13
+ visible: boolean;
14
+ position: DOMRect;
15
+ attributes: Record<string, string>;
16
+ }
17
+
18
+ declare class EventEmitter {
19
+ private events;
20
+ on(event: string, listener: (...args: any[]) => void): this;
21
+ off(event: string, listener: (...args: any[]) => void): this;
22
+ emit(event: string, ...args: any[]): boolean;
23
+ }
24
+
25
+ /**
26
+ * Initialize Floe SDK
27
+ * @param config Configuration options
28
+ * @returns SDK instance with a `ready` promise for initialization status
29
+ *
30
+ * @example
31
+ * // Fire and forget (errors logged to console)
32
+ * const sdk = Floe({ clientKey: 'your-key' });
33
+ *
34
+ * @example
35
+ * // Await initialization
36
+ * const sdk = Floe({ clientKey: 'your-key' });
37
+ * await sdk.ready;
38
+ * console.log('SDK initialized!');
39
+ *
40
+ * @example
41
+ * // Handle initialization errors
42
+ * const sdk = Floe({ clientKey: 'your-key' });
43
+ * sdk.ready.catch(err => console.error('Init failed:', err));
44
+ */
45
+ export declare function Floe(config: FloeConfig): FloeSDKInstance;
46
+
47
+ /**
48
+ * Floe SDK Configuration Options
49
+ */
50
+ export declare interface FloeConfig {
51
+ /** Your Floe API client key (required) */
52
+ clientKey: string;
53
+ /** Floe API URL (defaults to production) */
54
+ apiUrl?: string;
55
+ /** Enable screen sharing (default: true) */
56
+ enableScreenCapture?: boolean;
57
+ /** Enable voice interaction (default: true) */
58
+ enableAudio?: boolean;
59
+ /** User's industry for context */
60
+ industry?: string;
61
+ /** User's use case */
62
+ useCase?: string;
63
+ /** User's company name */
64
+ companyName?: string;
65
+ /** Company size */
66
+ companySize?: string;
67
+ /** User's role */
68
+ role?: string;
69
+ /** Enable debug logging */
70
+ debug?: boolean;
71
+ /** User identification for personalization */
72
+ userInfo?: FloeUserInfo;
73
+ /** Skip the welcome modal for returning users */
74
+ skipOnboardingModal?: boolean;
75
+ }
76
+
77
+ /**
78
+ * Extended SDK instance with ready promise
79
+ */
80
+ export declare interface FloeSDKInstance extends OnboardingSDK {
81
+ /** Promise that resolves when SDK is fully initialized */
82
+ ready: Promise<void>;
83
+ }
84
+
85
+ /**
86
+ * User information for personalization
87
+ */
88
+ export declare interface FloeUserInfo {
89
+ externalId?: string;
90
+ email?: string;
91
+ name?: string;
92
+ company?: string;
93
+ designation?: string;
94
+ metadata?: Record<string, any>;
95
+ }
96
+
97
+ /**
98
+ * Main Onboarding SDK
99
+ */
100
+ declare class OnboardingSDK extends EventEmitter {
101
+ private config;
102
+ private sessionId;
103
+ private overlay;
104
+ private capture;
105
+ private actionExecutor;
106
+ private pipecatClient;
107
+ private transport;
108
+ private isInitialized;
109
+ private reactRoot;
110
+ private reactContainer;
111
+ private agentState;
112
+ private pausedSessionId;
113
+ private pendingResumeSessionId;
114
+ private botTranscript;
115
+ private userTranscript;
116
+ private transcriptHistory;
117
+ private lastUserTranscript;
118
+ private isConnected;
119
+ private connectInFlight;
120
+ private micEnabled;
121
+ private userIsSpeaking;
122
+ private botIsSpeaking;
123
+ private audioLevels;
124
+ private _discoveryPopupShown;
125
+ private _pendingDiscoveryStart;
126
+ private botAudioAnalyzer;
127
+ private userAudioAnalyzer;
128
+ private userMicStream;
129
+ private audioElements;
130
+ private pageTracker;
131
+ private screenShareEnabled;
132
+ private domIntrospector;
133
+ private accessibleSnapshot;
134
+ private fastExecutionMode;
135
+ private batchedActionExecutor;
136
+ private navigationCompleteDetector;
137
+ private _botActionDepth;
138
+ private endUserStatus;
139
+ private connectionProgress;
140
+ private isReturningUser;
141
+ private _isMinimized;
142
+ constructor(config: SDKConfig);
143
+ /**
144
+ * Generate unique session ID
145
+ */
146
+ private generateSessionId;
147
+ /**
148
+ * Start screen sharing: sends the tab/window as a WebRTC video track to Pipecat.
149
+ */
150
+ private startScreenShare;
151
+ /**
152
+ * Initialize the SDK and connect to servers
153
+ */
154
+ init(): Promise<void>;
155
+ /**
156
+ * Setup audio playback for bot audio tracks with real-time level analysis.
157
+ * Centralizes all audio element handling, analyzer instantiation, and navigation detector setup.
158
+ * This is the single source of truth for audio/navigation initialization to prevent duplicates.
159
+ */
160
+ private setupAudioPlayback;
161
+ /**
162
+ * Setup user microphone analysis for waveform visualization
163
+ */
164
+ private setupUserMicAnalysis;
165
+ /**
166
+ * Initialize React UI components
167
+ */
168
+ private initReactUI;
169
+ /**
170
+ * Render React UI components
171
+ */
172
+ private renderReactUI;
173
+ /**
174
+ * Handle minimize from UI - keeps widget visible but collapsed
175
+ */
176
+ private handleMinimize;
177
+ /**
178
+ * Handle expand from UI
179
+ */
180
+ private handleExpand;
181
+ /**
182
+ * Update connection progress during connection
183
+ */
184
+ private setConnectionProgress;
185
+ /**
186
+ * Clear connection progress
187
+ */
188
+ private clearConnectionProgress;
189
+ /**
190
+ * Handle connection toggle from UI
191
+ * Now implements minimize behavior instead of full disconnect
192
+ */
193
+ private handleToggleConnection;
194
+ /**
195
+ * Disconnect and minimize the UI (instead of removing it)
196
+ */
197
+ private disconnectAndMinimize;
198
+ /**
199
+ * Connect with progress stages for better UX.
200
+ *
201
+ * NOTE: This method is intended ONLY for post-onboarding reconnects (e.g., when a user
202
+ * clicks the connect button after having already completed the initial onboarding flow).
203
+ * As such, it intentionally skips onboarding checks that are performed in init():
204
+ * - checkEndUserStatus() - not needed for reconnects
205
+ * - shouldSkipOnboardingModal() - onboarding already completed
206
+ * - welcome popup logic - user already onboarded
207
+ *
208
+ * For initial connections, use init() instead, which includes all onboarding logic.
209
+ */
210
+ private connectWithProgress;
211
+ /**
212
+ * Create Pipecat client callbacks (extracted for reuse)
213
+ * Contains the FULL callback logic matching init() to ensure all features work
214
+ */
215
+ private createPipecatCallbacks;
216
+ /**
217
+ * Resume a paused session
218
+ * Always forces a full reconnect since the bot's pipeline was cancelled during pause
219
+ */
220
+ resumeSession(sessionId: string): Promise<void>;
221
+ /**
222
+ * Stop/end a paused session (disconnect and clear paused state)
223
+ */
224
+ stopSession(): Promise<void>;
225
+ /**
226
+ * Handle screen share toggle from UI
227
+ */
228
+ private handleToggleScreenShare;
229
+ /**
230
+ * Send metadata to bot via Pipecat
231
+ * Data should include a 'type' field (e.g., 'click', 'page_metadata', 'form_input')
232
+ */
233
+ sendMetadata(data: any): void;
234
+ /**
235
+ * Send DOM snapshot to server for DOM Introspection Layer
236
+ * Server will use this for accurate element targeting via vision + DOM correlation
237
+ */
238
+ private sendDOMSnapshot;
239
+ /**
240
+ * Send accessible snapshot to server (improved LLM-friendly format)
241
+ *
242
+ * Key improvements over raw DOM snapshot:
243
+ * - Only interactive elements (~90% reduction in noise)
244
+ * - Computed accessible names (W3C accname algorithm)
245
+ * - Semantic roles and states (selected, checked, disabled)
246
+ * - Context awareness (row context, section headings)
247
+ * - Unique refs for easy element identification (B1, C2, T3)
248
+ */
249
+ private sendAccessibleSnapshot;
250
+ /**
251
+ * Handle user input
252
+ */
253
+ private handleUserInput;
254
+ /**
255
+ * Handle server messages from bot (via Pipecat ServerMessage events)
256
+ * Supports both legacy selector-based commands and new hybrid target format
257
+ *
258
+ * Message formats supported:
259
+ * 1. RTVIServerMessageFrame: { data: { type: 'ui_action', action: '...', target: {...} } }
260
+ * 2. Direct ui_action: { type: 'ui_action', action: '...', target: {...} }
261
+ * 3. Direct action: { action: '...', target: {...} }
262
+ * 4. Legacy: { type: 'highlight', selector: '...' }
263
+ */
264
+ private handleServerMessage;
265
+ /**
266
+ * Handle hybrid UI action from bot
267
+ * This is the core handler for the Hybrid UI Action System (HSE)
268
+ *
269
+ * Actions: highlight, click, type, focus, hover, scroll
270
+ */
271
+ private handleHybridAction;
272
+ /**
273
+ * Check a precondition and report the result to the server.
274
+ * Used for conditional task execution (e.g., check if an option exists before selecting it).
275
+ */
276
+ private handleCheckPrecondition;
277
+ /**
278
+ * Handle selecting multiple options from a dropdown.
279
+ * This handles the complex flow of:
280
+ * 1. Opening the dropdown
281
+ * 2. Clicking each value in selectedValues
282
+ * 3. Closing the dropdown
283
+ */
284
+ private handleMultiSelectAction;
285
+ /**
286
+ * Handle clicking a dropdown option when optionText is specified.
287
+ * This handles the complex flow of:
288
+ * 1. Opening the dropdown if not already open
289
+ * 2. Waiting for options to appear
290
+ * 3. Finding and clicking the actual option
291
+ */
292
+ private handleDropdownOptionClick;
293
+ /**
294
+ * Find a visible dropdown option by text
295
+ * Uses STRICT matching to avoid selecting wrong options
296
+ */
297
+ private findVisibleDropdownOption;
298
+ /**
299
+ * Try to scroll within the dropdown to find an option that might be off-screen.
300
+ * Returns the element if found after scrolling, null otherwise.
301
+ */
302
+ private scrollToDropdownOption;
303
+ /**
304
+ * Validate that an element is a valid dropdown element (not SDK UI, visible, clickable)
305
+ *
306
+ * @param el - The element to validate
307
+ * @param requireDropdownAncestor - If true, requires element to have a dropdown-like ancestor (for Strategy 5)
308
+ * @returns true if the element is valid for dropdown interaction
309
+ */
310
+ private isValidDropdownElement;
311
+ /**
312
+ * Find the dropdown trigger element (combobox input or select control)
313
+ *
314
+ * Priority:
315
+ * 1. dropdownTriggerSelector - captured CSS selector for the trigger
316
+ * 2. labelText - find dropdown by its form label (label, div, span, etc.)
317
+ * 3. Find currently open/focused dropdown on page
318
+ * 4. Fallback strategies
319
+ */
320
+ private findDropdownTrigger;
321
+ /**
322
+ * Find dropdown by its label text (searches label, div, span elements)
323
+ * Works with proper <label> elements AND improper div/span "labels"
324
+ */
325
+ private findDropdownByLabel;
326
+ /**
327
+ * Get the clickable container for a dropdown input
328
+ * (The input itself may not be clickable, but its container is)
329
+ */
330
+ private getClickableDropdownContainer;
331
+ /**
332
+ * Click a dropdown option with proper animation and feedback
333
+ */
334
+ private clickDropdownOption;
335
+ /**
336
+ * Find collapsed sidebar container that contains the element
337
+ * Returns the sidebar element if found, null otherwise
338
+ */
339
+ private findCollapsedSidebar;
340
+ /**
341
+ * Execute a single action quickly without cursor animation
342
+ * Used for fast mode where we want minimal visual overhead
343
+ *
344
+ * @param action The hybrid UI action to execute
345
+ * @returns true if action succeeded
346
+ */
347
+ private executeActionFast;
348
+ /**
349
+ * Handle batched navigation request from server
350
+ * Executes multiple navigation steps quickly without LLM round-trips
351
+ */
352
+ private handleBatchedNavigation;
353
+ /**
354
+ * Start navigation complete detection
355
+ * Call this when you want to monitor for page navigation completion
356
+ */
357
+ startNavigationDetection(onComplete: (url: string) => void): void;
358
+ /**
359
+ * Stop navigation complete detection
360
+ */
361
+ stopNavigationDetection(): void;
362
+ /**
363
+ * Check if currently in fast execution mode
364
+ */
365
+ isInFastMode(): boolean;
366
+ /**
367
+ * Extract intent from user input
368
+ */
369
+ private extractIntent;
370
+ /**
371
+ * Capture current context
372
+ */
373
+ captureContext(): Promise<ContextData>;
374
+ /**
375
+ * Extract page structure
376
+ */
377
+ private extractPageStructure;
378
+ /**
379
+ * Get unique selector for element
380
+ */
381
+ private getSelector;
382
+ /**
383
+ * Get element attributes
384
+ */
385
+ private getAttributes;
386
+ /**
387
+ * Public API Methods
388
+ */
389
+ /**
390
+ * Send text message
391
+ */
392
+ sendText(text: string): Promise<void>;
393
+ /**
394
+ * Toggle microphone mute
395
+ */
396
+ toggleMute(): boolean;
397
+ /**
398
+ * Highlight an element
399
+ */
400
+ highlight(selector: string, options?: any): void;
401
+ /**
402
+ * Clear highlights
403
+ */
404
+ clearHighlight(): void;
405
+ /**
406
+ * Show tooltip
407
+ */
408
+ showTooltip(text: string, options?: any): void;
409
+ /**
410
+ * Hide tooltip
411
+ */
412
+ hideTooltip(): void;
413
+ /**
414
+ * Execute an action
415
+ */
416
+ executeAction(action: UIAction): Promise<boolean>;
417
+ /**
418
+ * Take a screenshot
419
+ */
420
+ takeScreenshot(options?: ScreenshotOptions): Promise<string>;
421
+ /**
422
+ * Get session ID
423
+ */
424
+ getSessionId(): string;
425
+ /**
426
+ * Get connection status
427
+ */
428
+ getStatus(): {
429
+ initialized: boolean;
430
+ connected: boolean;
431
+ sessionId: string;
432
+ microphoneMuted: boolean;
433
+ };
434
+ /**
435
+ * Start guided discovery mode.
436
+ *
437
+ * Sends a message to the bot to begin the discovery flow, which will
438
+ * ask structured questions to determine the best onboarding plan for the user.
439
+ *
440
+ * @returns true if the message was sent successfully
441
+ */
442
+ startGuidedDiscovery(): boolean;
443
+ /**
444
+ * Skip discovery and let the user state their goal directly.
445
+ *
446
+ * This closes the welcome popup and lets the bot handle the conversation
447
+ * in the standard greeting flow.
448
+ */
449
+ skipDiscovery(): void;
450
+ /**
451
+ * Show the welcome popup and wait for user choice.
452
+ * Returns a Promise that resolves to true if user wants discovery.
453
+ *
454
+ * Uses Raycast-style dark theme to match other modals.
455
+ */
456
+ showWelcomePopupAsync(): Promise<boolean>;
457
+ /**
458
+ * Show the welcome popup for new users (legacy sync version).
459
+ *
460
+ * Displays a popup with options to start guided discovery or
461
+ * proceed with the standard flow.
462
+ * @deprecated Use showWelcomePopupAsync instead
463
+ */
464
+ showWelcomePopup(): void;
465
+ /**
466
+ * Hide the welcome popup.
467
+ */
468
+ hideWelcomePopup(): void;
469
+ /**
470
+ * Check if discovery mode should be shown for this user.
471
+ *
472
+ * Can be called after connection to determine if the welcome popup
473
+ * should be displayed. Returns true for new users or users who haven't
474
+ * completed onboarding.
475
+ */
476
+ shouldShowDiscoveryPrompt(): boolean;
477
+ /**
478
+ * Check EndUser status from API to determine if onboarding should be skipped.
479
+ * Called during init() if userInfo is provided.
480
+ */
481
+ private checkEndUserStatus;
482
+ /**
483
+ * Get EndUser preferences (for qualification pre-fill).
484
+ * Returns preferences from API if available.
485
+ */
486
+ getEndUserPreferences(): Record<string, any> | null;
487
+ /**
488
+ * Determine if onboarding modal should be skipped.
489
+ * Priority: explicit config > API EndUser.isNewUser > localStorage fallback
490
+ */
491
+ private shouldSkipOnboardingModal;
492
+ /**
493
+ * Mark that the user has visited (used to track new vs returning users).
494
+ */
495
+ markUserVisited(): void;
496
+ /**
497
+ * Mark onboarding as complete.
498
+ */
499
+ markOnboardingComplete(): void;
500
+ /**
501
+ * Disconnect and cleanup
502
+ */
503
+ disconnect(): Promise<void>;
504
+ }
505
+
506
+ declare interface PageStructure {
507
+ title: string;
508
+ url: string;
509
+ elements: ElementInfo[];
510
+ viewport: {
511
+ width: number;
512
+ height: number;
513
+ };
514
+ }
515
+
516
+ declare interface ScreenshotOptions {
517
+ redact?: boolean;
518
+ scale?: number;
519
+ quality?: number;
520
+ format?: 'webp' | 'jpeg' | 'png';
521
+ }
522
+
523
+ declare interface SDKConfig {
524
+ clientKey: string;
525
+ apiUrl?: string;
526
+ enableVideo?: boolean;
527
+ enableAudio?: boolean;
528
+ enableScreenCapture?: boolean;
529
+ redactionPatterns?: Record<string, RegExp>;
530
+ debug?: boolean;
531
+ industry?: string;
532
+ useCase?: string;
533
+ companyName?: string;
534
+ companySize?: string;
535
+ role?: string;
536
+ userInfo?: UserInfo;
537
+ skipOnboardingModal?: boolean;
538
+ enableDiscoveryPopup?: boolean;
539
+ }
540
+
541
+ declare interface UIAction {
542
+ type: 'click' | 'type' | 'select' | 'hover' | 'scroll';
543
+ selector: string;
544
+ value?: string;
545
+ description?: string;
546
+ }
547
+
548
+ /**
549
+ * AI Onboarding Agent SDK
550
+ * Voice-first onboarding platform with WebRTC connectivity to Pipecat server
551
+ */
552
+ declare interface UserInfo {
553
+ externalId?: string;
554
+ email?: string;
555
+ name?: string;
556
+ company?: string;
557
+ designation?: string;
558
+ metadata?: Record<string, any>;
559
+ }
560
+
561
+ export { }
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@floe-ai/sdk",
3
+ "version": "0.1.0-dev.10",
4
+ "description": "Floe AI Onboarding SDK for React applications",
5
+ "type": "module",
6
+ "main": "./dist-sdk/floe-sdk.es.js",
7
+ "module": "./dist-sdk/floe-sdk.es.js",
8
+ "types": "./dist-sdk/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist-sdk/index.d.ts",
12
+ "import": "./dist-sdk/floe-sdk.es.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist-sdk/floe-sdk.es.js",
17
+ "dist-sdk/floe-sdk.es.js.map",
18
+ "dist-sdk/floe-sdk.umd.js",
19
+ "dist-sdk/floe-sdk.umd.js.map",
20
+ "dist-sdk/floe-sdk.iife.js",
21
+ "dist-sdk/floe-sdk.iife.js.map",
22
+ "dist-sdk/index.d.ts",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "scripts": {
30
+ "dev": "vite",
31
+ "build": "tsc && vite build",
32
+ "build:sdk": "vite build --config vite.config.sdk.ts && BUILD_TARGET=cdn vite build --config vite.config.sdk.ts",
33
+ "build:all": "npm run build && npm run build:sdk",
34
+ "preview": "vite preview",
35
+ "serve": "node serve-dist.js",
36
+ "serve:sdk": "vite preview --config vite.config.sdk.ts --port 5174",
37
+ "clean": "rm -rf dist dist-sdk"
38
+ },
39
+ "peerDependencies": {
40
+ "react": "^18.0.0 || ^19.0.0",
41
+ "react-dom": "^18.0.0 || ^19.0.0"
42
+ },
43
+ "dependencies": {
44
+ "@pipecat-ai/client-js": "^1.4.1",
45
+ "@pipecat-ai/client-react": "^1.1.0",
46
+ "@pipecat-ai/daily-transport": "^1.4.1",
47
+ "@pipecat-ai/small-webrtc-transport": "^1.7.0",
48
+ "@pipecat-ai/voice-ui-kit": "^0.4.2"
49
+ },
50
+ "devDependencies": {
51
+ "@types/react": "^18.2.0 || ^19.0.0",
52
+ "@types/react-dom": "^18.2.0 || ^19.0.0",
53
+ "@vitejs/plugin-react": "^4.2.0",
54
+ "cors": "^2.8.5",
55
+ "express": "^5.1.0",
56
+ "patch-package": "^8.0.0",
57
+ "react": "^18.2.0",
58
+ "react-dom": "^18.2.0",
59
+ "typescript": "^5.3.0",
60
+ "vite": "^5.0.0",
61
+ "vite-plugin-dts": "^4.0.0"
62
+ },
63
+ "keywords": [
64
+ "floe",
65
+ "floe-ai",
66
+ "onboarding",
67
+ "sdk",
68
+ "react",
69
+ "ai",
70
+ "voice",
71
+ "pipecat"
72
+ ],
73
+ "license": "SEE LICENSE IN LICENSE"
74
+ }