@snf/qa-bot-core 0.2.5 → 0.2.7
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 +63 -0
- package/build/static/css/main.css +1 -1
- package/build/static/css/main.css.map +1 -1
- package/build/static/js/main.js +1 -1
- package/build/static/js/main.js.map +1 -1
- package/dist/qa-bot-core.js +2 -2
- package/dist/qa-bot-core.js.map +1 -1
- package/dist/qa-bot-core.standalone.js +5 -5
- package/dist/qa-bot-core.standalone.js.map +1 -1
- package/dist/qa-bot-core.umd.cjs +2 -2
- package/dist/qa-bot-core.umd.cjs.map +1 -1
- package/dist/types/components/HistoryButton.d.ts +11 -0
- package/dist/types/components/SessionMessageTracker.d.ts +18 -0
- package/dist/types/config.d.ts +48 -0
- package/dist/types/contexts/AnalyticsContext.d.ts +13 -0
- package/dist/types/contexts/SessionContext.d.ts +4 -0
- package/dist/types/lib.d.ts +3 -1
- package/dist/types/utils/fix-markdown-links.d.ts +20 -0
- package/dist/types/utils/flows/qa-flow.d.ts +26 -20
- package/dist/types/utils/logger.d.ts +17 -0
- package/dist/types/utils/session-utils.d.ts +53 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* HistoryButton Component
|
|
4
|
+
*
|
|
5
|
+
* A button that displays saved chat history when clicked.
|
|
6
|
+
* Shows in the header when user is logged in.
|
|
7
|
+
*
|
|
8
|
+
* @returns Rendered history button
|
|
9
|
+
*/
|
|
10
|
+
declare const HistoryButton: React.FC;
|
|
11
|
+
export default HistoryButton;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invisible component that stores each chat message with its session ID.
|
|
3
|
+
*
|
|
4
|
+
* Problem: React-Chatbotify stores all messages in a flat list with no session
|
|
5
|
+
* boundaries. When a user has multiple conversations, there's no way to know
|
|
6
|
+
* which messages belong to which conversation. Also, RCB's history storage
|
|
7
|
+
* is opaque and unreliable for session restore.
|
|
8
|
+
*
|
|
9
|
+
* Solution: This component listens for every message injection and stores
|
|
10
|
+
* the full message content in our own localStorage. The history dropdown
|
|
11
|
+
* restores sessions directly from our storage, not RCB's.
|
|
12
|
+
*
|
|
13
|
+
* Deduplication is handled by session-utils (checks message ID).
|
|
14
|
+
*
|
|
15
|
+
* Must be rendered inside ChatBotProvider.
|
|
16
|
+
*/
|
|
17
|
+
declare const SessionMessageTracker: React.FC;
|
|
18
|
+
export default SessionMessageTracker;
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
import type { Settings, Flow } from 'react-chatbotify';
|
|
2
|
+
/**
|
|
3
|
+
* Analytics event types fired by qa-bot-core
|
|
4
|
+
*/
|
|
5
|
+
export type QABotAnalyticsEventType = 'qa_bot_opened' | 'qa_bot_closed' | 'qa_new_chat_started' | 'qa_question_asked' | 'qa_response_received' | 'qa_response_error' | 'qa_response_rated' | 'qa_login_prompt_shown';
|
|
6
|
+
/**
|
|
7
|
+
* Analytics event payload
|
|
8
|
+
* Fields are populated based on event type:
|
|
9
|
+
* - qa_bot_opened: sessionId
|
|
10
|
+
* - qa_bot_closed: sessionId, messageCount, durationMs
|
|
11
|
+
* - qa_new_chat_started: sessionId, previousMessageCount
|
|
12
|
+
* - qa_question_asked: sessionId, queryId, questionLength
|
|
13
|
+
* - qa_response_received: sessionId, queryId, responseTimeMs, success, responseLength, hasMetadata
|
|
14
|
+
* - qa_response_error: sessionId, queryId, errorType
|
|
15
|
+
* - qa_response_rated: sessionId, queryId, rating
|
|
16
|
+
* - qa_login_prompt_shown: sessionId
|
|
17
|
+
*/
|
|
18
|
+
export interface QABotAnalyticsEvent {
|
|
19
|
+
type: QABotAnalyticsEventType;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
sessionId?: string;
|
|
22
|
+
queryId?: string;
|
|
23
|
+
questionLength?: number;
|
|
24
|
+
responseTimeMs?: number;
|
|
25
|
+
success?: boolean;
|
|
26
|
+
responseLength?: number;
|
|
27
|
+
hasMetadata?: boolean;
|
|
28
|
+
errorType?: string;
|
|
29
|
+
rating?: 'helpful' | 'not_helpful';
|
|
30
|
+
messageCount?: number;
|
|
31
|
+
durationMs?: number;
|
|
32
|
+
previousMessageCount?: number;
|
|
33
|
+
}
|
|
2
34
|
export interface QABotProps {
|
|
3
35
|
apiKey: string;
|
|
4
36
|
qaEndpoint: string;
|
|
@@ -31,12 +63,28 @@ export interface QABotProps {
|
|
|
31
63
|
* - Does not affect custom flows (tickets, security, etc.)
|
|
32
64
|
*/
|
|
33
65
|
allowAnonAccess?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* The acting user's identifier (e.g., email or username).
|
|
68
|
+
* - Sent to the backend in both headers (X-Acting-User) and body (acting_user)
|
|
69
|
+
* - Optional: if not provided, requests will be anonymous
|
|
70
|
+
*/
|
|
71
|
+
actingUser?: string;
|
|
34
72
|
/**
|
|
35
73
|
* Custom flow steps to merge with the built-in Q&A flow.
|
|
36
74
|
* Use this to add ticket creation flows, feedback flows, etc.
|
|
37
75
|
* These steps will be merged into the flow object.
|
|
38
76
|
*/
|
|
39
77
|
customFlow?: Flow;
|
|
78
|
+
/**
|
|
79
|
+
* Callback fired when trackable events occur.
|
|
80
|
+
* Use this to wire up analytics (GTM, GA4, etc.)
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* onAnalyticsEvent={(event) => {
|
|
84
|
+
* window.dataLayer?.push({ event: event.type, ...event });
|
|
85
|
+
* }}
|
|
86
|
+
*/
|
|
87
|
+
onAnalyticsEvent?: (event: QABotAnalyticsEvent) => void;
|
|
40
88
|
}
|
|
41
89
|
/**
|
|
42
90
|
* Default values for overridable props
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { QABotAnalyticsEvent } from '../config';
|
|
3
|
+
interface AnalyticsContextValue {
|
|
4
|
+
trackEvent: (event: Omit<QABotAnalyticsEvent, 'timestamp'>) => void;
|
|
5
|
+
}
|
|
6
|
+
interface AnalyticsProviderProps {
|
|
7
|
+
onAnalyticsEvent?: (event: QABotAnalyticsEvent) => void;
|
|
8
|
+
getSessionId: () => string | null;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare const AnalyticsProvider: React.FC<AnalyticsProviderProps>;
|
|
12
|
+
export declare const useAnalytics: () => AnalyticsContextValue;
|
|
13
|
+
export {};
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
interface SessionContextType {
|
|
3
|
+
getSessionId: () => string;
|
|
4
|
+
setSessionId: (sessionId: string) => void;
|
|
3
5
|
resetSession: () => void;
|
|
4
6
|
clearResettingFlag: () => void;
|
|
5
7
|
}
|
|
6
8
|
export declare const SessionProvider: React.FC<{
|
|
7
9
|
children: React.ReactNode;
|
|
10
|
+
getSessionId: () => string;
|
|
11
|
+
setSessionId: (sessionId: string) => void;
|
|
8
12
|
resetSession: () => void;
|
|
9
13
|
clearResettingFlag: () => void;
|
|
10
14
|
}>;
|
package/dist/types/lib.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import QABot from './components/QABot';
|
|
2
|
+
import type { QABotAnalyticsEvent } from './config';
|
|
2
3
|
import './styles/index.css';
|
|
3
4
|
export { QABot };
|
|
4
5
|
export { FileUploadComponent } from './components/FileUploadComponent';
|
|
@@ -9,7 +10,7 @@ export { fileToBase64, filesToBase64, validateFileSize, formatFileSize } from '.
|
|
|
9
10
|
export type { ProcessedFile } from './utils/file-utils';
|
|
10
11
|
export { applyFlowSettings } from './utils/flow-settings';
|
|
11
12
|
export type { FlowSettingsOptions } from './utils/flow-settings';
|
|
12
|
-
export type { QABotProps, BotControllerHandle } from './config';
|
|
13
|
+
export type { QABotProps, BotControllerHandle, QABotAnalyticsEvent, QABotAnalyticsEventType } from './config';
|
|
13
14
|
/**
|
|
14
15
|
* ===========================================
|
|
15
16
|
* PROGRAMMATIC API TYPES
|
|
@@ -34,6 +35,7 @@ interface QABotConfig {
|
|
|
34
35
|
footerText?: string;
|
|
35
36
|
footerLink?: string;
|
|
36
37
|
tooltipText?: string;
|
|
38
|
+
onAnalyticsEvent?: (event: QABotAnalyticsEvent) => void;
|
|
37
39
|
}
|
|
38
40
|
interface QABotInstance {
|
|
39
41
|
addMessage: (message: string) => void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fix-markdown-links.ts
|
|
3
|
+
*
|
|
4
|
+
* PRAGMATIC HACK: This file exists because react-chatbotify's MarkdownRenderer plugin
|
|
5
|
+
* doesn't process messages injected via replaceMessages() (used for history restoration).
|
|
6
|
+
*
|
|
7
|
+
* After trying several "proper" approaches (tag manipulation, JSX conversion, HTML strings),
|
|
8
|
+
* none worked without breaking message bubble styling. This DOM post-processing approach
|
|
9
|
+
* is a pragmatic solution that:
|
|
10
|
+
* - Preserves all message styling (bubbles render correctly first)
|
|
11
|
+
* - Simply finds raw markdown link patterns [text](url) in rendered text
|
|
12
|
+
* - Replaces them with actual <a> elements
|
|
13
|
+
*
|
|
14
|
+
* Only used after history restoration, not during normal chat flow.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Fixes markdown links in chat messages after they've been rendered.
|
|
18
|
+
* Call this after replaceMessages() to convert [text](url) patterns to clickable links.
|
|
19
|
+
*/
|
|
20
|
+
export declare const fixMarkdownLinksInDom: () => void;
|
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { QABotAnalyticsEvent } from '../../config';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
* Handles questions, responses, and optional ratings
|
|
5
|
-
*
|
|
6
|
-
* @param {Object} params Configuration
|
|
7
|
-
* @param {string} params.endpoint Q&A API endpoint (required)
|
|
8
|
-
* @param {string} params.ratingEndpoint Rating API endpoint (optional)
|
|
9
|
-
* @param {string} params.apiKey API key for authentication (optional)
|
|
10
|
-
* @param {Function} params.sessionId Function that returns current session ID
|
|
11
|
-
* @param {Function} params.isResetting Function that returns whether we're currently resetting
|
|
12
|
-
* @param {boolean} params.isLoggedIn Whether the user is logged in (required)
|
|
13
|
-
* @param {boolean} params.allowAnonAccess Allow Q&A without login (default: false)
|
|
14
|
-
* @param {string} params.loginUrl Login URL to redirect to (optional)
|
|
15
|
-
* @returns {Object} Q&A flow configuration
|
|
4
|
+
* Configuration for creating a Q&A flow
|
|
16
5
|
*/
|
|
17
|
-
export
|
|
18
|
-
endpoint
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
export interface CreateQAFlowParams {
|
|
7
|
+
/** Q&A API endpoint (required) */
|
|
8
|
+
endpoint: string;
|
|
9
|
+
/** Rating API endpoint (optional) */
|
|
10
|
+
ratingEndpoint?: string;
|
|
11
|
+
/** API key for authentication (optional) */
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
/** Function that returns current session ID */
|
|
14
|
+
sessionId: () => string | null;
|
|
15
|
+
/** Function that returns whether we're currently resetting */
|
|
22
16
|
isResetting?: () => boolean;
|
|
23
|
-
|
|
17
|
+
/** Whether the user is logged in (required) */
|
|
18
|
+
isLoggedIn: boolean;
|
|
19
|
+
/** Allow Q&A without login (default: false) */
|
|
24
20
|
allowAnonAccess?: boolean;
|
|
21
|
+
/** Login URL to redirect to (optional) */
|
|
25
22
|
loginUrl?: string;
|
|
26
|
-
|
|
23
|
+
/** The acting user's identifier (optional) */
|
|
24
|
+
actingUser?: string;
|
|
25
|
+
/** Callback for analytics events (optional) */
|
|
26
|
+
onAnalyticsEvent?: (event: QABotAnalyticsEvent) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates the basic Q&A conversation flow
|
|
30
|
+
* Handles questions, responses, and optional ratings
|
|
31
|
+
*/
|
|
32
|
+
export declare const createQAFlow: ({ endpoint, ratingEndpoint, apiKey, sessionId: getSessionId, isResetting, isLoggedIn, allowAnonAccess, loginUrl, actingUser, onAnalyticsEvent }: CreateQAFlowParams) => {
|
|
27
33
|
qa_loop: {
|
|
28
34
|
message: string;
|
|
29
35
|
component: React.JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for QA Bot Core
|
|
3
|
+
*
|
|
4
|
+
* Controls debug logging via localStorage:
|
|
5
|
+
* - QA_BOT_DEBUG: Set to 'true' to enable debug logging and version info
|
|
6
|
+
*
|
|
7
|
+
* Usage for consumers:
|
|
8
|
+
* localStorage.setItem('QA_BOT_DEBUG', 'true'); // Enable debug logs + version
|
|
9
|
+
*/
|
|
10
|
+
export declare const LIB_VERSION = "0.2.7";
|
|
11
|
+
export declare const logger: {
|
|
12
|
+
version: () => void;
|
|
13
|
+
session: (action: string, ...args: unknown[]) => void;
|
|
14
|
+
history: (action: string, ...args: unknown[]) => void;
|
|
15
|
+
warn: (...args: unknown[]) => void;
|
|
16
|
+
error: (...args: unknown[]) => void;
|
|
17
|
+
};
|
|
@@ -1,2 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stored message structure - minimal data needed for restore
|
|
3
|
+
*/
|
|
4
|
+
export interface StoredMessage {
|
|
5
|
+
id: string;
|
|
6
|
+
content: string;
|
|
7
|
+
sender: string;
|
|
8
|
+
type: string;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Session data structure
|
|
13
|
+
*/
|
|
14
|
+
export interface SessionMessageData {
|
|
15
|
+
messages: StoredMessage[];
|
|
16
|
+
startedAt: string;
|
|
17
|
+
preview: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SessionMessagesStore {
|
|
20
|
+
[sessionId: string]: SessionMessageData;
|
|
21
|
+
}
|
|
1
22
|
export declare const generateSessionId: () => string;
|
|
2
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Get the session messages store from localStorage
|
|
25
|
+
*/
|
|
26
|
+
export declare const getSessionMessagesStore: () => SessionMessagesStore;
|
|
27
|
+
/**
|
|
28
|
+
* Add a message to a session's storage.
|
|
29
|
+
* Called when RcbPreInjectMessageEvent fires.
|
|
30
|
+
* Stores the full message so we can restore sessions without relying on RCB's history.
|
|
31
|
+
*/
|
|
32
|
+
export declare const addMessageToSession: (sessionId: string, messageId: string, messageContent: string, sender: string, type: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Get all sessions with their metadata (for history display)
|
|
35
|
+
*/
|
|
36
|
+
export declare const getAllSessions: () => Array<{
|
|
37
|
+
sessionId: string;
|
|
38
|
+
} & SessionMessageData>;
|
|
39
|
+
/**
|
|
40
|
+
* Get all stored messages for a specific session.
|
|
41
|
+
* Returns messages in the format needed for RCB's replaceMessages().
|
|
42
|
+
*/
|
|
43
|
+
export declare const getSessionMessages: (sessionId: string) => StoredMessage[];
|
|
44
|
+
/**
|
|
45
|
+
* Get the message count for a session.
|
|
46
|
+
* Used for analytics (qa_bot_closed, qa_new_chat_started events).
|
|
47
|
+
*/
|
|
48
|
+
export declare const getSessionMessageCount: (sessionId: string) => number;
|
|
49
|
+
/**
|
|
50
|
+
* Compute how long a session has been active (in milliseconds).
|
|
51
|
+
* Calculates the difference between now and the session's startedAt timestamp.
|
|
52
|
+
* Used for analytics (qa_bot_closed event).
|
|
53
|
+
*/
|
|
54
|
+
export declare const computeSessionDurationMs: (sessionId: string) => number;
|
package/package.json
CHANGED