cmcts-c-agent-embedding 1.0.27 → 1.0.29-cagent

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.
Files changed (106) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/.idea/{Flowise-share-chatbox.iml → flowise-chatbox.iml} +0 -1
  3. package/.idea/modules.xml +1 -2
  4. package/.idea/vcs.xml +5 -6
  5. package/AGENTS.md +166 -0
  6. package/README.md +349 -349
  7. package/dist/BubbleChat.d.ts +9 -12
  8. package/dist/BubbleChat.d.ts.map +1 -1
  9. package/dist/FullPageChat.d.ts +17 -17
  10. package/dist/components/Bot.d.ts +11 -0
  11. package/dist/components/Bot.d.ts.map +1 -1
  12. package/dist/components/FeedbackContentDialog.d.ts.map +1 -1
  13. package/dist/components/Toast.d.ts +10 -0
  14. package/dist/components/Toast.d.ts.map +1 -0
  15. package/dist/components/bubbles/BotBubble.d.ts +7 -0
  16. package/dist/components/bubbles/BotBubble.d.ts.map +1 -1
  17. package/dist/components/bubbles/ChartBubble.d.ts +9 -0
  18. package/dist/components/bubbles/ChartBubble.d.ts.map +1 -0
  19. package/dist/components/bubbles/ChartLoadingPlaceholder.d.ts +8 -0
  20. package/dist/components/bubbles/ChartLoadingPlaceholder.d.ts.map +1 -0
  21. package/dist/components/bubbles/ChartPlaceholder.d.ts +16 -0
  22. package/dist/components/bubbles/ChartPlaceholder.d.ts.map +1 -0
  23. package/dist/components/bubbles/ChartPortalContainer.d.ts +12 -0
  24. package/dist/components/bubbles/ChartPortalContainer.d.ts.map +1 -0
  25. package/dist/components/bubbles/LoadingBubble.d.ts +7 -1
  26. package/dist/components/bubbles/LoadingBubble.d.ts.map +1 -1
  27. package/dist/components/bubbles/SourceBubble.d.ts.map +1 -1
  28. package/dist/components/bubbles/StableChartWrapper.d.ts +16 -0
  29. package/dist/components/bubbles/StableChartWrapper.d.ts.map +1 -0
  30. package/dist/components/bubbles/StarterPromptBubble.d.ts.map +1 -1
  31. package/dist/components/buttons/CopyMessageButton.d.ts +10 -0
  32. package/dist/components/buttons/CopyMessageButton.d.ts.map +1 -0
  33. package/dist/components/buttons/EditMessageButton.d.ts +8 -0
  34. package/dist/components/buttons/EditMessageButton.d.ts.map +1 -0
  35. package/dist/components/buttons/PopupToast.d.ts +7 -0
  36. package/dist/components/buttons/PopupToast.d.ts.map +1 -0
  37. package/dist/components/buttons/SendButton.d.ts +1 -0
  38. package/dist/components/buttons/SendButton.d.ts.map +1 -1
  39. package/dist/components/dialogs/EditMessageDialog.d.ts +9 -0
  40. package/dist/components/dialogs/EditMessageDialog.d.ts.map +1 -0
  41. package/dist/components/icons/AddImageIcon.d.ts.map +1 -1
  42. package/dist/components/icons/CheckIcon.d.ts +3 -0
  43. package/dist/components/icons/CheckIcon.d.ts.map +1 -0
  44. package/dist/components/icons/CopyIcon.d.ts +5 -0
  45. package/dist/components/icons/CopyIcon.d.ts.map +1 -0
  46. package/dist/components/icons/EditIcon.d.ts +5 -0
  47. package/dist/components/icons/EditIcon.d.ts.map +1 -0
  48. package/dist/components/icons/FullScreenIcon.d.ts +3 -0
  49. package/dist/components/icons/FullScreenIcon.d.ts.map +1 -0
  50. package/dist/components/icons/index.d.ts +4 -0
  51. package/dist/components/icons/index.d.ts.map +1 -1
  52. package/dist/components/image/PreviewImage.d.ts +5 -0
  53. package/dist/components/image/PreviewImage.d.ts.map +1 -0
  54. package/dist/components/inputs/textInput/components/ShortTextInput.d.ts +4 -0
  55. package/dist/components/inputs/textInput/components/ShortTextInput.d.ts.map +1 -1
  56. package/dist/components/inputs/textInput/components/TextInput.d.ts +16 -1
  57. package/dist/components/inputs/textInput/components/TextInput.d.ts.map +1 -1
  58. package/dist/constants.d.ts.map +1 -1
  59. package/dist/features/bubble/components/Bubble.d.ts.map +1 -1
  60. package/dist/features/bubble/types.d.ts +1 -0
  61. package/dist/features/bubble/types.d.ts.map +1 -1
  62. package/dist/features/full/components/Full.d.ts.map +1 -1
  63. package/dist/features/popup/components/Popup.d.ts.map +1 -1
  64. package/dist/index.js +1 -1
  65. package/dist/queries/sendMessageQuery.d.ts +26 -0
  66. package/dist/queries/sendMessageQuery.d.ts.map +1 -1
  67. package/dist/types/chart.d.ts +72 -0
  68. package/dist/types/chart.d.ts.map +1 -0
  69. package/dist/utils/chartInstanceManager.d.ts +43 -0
  70. package/dist/utils/chartInstanceManager.d.ts.map +1 -0
  71. package/dist/utils/chartPortalManager.d.ts +76 -0
  72. package/dist/utils/chartPortalManager.d.ts.map +1 -0
  73. package/dist/utils/chartTagParser.d.ts +39 -0
  74. package/dist/utils/chartTagParser.d.ts.map +1 -0
  75. package/dist/utils/index.d.ts +4 -0
  76. package/dist/utils/index.d.ts.map +1 -1
  77. package/dist/utils/textStreamSmoother.d.ts +40 -0
  78. package/dist/utils/textStreamSmoother.d.ts.map +1 -0
  79. package/dist/utils/transcriptApi.d.ts +8 -0
  80. package/dist/utils/transcriptApi.d.ts.map +1 -0
  81. package/dist/utils/ultimateJsonParser.d.ts +2 -0
  82. package/dist/utils/ultimateJsonParser.d.ts.map +1 -0
  83. package/dist/web.d.ts +4 -0
  84. package/dist/web.d.ts.map +1 -1
  85. package/dist/web.js +1 -1
  86. package/dist/window.d.ts +2 -0
  87. package/dist/window.d.ts.map +1 -1
  88. package/docs/chart-rendering-implementation-plan.md +565 -0
  89. package/package.json +9 -5
  90. package/public/index.html +6 -115
  91. package/server.js +401 -401
  92. package/.env +0 -36
  93. package/.husky/pre-commit +0 -18
  94. package/.idea/codeStyles/Project.xml +0 -60
  95. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  96. package/.idea/inspectionProfiles/Project_Default.xml +0 -16
  97. package/.idea/prettier.xml +0 -6
  98. package/a.json +0 -57
  99. package/bun.lockb +0 -0
  100. package/dist/components/ImageUploadButton.d.ts +0 -11
  101. package/dist/components/ImageUploadButton.d.ts.map +0 -1
  102. package/dist/components/RecordAudioButton.d.ts +0 -11
  103. package/dist/components/RecordAudioButton.d.ts.map +0 -1
  104. package/dist/components/SendButton.d.ts +0 -12
  105. package/dist/components/SendButton.d.ts.map +0 -1
  106. package/test.html +0 -17
