@courseecho/ai-widget-react 1.0.24 → 1.0.25

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.
@@ -1,387 +0,0 @@
1
- /**
2
- * AI Widget SDK - Core SDK
3
- * Main orchestrator that ties everything together
4
- */
5
- import { AiCommunicationService, ApiError } from './communication-service';
6
- import { ChatStateManager, ContextStateManager, ChartManager, SuggestionManager, } from './state-manager';
7
- import { PageContentScanner, AiSuggestionGenerator, } from './auto-suggestion-generator';
8
- export class AiWidgetSDK {
9
- constructor(config) {
10
- this.validateConfig(config);
11
- this.config = { apiEndpoint: 'https://ai.courseecho.com', ...config };
12
- // Initialize services
13
- this.communicationService = new AiCommunicationService(this.config.apiEndpoint, this.config.apiKey);
14
- this.chatStateManager = new ChatStateManager(config.maxChatHistory ?? 100);
15
- this.contextStateManager = new ContextStateManager(config.context);
16
- this.chartManager = new ChartManager();
17
- this.suggestionManager = new SuggestionManager(config.suggestionConfig);
18
- // Initialize auto-suggestion components
19
- this.pageContentScanner = new PageContentScanner(config.suggestionConfig?.pageScanning);
20
- this.suggestionGenerator = new AiSuggestionGenerator(config.suggestionConfig?.aiConfig, this.pageContentScanner);
21
- // Initialize auto-suggestions if enabled
22
- this.initializeAutoSuggestions();
23
- }
24
- /**
25
- * Initialize auto-suggestions based on page content
26
- */
27
- async initializeAutoSuggestions() {
28
- const suggestionConfig = this.config.suggestionConfig;
29
- // Check if auto-generation is enabled
30
- if (!suggestionConfig?.autoGenerate) {
31
- return;
32
- }
33
- // Check tier: free tier gets suggestions automatically
34
- if (suggestionConfig.autoGenerateFreeTier !== false) {
35
- try {
36
- const autoSuggestions = await this.suggestionGenerator.generateSuggestions();
37
- // Merge with user-provided suggestions if configured
38
- if (suggestionConfig.pageScanning?.mergeWithUserSuggestions !== false) {
39
- const existingSuggestions = this.suggestionManager.getSuggestions();
40
- this.suggestionManager.addSuggestions(autoSuggestions);
41
- }
42
- else {
43
- // Replace with auto-generated suggestions
44
- this.suggestionManager.clearSuggestions();
45
- this.suggestionManager.addSuggestions(autoSuggestions);
46
- }
47
- }
48
- catch (error) {
49
- console.error('Error generating auto-suggestions:', error);
50
- }
51
- }
52
- // Set up periodic re-scanning if configured
53
- if (suggestionConfig.pageScanning?.autoScan) {
54
- const scanInterval = suggestionConfig.pageScanning.scanInterval || 60000; // 60 seconds default
55
- this.autoSuggestionInterval = setInterval(async () => {
56
- try {
57
- const freshSuggestions = await this.suggestionGenerator.generateSuggestions();
58
- if (suggestionConfig.pageScanning?.mergeWithUserSuggestions === false) {
59
- this.suggestionManager.clearSuggestions();
60
- }
61
- this.suggestionManager.addSuggestions(freshSuggestions);
62
- }
63
- catch (error) {
64
- console.error('Error refreshing auto-suggestions:', error);
65
- }
66
- }, scanInterval);
67
- }
68
- }
69
- /**
70
- * Validate configuration
71
- */
72
- validateConfig(config) {
73
- if (!config.context) {
74
- throw new Error('context is required in config');
75
- }
76
- }
77
- /**
78
- * Set JWT token for authentication
79
- */
80
- setJwtToken(token) {
81
- this.communicationService.setJwtToken(token);
82
- }
83
- /**
84
- * Send a query to the AI backend
85
- */
86
- async sendQuery(userQuery) {
87
- try {
88
- this.chatStateManager.setLoading(true);
89
- this.chatStateManager.setError(null);
90
- // Add user message to chat
91
- const userMessage = {
92
- id: this.generateId(),
93
- role: 'user',
94
- content: userQuery,
95
- timestamp: new Date(),
96
- };
97
- this.chatStateManager.addMessage(userMessage);
98
- // Prepare request
99
- const request = {
100
- userQuery,
101
- pageType: this.contextStateManager.getContext().pageType,
102
- entityId: this.contextStateManager.getContext().entityId,
103
- contextData: this.contextStateManager.getContext().customData,
104
- };
105
- // Send to backend
106
- const response = await this.communicationService.sendQuery(request);
107
- // Add assistant message
108
- const assistantMessage = {
109
- id: response.sessionId,
110
- role: 'assistant',
111
- content: response.response,
112
- timestamp: response.timestamp,
113
- metadata: {
114
- hasChart: false,
115
- charts: [],
116
- suggestedFollowUps: [],
117
- },
118
- };
119
- // Cache charts if any
120
- if (assistantMessage.metadata?.charts && assistantMessage.metadata.charts.length > 0) {
121
- assistantMessage.metadata.hasChart = true;
122
- assistantMessage.metadata.charts.forEach((chart, index) => {
123
- this.chartManager.cacheChart(`${response.sessionId}_${index}`, chart);
124
- });
125
- }
126
- this.chatStateManager.addMessage(assistantMessage);
127
- return assistantMessage;
128
- }
129
- catch (error) {
130
- const errorMessage = this.getErrorMessage(error);
131
- this.chatStateManager.setError(errorMessage);
132
- throw error;
133
- }
134
- finally {
135
- this.chatStateManager.setLoading(false);
136
- }
137
- }
138
- /**
139
- * Update context
140
- */
141
- setContext(context) {
142
- const currentContext = this.contextStateManager.getContext();
143
- this.contextStateManager.setContext({
144
- ...currentContext,
145
- ...context,
146
- });
147
- }
148
- /**
149
- * Update single context property
150
- */
151
- updateContextProperty(key, value) {
152
- this.contextStateManager.updateProperty(key, value);
153
- }
154
- /**
155
- * Get current context
156
- */
157
- getContext() {
158
- return this.contextStateManager.getContext();
159
- }
160
- /**
161
- * Clear chat history
162
- */
163
- clearChatHistory() {
164
- this.chatStateManager.clearMessages();
165
- this.chartManager.clearCache();
166
- }
167
- /**
168
- * Get chat messages
169
- */
170
- getMessages() {
171
- return this.chatStateManager.getMessages();
172
- }
173
- /**
174
- * Get current error
175
- */
176
- getError() {
177
- return this.chatStateManager.getError();
178
- }
179
- /**
180
- * Check if loading
181
- */
182
- isLoading() {
183
- return this.chatStateManager.isLoadingState();
184
- }
185
- /**
186
- * Export chat history
187
- */
188
- exportChats(format = 'json') {
189
- const messages = this.getMessages();
190
- if (format === 'json') {
191
- return JSON.stringify({
192
- context: this.getContext(),
193
- messages,
194
- exportedAt: new Date(),
195
- }, null, 2);
196
- }
197
- else {
198
- const headers = ['Timestamp', 'Role', 'Content'];
199
- const rows = [headers.join(',')];
200
- messages.forEach((msg) => {
201
- const row = [
202
- new Date(msg.timestamp).toISOString(),
203
- msg.role,
204
- `"${msg.content.replace(/"/g, '""')}"`, // Escape quotes
205
- ];
206
- rows.push(row.join(','));
207
- });
208
- return rows.join('\n');
209
- }
210
- }
211
- /**
212
- * Export charts
213
- */
214
- exportCharts(format = 'json') {
215
- if (format === 'json') {
216
- return this.chartManager.exportToJSON();
217
- }
218
- else {
219
- return this.chartManager.exportToCSV();
220
- }
221
- }
222
- /**
223
- * Check backend health
224
- */
225
- async checkHealth() {
226
- return this.communicationService.checkHealth();
227
- }
228
- /**
229
- * Subscribe to message changes
230
- */
231
- onMessagesChange(listener) {
232
- return this.chatStateManager.onMessagesChange(listener);
233
- }
234
- /**
235
- * Subscribe to loading changes
236
- */
237
- onLoadingChange(listener) {
238
- return this.chatStateManager.onLoadingChange(listener);
239
- }
240
- /**
241
- * Subscribe to error changes
242
- */
243
- onErrorChange(listener) {
244
- return this.chatStateManager.onErrorChange(listener);
245
- }
246
- /**
247
- * Subscribe to context changes
248
- */
249
- onContextChange(listener) {
250
- return this.contextStateManager.onContextChange(listener);
251
- }
252
- /**
253
- * Get all suggestions
254
- */
255
- getSuggestions() {
256
- return this.suggestionManager.getSuggestions();
257
- }
258
- /**
259
- * Filter suggestions based on query
260
- */
261
- filterSuggestions(query) {
262
- return this.suggestionManager.filterSuggestions(query);
263
- }
264
- /**
265
- * Get suggestions by category
266
- */
267
- getSuggestionsByCategory(category) {
268
- return this.suggestionManager.getSuggestionsByCategory(category);
269
- }
270
- /**
271
- * Add a suggestion
272
- */
273
- addSuggestion(suggestion) {
274
- this.suggestionManager.addSuggestion(suggestion);
275
- }
276
- /**
277
- * Add multiple suggestions
278
- */
279
- addSuggestions(suggestions) {
280
- this.suggestionManager.addSuggestions(suggestions);
281
- }
282
- /**
283
- * Remove a suggestion by id
284
- */
285
- removeSuggestion(id) {
286
- this.suggestionManager.removeSuggestion(id);
287
- }
288
- /**
289
- * Clear all suggestions
290
- */
291
- clearSuggestions() {
292
- this.suggestionManager.clearSuggestions();
293
- }
294
- /**
295
- * Update suggestion
296
- */
297
- updateSuggestion(id, updates) {
298
- this.suggestionManager.updateSuggestion(id, updates);
299
- }
300
- /**
301
- * Subscribe to suggestion changes
302
- */
303
- onSuggestionsChange(listener) {
304
- return this.suggestionManager.onSuggestionsChange(listener);
305
- }
306
- /**
307
- * Get suggestion manager for advanced use
308
- */
309
- getSuggestionManager() {
310
- return this.suggestionManager;
311
- }
312
- /**
313
- * Get internal services (for advanced use)
314
- */
315
- getServices() {
316
- return {
317
- communication: this.communicationService,
318
- chatState: this.chatStateManager,
319
- contextState: this.contextStateManager,
320
- charts: this.chartManager,
321
- suggestions: this.suggestionManager,
322
- };
323
- }
324
- /**
325
- * Trigger manual page scan for auto-suggestions
326
- */
327
- async triggerAutoSuggestions() {
328
- try {
329
- const suggestions = await this.suggestionGenerator.generateSuggestions();
330
- if (this.config.suggestionConfig?.pageScanning?.mergeWithUserSuggestions === false) {
331
- this.suggestionManager.clearSuggestions();
332
- }
333
- this.suggestionManager.addSuggestions(suggestions);
334
- }
335
- catch (error) {
336
- console.error('Error triggering auto-suggestions:', error);
337
- }
338
- }
339
- /**
340
- * Get page content scanner
341
- */
342
- getPageContentScanner() {
343
- return this.pageContentScanner;
344
- }
345
- /**
346
- * Get suggestion generator
347
- */
348
- getSuggestionGenerator() {
349
- return this.suggestionGenerator;
350
- }
351
- /**
352
- * Stop auto-suggestion scanning
353
- */
354
- stopAutoSuggestions() {
355
- if (this.autoSuggestionInterval) {
356
- clearInterval(this.autoSuggestionInterval);
357
- this.autoSuggestionInterval = undefined;
358
- }
359
- }
360
- /**
361
- * Private helper to generate unique IDs
362
- */
363
- generateId() {
364
- return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
365
- }
366
- /**
367
- * Private helper to extract error message
368
- */
369
- getErrorMessage(error) {
370
- if (error instanceof ApiError) {
371
- if (error.isRateLimited()) {
372
- return 'Too many requests. Please wait before sending more queries.';
373
- }
374
- if (error.isUnauthorized()) {
375
- return 'Authentication failed. Please check your token.';
376
- }
377
- if (error.isBadRequest()) {
378
- return 'Invalid request. Please check your query.';
379
- }
380
- if (error.isServerError()) {
381
- return 'Server error. Please try again later.';
382
- }
383
- return error.message;
384
- }
385
- return String(error);
386
- }
387
- }
@@ -1,200 +0,0 @@
1
- /**
2
- * AI Widget SDK - Core Chat State Manager
3
- * Manage chat messages, loading state, errors - framework-agnostic
4
- */
5
- import { AiMessage, AiChart, AiContext, AiSuggestion, SuggestionConfig } from './models';
6
- export type StateListener<T> = (state: T) => void;
7
- /**
8
- * Core Chat State - manages messages and loading states
9
- */
10
- export declare class ChatStateManager {
11
- private messages;
12
- private maxChatHistory;
13
- private isLoading;
14
- private error;
15
- private messageListeners;
16
- private loadingListeners;
17
- private errorListeners;
18
- constructor(maxChatHistory?: number);
19
- /**
20
- * Add a new message
21
- */
22
- addMessage(message: AiMessage): void;
23
- /**
24
- * Get all messages
25
- */
26
- getMessages(): AiMessage[];
27
- /**
28
- * Clear all messages
29
- */
30
- clearMessages(): void;
31
- /**
32
- * Set loading state
33
- */
34
- setLoading(isLoading: boolean): void;
35
- /**
36
- * Get loading state
37
- */
38
- isLoadingState(): boolean;
39
- /**
40
- * Set error
41
- */
42
- setError(error: string | null): void;
43
- /**
44
- * Get current error
45
- */
46
- getError(): string | null;
47
- /**
48
- * Get last message
49
- */
50
- getLastMessage(): AiMessage | undefined;
51
- /**
52
- * Get message count
53
- */
54
- getMessageCount(): number;
55
- /**
56
- * Subscribe to message changes
57
- */
58
- onMessagesChange(listener: StateListener<AiMessage[]>): () => void;
59
- /**
60
- * Subscribe to loading changes
61
- */
62
- onLoadingChange(listener: StateListener<boolean>): () => void;
63
- /**
64
- * Subscribe to error changes
65
- */
66
- onErrorChange(listener: StateListener<string | null>): () => void;
67
- private notifyMessageListeners;
68
- private notifyLoadingListeners;
69
- private notifyErrorListeners;
70
- }
71
- /**
72
- * Core Context State - manages page context
73
- */
74
- export declare class ContextStateManager {
75
- private context;
76
- private contextHistory;
77
- private contextListeners;
78
- constructor(initialContext: AiContext);
79
- /**
80
- * Update entire context
81
- */
82
- setContext(context: AiContext): void;
83
- /**
84
- * Update single context property
85
- */
86
- updateProperty(key: string, value: any): void;
87
- /**
88
- * Get current context
89
- */
90
- getContext(): AiContext;
91
- /**
92
- * Get context history
93
- */
94
- getHistory(): AiContext[];
95
- /**
96
- * Get single context property
97
- */
98
- getProperty(key: string): any;
99
- /**
100
- * Subscribe to context changes
101
- */
102
- onContextChange(listener: StateListener<AiContext>): () => void;
103
- /**
104
- * Serialize context
105
- */
106
- serialize(): string;
107
- private notifyContextListeners;
108
- }
109
- /**
110
- * Chart Manager - manage charts caching and export
111
- */
112
- export declare class ChartManager {
113
- private charts;
114
- /**
115
- * Cache a chart
116
- */
117
- cacheChart(id: string, chart: AiChart): void;
118
- /**
119
- * Get cached chart
120
- */
121
- getChart(id: string): AiChart | undefined;
122
- /**
123
- * Get all cached charts
124
- */
125
- getAllCharts(): AiChart[];
126
- /**
127
- * Clear cache
128
- */
129
- clearCache(): void;
130
- /**
131
- * Export charts to CSV
132
- */
133
- exportToCSV(filename?: string): string;
134
- /**
135
- * Export charts to JSON
136
- */
137
- exportToJSON(): string;
138
- }
139
- /**
140
- * Suggestion Manager - manage suggestions for chat queries
141
- */
142
- export declare class SuggestionManager {
143
- private suggestions;
144
- private config;
145
- private suggestionListeners;
146
- constructor(config?: SuggestionConfig);
147
- /**
148
- * Get all suggestions
149
- */
150
- getSuggestions(): AiSuggestion[];
151
- /**
152
- * Filter suggestions based on query
153
- */
154
- filterSuggestions(query: string): AiSuggestion[];
155
- /**
156
- * Get suggestions by category
157
- */
158
- getSuggestionsByCategory(category: string): AiSuggestion[];
159
- /**
160
- * Add a suggestion
161
- */
162
- addSuggestion(suggestion: AiSuggestion): void;
163
- /**
164
- * Add multiple suggestions
165
- */
166
- addSuggestions(suggestions: AiSuggestion[]): void;
167
- /**
168
- * Remove a suggestion by id
169
- */
170
- removeSuggestion(id: string): void;
171
- /**
172
- * Clear all suggestions
173
- */
174
- clearSuggestions(): void;
175
- /**
176
- * Update suggestion
177
- */
178
- updateSuggestion(id: string, updates: Partial<AiSuggestion>): void;
179
- /**
180
- * Check if suggestions are enabled
181
- */
182
- isEnabled(): boolean;
183
- /**
184
- * Toggle suggestions on/off
185
- */
186
- toggleEnabled(): void;
187
- /**
188
- * Subscribe to suggestion changes
189
- */
190
- onSuggestionsChange(listener: StateListener<AiSuggestion[]>): () => void;
191
- /**
192
- * Get config
193
- */
194
- getConfig(): SuggestionConfig;
195
- /**
196
- * Update config
197
- */
198
- updateConfig(config: Partial<SuggestionConfig>): void;
199
- private notifySuggestionListeners;
200
- }