@courseecho/ai-widget-react 1.0.23 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ /**
2
+ * AI Widget SDK - Core Communication Service
3
+ * Handle HTTP requests to backend API
4
+ */
5
+ /** Safely parse a Response body as JSON — returns null for empty/non-JSON bodies instead of throwing. */
6
+ async function safeJson(res) {
7
+ const text = await res.text();
8
+ if (!text || !text.trim())
9
+ return null;
10
+ try {
11
+ return JSON.parse(text);
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ export class AiCommunicationService {
18
+ constructor(apiEndpoint, apiKey) {
19
+ if (!apiEndpoint) {
20
+ throw new Error('apiEndpoint is required');
21
+ }
22
+ this.apiEndpoint = apiEndpoint.replace(/\/$/, ''); // Remove trailing slash
23
+ this.apiKey = apiKey;
24
+ }
25
+ /**
26
+ * Set JWT token for authentication
27
+ */
28
+ setJwtToken(token) {
29
+ this.jwtToken = token;
30
+ }
31
+ /**
32
+ * Get current JWT token
33
+ */
34
+ getJwtToken() {
35
+ return this.jwtToken;
36
+ }
37
+ /**
38
+ * Check if JWT token is set
39
+ */
40
+ isAuthenticated() {
41
+ return !!this.jwtToken;
42
+ }
43
+ /**
44
+ * Send query to backend API
45
+ */
46
+ async sendQuery(request) {
47
+ if (!this.jwtToken && !this.apiKey) {
48
+ throw new Error('Authentication required: Set JWT token or API key. Call setJwtToken() first.');
49
+ }
50
+ const headers = {
51
+ 'Content-Type': 'application/json',
52
+ };
53
+ if (this.jwtToken) {
54
+ headers['Authorization'] = `Bearer ${this.jwtToken}`;
55
+ }
56
+ else if (this.apiKey) {
57
+ headers['X-API-Key'] = this.apiKey;
58
+ }
59
+ try {
60
+ const response = await fetch(`${this.apiEndpoint}/api/aiorchestrator/query`, {
61
+ method: 'POST',
62
+ headers,
63
+ body: JSON.stringify(request),
64
+ });
65
+ if (!response.ok) {
66
+ const errorData = await safeJson(response);
67
+ throw new ApiError(errorData?.message || `HTTP ${response.status}`, response.status, errorData);
68
+ }
69
+ const data = (await safeJson(response));
70
+ if (!data)
71
+ throw new ApiError('Empty response from server', 500);
72
+ // Ensure timestamp is a Date object
73
+ data.timestamp = new Date(data.timestamp);
74
+ return data;
75
+ }
76
+ catch (error) {
77
+ if (error instanceof ApiError) {
78
+ throw error;
79
+ }
80
+ throw new ApiError(`Failed to send query: ${String(error)}`, 500);
81
+ }
82
+ }
83
+ /**
84
+ * Check backend health
85
+ */
86
+ async checkHealth() {
87
+ try {
88
+ const response = await fetch(`${this.apiEndpoint}/health`);
89
+ return response.ok;
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ /**
96
+ * Get API endpoint
97
+ */
98
+ getApiEndpoint() {
99
+ return this.apiEndpoint;
100
+ }
101
+ }
102
+ /**
103
+ * Custom API Error class
104
+ */
105
+ export class ApiError extends Error {
106
+ constructor(message, statusCode, responseData) {
107
+ super(message);
108
+ this.statusCode = statusCode;
109
+ this.responseData = responseData;
110
+ this.name = 'ApiError';
111
+ }
112
+ isRateLimited() {
113
+ return this.statusCode === 429;
114
+ }
115
+ isUnauthorized() {
116
+ return this.statusCode === 401;
117
+ }
118
+ isBadRequest() {
119
+ return this.statusCode === 400;
120
+ }
121
+ isServerError() {
122
+ return this.statusCode >= 500;
123
+ }
124
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * AI Widget Core SDK - Public API
3
+ * Framework-agnostic core library
4
+ */
5
+ export * from './models';
6
+ export { AiCommunicationService, ApiError } from './communication-service';
7
+ export { ChatStateManager, ContextStateManager, ChartManager, SuggestionManager, } from './state-manager';
8
+ export { PageContentScanner, AiSuggestionGenerator, type PageContent, } from './auto-suggestion-generator';
9
+ export { AiWidgetSDK } from './sdk';
10
+ export type { StateListener } from './state-manager';
11
+ export { WIDGET_CSS } from './widget-css';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AI Widget Core SDK - Public API
3
+ * Framework-agnostic core library
4
+ */
5
+ // Models
6
+ export * from './models';
7
+ // Services
8
+ export { AiCommunicationService, ApiError } from './communication-service';
9
+ export { ChatStateManager, ContextStateManager, ChartManager, SuggestionManager, } from './state-manager';
10
+ // Auto-suggestion & page scanning
11
+ export { PageContentScanner, AiSuggestionGenerator, } from './auto-suggestion-generator';
12
+ // Main SDK
13
+ export { AiWidgetSDK } from './sdk';
14
+ // Canonical widget CSS (used by all framework packages)
15
+ export { WIDGET_CSS } from './widget-css';
@@ -0,0 +1,137 @@
1
+ /**
2
+ * AI Widget SDK - Shared Models
3
+ * Framework-agnostic type definitions used across all implementations
4
+ */
5
+ export interface AiMessage {
6
+ id: string;
7
+ role: 'user' | 'assistant';
8
+ content: string;
9
+ timestamp: Date;
10
+ metadata?: {
11
+ hasChart: boolean;
12
+ charts?: AiChart[];
13
+ suggestedFollowUps?: string[];
14
+ };
15
+ }
16
+ export interface AiChart {
17
+ type: 'bar' | 'line' | 'pie' | 'doughnut' | 'radar';
18
+ title: string;
19
+ labels: string[];
20
+ datasets: ChartDataset[];
21
+ options?: ChartOptions;
22
+ }
23
+ export interface ChartDataset {
24
+ label: string;
25
+ data: number[];
26
+ backgroundColor?: string | string[];
27
+ borderColor?: string | string[];
28
+ tension?: number;
29
+ fill?: boolean;
30
+ }
31
+ export interface ChartOptions {
32
+ responsive?: boolean;
33
+ maintainAspectRatio?: boolean;
34
+ plugins?: {
35
+ legend?: {
36
+ display?: boolean;
37
+ position?: 'top' | 'bottom' | 'left' | 'right';
38
+ };
39
+ tooltip?: {
40
+ enabled?: boolean;
41
+ };
42
+ };
43
+ scales?: Record<string, any>;
44
+ }
45
+ export interface AiContext {
46
+ pageType: string;
47
+ entityId?: string;
48
+ userId?: string;
49
+ customData?: Record<string, any>;
50
+ }
51
+ export interface AiContextConfig {
52
+ context: AiContext;
53
+ apiEndpoint?: string;
54
+ apiKey?: string;
55
+ maxChatHistory?: number;
56
+ theme?: 'light' | 'dark';
57
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
58
+ enableCharts?: boolean;
59
+ enableExport?: boolean;
60
+ suggestionConfig?: SuggestionConfig;
61
+ }
62
+ export interface AiQueryRequest {
63
+ userQuery: string;
64
+ pageType: string;
65
+ entityId?: string;
66
+ contextData?: Record<string, any>;
67
+ [key: string]: any;
68
+ }
69
+ export interface AiQueryResponse {
70
+ sessionId: string;
71
+ response: string;
72
+ toolsUsed: string[];
73
+ tokensUsed: number;
74
+ cost: number;
75
+ timestamp: Date;
76
+ }
77
+ export interface AiErrorResponse {
78
+ error: string;
79
+ message: string;
80
+ statusCode: number;
81
+ timestamp: Date;
82
+ }
83
+ export interface ChartExportOptions {
84
+ format: 'csv' | 'json';
85
+ filename?: string;
86
+ }
87
+ export interface ChatExportData {
88
+ sessionId: string;
89
+ messages: AiMessage[];
90
+ charts: AiChart[];
91
+ exportedAt: Date;
92
+ }
93
+ /**
94
+ * Suggestion Models for Auto-suggestion Feature
95
+ */
96
+ export interface AiSuggestion {
97
+ id: string;
98
+ text: string;
99
+ category?: string;
100
+ icon?: string;
101
+ description?: string;
102
+ metadata?: Record<string, any>;
103
+ }
104
+ export interface SuggestionGroup {
105
+ category: string;
106
+ suggestions: AiSuggestion[];
107
+ icon?: string;
108
+ }
109
+ export interface PageScanConfig {
110
+ enabled?: boolean;
111
+ autoScan?: boolean;
112
+ scanInterval?: number;
113
+ maxTextLength?: number;
114
+ excludeSelectors?: string[];
115
+ cacheDuration?: number;
116
+ mergeWithUserSuggestions?: boolean;
117
+ }
118
+ export interface AiSuggestionGeneratorConfig {
119
+ enabled?: boolean;
120
+ tier?: 'free' | 'premium';
121
+ backendUrl?: string;
122
+ apiKey?: string;
123
+ timeoutMs?: number;
124
+ }
125
+ export interface SuggestionConfig {
126
+ enabled: boolean;
127
+ suggestions?: AiSuggestion[];
128
+ categories?: SuggestionGroup[];
129
+ maxVisibleSuggestions?: number;
130
+ showOnFocus?: boolean;
131
+ showOnClick?: boolean;
132
+ customSuggestions?: (query: string) => Promise<AiSuggestion[]>;
133
+ autoGenerate?: boolean;
134
+ autoGenerateFreeTier?: boolean;
135
+ pageScanning?: PageScanConfig;
136
+ aiConfig?: AiSuggestionGeneratorConfig;
137
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * AI Widget SDK - Shared Models
3
+ * Framework-agnostic type definitions used across all implementations
4
+ */
5
+ export {};
@@ -0,0 +1,166 @@
1
+ /**
2
+ * AI Widget SDK - Core SDK
3
+ * Main orchestrator that ties everything together
4
+ */
5
+ import { AiCommunicationService } from './communication-service';
6
+ import { ChatStateManager, ContextStateManager, ChartManager, SuggestionManager } from './state-manager';
7
+ import { AiContextConfig, AiMessage, AiSuggestion } from './models';
8
+ import { PageContentScanner, AiSuggestionGenerator } from './auto-suggestion-generator';
9
+ export declare class AiWidgetSDK {
10
+ private communicationService;
11
+ private chatStateManager;
12
+ private contextStateManager;
13
+ private chartManager;
14
+ private suggestionManager;
15
+ private pageContentScanner;
16
+ private suggestionGenerator;
17
+ private config;
18
+ private autoSuggestionInterval?;
19
+ constructor(config: AiContextConfig);
20
+ /**
21
+ * Initialize auto-suggestions based on page content
22
+ */
23
+ initializeAutoSuggestions(): Promise<void>;
24
+ /**
25
+ * Validate configuration
26
+ */
27
+ private validateConfig;
28
+ /**
29
+ * Set JWT token for authentication
30
+ */
31
+ setJwtToken(token: string): void;
32
+ /**
33
+ * Send a query to the AI backend
34
+ */
35
+ sendQuery(userQuery: string): Promise<AiMessage>;
36
+ /**
37
+ * Update context
38
+ */
39
+ setContext(context: Partial<AiContextConfig['context']>): void;
40
+ /**
41
+ * Update single context property
42
+ */
43
+ updateContextProperty(key: string, value: any): void;
44
+ /**
45
+ * Get current context
46
+ */
47
+ getContext(): import("src").AiContext;
48
+ /**
49
+ * Clear chat history
50
+ */
51
+ clearChatHistory(): void;
52
+ /**
53
+ * Get chat messages
54
+ */
55
+ getMessages(): AiMessage[];
56
+ /**
57
+ * Get current error
58
+ */
59
+ getError(): string | null;
60
+ /**
61
+ * Check if loading
62
+ */
63
+ isLoading(): boolean;
64
+ /**
65
+ * Export chat history
66
+ */
67
+ exportChats(format?: 'json' | 'csv'): string;
68
+ /**
69
+ * Export charts
70
+ */
71
+ exportCharts(format?: 'json' | 'csv'): string;
72
+ /**
73
+ * Check backend health
74
+ */
75
+ checkHealth(): Promise<boolean>;
76
+ /**
77
+ * Subscribe to message changes
78
+ */
79
+ onMessagesChange(listener: (messages: AiMessage[]) => void): () => void;
80
+ /**
81
+ * Subscribe to loading changes
82
+ */
83
+ onLoadingChange(listener: (isLoading: boolean) => void): () => void;
84
+ /**
85
+ * Subscribe to error changes
86
+ */
87
+ onErrorChange(listener: (error: string | null) => void): () => void;
88
+ /**
89
+ * Subscribe to context changes
90
+ */
91
+ onContextChange(listener: (context: any) => void): () => void;
92
+ /**
93
+ * Get all suggestions
94
+ */
95
+ getSuggestions(): AiSuggestion[];
96
+ /**
97
+ * Filter suggestions based on query
98
+ */
99
+ filterSuggestions(query: string): AiSuggestion[];
100
+ /**
101
+ * Get suggestions by category
102
+ */
103
+ getSuggestionsByCategory(category: string): AiSuggestion[];
104
+ /**
105
+ * Add a suggestion
106
+ */
107
+ addSuggestion(suggestion: AiSuggestion): void;
108
+ /**
109
+ * Add multiple suggestions
110
+ */
111
+ addSuggestions(suggestions: AiSuggestion[]): void;
112
+ /**
113
+ * Remove a suggestion by id
114
+ */
115
+ removeSuggestion(id: string): void;
116
+ /**
117
+ * Clear all suggestions
118
+ */
119
+ clearSuggestions(): void;
120
+ /**
121
+ * Update suggestion
122
+ */
123
+ updateSuggestion(id: string, updates: Partial<AiSuggestion>): void;
124
+ /**
125
+ * Subscribe to suggestion changes
126
+ */
127
+ onSuggestionsChange(listener: (suggestions: AiSuggestion[]) => void): () => void;
128
+ /**
129
+ * Get suggestion manager for advanced use
130
+ */
131
+ getSuggestionManager(): SuggestionManager;
132
+ /**
133
+ * Get internal services (for advanced use)
134
+ */
135
+ getServices(): {
136
+ communication: AiCommunicationService;
137
+ chatState: ChatStateManager;
138
+ contextState: ContextStateManager;
139
+ charts: ChartManager;
140
+ suggestions: SuggestionManager;
141
+ };
142
+ /**
143
+ * Trigger manual page scan for auto-suggestions
144
+ */
145
+ triggerAutoSuggestions(): Promise<void>;
146
+ /**
147
+ * Get page content scanner
148
+ */
149
+ getPageContentScanner(): PageContentScanner;
150
+ /**
151
+ * Get suggestion generator
152
+ */
153
+ getSuggestionGenerator(): AiSuggestionGenerator;
154
+ /**
155
+ * Stop auto-suggestion scanning
156
+ */
157
+ stopAutoSuggestions(): void;
158
+ /**
159
+ * Private helper to generate unique IDs
160
+ */
161
+ private generateId;
162
+ /**
163
+ * Private helper to extract error message
164
+ */
165
+ private getErrorMessage;
166
+ }