package/dist/window.d.ts CHANGED
@@ -9,6 +9,8 @@ type BotProps = {
9
9
  theme?: BubbleTheme;
10
10
  chatwootUrl?: string;
11
11
  roomIds?: Record<string, string>;
12
+ isUseFAQ?: boolean;
13
+ onResetChat?: () => Promise<void>;
12
14
  };
13
15
  export declare const initFull: (props: BotProps & {
14
16
  id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,KAAK,QAAQ,GAAG;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAIF,eAAO,MAAM,QAAQ,UAAW,QAAQ,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAMzD,CAAC;AAEF,eAAO,MAAM,IAAI,UAAW,QAAQ,SAMnC,CAAC;AAEF,eAAO,MAAM,OAAO,YAEnB,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,OAAO,CAAC;CACzB,CAAC;AAQF,eAAO,MAAM,YAAY;sBAhCO,QAAQ,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE;kBAQ9B,QAAQ;;CA4BlC,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAAS,OAAO,SAGjD,CAAC"}
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,KAAK,QAAQ,GAAG;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,CAAC;AAIF,eAAO,MAAM,QAAQ,UAAW,QAAQ,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAMzD,CAAC;AAEF,eAAO,MAAM,IAAI,UAAW,QAAQ,SAOnC,CAAC;AAEF,eAAO,MAAM,OAAO,YAEnB,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,OAAO,CAAC;CACzB,CAAC;AAQF,eAAO,MAAM,YAAY;sBAjCO,QAAQ,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE;kBAQ9B,QAAQ;;CA6BlC,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAAS,OAAO,SAGjD,CAAC"}
@@ -0,0 +1,565 @@
1
+ # Chart Rendering Implementation Plan
2
+
3
+ ## Overview
4
+
5
+ This document outlines the implementation plan for rendering Chart.js charts by parsing XML tags from SSE streaming API responses in the Flowise chatbot embed.
6
+
7
+ ## Table of Contents
8
+
9
+ 1. [Architecture Overview](#architecture-overview)
10
+ 2. [Data Flow](#data-flow)
11
+ 3. [New Components and Utilities](#new-components-and-utilities)
12
+ 4. [Modifications to Existing Components](#modifications-to-existing-components)
13
+ 5. [Implementation Steps](#implementation-steps)
14
+ 6. [Edge Cases and Error Handling](#edge-cases-and-error-handling)
15
+ 7. [Testing Strategy](#testing-strategy)
16
+
17
+ ---
18
+
19
+ ## Architecture Overview
20
+
21
+ ### Current Architecture
22
+
23
+ ```
24
+ SSE Stream → fetchEventSource → token event → addToStreamBuffer → processTextBuffer → updateLastMessage → BotBubble (Marked.parse) → innerHTML
25
+ ```
26
+
27
+ ### Proposed Architecture
28
+
29
+ ```
30
+ SSE Stream → fetchEventSource → token event → ChartTagParser (intercepts) →
31
+ ├── Regular text → addToStreamBuffer → processTextBuffer → updateLastMessage
32
+ └── Chart tags → ChartBuffer (accumulates) → Complete chart → ChartRenderer
33
+
34
+ BotBubble (renders mixed content: text + charts)
35
+ ```
36
+
37
+ ### Key Architectural Decisions
38
+
39
+ 1. **Separation of Concerns**: Chart parsing logic is isolated in a dedicated utility (`ChartTagParser`)
40
+ 2. **State Machine Approach**: Use a state machine to track whether we're inside a chart tag, parsing text, or in an incomplete state
41
+ 3. **Deferred Rendering**: Charts render only when the complete `<chart>...</chart>` tag is received
42
+ 4. **Placeholder System**: Show loading skeleton while chart data is streaming
43
+ 5. **Chart Instance Management**: Track Chart.js instances for proper cleanup to prevent memory leaks
44
+
45
+ ---
46
+
47
+ ## Data Flow
48
+
49
+ ### Streaming Flow (Detailed)
50
+
51
+ 1. **Token arrives** via SSE `token` event in `Bot.tsx`
52
+ 2. **ChartTagParser.processToken(token)** analyzes the token:
53
+ - If currently inside a chart tag: buffer the token
54
+ - If token starts a chart tag: start buffering, emit placeholder ID
55
+ - If token completes a chart tag: parse and emit chart config
56
+ - Otherwise: pass through as regular text
57
+ 3. **Regular text** flows to existing `addToStreamBuffer` → `processTextBuffer` pipeline
58
+ 4. **Chart placeholders** are inserted as special markers: `<!--chart:uuid-->`
59
+ 5. **BotBubble.updateBotMessageContent()** is modified to:
60
+ - Parse markdown as usual
61
+ - Detect chart placeholder markers
62
+ - Replace markers with chart container elements
63
+ - Initialize Chart.js instances for completed charts
64
+
65
+ ### State Machine States
66
+
67
+ ```
68
+ IDLE → OPENING_TAG → INSIDE_TAG → CLOSING_TAG → IDLE
69
+ ↓ ↓ ↓
70
+ (partial) (buffering) (partial)
71
+ ```
72
+
73
+ ---
74
+
75
+ ## New Components and Utilities
76
+
77
+ ### 1. `src/utils/chartTagParser.ts`
78
+
79
+ **Purpose**: Parse and extract chart XML tags from streaming tokens
80
+
81
+ ```typescript
82
+ // Core interfaces
83
+ interface ChartConfig {
84
+ id: string;
85
+ type: 'line' | 'bar' | 'pie' | 'doughnut' | 'radar' | 'polarArea' | 'bubble' | 'scatter';
86
+ title: string;
87
+ data: ChartData;
88
+ options?: ChartOptions;
89
+ }
90
+
91
+ interface ParseResult {
92
+ textContent: string; // Regular text to render
93
+ chartPlaceholders: string[]; // Chart placeholder IDs added
94
+ completedCharts: ChartConfig[]; // Fully parsed charts
95
+ }
96
+
97
+ class ChartTagParser {
98
+ // Parser state
99
+ private state: ParserState;
100
+ private buffer: string;
101
+ private pendingCharts: Map<string, Partial<ChartConfig>>;
102
+
103
+ // Main method called for each token
104
+ processToken(token: string): ParseResult;
105
+
106
+ // Flush any remaining buffer (called on stream end)
107
+ flush(): ParseResult;
108
+
109
+ // Reset parser state (called on new message)
110
+ reset(): void;
111
+ }
112
+ ```
113
+
114
+ **Key Features**:
115
+ - Handles tokens split across tag boundaries
116
+ - Generates unique IDs for each chart placeholder
117
+ - Validates JSON configuration before parsing
118
+ - Supports multiple charts in a single message
119
+
120
+ ### 2. `src/components/bubbles/ChartBubble.tsx`
121
+
122
+ **Purpose**: SolidJS component that renders a Chart.js chart
123
+
124
+ ```typescript
125
+ interface ChartBubbleProps {
126
+ config: ChartConfig;
127
+ backgroundColor?: string;
128
+ onDestroy?: () => void;
129
+ }
130
+
131
+ // Component responsibilities:
132
+ // - Creates canvas element
133
+ // - Initializes Chart.js instance
134
+ // - Handles responsive sizing
135
+ // - Cleans up on unmount
136
+ ```
137
+
138
+ ### 3. `src/components/bubbles/ChartLoadingPlaceholder.tsx`
139
+
140
+ **Purpose**: Loading skeleton shown while chart data streams
141
+
142
+ ```typescript
143
+ interface ChartLoadingPlaceholderProps {
144
+ chartId: string;
145
+ }
146
+
147
+ // Shows animated skeleton with:
148
+ // - Chart icon
149
+ // - "Loading chart..." text
150
+ // - Pulsing animation
151
+ ```
152
+
153
+ ### 4. `src/utils/chartInstanceManager.ts`
154
+
155
+ **Purpose**: Manage Chart.js instances lifecycle to prevent memory leaks
156
+
157
+ ```typescript
158
+ class ChartInstanceManager {
159
+ private instances: Map<string, Chart>;
160
+
161
+ register(id: string, chart: Chart): void;
162
+ destroy(id: string): void;
163
+ destroyAll(): void;
164
+ get(id: string): Chart | undefined;
165
+ }
166
+
167
+ // Singleton instance exported for global access
168
+ export const chartManager = new ChartInstanceManager();
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Modifications to Existing Components
174
+
175
+ ### 1. `src/components/Bot.tsx`
176
+
177
+ **Changes Required**:
178
+
179
+ #### a. Import ChartTagParser
180
+ ```typescript
181
+ import { ChartTagParser, ChartConfig } from '@/utils/chartTagParser';
182
+ ```
183
+
184
+ #### b. Add chart parser instance and state
185
+ ```typescript
186
+ // Add near other streaming state variables (around line 250)
187
+ let chartParser: ChartTagParser | null = null;
188
+ const [pendingCharts, setPendingCharts] = createSignal<Map<string, Partial<ChartConfig>>>(new Map());
189
+ const [completedCharts, setCompletedCharts] = createSignal<Map<string, ChartConfig>>(new Map());
190
+ ```
191
+
192
+ #### c. Modify token handling in `fetchResponseFromEventStream`
193
+ ```typescript
194
+ case 'token':
195
+ setCurrentStatusMsg('');
196
+
197
+ // Process token through chart parser first
198
+ if (!chartParser) chartParser = new ChartTagParser();
199
+ const parseResult = chartParser.processToken(payload.data);
200
+
201
+ // Handle regular text content
202
+ if (parseResult.textContent) {
203
+ addToStreamBuffer(parseResult.textContent);
204
+ }
205
+
206
+ // Track new chart placeholders
207
+ parseResult.chartPlaceholders.forEach(id => {
208
+ setPendingCharts(prev => new Map(prev).set(id, { id }));
209
+ });
210
+
211
+ // Handle completed charts
212
+ parseResult.completedCharts.forEach(chart => {
213
+ setCompletedCharts(prev => new Map(prev).set(chart.id, chart));
214
+ setPendingCharts(prev => {
215
+ const next = new Map(prev);
216
+ next.delete(chart.id);
217
+ return next;
218
+ });
219
+ });
220
+ break;
221
+ ```
222
+
223
+ #### d. Modify 'start' event to reset parser
224
+ ```typescript
225
+ case 'start':
226
+ // ... existing code ...
227
+ chartParser = new ChartTagParser(); // Reset parser for new message
228
+ setPendingCharts(new Map());
229
+ setCompletedCharts(new Map());
230
+ break;
231
+ ```
232
+
233
+ #### e. Modify 'end' event to flush parser
234
+ ```typescript
235
+ case 'end':
236
+ // Flush any remaining chart parser content
237
+ if (chartParser) {
238
+ const flushResult = chartParser.flush();
239
+ if (flushResult.textContent) {
240
+ addToStreamBuffer(flushResult.textContent);
241
+ }
242
+ // Handle any final completed charts
243
+ flushResult.completedCharts.forEach(chart => {
244
+ setCompletedCharts(prev => new Map(prev).set(chart.id, chart));
245
+ });
246
+ }
247
+ // ... existing code ...
248
+ break;
249
+ ```
250
+
251
+ #### f. Pass chart data to BotBubble
252
+ ```typescript
253
+ <BotBubble
254
+ // ... existing props ...
255
+ pendingCharts={pendingCharts()}
256
+ completedCharts={completedCharts()}
257
+ />
258
+ ```
259
+
260
+ ### 2. `src/components/bubbles/BotBubble.tsx`
261
+
262
+ **Changes Required**:
263
+
264
+ #### a. Add new props
265
+ ```typescript
266
+ type Props = {
267
+ // ... existing props ...
268
+ pendingCharts?: Map<string, Partial<ChartConfig>>;
269
+ completedCharts?: Map<string, ChartConfig>;
270
+ };
271
+ ```
272
+
273
+ #### b. Modify updateBotMessageContent function
274
+ ```typescript
275
+ function updateBotMessageContent(newMessage: string) {
276
+ if (botMessageEl) {
277
+ const safeMessage = convertEmailToMarkdownLink(newMessage);
278
+ let htmlContent = Marked.parse(safeMessage);
279
+
280
+ // Replace chart placeholders with actual chart containers
281
+ htmlContent = replaceChartPlaceholders(htmlContent, props.completedCharts, props.pendingCharts);
282
+
283
+ botMessageEl.innerHTML = htmlContent;
284
+
285
+ // Initialize Chart.js instances for completed charts
286
+ initializeCharts(botMessageEl, props.completedCharts);
287
+
288
+ botMessageEl.querySelectorAll('a').forEach((link) => {
289
+ link.target = '_blank';
290
+ });
291
+ }
292
+ }
293
+ ```
294
+
295
+ #### c. Add chart initialization and cleanup
296
+ ```typescript
297
+ import { chartManager } from '@/utils/chartInstanceManager';
298
+
299
+ // In component cleanup
300
+ onCleanup(() => {
301
+ // Destroy all chart instances for this bubble
302
+ props.completedCharts?.forEach((_, id) => {
303
+ chartManager.destroy(id);
304
+ });
305
+ });
306
+ ```
307
+
308
+ ---
309
+
310
+ ## Implementation Steps
311
+
312
+ ### Phase 1: Setup and Dependencies (Priority: High)
313
+ 1. **Add Chart.js dependency**: `yarn add chart.js`
314
+ 2. **Create type definitions** for chart configurations
315
+ 3. **Create chartTagParser.ts** with basic parsing logic
316
+
317
+ ### Phase 2: Core Parser Implementation (Priority: High)
318
+ 4. **Implement state machine** in ChartTagParser
319
+ 5. **Handle edge cases**: partial tags, malformed JSON, nested content
320
+ 6. **Write unit tests** for parser
321
+
322
+ ### Phase 3: Chart Rendering Components (Priority: High)
323
+ 7. **Create ChartBubble.tsx** component
324
+ 8. **Create ChartLoadingPlaceholder.tsx** component
325
+ 9. **Create chartInstanceManager.ts** utility
326
+
327
+ ### Phase 4: Integration with Streaming (Priority: High)
328
+ 10. **Modify Bot.tsx** to integrate ChartTagParser
329
+ 11. **Modify BotBubble.tsx** to render charts
330
+ 12. **Test with live SSE streaming**
331
+
332
+ ### Phase 5: Styling and Polish (Priority: Medium)
333
+ 13. **Add responsive chart sizing**
334
+ 14. **Style chart containers** to match chat UI
335
+ 15. **Add error states** for failed chart rendering
336
+
337
+ ### Phase 6: Testing and Edge Cases (Priority: High)
338
+ 16. **Test multiple charts** in single message
339
+ 17. **Test chart + text** mixed content
340
+ 18. **Test memory cleanup** on message updates
341
+ 19. **Test with various chart types**
342
+
343
+ ---
344
+
345
+ ## Edge Cases and Error Handling
346
+
347
+ ### Edge Case 1: Incomplete Chart Tag at Stream End
348
+ **Scenario**: Stream ends while inside a chart tag
349
+ **Solution**: `flush()` method treats incomplete tag as plain text
350
+ ```typescript
351
+ flush(): ParseResult {
352
+ if (this.state !== ParserState.IDLE) {
353
+ // Emit buffered content as plain text
354
+ return { textContent: this.buffer, chartPlaceholders: [], completedCharts: [] };
355
+ }
356
+ return { textContent: '', chartPlaceholders: [], completedCharts: [] };
357
+ }
358
+ ```
359
+
360
+ ### Edge Case 2: Malformed JSON in Chart Tag
361
+ **Scenario**: Chart tag contains invalid JSON
362
+ **Solution**: Render error message inline instead of chart
363
+ ```typescript
364
+ try {
365
+ const config = JSON.parse(jsonContent);
366
+ return { type: 'chart', config };
367
+ } catch (e) {
368
+ return { type: 'error', message: 'Invalid chart configuration' };
369
+ }
370
+ ```
371
+
372
+ ### Edge Case 3: Token Splits Tag Boundary
373
+ **Scenario**: Token contains partial opening/closing tag
374
+ ```
375
+ Token 1: "Here is the data: <cha"
376
+ Token 2: "rt type=\"line\">"
377
+ Token 3: "{\"labels\": [...]}"
378
+ Token 4: "</chart>"
379
+ ```
380
+ **Solution**: State machine buffers partial tags until complete
381
+
382
+ ### Edge Case 4: Nested or Escaped Content
383
+ **Scenario**: JSON contains `</chart>` as string value
384
+ **Solution**: Track brace depth to find true closing tag
385
+ ```typescript
386
+ // Count braces to find actual JSON end
387
+ let braceDepth = 0;
388
+ for (let i = 0; i < content.length; i++) {
389
+ if (content[i] === '{') braceDepth++;
390
+ if (content[i] === '}') braceDepth--;
391
+ if (braceDepth === 0) {
392
+ // Found JSON end
393
+ }
394
+ }
395
+ ```
396
+
397
+ ### Edge Case 5: Multiple Charts Back-to-Back
398
+ **Scenario**: `<chart>...</chart><chart>...</chart>`
399
+ **Solution**: Parser resets to IDLE after each complete tag
400
+
401
+ ### Edge Case 6: Chart in Middle of Text
402
+ **Scenario**: "Here's the chart: <chart>...</chart> And here's more text."
403
+ **Solution**: Emit text before chart, placeholder, then text after
404
+
405
+ ### Edge Case 7: Memory Leaks from Chart Instances
406
+ **Scenario**: Charts created but never destroyed
407
+ **Solution**: ChartInstanceManager tracks all instances, cleanup on:
408
+ - Component unmount
409
+ - Message update (chart replaced)
410
+ - Chat clear
411
+
412
+ ### Edge Case 8: Rapid Streaming Updates
413
+ **Scenario**: Chart placeholder created, then immediately completed
414
+ **Solution**: Debounce chart initialization, check if placeholder still exists
415
+
416
+ ---
417
+
418
+ ## Testing Strategy
419
+
420
+ ### Unit Tests
421
+
422
+ 1. **ChartTagParser Tests**
423
+ - Parse complete chart tag in single token
424
+ - Parse chart tag split across multiple tokens
425
+ - Handle malformed JSON gracefully
426
+ - Handle multiple charts in sequence
427
+ - Handle chart embedded in text
428
+ - Handle incomplete tags on flush
429
+
430
+ 2. **ChartInstanceManager Tests**
431
+ - Register and retrieve instances
432
+ - Destroy individual instance
433
+ - Destroy all instances
434
+ - Handle destroy of non-existent instance
435
+
436
+ ### Integration Tests
437
+
438
+ 1. **Streaming Simulation**
439
+ - Simulate SSE tokens with chart tags
440
+ - Verify placeholder appears during streaming
441
+ - Verify chart renders on completion
442
+
443
+ 2. **BotBubble Rendering**
444
+ - Render message with chart
445
+ - Render message with multiple charts
446
+ - Render mixed text and charts
447
+ - Verify chart cleanup on unmount
448
+
449
+ ### Manual Testing Checklist
450
+
451
+ - [ ] Single line chart renders correctly
452
+ - [ ] Bar chart renders correctly
453
+ - [ ] Pie/doughnut chart renders correctly
454
+ - [ ] Chart title displays correctly
455
+ - [ ] Chart is responsive (resizes with container)
456
+ - [ ] Multiple charts in one message
457
+ - [ ] Chart between paragraphs of text
458
+ - [ ] Loading placeholder shows during streaming
459
+ - [ ] Error message for invalid chart config
460
+ - [ ] No console errors on chat clear
461
+ - [ ] No memory leaks (check dev tools)
462
+
463
+ ---
464
+
465
+ ## Chart XML Tag Format Reference
466
+
467
+ ### Basic Structure
468
+ ```xml
469
+ <chart type="line" title="Chart Title">
470
+ {
471
+ "labels": ["Label1", "Label2", ...],
472
+ "datasets": [
473
+ {
474
+ "label": "Dataset Label",
475
+ "data": [1, 2, 3, ...],
476
+ "backgroundColor": "rgba(54, 162, 235, 0.2)",
477
+ "borderColor": "rgba(54, 162, 235, 1)",
478
+ "borderWidth": 2
479
+ }
480
+ ],
481
+ "options": {
482
+ "responsive": true,
483
+ "plugins": {
484
+ "legend": { "position": "top" }
485
+ }
486
+ }
487
+ }
488
+ </chart>
489
+ ```
490
+
491
+ ### Supported Chart Types
492
+ - `line` - Line chart
493
+ - `bar` - Bar chart
494
+ - `pie` - Pie chart
495
+ - `doughnut` - Doughnut chart
496
+ - `radar` - Radar chart
497
+ - `polarArea` - Polar area chart
498
+ - `bubble` - Bubble chart
499
+ - `scatter` - Scatter chart
500
+
501
+ ### Required Fields
502
+ - `type` attribute (chart type)
503
+ - `labels` array in JSON body
504
+ - `datasets` array with at least one dataset
505
+ - Each dataset must have `data` array
506
+
507
+ ### Optional Fields
508
+ - `title` attribute (displayed above chart)
509
+ - `options` object (Chart.js options)
510
+ - Dataset styling properties (colors, borders, etc.)
511
+
512
+ ---
513
+
514
+ ## Dependencies to Add
515
+
516
+ ```json
517
+ {
518
+ "dependencies": {
519
+ "chart.js": "^4.4.0"
520
+ }
521
+ }
522
+ ```
523
+
524
+ **Installation Command**: `yarn add chart.js`
525
+
526
+ ---
527
+
528
+ ## File Structure After Implementation
529
+
530
+ ```
531
+ src/
532
+ ├── components/
533
+ │ ├── bubbles/
534
+ │ │ ├── BotBubble.tsx (modified)
535
+ │ │ ├── ChartBubble.tsx (new)
536
+ │ │ └── ChartLoadingPlaceholder.tsx (new)
537
+ │ └── Bot.tsx (modified)
538
+ ├── utils/
539
+ │ ├── chartTagParser.ts (new)
540
+ │ ├── chartInstanceManager.ts (new)
541
+ │ └── index.ts
542
+ └── types/
543
+ └── chart.ts (new - type definitions)
544
+ ```
545
+
546
+ ---
547
+
548
+ ## Performance Considerations
549
+
550
+ 1. **Lazy Loading**: Consider lazy-loading Chart.js to reduce initial bundle size
551
+ 2. **Canvas Optimization**: Use `devicePixelRatio` option for crisp rendering
552
+ 3. **Animation**: Disable animations during streaming for smoother experience
553
+ 4. **Debouncing**: Debounce chart updates if data changes rapidly
554
+ 5. **Memory**: Always destroy Chart instances when no longer needed
555
+
556
+ ---
557
+
558
+ ## Future Enhancements (Out of Scope)
559
+
560
+ 1. **Interactive Charts**: Click handlers, tooltips, zoom
561
+ 2. **Chart Export**: Download as PNG/SVG
562
+ 3. **Chart Editing**: Allow users to modify chart after rendering
563
+ 4. **More Chart Types**: Support for additional Chart.js plugins
564
+ 5. **Real-time Updates**: Support for updating chart data after initial render
565
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cmcts-c-agent-embedding",
3
- "version": "1.0.27",
3
+ "version": "1.0.29-cagent",
4
4
  "description": "Javascript library to display flowise chatbot on your website",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,13 +8,15 @@
8
8
  "scripts": {
9
9
  "dev": "cross-env NODE_ENV=development rollup --watch --config rollup.config.js",
10
10
  "build": "cross-env NODE_ENV=production rollup --config rollup.config.js",
11
- "lint": "eslint \"src/**/*.ts*\"",
12
- "lint-fix": "eslint --fix \"src/**/*.ts*\"",
11
+ "type-check": "tsc --noEmit",
12
+ "lint": "eslint --quiet \"src/**/*.ts*\"",
13
+ "lint-fix": "eslint --quiet --fix \"src/**/*.ts*\"",
13
14
  "format": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
14
15
  "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
15
16
  "prepare": "husky install",
16
17
  "start": "node server.js",
17
- "build-and-publish": "yarn build && npm login && npm publish"
18
+ "build-and-publish": "yarn build && npm publish",
19
+ "prepublishOnly": "yarn build"
18
20
  },
19
21
  "license": "MIT",
20
22
  "dependencies": {
@@ -25,6 +27,8 @@
25
27
  "axios": "^1.7.7",
26
28
  "c-agent-embedding": "^1.0.4",
27
29
  "c-agent-embedding-react": "^1.0.1",
30
+ "chart.js": "^4.5.1",
31
+ "chartjs-plugin-datalabels": "^2.2.0",
28
32
  "cors": "^2.8.5",
29
33
  "cross-env": "^7.0.3",
30
34
  "device-detector-js": "^3.0.3",
@@ -77,4 +81,4 @@
77
81
  "uuid": "^9.0.1"
78
82
  },
79
83
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
80
- }
84
+ }