guideai-app 0.2.5 → 0.2.6
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/GuideAI.js +1 -1
- package/GuideAI.js.map +1 -1
- package/README.md +39 -1
- package/dist/GuideAI.js +1 -1
- package/dist/GuideAI.js.map +1 -1
- package/dist/components/TextInput.d.ts +8 -0
- package/dist/components/TranscriptBox.d.ts +17 -0
- package/dist/index.d.ts +2 -0
- package/dist/metric/event-listner.d.ts +113 -0
- package/dist/metric/index.d.ts +4 -0
- package/dist/metric/metadata-tracker.d.ts +33 -0
- package/dist/styles/GuideAI.styles.d.ts +1 -1
- package/dist/types/GuideAI.types.d.ts +18 -0
- package/dist/types/metadata.types.d.ts +46 -0
- package/dist/utils/api.d.ts +4 -0
- package/dist/utils/messageStorage.d.ts +1 -1
- package/metadata-tracking-example.md +324 -0
- package/package.json +1 -1
- package/text-input-usage.md +321 -0
- package/transcript-toggle-usage.md +267 -0
- package/dist/GuideAI.js.LICENSE.txt +0 -16
- package/dist/components/Styles.d.ts +0 -3
- package/dist/components/Styles.js +0 -6
- package/dist/components/Styles.js.map +0 -1
- package/dist/hooks/useConversation.d.ts +0 -11
- package/dist/hooks/useConversation.js +0 -286
- package/dist/hooks/useConversation.js.map +0 -1
- package/dist/hooks/useRecording.d.ts +0 -12
- package/dist/hooks/useRecording.js +0 -362
- package/dist/hooks/useRecording.js.map +0 -1
- package/dist/index.esm.js +0 -1
- package/dist/index.esm.js.map +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +0 -1
- package/dist/messageStorageUtils.d.ts +0 -26
- package/dist/types/index.d.ts +0 -20
- package/dist/types/index.js +0 -2
- package/dist/types/index.js.map +0 -1
- package/dist/types/workflow.d.ts +0 -24
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/api-services.d.ts +0 -5
- package/dist/utils/api-services.js +0 -203
- package/dist/utils/api-services.js.map +0 -1
- package/dist/utils/dom-interaction.d.ts +0 -2
- package/dist/utils/dom-interaction.js +0 -195
- package/dist/utils/dom-interaction.js.map +0 -1
- package/dist/utils/dom.d.ts +0 -1
- package/dist/utils/messageStorageUtils.d.ts +0 -26
- package/dist/utils/react-hooks.d.ts +0 -9
- package/dist/utils/react-hooks.js +0 -19
- package/dist/utils/react-hooks.js.map +0 -1
- package/dist/utils/storage.d.ts +0 -14
- package/dist/utils/storage.js +0 -27
- package/dist/utils/storage.js.map +0 -1
- package/dist/utils/webrtc.d.ts +0 -3
- package/dist/utils/webrtc.js +0 -135
- package/dist/utils/webrtc.js.map +0 -1
- package/dist/utils/workflowUtils.d.ts +0 -17
- package/dist/utils/workflowValidator.d.ts +0 -17
- package/dist/workflows/certificateWorkflow.d.ts +0 -7
- package/dist/workflows/index.d.ts +0 -6
- package/todo.md +0 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StoredMessage } from '../utils/messageStorage';
|
|
3
|
+
interface TranscriptBoxProps {
|
|
4
|
+
messages: StoredMessage[];
|
|
5
|
+
isVisible: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
showToggleButton?: boolean;
|
|
8
|
+
onToggle?: () => void;
|
|
9
|
+
showTextInput?: boolean;
|
|
10
|
+
textInput?: string;
|
|
11
|
+
onTextInputChange?: (value: string) => void;
|
|
12
|
+
onTextSubmit?: () => void;
|
|
13
|
+
onTextKeyPress?: (event: React.KeyboardEvent) => void;
|
|
14
|
+
textPlaceholder?: string;
|
|
15
|
+
}
|
|
16
|
+
declare const TranscriptBox: React.FC<TranscriptBoxProps>;
|
|
17
|
+
export default TranscriptBox;
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
interface EventData {
|
|
2
|
+
type: 'click' | 'focus' | 'change' | 'submit' | 'route_change';
|
|
3
|
+
element?: Element;
|
|
4
|
+
tagName?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
textContent?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
formData?: FormData;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
url: string;
|
|
12
|
+
previousUrl?: string;
|
|
13
|
+
event?: Event;
|
|
14
|
+
customerId?: string;
|
|
15
|
+
customerType?: string;
|
|
16
|
+
customerSegment?: string;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
deviceType?: 'desktop' | 'mobile' | 'tablet';
|
|
19
|
+
userAgent?: string;
|
|
20
|
+
screenResolution?: string;
|
|
21
|
+
currentPage?: string;
|
|
22
|
+
userRole?: string;
|
|
23
|
+
organizationId?: string;
|
|
24
|
+
timezone?: string;
|
|
25
|
+
locale?: string;
|
|
26
|
+
}
|
|
27
|
+
declare class EventTracker {
|
|
28
|
+
private isTracking;
|
|
29
|
+
private eventData;
|
|
30
|
+
private batchSize;
|
|
31
|
+
private batchTimeout;
|
|
32
|
+
private batchTimer;
|
|
33
|
+
private pendingEvents;
|
|
34
|
+
private currentUrl;
|
|
35
|
+
private organizationKey?;
|
|
36
|
+
private customerMetadata;
|
|
37
|
+
constructor(options?: {
|
|
38
|
+
customerId?: string;
|
|
39
|
+
customerType?: string;
|
|
40
|
+
organizationId?: string;
|
|
41
|
+
organizationKey?: string;
|
|
42
|
+
});
|
|
43
|
+
setCustomerMetadata(metadata: Partial<typeof this.customerMetadata>): void;
|
|
44
|
+
getCustomerMetadata(): typeof this.customerMetadata;
|
|
45
|
+
clearCustomerMetadata(): void;
|
|
46
|
+
initialize(): void;
|
|
47
|
+
private enrichEventData;
|
|
48
|
+
private getSessionId;
|
|
49
|
+
private getDeviceType;
|
|
50
|
+
startTracking(): void;
|
|
51
|
+
stopTracking(): void;
|
|
52
|
+
private trackClickEvents;
|
|
53
|
+
private trackFocusEvents;
|
|
54
|
+
private trackChangeEvents;
|
|
55
|
+
private trackSubmitEvents;
|
|
56
|
+
private trackRouteChanges;
|
|
57
|
+
private handleClick;
|
|
58
|
+
private handleFocus;
|
|
59
|
+
private handleChange;
|
|
60
|
+
private handleSubmit;
|
|
61
|
+
private handlePopstate;
|
|
62
|
+
private handleHashChange;
|
|
63
|
+
private interceptHistoryAPI;
|
|
64
|
+
private getPreviousUrl;
|
|
65
|
+
private getSafeValue;
|
|
66
|
+
private isFocusable;
|
|
67
|
+
private isFormElement;
|
|
68
|
+
private logEvent;
|
|
69
|
+
private startBatchTimer;
|
|
70
|
+
private emitBatch;
|
|
71
|
+
getEventData(): EventData[];
|
|
72
|
+
clearEventData(): void;
|
|
73
|
+
getEventDataByType(type: EventData['type']): EventData[];
|
|
74
|
+
getEventDataByElement(tagName: string): EventData[];
|
|
75
|
+
getEventDataByUrl(url: string): EventData[];
|
|
76
|
+
emitPendingEvents(): void;
|
|
77
|
+
setBatchConfig(batchSize: number, batchTimeout: number): void;
|
|
78
|
+
getPendingEventsCount(): number;
|
|
79
|
+
getCustomerAnalytics(): {
|
|
80
|
+
totalEvents: number;
|
|
81
|
+
eventsByCustomer: Record<string, number>;
|
|
82
|
+
eventsByType: Record<string, number>;
|
|
83
|
+
eventsByPage: Record<string, number>;
|
|
84
|
+
eventsByDevice: Record<string, number>;
|
|
85
|
+
sessionDuration: number;
|
|
86
|
+
lastActivity: number;
|
|
87
|
+
};
|
|
88
|
+
private getSessionStartTime;
|
|
89
|
+
identifyCustomerFromContext(): void;
|
|
90
|
+
setCustomerFromAuth(authData: {
|
|
91
|
+
id?: string;
|
|
92
|
+
role?: string;
|
|
93
|
+
customerType?: 'individual' | 'business' | 'agent' | 'admin';
|
|
94
|
+
customerSegment?: string;
|
|
95
|
+
}): void;
|
|
96
|
+
}
|
|
97
|
+
export default EventTracker;
|
|
98
|
+
export type { EventData };
|
|
99
|
+
export interface CustomerMetadata {
|
|
100
|
+
customerId?: string;
|
|
101
|
+
customerType?: 'individual' | 'business' | 'agent' | 'admin';
|
|
102
|
+
customerSegment?: string;
|
|
103
|
+
userRole?: string;
|
|
104
|
+
}
|
|
105
|
+
export interface CustomerAnalytics {
|
|
106
|
+
totalEvents: number;
|
|
107
|
+
eventsByCustomer: Record<string, number>;
|
|
108
|
+
eventsByType: Record<string, number>;
|
|
109
|
+
eventsByPage: Record<string, number>;
|
|
110
|
+
eventsByDevice: Record<string, number>;
|
|
111
|
+
sessionDuration: number;
|
|
112
|
+
lastActivity: number;
|
|
113
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { UserMetadata, MetadataConfig, MetadataUpdate } from '../types/metadata.types';
|
|
2
|
+
declare class UserMetadataTracker {
|
|
3
|
+
private config;
|
|
4
|
+
private metadata;
|
|
5
|
+
private syncTimer;
|
|
6
|
+
private pendingUpdates;
|
|
7
|
+
private isInitialized;
|
|
8
|
+
private onError?;
|
|
9
|
+
constructor(organizationKey: string, config?: MetadataConfig, onError?: (error: Error, context: string) => void);
|
|
10
|
+
private init;
|
|
11
|
+
updateUserInfo(userInfo: Partial<UserMetadata>): void;
|
|
12
|
+
trackLogin(additionalInfo?: Partial<UserMetadata>): void;
|
|
13
|
+
trackVisit(): void;
|
|
14
|
+
trackCustomEvent(eventType: string, customData: Record<string, any>): void;
|
|
15
|
+
getMetadata(): UserMetadata;
|
|
16
|
+
getPendingUpdates(): MetadataUpdate[];
|
|
17
|
+
clearPendingUpdates(): void;
|
|
18
|
+
syncNow(): MetadataUpdate[];
|
|
19
|
+
private loadMetadata;
|
|
20
|
+
private saveMetadata;
|
|
21
|
+
private collectBrowserInfo;
|
|
22
|
+
private parseBrowserInfo;
|
|
23
|
+
private startSyncTimer;
|
|
24
|
+
private setupEventTrackerIntegration;
|
|
25
|
+
private stopSyncTimer;
|
|
26
|
+
private emitPendingUpdates;
|
|
27
|
+
private getFromStorage;
|
|
28
|
+
private setToStorage;
|
|
29
|
+
private clearStorage;
|
|
30
|
+
destroy(): void;
|
|
31
|
+
}
|
|
32
|
+
export default UserMetadataTracker;
|
|
33
|
+
export type { UserMetadata, MetadataConfig, MetadataUpdate };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const guideAIStyles = "\n.sarge-main-ui {\n position: relative;\n}\n\n.sarge-welcome-bubble {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: #0066ff;\n color: white;\n padding: 10px 16px;\n border-radius: 20px;\n font-size: 14px;\n white-space: normal;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n animation: bubble-pulse 2s infinite;\n max-width: 280px;\n min-width: 200px;\n text-align: center;\n line-height: 1.3;\n}\n\n.sarge-welcome-bubble.above {\n bottom: calc(100% + 10px);\n}\n\n.sarge-welcome-bubble.below {\n top: calc(100% + 10px);\n}\n\n.sarge-welcome-bubble.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid #0066ff;\n}\n\n.sarge-welcome-bubble.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #0066ff;\n}\n\n@keyframes bubble-pulse {\n 0% { transform: translateX(-50%) scale(1); }\n 50% { transform: translateX(-50%) scale(1.05); }\n 100% { transform: translateX(-50%) scale(1); }\n}\n\n.sarge-icon-wrapper {\n width: 100%;\n height: 100%;\n min-width: 30px;\n min-height: 30px;\n max-width: 60px;\n max-height: 60px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255, 0.9);\n border-radius: 50%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sarge-icon-wrapper:not(.initializing):hover {\n transform: scale(1.1);\n}\n\n.sarge-icon-wrapper.initializing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(128, 128, 128, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: sarge-spin 1.5s linear infinite;\n opacity: 0.7;\n cursor: default;\n}\n\n.sarge-icon-wrapper.recording {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: sarge-pulse 1s infinite alternate;\n}\n\n.sarge-icon-wrapper.processing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 165, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: sarge-spin 1s linear infinite;\n}\n\n.sarge-icon-wrapper.playing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(0, 128, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n@keyframes sarge-pulse {\n 0% { transform: scale(1); }\n 100% { transform: scale(1.05); }\n}\n\n@keyframes sarge-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes click-ripple-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.6; }\n 100% { transform: translate(-50%, -50%) scale(2.5); opacity: 0; }\n}\n\n@keyframes click-dot-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 60% { transform: translate(-50%, -50%) scale(1); opacity: 1; }\n 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }\n}\n\n@keyframes cursor-jiggle {\n 0% { transform: translate(-50%, 0) scale(1); }\n 25% { transform: translate(-50%, -5px) scale(1.1); }\n 50% { transform: translate(-50%, 0) scale(1); }\n 75% { transform: translate(-50%, 5px) scale(1.1); }\n 100% { transform: translate(-50%, 0) scale(1); filter: drop-shadow(0 0 8px #0066ff); }\n}\n\n.sarge-icon {\n width: 60%;\n height: 60%;\n min-width: 16px;\n min-height: 16px;\n max-width: 40px;\n max-height: 40px;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n.sarge-icon.initializing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23808080\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.sarge-icon.microphone {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%230000FF\" d=\"M176 352c53.02 0 96-42.98 96-96V96c0-53.02-42.98-96-96-96S80 42.98 80 96v160c0 53.02 42.98 96 96 96zm160-160h-16c-8.84 0-16 7.16-16 16v48c0 74.8-64.49 134.82-140.79 127.38C96.71 376.89 48 317.11 48 250.3V208c0-8.84-7.16-16-16-16H16c-8.84 0-16 7.16-16 16v40.16c0 89.64 63.97 169.55 152 181.69V464H96c-8.84 0-16 7.16-16 16v16c0 8.84 7.16 16 16 16h160c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16h-56v-33.77C285.71 418.47 352 344.9 352 256v-48c0-8.84-7.16-16-16-16z\"/></svg>');\n}\n\n.sarge-icon.recording {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><circle cx=\"256\" cy=\"256\" r=\"128\" fill=\"%23FF0000\"/><circle cx=\"256\" cy=\"256\" r=\"200\" stroke=\"%23FF0000\" stroke-width=\"20\" fill=\"none\"/></svg>');\n}\n\n.sarge-icon.processing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23FFA500\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.sarge-icon.playing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%23008000\" d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>');\n}\n\n/* Onboarding styles */\n.sarge-onboarding {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n width: 300px;\n max-width: 90vw;\n z-index: 1002;\n animation: onboarding-fade-in 0.3s ease-out;\n}\n\n.sarge-onboarding.above {\n bottom: calc(100% + 15px);\n}\n\n.sarge-onboarding.below {\n top: calc(100% + 15px);\n}\n\n.sarge-onboarding.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid white;\n filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));\n}\n\n.sarge-onboarding.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid white;\n filter: drop-shadow(0 -2px 4px rgba(0, 0, 0, 0.1));\n}\n\n@keyframes onboarding-fade-in {\n from { opacity: 0; transform: translateX(-50%) translateY(-10px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n}\n\n.sarge-onboarding-content {\n padding: 16px;\n position: relative;\n}\n\n.sarge-onboarding-close {\n position: absolute;\n top: 10px;\n right: 10px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #999;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n}\n\n.sarge-onboarding-close:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.sarge-onboarding-step {\n text-align: center;\n margin-bottom: 12px;\n}\n\n.sarge-onboarding-icon {\n font-size: 32px;\n margin-bottom: 8px;\n display: inline-block;\n}\n\n.sarge-onboarding-step h3 {\n margin: 0 0 8px;\n font-size: 16px;\n color: #333;\n font-weight: 600;\n}\n\n.sarge-onboarding-step p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n}\n\n.sarge-onboarding-dots {\n display: flex;\n justify-content: center;\n margin: 12px 0;\n}\n\n.sarge-onboarding-dots .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #ddd;\n margin: 0 4px;\n transition: all 0.3s ease;\n}\n\n.sarge-onboarding-dots .dot.active {\n background: #0066ff;\n transform: scale(1.2);\n}\n\n.sarge-onboarding-next {\n display: block;\n width: 100%;\n padding: 10px;\n background: #0066ff;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.sarge-onboarding-next:hover {\n background: #0055cc;\n}\n";
|
|
1
|
+
export declare const guideAIStyles = "\n.guideai-main-ui {\n position: relative;\n}\n\n.guideai-welcome-bubble {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: #0066ff;\n color: white;\n padding: 10px 16px;\n border-radius: 20px;\n font-size: 14px;\n white-space: normal;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n animation: bubble-pulse 2s infinite;\n max-width: 280px;\n min-width: 200px;\n text-align: center;\n line-height: 1.3;\n}\n\n.guideai-welcome-bubble.above {\n bottom: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.below {\n top: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid #0066ff;\n}\n\n.guideai-welcome-bubble.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #0066ff;\n}\n\n@keyframes bubble-pulse {\n 0% { transform: translateX(-50%) scale(1); }\n 50% { transform: translateX(-50%) scale(1.05); }\n 100% { transform: translateX(-50%) scale(1); }\n}\n\n.guideai-icon-wrapper {\n width: 50px;\n height: 50px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255, 0.9);\n border: 2px solid transparent;\n border-radius: 50%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.guideai-icon-wrapper:not(.initializing):hover {\n transform: scale(1.1);\n}\n\n.guideai-icon-wrapper.initializing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(128, 128, 128, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-spin 1.5s linear infinite;\n opacity: 0.7;\n cursor: default;\n}\n\n.guideai-icon-wrapper.recording {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-pulse 1s infinite alternate;\n}\n\n.guideai-icon-wrapper.processing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 165, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-spin 1s linear infinite;\n}\n\n.guideai-icon-wrapper.playing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(0, 128, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n@keyframes guideai-pulse {\n 0% { transform: scale(1); }\n 100% { transform: scale(1.05); }\n}\n\n@keyframes guideai-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes click-ripple-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.6; }\n 100% { transform: translate(-50%, -50%) scale(2.5); opacity: 0; }\n}\n\n@keyframes click-dot-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 60% { transform: translate(-50%, -50%) scale(1); opacity: 1; }\n 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }\n}\n\n@keyframes cursor-jiggle {\n 0% { transform: translate(-50%, 0) scale(1); }\n 25% { transform: translate(-50%, -5px) scale(1.1); }\n 50% { transform: translate(-50%, 0) scale(1); }\n 75% { transform: translate(-50%, 5px) scale(1.1); }\n 100% { transform: translate(-50%, 0) scale(1); filter: drop-shadow(0 0 8px #0066ff); }\n}\n\n.guideai-icon {\n width: 60%;\n height: 60%;\n min-width: 16px;\n min-height: 16px;\n max-width: 40px;\n max-height: 40px;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n.guideai-icon.initializing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23808080\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.guideai-icon.microphone {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%230000FF\" d=\"M176 352c53.02 0 96-42.98 96-96V96c0-53.02-42.98-96-96-96S80 42.98 80 96v160c0 53.02 42.98 96 96 96zm160-160h-16c-8.84 0-16 7.16-16 16v48c0 74.8-64.49 134.82-140.79 127.38C96.71 376.89 48 317.11 48 250.3V208c0-8.84-7.16-16-16-16H16c-8.84 0-16 7.16-16 16v40.16c0 89.64 63.97 169.55 152 181.69V464H96c-8.84 0-16 7.16-16 16v16c0 8.84 7.16 16 16 16h160c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16h-56v-33.77C285.71 418.47 352 344.9 352 256v-48c0-8.84-7.16-16-16-16z\"/></svg>');\n}\n\n.guideai-icon.recording {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><circle cx=\"256\" cy=\"256\" r=\"128\" fill=\"%23FF0000\"/><circle cx=\"256\" cy=\"256\" r=\"200\" stroke=\"%23FF0000\" stroke-width=\"20\" fill=\"none\"/></svg>');\n}\n\n.guideai-icon.processing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23FFA500\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.guideai-icon.playing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%23008000\" d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>');\n}\n\n/* Onboarding styles */\n.guideai-onboarding {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n width: 300px;\n max-width: 90vw;\n z-index: 1002;\n animation: onboarding-fade-in 0.3s ease-out;\n}\n\n.guideai-onboarding.above {\n bottom: calc(100% + 15px);\n}\n\n.guideai-onboarding.below {\n top: calc(100% + 15px);\n}\n\n.guideai-onboarding.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid white;\n filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));\n}\n\n.guideai-onboarding.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid white;\n filter: drop-shadow(0 -2px 4px rgba(0, 0, 0, 0.1));\n}\n\n@keyframes onboarding-fade-in {\n from { opacity: 0; transform: translateX(-50%) translateY(-10px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n}\n\n.guideai-onboarding-content {\n padding: 16px;\n position: relative;\n}\n\n.guideai-onboarding-close {\n position: absolute;\n top: 10px;\n right: 10px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #999;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n}\n\n.guideai-onboarding-close:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.guideai-onboarding-step {\n text-align: center;\n margin-bottom: 12px;\n}\n\n.guideai-onboarding-icon {\n font-size: 32px;\n margin-bottom: 8px;\n display: inline-block;\n}\n\n.guideai-onboarding-step h3 {\n margin: 0 0 8px;\n font-size: 16px;\n color: #333;\n font-weight: 600;\n}\n\n.guideai-onboarding-step p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n}\n\n.guideai-onboarding-dots {\n display: flex;\n justify-content: center;\n margin: 12px 0;\n}\n\n.guideai-onboarding-dots .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #ddd;\n margin: 0 4px;\n transition: all 0.3s ease;\n}\n\n.guideai-onboarding-dots .dot.active {\n background: #0066ff;\n transform: scale(1.2);\n}\n\n.guideai-onboarding-next {\n display: block;\n width: 100%;\n padding: 10px;\n background: #0066ff;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.guideai-onboarding-next:hover {\n background: #0055cc;\n}\n\n/* Transcript Box Styles */\n.guideai-transcript-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: transparent;\n display: flex;\n justify-content: flex-end;\n align-items: flex-end;\n padding-bottom: 40px;\n padding-right: 40px;\n z-index: 10000;\n animation: transcript-fade-in 0.3s ease-out;\n pointer-events: none;\n}\n\n.guideai-transcript-box {\n background: rgba(40, 44, 52, 0.85);\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 16px;\n box-shadow: \n 0 8px 32px rgba(0, 0, 0, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n inset 0 -1px 0 rgba(0, 0, 0, 0.1);\n width: 280px;\n max-height: 280px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: transcript-slide-up 0.4s ease-out;\n pointer-events: auto;\n margin-right: 60px;\n position: relative;\n}\n\n.guideai-transcript-box::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);\n border-radius: 16px 16px 0 0;\n}\n\n\n\n.guideai-transcript-messages {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n max-height: 200px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar {\n width: 6px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-track {\n background: rgba(0, 0, 0, 0.05);\n border-radius: 3px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.3);\n}\n\n.guideai-transcript-empty {\n text-align: center;\n padding: 20px 12px;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-empty-icon {\n font-size: 24px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n.guideai-transcript-empty p {\n margin: 0;\n font-size: 11px;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-message {\n margin-bottom: 8px;\n animation: message-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-message.human {\n text-align: right;\n}\n\n.guideai-transcript-message.guideai {\n text-align: left;\n}\n\n.guideai-transcript-message-content {\n display: inline-block;\n max-width: 85%;\n padding: 6px 10px;\n border-radius: 12px;\n position: relative;\n}\n\n.guideai-transcript-message.human .guideai-transcript-message-content {\n background: rgba(255, 255, 255, 0.15);\n color: rgba(255, 255, 255, 0.95);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-bottom-right-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.guideai-transcript-message.guideai .guideai-transcript-message-content {\n background: rgba(0, 0, 0, 0.1);\n color: rgba(255, 255, 255, 0.9);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-bottom-left-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.guideai-transcript-message-sender {\n font-size: 9px;\n font-weight: 600;\n margin-bottom: 2px;\n opacity: 0.8;\n}\n\n.guideai-transcript-message-text {\n font-size: 11px;\n line-height: 1.3;\n word-wrap: break-word;\n}\n\n.guideai-transcript-message-time {\n font-size: 8px;\n opacity: 0.6;\n margin-top: 2px;\n}\n\n\n\n@keyframes transcript-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes transcript-slide-up {\n from { \n opacity: 0; \n transform: translateX(40px) scale(0.95); \n }\n to { \n opacity: 1; \n transform: translateX(0) scale(1); \n }\n}\n\n@keyframes message-fade-in {\n from { \n opacity: 0; \n transform: translateY(10px); \n }\n to { \n opacity: 1; \n transform: translateY(0); \n }\n}\n\n/* Transcript Toggle Button Styles - positioned at top of transcript area */\n.guideai-transcript-toggle-button {\n position: fixed;\n bottom: 60px;\n right: 40px;\n width: 36px;\n height: 36px;\n background: rgba(40, 44, 52, 0.9);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.15);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n transition: all 0.2s ease;\n z-index: 10001;\n font-size: 14px;\n padding: 0;\n color: rgba(255, 255, 255, 0.9);\n animation: toggle-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-toggle-button:hover {\n background: rgba(40, 44, 52, 1);\n transform: scale(1.1);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);\n}\n\n.guideai-transcript-toggle-button:active {\n transform: scale(0.95);\n}\n\n.guideai-transcript-toggle-icon {\n display: inline-block;\n transition: all 0.2s ease;\n filter: none;\n}\n\n/* Position transcript toggle button based on transcript position */\n.guideai-transcript-overlay {\n pointer-events: none;\n}\n\n.guideai-transcript-toggle-button {\n pointer-events: auto;\n}\n\n/* Input Options Container - Two Stage Layout */\n.guideai-input-options {\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n animation: options-slide-in 0.4s ease-out;\n}\n\n@keyframes options-slide-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Individual Input Option Button */\n.guideai-input-option {\n width: 50px;\n height: 50px;\n background: rgba(255, 255, 255, 0.9);\n border: 2px solid rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n font-size: 18px;\n padding: 0;\n position: relative;\n}\n\n.guideai-input-option:hover:not(:disabled) {\n background: rgba(255, 255, 255, 1);\n transform: scale(1.1);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n}\n\n.guideai-input-option:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.guideai-input-option:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Voice Option Specific Styling */\n.guideai-input-option.voice-option {\n background: linear-gradient(135deg, rgba(76, 175, 80, 0.1), rgba(139, 195, 74, 0.1));\n border-color: rgba(76, 175, 80, 0.3);\n}\n\n.guideai-input-option.voice-option:hover:not(:disabled) {\n background: linear-gradient(135deg, rgba(76, 175, 80, 0.2), rgba(139, 195, 74, 0.2));\n border-color: rgba(76, 175, 80, 0.5);\n}\n\n/* Text Option Specific Styling */\n.guideai-input-option.text-option {\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.1), rgba(63, 81, 181, 0.1));\n border-color: rgba(33, 150, 243, 0.3);\n}\n\n.guideai-input-option.text-option:hover:not(:disabled) {\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.2), rgba(63, 81, 181, 0.2));\n border-color: rgba(33, 150, 243, 0.5);\n}\n\n.guideai-input-option-icon {\n display: inline-block;\n transition: all 0.2s ease;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));\n}\n\n/* Text Input integrated into Transcript Box */\n.guideai-transcript-text-input {\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n padding: 12px;\n display: flex;\n gap: 8px;\n align-items: flex-end;\n background: rgba(0, 0, 0, 0.02);\n border-radius: 0 0 16px 16px;\n animation: text-input-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-input-field {\n flex: 1;\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n padding: 8px 12px;\n color: rgba(255, 255, 255, 0.95);\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n resize: none;\n outline: none;\n transition: all 0.2s ease;\n min-height: 32px;\n}\n\n.guideai-transcript-input-field::placeholder {\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-input-field:focus {\n border-color: rgba(255, 255, 255, 0.4);\n background: rgba(255, 255, 255, 0.2);\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2);\n}\n\n.guideai-transcript-send-button {\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 6px;\n padding: 6px 10px;\n color: rgba(255, 255, 255, 0.9);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 36px;\n height: 32px;\n}\n\n.guideai-transcript-send-button:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.3);\n transform: translateY(-1px);\n}\n\n.guideai-transcript-send-button:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.guideai-transcript-send-button:disabled {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.4);\n cursor: not-allowed;\n transform: none;\n}\n\n.guideai-transcript-send-icon {\n font-size: 11px;\n}\n\n/* Animation for text input appearance */\n@keyframes text-input-fade-in {\n from { \n opacity: 0; \n transform: translateY(10px); \n }\n to { \n opacity: 1; \n transform: translateY(0); \n }\n}\n\n@keyframes toggle-fade-in {\n from { \n opacity: 0; \n transform: scale(0.8); \n }\n to { \n opacity: 1; \n transform: scale(1); \n }\n}\n\n\n";
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { MetadataConfig, UserMetadata } from './metadata.types';
|
|
2
3
|
export type RecordingStatus = 'idle' | 'recording' | 'processing' | 'playing';
|
|
3
4
|
export type UseStateHook = typeof React.useState;
|
|
4
5
|
export type UseEffectHook = typeof React.useEffect;
|
|
5
6
|
export type UseRefHook = typeof React.useRef;
|
|
7
|
+
export type UseCallbackHook = typeof React.useCallback;
|
|
6
8
|
export interface GuideAIProps {
|
|
7
9
|
organizationKey: string;
|
|
8
10
|
position?: {
|
|
@@ -17,5 +19,21 @@ export interface GuideAIProps {
|
|
|
17
19
|
transform?: string;
|
|
18
20
|
};
|
|
19
21
|
onError?: (error: string | Error, context?: string) => void;
|
|
22
|
+
metadata?: {
|
|
23
|
+
config?: MetadataConfig;
|
|
24
|
+
initialUserData?: Partial<UserMetadata>;
|
|
25
|
+
onMetadataUpdate?: (metadata: UserMetadata) => void;
|
|
26
|
+
};
|
|
27
|
+
transcript?: {
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
showToggleButton?: boolean;
|
|
30
|
+
position?: 'right' | 'left' | 'top' | 'bottom';
|
|
31
|
+
};
|
|
32
|
+
input?: {
|
|
33
|
+
enableTextInput?: boolean;
|
|
34
|
+
showInputToggle?: boolean;
|
|
35
|
+
defaultMode?: 'voice' | 'text';
|
|
36
|
+
placeholder?: string;
|
|
37
|
+
};
|
|
20
38
|
}
|
|
21
39
|
export type PopupPosition = 'above' | 'below';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface UserMetadata {
|
|
2
|
+
userId?: string;
|
|
3
|
+
userType?: 'agent' | 'admin' | 'manager' | 'customer' | 'guest' | string;
|
|
4
|
+
customerType?: 'individual' | 'business' | 'enterprise' | string;
|
|
5
|
+
customerLicense?: string;
|
|
6
|
+
firstVisit?: number;
|
|
7
|
+
lastVisit?: number;
|
|
8
|
+
visitCount?: number;
|
|
9
|
+
loginCount?: number;
|
|
10
|
+
lastLogin?: number;
|
|
11
|
+
organizationKey: string;
|
|
12
|
+
sessionId?: string;
|
|
13
|
+
userAgent?: string;
|
|
14
|
+
browserInfo?: {
|
|
15
|
+
name?: string;
|
|
16
|
+
version?: string;
|
|
17
|
+
platform?: string;
|
|
18
|
+
};
|
|
19
|
+
customFields?: Record<string, string | number | boolean>;
|
|
20
|
+
}
|
|
21
|
+
export interface MetadataUpdate {
|
|
22
|
+
type: 'visit' | 'login' | 'user_info' | 'session' | 'custom';
|
|
23
|
+
timestamp: number;
|
|
24
|
+
data: Partial<UserMetadata>;
|
|
25
|
+
}
|
|
26
|
+
export interface MetadataConfig {
|
|
27
|
+
trackVisits?: boolean;
|
|
28
|
+
trackLogins?: boolean;
|
|
29
|
+
syncInterval?: number;
|
|
30
|
+
storage?: 'localStorage' | 'sessionStorage' | 'memory';
|
|
31
|
+
customFields?: string[];
|
|
32
|
+
collectBrowserInfo?: boolean;
|
|
33
|
+
collectUserAgent?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface MetadataStorageData {
|
|
36
|
+
metadata: UserMetadata;
|
|
37
|
+
lastUpdated: number;
|
|
38
|
+
version: string;
|
|
39
|
+
}
|
|
40
|
+
export type MetadataEventType = 'user_visit' | 'user_login' | 'user_info_update' | 'session_start' | 'session_end' | 'custom_event';
|
|
41
|
+
export interface MetadataEvent {
|
|
42
|
+
type: MetadataEventType;
|
|
43
|
+
timestamp: number;
|
|
44
|
+
metadata: Partial<UserMetadata>;
|
|
45
|
+
source?: string;
|
|
46
|
+
}
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UserMetadata, MetadataUpdate } from '../types/metadata.types';
|
|
1
2
|
interface ConversationData {
|
|
2
3
|
id: string;
|
|
3
4
|
ephemeralToken: string;
|
|
@@ -5,4 +6,7 @@ interface ConversationData {
|
|
|
5
6
|
}
|
|
6
7
|
export declare const createNewConversation: (organizationKey: string, onError: (error: Error, context: string) => void) => Promise<ConversationData | null>;
|
|
7
8
|
export declare const logMessage: (content: string, sender: "GUIDEAI" | "HUMAN", conversationId: string | null, organizationKey: string, onError: (error: Error, context: string) => void) => Promise<void>;
|
|
9
|
+
export declare const sendUserMetadata: (metadata: UserMetadata, organizationKey: string, onError: (error: Error, context: string) => void) => Promise<boolean>;
|
|
10
|
+
export declare const sendMetadataUpdates: (updates: MetadataUpdate[], organizationKey: string, onError: (error: Error, context: string) => void) => Promise<boolean>;
|
|
11
|
+
export declare const updateUserMetadata: (userId: string, metadataUpdate: Partial<UserMetadata>, organizationKey: string, onError: (error: Error, context: string) => void) => Promise<boolean>;
|
|
8
12
|
export {};
|
|
@@ -11,7 +11,7 @@ export interface StoredConversation {
|
|
|
11
11
|
}
|
|
12
12
|
export declare const CONVERSATION_STORAGE_KEY = "guideai_conversation";
|
|
13
13
|
export declare const CONVERSATION_EXPIRY_MINUTES = 30;
|
|
14
|
-
export declare const MAX_STORED_MESSAGES =
|
|
14
|
+
export declare const MAX_STORED_MESSAGES = 100;
|
|
15
15
|
export declare const isLocalStorageAvailable: () => boolean;
|
|
16
16
|
export declare const isConversationExpired: (conversation: StoredConversation) => boolean;
|
|
17
17
|
export declare const saveConversationToStorage: (conversation: StoredConversation) => void;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# User Metadata Tracking - Implementation Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The GuideAI package now includes comprehensive user metadata tracking capabilities designed for integration with Overproof. This system tracks the following metadata:
|
|
6
|
+
|
|
7
|
+
- **User's First Visit** - Timestamp of the first time the user interacted with GuideAI
|
|
8
|
+
- **User's Last Visit** - Timestamp of the most recent user interaction
|
|
9
|
+
- **User Logins** - Count and timestamp of login events
|
|
10
|
+
- **User Type** - Classification of the user (agent, admin, manager, customer, guest, etc.)
|
|
11
|
+
- **Customer Type** - Type of customer (individual, business, enterprise, etc.)
|
|
12
|
+
- **Customer License** - License identifier for the customer
|
|
13
|
+
|
|
14
|
+
## Basic Usage
|
|
15
|
+
|
|
16
|
+
### 1. Basic Integration
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { GuideAI } from 'guide-ai-package';
|
|
20
|
+
|
|
21
|
+
function App() {
|
|
22
|
+
return (
|
|
23
|
+
<GuideAI
|
|
24
|
+
organizationKey="your-org-key"
|
|
25
|
+
metadata={{
|
|
26
|
+
config: {
|
|
27
|
+
trackVisits: true,
|
|
28
|
+
trackLogins: true,
|
|
29
|
+
syncInterval: 30000, // Sync every 30 seconds
|
|
30
|
+
storage: 'localStorage'
|
|
31
|
+
},
|
|
32
|
+
initialUserData: {
|
|
33
|
+
userType: 'agent',
|
|
34
|
+
customerType: 'business',
|
|
35
|
+
customerLicense: 'OVERPRF-12345'
|
|
36
|
+
},
|
|
37
|
+
onMetadataUpdate: (metadata) => {
|
|
38
|
+
console.log('Metadata updated:', metadata);
|
|
39
|
+
// Send to your analytics system
|
|
40
|
+
}
|
|
41
|
+
}}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Tracking User Login Events
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { useRef } from 'react';
|
|
51
|
+
|
|
52
|
+
function LoginComponent() {
|
|
53
|
+
const guideAIRef = useRef();
|
|
54
|
+
|
|
55
|
+
const handleLogin = async (userInfo) => {
|
|
56
|
+
// Your login logic here
|
|
57
|
+
const loginResult = await performLogin(userInfo);
|
|
58
|
+
|
|
59
|
+
if (loginResult.success) {
|
|
60
|
+
// Track the login with GuideAI
|
|
61
|
+
guideAIRef.current?.trackLogin({
|
|
62
|
+
userId: loginResult.userId,
|
|
63
|
+
userType: loginResult.userType,
|
|
64
|
+
customerType: loginResult.customerType,
|
|
65
|
+
customerLicense: loginResult.license
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<GuideAI
|
|
73
|
+
ref={guideAIRef}
|
|
74
|
+
organizationKey="your-org-key"
|
|
75
|
+
metadata={{
|
|
76
|
+
config: { trackLogins: true }
|
|
77
|
+
}}
|
|
78
|
+
/>
|
|
79
|
+
<button onClick={handleLogin}>Login</button>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Updating User Information
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
function UserProfileComponent() {
|
|
89
|
+
const guideAIRef = useRef();
|
|
90
|
+
|
|
91
|
+
const updateUserProfile = (newUserData) => {
|
|
92
|
+
// Update user profile in your system
|
|
93
|
+
saveUserProfile(newUserData);
|
|
94
|
+
|
|
95
|
+
// Update GuideAI metadata
|
|
96
|
+
guideAIRef.current?.updateUserInfo({
|
|
97
|
+
userType: newUserData.role,
|
|
98
|
+
customerType: newUserData.accountType,
|
|
99
|
+
customerLicense: newUserData.license,
|
|
100
|
+
customFields: {
|
|
101
|
+
department: newUserData.department,
|
|
102
|
+
region: newUserData.region
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<GuideAI
|
|
109
|
+
ref={guideAIRef}
|
|
110
|
+
organizationKey="your-org-key"
|
|
111
|
+
metadata={{
|
|
112
|
+
config: {
|
|
113
|
+
customFields: ['department', 'region'],
|
|
114
|
+
collectBrowserInfo: true
|
|
115
|
+
}
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Configuration Options
|
|
123
|
+
|
|
124
|
+
### MetadataConfig
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
interface MetadataConfig {
|
|
128
|
+
// Whether to automatically track visits (default: true)
|
|
129
|
+
trackVisits?: boolean;
|
|
130
|
+
|
|
131
|
+
// Whether to automatically track logins (default: true)
|
|
132
|
+
trackLogins?: boolean;
|
|
133
|
+
|
|
134
|
+
// How often to sync metadata to backend in milliseconds (default: 30000)
|
|
135
|
+
syncInterval?: number;
|
|
136
|
+
|
|
137
|
+
// Storage strategy (default: 'localStorage')
|
|
138
|
+
storage?: 'localStorage' | 'sessionStorage' | 'memory';
|
|
139
|
+
|
|
140
|
+
// Custom metadata fields to collect
|
|
141
|
+
customFields?: string[];
|
|
142
|
+
|
|
143
|
+
// Whether to collect browser information (default: true)
|
|
144
|
+
collectBrowserInfo?: boolean;
|
|
145
|
+
|
|
146
|
+
// Whether to collect user agent (default: true)
|
|
147
|
+
collectUserAgent?: boolean;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### UserMetadata Structure
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
interface UserMetadata {
|
|
155
|
+
// Core identification
|
|
156
|
+
userId?: string;
|
|
157
|
+
userType?: 'agent' | 'admin' | 'manager' | 'customer' | 'guest' | string;
|
|
158
|
+
|
|
159
|
+
// Customer-specific metadata
|
|
160
|
+
customerType?: 'individual' | 'business' | 'enterprise' | string;
|
|
161
|
+
customerLicense?: string;
|
|
162
|
+
|
|
163
|
+
// Visit tracking (automatically managed)
|
|
164
|
+
firstVisit?: number; // timestamp
|
|
165
|
+
lastVisit?: number; // timestamp
|
|
166
|
+
visitCount?: number;
|
|
167
|
+
|
|
168
|
+
// Login tracking (requires manual tracking)
|
|
169
|
+
loginCount?: number;
|
|
170
|
+
lastLogin?: number; // timestamp
|
|
171
|
+
|
|
172
|
+
// Session metadata (automatically managed)
|
|
173
|
+
organizationKey: string;
|
|
174
|
+
sessionId?: string;
|
|
175
|
+
|
|
176
|
+
// Browser information (automatically collected if enabled)
|
|
177
|
+
userAgent?: string;
|
|
178
|
+
browserInfo?: {
|
|
179
|
+
name?: string;
|
|
180
|
+
version?: string;
|
|
181
|
+
platform?: string;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Custom fields for Overproof-specific needs
|
|
185
|
+
customFields?: Record<string, string | number | boolean>;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## API Integration
|
|
190
|
+
|
|
191
|
+
The system automatically sends metadata updates to these endpoints:
|
|
192
|
+
|
|
193
|
+
### POST `/user-metadata`
|
|
194
|
+
Sends complete user metadata object when initially collected.
|
|
195
|
+
|
|
196
|
+
### POST `/metadata-updates`
|
|
197
|
+
Sends batched metadata updates periodically.
|
|
198
|
+
|
|
199
|
+
### PATCH `/users/{userId}/metadata`
|
|
200
|
+
Updates specific user metadata when userId is available.
|
|
201
|
+
|
|
202
|
+
## Backend Implementation
|
|
203
|
+
|
|
204
|
+
You'll need to implement these endpoints in your backend:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Example Express.js implementation
|
|
208
|
+
app.post('/api/user-metadata', (req, res) => {
|
|
209
|
+
const { organizationKey, metadata, timestamp } = req.body;
|
|
210
|
+
|
|
211
|
+
// Store metadata in your database
|
|
212
|
+
await UserMetadata.upsert({
|
|
213
|
+
organizationKey,
|
|
214
|
+
userId: metadata.userId || 'anonymous',
|
|
215
|
+
...metadata,
|
|
216
|
+
lastUpdated: new Date(timestamp)
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
res.json({ success: true });
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
app.post('/api/metadata-updates', (req, res) => {
|
|
223
|
+
const { organizationKey, updates, batchTimestamp } = req.body;
|
|
224
|
+
|
|
225
|
+
// Process batch updates
|
|
226
|
+
for (const update of updates) {
|
|
227
|
+
await processMetadataUpdate(organizationKey, update);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
res.json({ success: true });
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Privacy Considerations
|
|
235
|
+
|
|
236
|
+
- **User Agent Collection**: Can be disabled via `collectUserAgent: false`
|
|
237
|
+
- **Browser Info Collection**: Can be disabled via `collectBrowserInfo: false`
|
|
238
|
+
- **Custom Fields**: Only fields specified in `customFields` array are collected
|
|
239
|
+
- **Storage**: Can be set to `'memory'` for session-only storage without persistence
|
|
240
|
+
|
|
241
|
+
## Testing
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// Get current metadata
|
|
245
|
+
const metadata = guideAIRef.current?.getMetadata();
|
|
246
|
+
console.log('Current metadata:', metadata);
|
|
247
|
+
|
|
248
|
+
// Force sync metadata now
|
|
249
|
+
await guideAIRef.current?.syncMetadata();
|
|
250
|
+
|
|
251
|
+
// Track custom events
|
|
252
|
+
guideAIRef.current?.trackCustomEvent('document_viewed', {
|
|
253
|
+
documentType: 'policy',
|
|
254
|
+
documentId: 'POL-12345'
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Overproof Integration Example
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
function OverproofApp() {
|
|
262
|
+
const guideAIRef = useRef();
|
|
263
|
+
|
|
264
|
+
// Track when user logs into Overproof
|
|
265
|
+
const handleOverproofLogin = (user) => {
|
|
266
|
+
guideAIRef.current?.trackLogin({
|
|
267
|
+
userId: user.id,
|
|
268
|
+
userType: user.role, // 'agent', 'admin', etc.
|
|
269
|
+
customerType: user.accountType,
|
|
270
|
+
customerLicense: user.licenseNumber,
|
|
271
|
+
customFields: {
|
|
272
|
+
agencyId: user.agencyId,
|
|
273
|
+
territory: user.territory,
|
|
274
|
+
permissions: user.permissions.join(',')
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Track when user profile is updated
|
|
280
|
+
const handleProfileUpdate = (updatedProfile) => {
|
|
281
|
+
guideAIRef.current?.updateUserInfo({
|
|
282
|
+
userType: updatedProfile.role,
|
|
283
|
+
customerLicense: updatedProfile.licenseNumber,
|
|
284
|
+
customFields: {
|
|
285
|
+
agencyId: updatedProfile.agencyId,
|
|
286
|
+
territory: updatedProfile.territory
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<GuideAI
|
|
293
|
+
ref={guideAIRef}
|
|
294
|
+
organizationKey="overproof-org-key"
|
|
295
|
+
metadata={{
|
|
296
|
+
config: {
|
|
297
|
+
trackVisits: true,
|
|
298
|
+
trackLogins: true,
|
|
299
|
+
syncInterval: 15000, // More frequent syncing for Overproof
|
|
300
|
+
customFields: ['agencyId', 'territory', 'permissions'],
|
|
301
|
+
collectBrowserInfo: true
|
|
302
|
+
},
|
|
303
|
+
onMetadataUpdate: (metadata) => {
|
|
304
|
+
// Send to Overproof analytics
|
|
305
|
+
window.OverproofAnalytics?.track('guideai_metadata_update', metadata);
|
|
306
|
+
}
|
|
307
|
+
}}
|
|
308
|
+
/>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Storage and Data Persistence
|
|
314
|
+
|
|
315
|
+
- **localStorage**: Persists across browser sessions (default)
|
|
316
|
+
- **sessionStorage**: Persists only for current session
|
|
317
|
+
- **memory**: No persistence, data lost on page refresh
|
|
318
|
+
|
|
319
|
+
Metadata is automatically:
|
|
320
|
+
- Saved locally based on storage configuration
|
|
321
|
+
- Synced to backend at configured intervals
|
|
322
|
+
- Restored when user returns (if using persistent storage)
|
|
323
|
+
|
|
324
|
+
This implementation provides a robust foundation for tracking user metadata in the Overproof environment while maintaining flexibility for other use cases.
|