guideai-app 0.4.3 → 0.5.0
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 +86 -5
- package/dist/GuideAI.d.ts +1 -1
- package/dist/GuideAI.js +1 -1
- package/dist/GuideAI.js.map +1 -1
- package/dist/components/AnimatedSettingsItem.d.ts +9 -0
- package/dist/components/Microphone.d.ts +19 -0
- package/dist/components/MuteButton.d.ts +11 -0
- package/dist/components/ResetButton.d.ts +9 -0
- package/dist/components/SettingsMenu.d.ts +16 -0
- package/dist/components/SettingsToggle.d.ts +7 -0
- package/dist/components/TranscriptBox.d.ts +19 -12
- package/dist/components/TranscriptMessages.d.ts +8 -0
- package/dist/components/TranscriptTextInput.d.ts +11 -0
- package/dist/components/TranscriptToggle.d.ts +7 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/useGuideAIAPI.d.ts +22 -0
- package/dist/hooks/useTranscriptState.d.ts +21 -0
- package/dist/hooks/useWebRTC.d.ts +63 -0
- package/dist/index.d.ts +2 -1
- package/dist/styles/GuideAI.styles.d.ts +7 -1
- package/dist/types/GuideAI.types.d.ts +19 -21
- package/dist/utils/api.d.ts +17 -18
- package/dist/utils/constants.d.ts +20 -5
- package/dist/utils/conversationManager.d.ts +89 -0
- package/dist/utils/dataChannel.d.ts +85 -0
- package/dist/utils/elementInteractions.d.ts +38 -2
- package/dist/utils/highlightThenClick.d.ts +2 -1
- package/dist/utils/hover.d.ts +2 -0
- package/dist/utils/hoverThenClick.d.ts +2 -1
- package/dist/utils/isChromeExtension.d.ts +5 -0
- package/dist/utils/localStorageHelper.d.ts +57 -0
- package/dist/utils/logger.d.ts +50 -9
- package/dist/utils/messageStorage.d.ts +16 -3
- package/dist/utils/positionUtils.d.ts +39 -0
- package/dist/utils/webrtcConnection.d.ts +56 -0
- package/dist/visualContext/VisualContextScheduler.d.ts +11 -14
- package/dist/visualContext/domChangeTracker.d.ts +16 -0
- package/dist/visualContext/index.d.ts +8 -1
- package/dist/visualContext/types.d.ts +4 -0
- package/dist/visualContext/useVisualContext.d.ts +32 -0
- package/package.json +12 -6
- package/.workflow-test +0 -1
- package/API_DATA_CONTRACTS.md +0 -516
- package/API_SESSIONID_TESTING.md +0 -215
- package/GuideAI.d.ts +0 -19
- package/GuideAI.js +0 -1
- package/GuideAI.js.LICENSE.txt +0 -16
- package/GuideAI.js.map +0 -1
- package/PII_HASHING_EPIC.md +0 -886
- package/PII_HASHING_STORIES_SUMMARY.md +0 -275
- package/PRODUCTION_RELEASE.md +0 -126
- package/SESSION_ID_VERIFICATION.md +0 -122
- package/VISIT_COUNT_TESTING.md +0 -453
- package/dist/metric/event-listner.d.ts +0 -143
- package/dist/metric/index.d.ts +0 -2
- package/dist/metric/metadata-tracker.d.ts +0 -50
- package/dist/types/metadata.types.d.ts +0 -48
- package/dist/utils/gemini.d.ts +0 -5
- package/dist/utils/highlightAndClick.d.ts +0 -3
- package/dist/utils/hoverAndClick.d.ts +0 -4
- package/index.d.ts +0 -7
- package/jest.config.js +0 -26
- package/jest.setup.js +0 -21
- package/metadata-tracking-example.md +0 -324
- package/obfuscate.js +0 -40
- package/obfuscator.prod.json +0 -24
- package/rollup.config.js +0 -34
- package/structure.md +0 -128
- package/text-input-usage.md +0 -321
- package/transcript-toggle-usage.md +0 -267
- package/visit-tracking-usage.md +0 -134
- package/webpack.config.js +0 -55
- package/workflow-trigger-usage.md +0 -398
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface AnimatedSettingsItemProps {
|
|
2
|
+
visible: boolean;
|
|
3
|
+
gap: number;
|
|
4
|
+
isLast?: boolean;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
React: typeof import('react');
|
|
7
|
+
}
|
|
8
|
+
declare const AnimatedSettingsItem: ({ visible, gap, isLast, children, React }: AnimatedSettingsItemProps) => import("react").JSX.Element;
|
|
9
|
+
export default AnimatedSettingsItem;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { PopupPosition, RecordingStatus } from '../types/GuideAI.types';
|
|
2
|
+
interface MicrophoneProps {
|
|
3
|
+
componentRef: React.RefObject<HTMLDivElement>;
|
|
4
|
+
baseStyles: React.CSSProperties;
|
|
5
|
+
hasInteracted: boolean;
|
|
6
|
+
popupPosition: PopupPosition;
|
|
7
|
+
showOnboarding: boolean;
|
|
8
|
+
handleOnboardingComplete: () => void;
|
|
9
|
+
handleOnboardingClose: () => void;
|
|
10
|
+
isConnecting: boolean;
|
|
11
|
+
status: RecordingStatus;
|
|
12
|
+
handleToggleConversation: () => void;
|
|
13
|
+
showTranscript: boolean;
|
|
14
|
+
hasMic: boolean;
|
|
15
|
+
isMuted: boolean;
|
|
16
|
+
React: typeof import('react');
|
|
17
|
+
}
|
|
18
|
+
declare const Microphone: ({ componentRef, baseStyles, hasInteracted, popupPosition, showOnboarding, handleOnboardingComplete, handleOnboardingClose, isConnecting, status, handleToggleConversation, showTranscript, hasMic, isMuted, React }: MicrophoneProps) => import("react").JSX.Element;
|
|
19
|
+
export default Microphone;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface MuteButtonProps {
|
|
2
|
+
hasMic: boolean;
|
|
3
|
+
isMuted?: boolean;
|
|
4
|
+
handleToggleMute?: () => void;
|
|
5
|
+
React: typeof import('react');
|
|
6
|
+
}
|
|
7
|
+
declare const MuteButton: {
|
|
8
|
+
({ hasMic, isMuted, handleToggleMute, React }: MuteButtonProps): import("react").JSX.Element;
|
|
9
|
+
displayName: string;
|
|
10
|
+
};
|
|
11
|
+
export default MuteButton;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface ResetButtonProps {
|
|
2
|
+
handleResetChat?: () => void;
|
|
3
|
+
React: typeof import('react');
|
|
4
|
+
}
|
|
5
|
+
declare const ResetButton: {
|
|
6
|
+
({ handleResetChat, React }: ResetButtonProps): import("react").JSX.Element;
|
|
7
|
+
displayName: string;
|
|
8
|
+
};
|
|
9
|
+
export default ResetButton;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TranscriptPosition, MicButtonPosition } from '../types/GuideAI.types';
|
|
2
|
+
interface SettingsMenuProps {
|
|
3
|
+
handleResetChat?: () => void;
|
|
4
|
+
hasMic: boolean;
|
|
5
|
+
isMuted: boolean;
|
|
6
|
+
handleToggleMute: () => void;
|
|
7
|
+
showTranscript: boolean;
|
|
8
|
+
handleToggleTranscript: () => void;
|
|
9
|
+
showSettings: boolean;
|
|
10
|
+
setShowSettings?: (value: boolean) => void;
|
|
11
|
+
transcriptPosition: TranscriptPosition;
|
|
12
|
+
micPosition?: MicButtonPosition;
|
|
13
|
+
React: typeof import('react');
|
|
14
|
+
}
|
|
15
|
+
declare const SettingsMenu: ({ handleResetChat, hasMic, isMuted, handleToggleMute, showTranscript, handleToggleTranscript, showSettings, setShowSettings, transcriptPosition, micPosition, React }: SettingsMenuProps) => import("react").JSX.Element;
|
|
16
|
+
export default SettingsMenu;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface SettingsToggleProps {
|
|
2
|
+
showSettings: boolean;
|
|
3
|
+
setShowSettings?: (value: boolean) => void;
|
|
4
|
+
React: typeof import('react');
|
|
5
|
+
}
|
|
6
|
+
declare const SettingsToggle: ({ showSettings, setShowSettings, React }: SettingsToggleProps) => import("react").JSX.Element;
|
|
7
|
+
export default SettingsToggle;
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import { StoredMessage } from '../utils/messageStorage';
|
|
2
|
-
import {
|
|
2
|
+
import { TranscriptPosition, MicButtonPosition } from '../types/GuideAI.types';
|
|
3
3
|
interface TranscriptBoxProps {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
allMessages: StoredMessage[];
|
|
5
|
+
showTranscript: boolean;
|
|
6
|
+
handleCloseTranscript: () => void;
|
|
7
7
|
showToggleButton?: boolean;
|
|
8
|
-
|
|
8
|
+
handleToggleTranscript?: () => void;
|
|
9
9
|
showTextInput?: boolean;
|
|
10
10
|
textInput?: string;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
setTextInput?: (value: string) => void;
|
|
12
|
+
handleTextSubmit?: () => void;
|
|
13
|
+
handleTextKeyPress?: (event: React.KeyboardEvent) => void;
|
|
14
14
|
textPlaceholder?: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
micPosition?: MicButtonPosition;
|
|
16
|
+
transcriptPosition: TranscriptPosition;
|
|
17
|
+
hasMic: boolean;
|
|
18
|
+
isMuted?: boolean;
|
|
19
|
+
handleToggleMute?: () => void;
|
|
20
|
+
isConversationActive?: boolean;
|
|
21
|
+
handleResetChat?: () => void;
|
|
22
|
+
showSettings?: boolean;
|
|
23
|
+
setShowSettings?: (value: boolean) => void;
|
|
24
|
+
isDataChannelOpen?: boolean;
|
|
18
25
|
React: typeof import('react');
|
|
19
26
|
}
|
|
20
27
|
declare const TranscriptBox: {
|
|
21
|
-
(
|
|
28
|
+
({ allMessages, showTranscript, handleCloseTranscript, handleToggleTranscript, showTextInput, textInput, setTextInput, handleTextSubmit, handleTextKeyPress, textPlaceholder, micPosition, transcriptPosition, hasMic, isMuted, handleToggleMute, isConversationActive, handleResetChat, showSettings, setShowSettings, isDataChannelOpen, React }: TranscriptBoxProps): import("react").JSX.Element | null;
|
|
22
29
|
displayName: string;
|
|
23
30
|
};
|
|
24
31
|
export default TranscriptBox;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StoredMessage } from '../utils/messageStorage';
|
|
2
|
+
interface TranscriptMessagesProps {
|
|
3
|
+
allMessages: StoredMessage[];
|
|
4
|
+
messagesEndRef: React.RefObject<HTMLDivElement>;
|
|
5
|
+
React: typeof import('react');
|
|
6
|
+
}
|
|
7
|
+
declare const TranscriptMessages: ({ allMessages, messagesEndRef, React }: TranscriptMessagesProps) => import("react").JSX.Element;
|
|
8
|
+
export default TranscriptMessages;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface TranscriptTextInputProps {
|
|
2
|
+
textInput?: string;
|
|
3
|
+
setTextInput?: (value: string) => void;
|
|
4
|
+
handleTextSubmit?: () => void;
|
|
5
|
+
handleTextKeyPress?: (event: React.KeyboardEvent) => void;
|
|
6
|
+
textPlaceholder?: string;
|
|
7
|
+
isDataChannelOpen?: boolean;
|
|
8
|
+
React: typeof import('react');
|
|
9
|
+
}
|
|
10
|
+
declare const TranscriptTextInput: ({ textInput, setTextInput, handleTextSubmit, handleTextKeyPress, textPlaceholder, isDataChannelOpen, React }: TranscriptTextInputProps) => import("react").JSX.Element;
|
|
11
|
+
export default TranscriptTextInput;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface TranscriptToggleProps {
|
|
2
|
+
showTranscript: boolean;
|
|
3
|
+
handleToggleTranscript?: () => void;
|
|
4
|
+
React: typeof import('react');
|
|
5
|
+
}
|
|
6
|
+
declare const TranscriptToggle: ({ showTranscript, handleToggleTranscript, React }: TranscriptToggleProps) => import("react").JSX.Element;
|
|
7
|
+
export default TranscriptToggle;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exposes GuideAI methods globally on window for external access.
|
|
3
|
+
*/
|
|
4
|
+
import type { UseEffectHook } from '../types/GuideAI.types';
|
|
5
|
+
export interface UseGuideAIAPIParams {
|
|
6
|
+
useEffect: UseEffectHook;
|
|
7
|
+
organizationKey: string;
|
|
8
|
+
setShowTranscript: (value: React.SetStateAction<boolean>) => void;
|
|
9
|
+
showTranscript: boolean;
|
|
10
|
+
setInputMode: (mode: 'voice' | 'text') => void;
|
|
11
|
+
setShowTextInput: (value: React.SetStateAction<boolean>) => void;
|
|
12
|
+
inputMode: 'voice' | 'text';
|
|
13
|
+
setTextInput: (value: React.SetStateAction<string>) => void;
|
|
14
|
+
inputOptions?: {
|
|
15
|
+
enableTextInput?: boolean;
|
|
16
|
+
};
|
|
17
|
+
isConversationActive: boolean;
|
|
18
|
+
handleToggleInputMode: () => void;
|
|
19
|
+
handleTextSubmit: (text?: string) => Promise<void>;
|
|
20
|
+
visualContextWindowAPI: any;
|
|
21
|
+
}
|
|
22
|
+
export declare function useGuideAIAPI(params: UseGuideAIAPIParams): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages transcript/message state: sync from storage, streaming updates.
|
|
3
|
+
*/
|
|
4
|
+
import type { StoredMessage } from '../utils/messageStorage';
|
|
5
|
+
import type { RecordingStatus } from '../types/GuideAI.types';
|
|
6
|
+
export interface UseTranscriptStateParams {
|
|
7
|
+
hooks: {
|
|
8
|
+
useRef: <T>(initialValue: T) => {
|
|
9
|
+
current: T;
|
|
10
|
+
};
|
|
11
|
+
useCallback: <T extends (...args: any[]) => any>(callback: T, deps: any[]) => T;
|
|
12
|
+
};
|
|
13
|
+
organizationKey: string;
|
|
14
|
+
setAllMessages: React.Dispatch<React.SetStateAction<StoredMessage[]>>;
|
|
15
|
+
setStatus: (status: RecordingStatus) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function useTranscriptState(params: UseTranscriptStateParams): {
|
|
18
|
+
syncMessagesFromStorage: () => StoredMessage[];
|
|
19
|
+
cleanupStreamingMessageState: () => void;
|
|
20
|
+
updateStreamingMessage: (text: string) => void;
|
|
21
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebRTC connection management hook.
|
|
3
|
+
* Handles peer connection, data channel, audio element refs, cleanup, and initialization.
|
|
4
|
+
*/
|
|
5
|
+
import { WebRTCConnection } from '../utils/webrtcConnection';
|
|
6
|
+
import { DataChannelManager } from '../utils/dataChannel';
|
|
7
|
+
import { ConversationManager } from '../utils/conversationManager';
|
|
8
|
+
import type { RecordingStatus } from '../types/GuideAI.types';
|
|
9
|
+
import type { GuideAIEnvironment } from '../types/GuideAI.types';
|
|
10
|
+
import type { StoredMessage } from '../utils/messageStorage';
|
|
11
|
+
export interface UseWebRTCParams {
|
|
12
|
+
hooks: {
|
|
13
|
+
useRef: <T>(initialValue: T) => {
|
|
14
|
+
current: T;
|
|
15
|
+
};
|
|
16
|
+
useCallback: <T extends (...args: any[]) => any>(callback: T, deps: any[]) => T;
|
|
17
|
+
};
|
|
18
|
+
organizationKey: string;
|
|
19
|
+
environment: GuideAIEnvironment;
|
|
20
|
+
setIsDataChannelOpen: (open: boolean) => void;
|
|
21
|
+
setIsConnecting: (connecting: boolean) => void;
|
|
22
|
+
setStatus: (status: RecordingStatus) => void;
|
|
23
|
+
handleHighlightThenClick: (out: any) => Promise<boolean>;
|
|
24
|
+
handleHoverThenClick: (out: any) => Promise<boolean>;
|
|
25
|
+
handleHover: (out: any) => Promise<boolean>;
|
|
26
|
+
handleGoToAElmLink: (linkText: string, delay?: number) => Promise<boolean>;
|
|
27
|
+
handleResetChatRef: {
|
|
28
|
+
current: () => Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
endConversationSessionRef: {
|
|
31
|
+
current: () => void;
|
|
32
|
+
};
|
|
33
|
+
updateStreamingMessage: (text: string) => void;
|
|
34
|
+
cleanupStreamingMessageState: () => void;
|
|
35
|
+
allMessages: StoredMessage[];
|
|
36
|
+
status: RecordingStatus;
|
|
37
|
+
conversationManagerRef: {
|
|
38
|
+
current: ConversationManager | null;
|
|
39
|
+
};
|
|
40
|
+
onMessageLogged: () => void;
|
|
41
|
+
}
|
|
42
|
+
export declare function useWebRTC(params: UseWebRTCParams): {
|
|
43
|
+
peerConnectionRef: {
|
|
44
|
+
current: RTCPeerConnection | null;
|
|
45
|
+
};
|
|
46
|
+
dataChannelManagerRef: {
|
|
47
|
+
current: DataChannelManager | null;
|
|
48
|
+
};
|
|
49
|
+
mediaStreamRef: {
|
|
50
|
+
current: MediaStream | null;
|
|
51
|
+
};
|
|
52
|
+
audioElementRef: {
|
|
53
|
+
current: HTMLAudioElement | null;
|
|
54
|
+
};
|
|
55
|
+
webrtcConnectionRef: {
|
|
56
|
+
current: WebRTCConnection | null;
|
|
57
|
+
};
|
|
58
|
+
conversationIdRef: {
|
|
59
|
+
current: string | null;
|
|
60
|
+
};
|
|
61
|
+
cleanupWebRTC: () => void;
|
|
62
|
+
initializeWebRTC: (audioStream: MediaStream | null) => Promise<boolean>;
|
|
63
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import GuideAI from './GuideAI';
|
|
|
2
2
|
import TranscriptBox from './components/TranscriptBox';
|
|
3
3
|
export default GuideAI;
|
|
4
4
|
export { TranscriptBox };
|
|
5
|
-
export type { GuideAIProps } from './types/GuideAI.types';
|
|
5
|
+
export type { GuideAIProps, GuideAIEnvironment } from './types/GuideAI.types';
|
|
6
6
|
export * from './visualContext';
|
|
7
7
|
export * from './visualContext/types';
|
|
8
8
|
export { getSessionId, clearSessionId, peekSessionId } from './utils/session';
|
|
9
|
+
export { STORAGE_KEYS } from './utils/localStorageHelper';
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
export declare const guideAIStyles = "\n.guideai-main-ui {\n position: relative;\n}\n\n.guideai-main-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n}\n\n.guideai-welcome-bubble {\n position: absolute;\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/* Vertical positioning - backwards compatible */\n.guideai-welcome-bubble.above,\n.guideai-welcome-bubble.above-center,\n.guideai-welcome-bubble.above-left,\n.guideai-welcome-bubble.above-right {\n bottom: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.below,\n.guideai-welcome-bubble.below-center,\n.guideai-welcome-bubble.below-left,\n.guideai-welcome-bubble.below-right {\n top: calc(100% + 10px);\n}\n\n/* Horizontal positioning - centered (default) */\n.guideai-welcome-bubble.above,\n.guideai-welcome-bubble.above-center,\n.guideai-welcome-bubble.below,\n.guideai-welcome-bubble.below-center {\n left: 50%;\n transform: translateX(-50%);\n}\n\n/* Horizontal positioning - left aligned */\n.guideai-welcome-bubble.above-left,\n.guideai-welcome-bubble.below-left {\n left: 0;\n transform: translateX(0);\n animation: bubble-pulse-left 2s infinite;\n}\n\n/* Horizontal positioning - right aligned */\n.guideai-welcome-bubble.above-right,\n.guideai-welcome-bubble.below-right {\n left: auto;\n right: 0;\n transform: translateX(0);\n animation: bubble-pulse-right 2s infinite;\n}\n\n/* Arrow pointers - centered versions */\n.guideai-welcome-bubble.above::after,\n.guideai-welcome-bubble.above-center::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.guideai-welcome-bubble.below-center::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/* Arrow pointers - left aligned versions */\n.guideai-welcome-bubble.above-left::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 25px;\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-left::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 25px;\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #0066ff;\n}\n\n/* Arrow pointers - right aligned versions */\n.guideai-welcome-bubble.above-right::after {\n content: '';\n position: absolute;\n top: 100%;\n right: 25px;\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-right::after {\n content: '';\n position: absolute;\n bottom: 100%;\n right: 25px;\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@keyframes bubble-pulse-left {\n 0% { transform: translateX(0) scale(1); }\n 50% { transform: translateX(0) scale(1.05); }\n 100% { transform: translateX(0) scale(1); }\n}\n\n@keyframes bubble-pulse-right {\n 0% { transform: translateX(0) scale(1); }\n 50% { transform: translateX(0) scale(1.05); }\n 100% { transform: translateX(0) 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.guideai-icon.text-mode {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%230066ff\" d=\"M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM7 10v2h2v-2H7zm6 2h-2v-2h2v2zm4 0h-2v-2h2v2z\"/></svg>');\n}\n\n.guideai-icon.voice-mode {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%23008000\" 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\n/* Onboarding styles */\n.guideai-onboarding {\n position: absolute;\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: 90009000;\n animation: onboarding-fade-in 0.3s ease-out;\n}\n\n/* Vertical positioning - backwards compatible */\n.guideai-onboarding.above,\n.guideai-onboarding.above-center,\n.guideai-onboarding.above-left,\n.guideai-onboarding.above-right {\n bottom: calc(100% + 15px);\n}\n\n.guideai-onboarding.below,\n.guideai-onboarding.below-center,\n.guideai-onboarding.below-left,\n.guideai-onboarding.below-right {\n top: calc(100% + 15px);\n}\n\n/* Horizontal positioning - centered (default) */\n.guideai-onboarding.above,\n.guideai-onboarding.above-center,\n.guideai-onboarding.below,\n.guideai-onboarding.below-center {\n left: 50%;\n transform: translateX(-50%);\n}\n\n/* Horizontal positioning - left aligned (prevents right overflow) */\n.guideai-onboarding.above-left,\n.guideai-onboarding.below-left {\n left: 0;\n transform: translateX(0);\n}\n\n/* Horizontal positioning - right aligned (prevents left overflow) */\n.guideai-onboarding.above-right,\n.guideai-onboarding.below-right {\n left: auto;\n right: 0;\n transform: translateX(0);\n}\n\n/* Arrow pointers - centered versions */\n.guideai-onboarding.above::after,\n.guideai-onboarding.above-center::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.guideai-onboarding.below-center::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/* Arrow pointers - left aligned versions */\n.guideai-onboarding.above-left::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 25px;\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-left::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 25px;\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/* Arrow pointers - right aligned versions */\n.guideai-onboarding.above-right::after {\n content: '';\n position: absolute;\n top: 100%;\n right: 25px;\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-right::after {\n content: '';\n position: absolute;\n bottom: 100%;\n right: 25px;\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; }\n to { opacity: 1; }\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: 90009000;\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 directly above mic button */\n.guideai-transcript-toggle-button {\n position: fixed;\n bottom: 110px; /* Default position (will be overridden by inline styles) */\n right: 40px; /* Default position (will be overridden by inline styles) */\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: 90009000;\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/* Hover effect animations */\n@keyframes hover-pulse {\n 0%, 100% {\n opacity: 0.6;\n transform: scale(1);\n box-shadow: 0 0 10px rgba(255, 165, 0, 0.6);\n }\n 25% {\n opacity: 0.9;\n transform: scale(1.03);\n box-shadow: 0 0 20px rgba(255, 165, 0, 0.8);\n }\n 50% {\n opacity: 1;\n transform: scale(1.05);\n box-shadow: 0 0 25px rgba(255, 165, 0, 1);\n }\n 75% {\n opacity: 0.9;\n transform: scale(1.03);\n box-shadow: 0 0 20px rgba(255, 165, 0, 0.8);\n }\n}\n\n@keyframes hover-indicator-fade {\n from { \n opacity: 0; \n transform: translateX(-50%) translateY(-10px); \n }\n to { \n opacity: 1; \n transform: translateX(-50%) translateY(0); \n }\n}\n\n@keyframes cursor-hover-float {\n 0%, 100% {\n transform: translate(-50%, 0) translateY(0px);\n }\n 25% {\n transform: translate(-50%, 0) translateY(-3px);\n }\n 50% {\n transform: translate(-50%, 0) translateY(-6px);\n }\n 75% {\n transform: translate(-50%, 0) translateY(-3px);\n }\n}\n\n\n";
|
|
1
|
+
export interface ZIndexConfig {
|
|
2
|
+
main: number;
|
|
3
|
+
transcript: number;
|
|
4
|
+
microphone: number;
|
|
5
|
+
onboarding: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const guideAIStyles: (zIndexConfig: ZIndexConfig) => string;
|
|
@@ -1,38 +1,35 @@
|
|
|
1
|
-
import { MetadataConfig, UserMetadata } from './metadata.types';
|
|
2
1
|
import { VisualContextConfig } from '../visualContext/types';
|
|
3
|
-
export type RecordingStatus = 'idle' | 'recording' | 'processing' | 'playing';
|
|
2
|
+
export type RecordingStatus = 'idle' | 'recording' | 'active' | 'processing' | 'playing';
|
|
4
3
|
export type UseStateHook = <T>(initialState: T | (() => T)) => [T, (value: T | ((prev: T) => T)) => void];
|
|
5
4
|
export type UseEffectHook = (effect: () => void | (() => void), deps?: any[]) => void;
|
|
6
5
|
export type UseRefHook = <T>(initialValue: T) => {
|
|
7
6
|
current: T;
|
|
8
7
|
};
|
|
9
8
|
export type UseCallbackHook = <T extends (...args: any[]) => any>(callback: T, deps: any[]) => T;
|
|
9
|
+
export type GuideAIEnvironment = 'development' | 'production' | 'local';
|
|
10
|
+
export type GuideAIPosition = {
|
|
11
|
+
top?: string;
|
|
12
|
+
right?: string;
|
|
13
|
+
bottom?: string;
|
|
14
|
+
left?: string;
|
|
15
|
+
marginTop?: string;
|
|
16
|
+
marginRight?: string;
|
|
17
|
+
marginBottom?: string;
|
|
18
|
+
marginLeft?: string;
|
|
19
|
+
transform?: string;
|
|
20
|
+
zIndex?: number;
|
|
21
|
+
};
|
|
22
|
+
export type MicButtonPosition = GuideAIPosition;
|
|
10
23
|
export interface GuideAIProps {
|
|
11
24
|
organizationKey: string;
|
|
12
25
|
workflowKey?: string;
|
|
26
|
+
environment?: GuideAIEnvironment;
|
|
13
27
|
React: typeof import('react');
|
|
14
28
|
ReactDOM: any;
|
|
15
|
-
position?:
|
|
16
|
-
top?: string;
|
|
17
|
-
right?: string;
|
|
18
|
-
bottom?: string;
|
|
19
|
-
left?: string;
|
|
20
|
-
marginTop?: string;
|
|
21
|
-
marginRight?: string;
|
|
22
|
-
marginBottom?: string;
|
|
23
|
-
marginLeft?: string;
|
|
24
|
-
transform?: string;
|
|
25
|
-
};
|
|
26
|
-
onError?: (error: string | Error, context?: string) => void;
|
|
27
|
-
metadata?: {
|
|
28
|
-
config?: MetadataConfig;
|
|
29
|
-
initialUserData?: Partial<UserMetadata>;
|
|
30
|
-
onMetadataUpdate?: (metadata: UserMetadata) => void;
|
|
31
|
-
};
|
|
29
|
+
position?: GuideAIPosition;
|
|
32
30
|
transcript?: {
|
|
33
31
|
enabled?: boolean;
|
|
34
|
-
|
|
35
|
-
position?: 'right' | 'left' | 'top' | 'bottom';
|
|
32
|
+
position?: TranscriptPosition;
|
|
36
33
|
};
|
|
37
34
|
input?: {
|
|
38
35
|
enableTextInput?: boolean;
|
|
@@ -42,4 +39,5 @@ export interface GuideAIProps {
|
|
|
42
39
|
};
|
|
43
40
|
visualContext?: VisualContextConfig;
|
|
44
41
|
}
|
|
42
|
+
export type TranscriptPosition = 'right' | 'left';
|
|
45
43
|
export type PopupPosition = 'above' | 'below' | 'above-left' | 'above-right' | 'above-center' | 'below-left' | 'below-right' | 'below-center';
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { GuideAIEnvironment } from '../types/GuideAI.types';
|
|
2
|
+
import { MessageData } from './conversationManager';
|
|
3
|
+
export declare function getApiHeaders(): Record<string, string>;
|
|
4
|
+
export interface Workflow {
|
|
3
5
|
id: string;
|
|
4
6
|
name: string;
|
|
5
7
|
triggers: string[];
|
|
6
8
|
organizationKey: string;
|
|
7
9
|
prompt: string;
|
|
8
|
-
archived
|
|
9
|
-
createdAt
|
|
10
|
-
updatedAt
|
|
10
|
+
archived?: boolean;
|
|
11
|
+
createdAt?: string;
|
|
12
|
+
updatedAt?: string;
|
|
11
13
|
}
|
|
12
|
-
interface
|
|
14
|
+
export interface InitializeWebRTCPayload {
|
|
15
|
+
sdp: string;
|
|
16
|
+
organizationKey: string;
|
|
17
|
+
user?: string;
|
|
18
|
+
conversationId?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface InitializeWebRTCResponse {
|
|
21
|
+
answerSdp: string;
|
|
13
22
|
id: string;
|
|
14
|
-
ephemeralToken: string;
|
|
15
|
-
prompt: string;
|
|
16
|
-
workflows: Workflow[];
|
|
17
|
-
userMetadata?: {
|
|
18
|
-
visitCount: number;
|
|
19
|
-
loginCount?: number;
|
|
20
|
-
email?: string;
|
|
21
|
-
};
|
|
22
23
|
}
|
|
23
|
-
export declare const
|
|
24
|
-
export
|
|
25
|
-
export declare const logMessage: (content: string, sender: "GUIDEAI" | "HUMAN", conversationId: string | null, organizationKey: string, onError: (error: Error, context: string) => void) => Promise<void>;
|
|
26
|
-
export declare const sendMetadataUpdates: (updates: MetadataUpdate[], organizationKey: string, onError: (error: Error, context: string) => void) => Promise<boolean>;
|
|
24
|
+
export declare const initializeWebRTC: (endpoint: string, payload: InitializeWebRTCPayload) => Promise<InitializeWebRTCResponse>;
|
|
25
|
+
export declare const logMessage: (messageData: MessageData, conversationId: string | null, organizationKey: string, user?: string, environment?: GuideAIEnvironment) => Promise<void>;
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
export declare const DEFAULT_PROMPT = "you are Guide AI.\n Your role is to answer any question directly and succinctly that a user has. NEVER DIRECTLY MENTION THE SCREENSHOT, but use its information as much as possible to target your responses.\n If nothing is asked, then your goal is to generally assist them.\n IMPORTANT: NEVER answer in more than 10 words. Always be concise and limit answers to 1 sentence maximum. Be simple and as short as possible.\n Your job is to help them get it done through asking more and more targeted specific questions.";
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
5
|
-
export declare const
|
|
6
|
-
export declare const
|
|
2
|
+
export declare const GUIDE_AI_API_BASE_PROD = "https://app.getguide.ai/api";
|
|
3
|
+
export declare const GUIDE_AI_API_BASE_DEV = "https://dev.getguide.ai/api";
|
|
4
|
+
export declare const GUIDE_AI_API_BASE_LOCAL = "http://localhost:3000/api";
|
|
5
|
+
export declare const getApiBaseUrl: (environment?: "development" | "production" | "local") => string;
|
|
6
|
+
export declare const GUIDE_AI_API_BASE = "https://app.getguide.ai/api";
|
|
7
|
+
export declare const OPENAI_REALTIME_BASE = "https://api.openai.com/v1/realtime/calls";
|
|
7
8
|
export type ElementInteractionType = "HIGHLIGHT" | "HOVERANDCLICK";
|
|
9
|
+
export declare const UI_LAYOUT: {
|
|
10
|
+
/** Mic/icon wrapper size - matches .guideai-icon-wrapper */
|
|
11
|
+
readonly micButtonSize: 50;
|
|
12
|
+
/** Space between mic top and lowest toggle bottom */
|
|
13
|
+
readonly toggleAboveMicGap: 12;
|
|
14
|
+
/** Gap between stacked buttons (e.g. transcript above settings) */
|
|
15
|
+
readonly stackedButtonGap: 8;
|
|
16
|
+
/** Horizontal offset from edge when using right/left positioning */
|
|
17
|
+
readonly horizontalEdgeOffset: 6;
|
|
18
|
+
/** Default bottom when micPosition is not provided */
|
|
19
|
+
readonly defaultBottom: 20;
|
|
20
|
+
/** Default horizontal offset when position is not provided */
|
|
21
|
+
readonly defaultHorizontalOffset: 40;
|
|
22
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { GuideAIEnvironment } from '../types/GuideAI.types';
|
|
2
|
+
/**
|
|
3
|
+
* Message type options
|
|
4
|
+
*/
|
|
5
|
+
export type MessageType = 'log' | 'voice' | 'text' | 'action' | 'error' | 'screenshot';
|
|
6
|
+
/**
|
|
7
|
+
* Sender type options
|
|
8
|
+
*/
|
|
9
|
+
export type MessageSender = 'GUIDEAI' | 'HUMAN' | 'SYSTEM';
|
|
10
|
+
/**
|
|
11
|
+
* Message data structure for API
|
|
12
|
+
*/
|
|
13
|
+
export interface MessageData {
|
|
14
|
+
content: string;
|
|
15
|
+
sender: MessageSender;
|
|
16
|
+
type: MessageType;
|
|
17
|
+
url?: string;
|
|
18
|
+
session?: string;
|
|
19
|
+
logdata?: any;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* ConversationManager class
|
|
23
|
+
* Centralized message logging with validation and automatic field population
|
|
24
|
+
*/
|
|
25
|
+
export declare class ConversationManager {
|
|
26
|
+
private organizationKey;
|
|
27
|
+
private conversationId;
|
|
28
|
+
private environment?;
|
|
29
|
+
private allMessages;
|
|
30
|
+
private onMessageLogged?;
|
|
31
|
+
constructor(organizationKey: string, conversationId: string | null, environment?: GuideAIEnvironment, onMessageLogged?: () => void);
|
|
32
|
+
/**
|
|
33
|
+
* Update conversation ID (called when conversation is created/updated)
|
|
34
|
+
*/
|
|
35
|
+
setConversationId(conversationId: string | null): void;
|
|
36
|
+
/**
|
|
37
|
+
* Update session ID in localStorage
|
|
38
|
+
*/
|
|
39
|
+
updateSessionId(sessionId: string | null): void;
|
|
40
|
+
/**
|
|
41
|
+
* Refresh messages from storage
|
|
42
|
+
*/
|
|
43
|
+
refreshMessages(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Primary utility function for logging messages
|
|
46
|
+
* Handles validation, duplicate checking, and field population
|
|
47
|
+
*/
|
|
48
|
+
private logMessage;
|
|
49
|
+
/**
|
|
50
|
+
* Private wrapper for logMessage - defaults type to voice
|
|
51
|
+
*/
|
|
52
|
+
private logVoiceMessage;
|
|
53
|
+
/**
|
|
54
|
+
* Public wrapper - log user voice message
|
|
55
|
+
*/
|
|
56
|
+
logUserVoiceMessage(content: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Public wrapper - log GuideAI voice message
|
|
59
|
+
*/
|
|
60
|
+
logGuideAIMessage(content: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Public wrapper - log data message (type defaults to 'log')
|
|
63
|
+
*/
|
|
64
|
+
logDataMessage(content: string, data?: any, type?: any): void;
|
|
65
|
+
/**
|
|
66
|
+
* Private wrapper for logMessage - defaults type to text
|
|
67
|
+
*/
|
|
68
|
+
private logTextMessage;
|
|
69
|
+
/**
|
|
70
|
+
* Public wrapper - log user text message
|
|
71
|
+
*/
|
|
72
|
+
logUserTextMessage(content: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Public wrapper - log action message
|
|
75
|
+
*/
|
|
76
|
+
logActionMessage(content: string, data?: any): void;
|
|
77
|
+
/**
|
|
78
|
+
* Public wrapper - log debug message
|
|
79
|
+
*/
|
|
80
|
+
logDebugMessage(content: string, data?: any): void;
|
|
81
|
+
/**
|
|
82
|
+
* Public wrapper - log error message
|
|
83
|
+
*/
|
|
84
|
+
logErrorMessage(content: string, data?: any): void;
|
|
85
|
+
/**
|
|
86
|
+
* Public wrapper - log visual context message
|
|
87
|
+
*/
|
|
88
|
+
logVisualContextMessage(content: string, data?: any): void;
|
|
89
|
+
}
|