@fusioni/client-sdk 1.1.0 → 1.1.2

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/dist/index.js CHANGED
@@ -4173,7 +4173,7 @@ class PipelineService {
4173
4173
  throw new Error('agency_id is required for pipeline execution');
4174
4174
  }
4175
4175
  const apiClient = this.getApiClient();
4176
- const response = await apiClient.client.post(`/pipeline/${request.agency_id}/exec`, request);
4176
+ const response = await apiClient.client.post(`/journey/${request.agency_id}/exec`, request);
4177
4177
  console.log('✅ PipelineService.executePipeline - Response received:', {
4178
4178
  answerCount: response.data.answer?.length || 0,
4179
4179
  messagesCount: response.data.messages?.length || 0,
@@ -4339,6 +4339,7 @@ const en = {
4339
4339
  }
4340
4340
  },
4341
4341
  attachedImages: 'Images',
4342
+ attachedVideos: 'Videos',
4342
4343
  messages: {
4343
4344
  loading: 'Working on it...',
4344
4345
  error: 'Oops! Something went wrong. Please try again later.',
@@ -4432,6 +4433,7 @@ const el = {
4432
4433
  }
4433
4434
  },
4434
4435
  attachedImages: 'Εικόνες',
4436
+ attachedVideos: 'Βίντεο',
4435
4437
  messages: {
4436
4438
  loading: 'Εργάζομαι...',
4437
4439
  error: 'Ουπς! Κάτι πήγε στραβά. Παρακαλώ δοκιμάστε ξανά αργότερα.',
@@ -4932,6 +4934,40 @@ const DocumentImageGrid = ({ images, onOpenGallery, attachedImagesLabel, }) => {
4932
4934
  return (jsxRuntime.jsx("button", { type: "button", className: "fusioni-document-image-btn", "aria-label": `Preview attached image ${gi + 1}`, onClick: () => onOpenGallery({ images: visible, index: gi }), children: jsxRuntime.jsx("div", { className: "fusioni-document-image-aspect", children: jsxRuntime.jsx("img", { src: img, alt: "", loading: "lazy", decoding: "async", referrerPolicy: "no-referrer", onError: () => setVisible((v) => v.filter((u) => u !== img)) }) }) }));
4933
4935
  } })] }));
4934
4936
  };
4937
+ const DocumentVideoGrid = ({ videos, attachedVideosLabel, }) => {
4938
+ const cols = useGalleryStripColumns();
4939
+ const [visible, setVisible] = react.useState(videos);
4940
+ const [page, setPage] = react.useState(0);
4941
+ const pageSize = cols * GALLERY_STRIP_MAX_ROWS;
4942
+ const pageCount = visible.length > 0 ? Math.ceil(visible.length / pageSize) : 0;
4943
+ const prevPageSizeRef = react.useRef(pageSize);
4944
+ react.useEffect(() => setVisible(videos), [videos]);
4945
+ react.useEffect(() => {
4946
+ const old = prevPageSizeRef.current;
4947
+ if (old !== pageSize && old > 0 && pageSize > 0) {
4948
+ setPage((p) => {
4949
+ const firstGlobal = p * old;
4950
+ const np = Math.floor(firstGlobal / pageSize);
4951
+ const pc = visible.length > 0 ? Math.ceil(visible.length / pageSize) : 0;
4952
+ return pc <= 0 ? 0 : Math.min(Math.max(0, np), pc - 1);
4953
+ });
4954
+ }
4955
+ prevPageSizeRef.current = pageSize;
4956
+ }, [pageSize, visible.length]);
4957
+ react.useEffect(() => {
4958
+ setPage((p) => {
4959
+ if (pageCount <= 0)
4960
+ return 0;
4961
+ return Math.min(p, pageCount - 1);
4962
+ });
4963
+ }, [pageCount]);
4964
+ if (!visible.length)
4965
+ return null;
4966
+ return (jsxRuntime.jsxs("div", { className: "fusioni-document-videos", children: [jsxRuntime.jsx("div", { className: "fusioni-document-videos-header", children: jsxRuntime.jsxs("span", { className: "fusioni-document-videos-header-label", children: [jsxRuntime.jsxs("svg", { className: "fusioni-document-videos-header-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: [jsxRuntime.jsx("polygon", { points: "23 7 16 12 23 17 23 7" }), jsxRuntime.jsx("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2", ry: "2" })] }), attachedVideosLabel] }) }), jsxRuntime.jsx(PaginatedGalleryStrip, { variant: "document", itemCount: visible.length, columns: cols, page: page, onPageChange: setPage, renderCell: (gi) => {
4967
+ const vid = visible[gi];
4968
+ return (jsxRuntime.jsx("div", { className: "fusioni-document-video-wrap", "aria-label": `Attached video ${gi + 1}`, children: jsxRuntime.jsx("div", { className: "fusioni-document-video-aspect", children: jsxRuntime.jsx("video", { src: vid, controls: true, preload: "metadata", playsInline: true, onError: () => setVisible((v) => v.filter((u) => u !== vid)) }) }) }));
4969
+ } })] }));
4970
+ };
4935
4971
  // Module-level Set to track which message IDs have been animated
4936
4972
  // This persists across component unmounts/remounts (e.g., when chat closes and reopens)
4937
4973
  const animatedMessageIds = new Set();
@@ -5026,36 +5062,83 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
5026
5062
  }
5027
5063
  // Reset displayed content
5028
5064
  setDisplayedContent('');
5029
- const fullContent = message.content;
5030
- // Parse content into segments: text segments and HTML tag segments
5065
+ // Type the same HTML string that will be rendered (after any transformations),
5066
+ // otherwise we can end up animating an HTML-escaped variant.
5067
+ const fullContent = enhanceMessageContent(message.content);
5068
+ // Parse content into segments: text segments and HTML tag segments.
5069
+ // Important: this parser is quote-aware so it won't break on `>` inside quoted attributes.
5031
5070
  const segments = [];
5071
+ const readTagAt = (html, start) => {
5072
+ if (html[start] !== '<')
5073
+ return null;
5074
+ // Handle comments: <!-- ... -->
5075
+ if (html.startsWith('<!--', start)) {
5076
+ const endIdx = html.indexOf('-->', start + 4);
5077
+ if (endIdx === -1)
5078
+ return { tag: html.slice(start), end: html.length };
5079
+ return { tag: html.slice(start, endIdx + 3), end: endIdx + 3 };
5080
+ }
5081
+ let i = start + 1;
5082
+ let quote = null;
5083
+ while (i < html.length) {
5084
+ const ch = html[i];
5085
+ if (quote) {
5086
+ if (ch === quote)
5087
+ quote = null;
5088
+ i++;
5089
+ continue;
5090
+ }
5091
+ if (ch === '"' || ch === "'") {
5092
+ quote = ch;
5093
+ i++;
5094
+ continue;
5095
+ }
5096
+ if (ch === '>') {
5097
+ return { tag: html.slice(start, i + 1), end: i + 1 };
5098
+ }
5099
+ i++;
5100
+ }
5101
+ // No closing `>` found; treat the remainder as text to avoid exposing partial tags.
5102
+ return null;
5103
+ };
5032
5104
  let currentIndex = 0;
5033
5105
  while (currentIndex < fullContent.length) {
5034
- const remainingContent = fullContent.substring(currentIndex);
5035
- const tagMatch = remainingContent.match(/^<[^>]*>/);
5036
- if (tagMatch) {
5037
- // Found an HTML tag - add it as a complete segment
5038
- segments.push({ type: 'tag', content: tagMatch[0] });
5039
- currentIndex += tagMatch[0].length;
5106
+ const nextLt = fullContent.indexOf('<', currentIndex);
5107
+ if (nextLt === -1) {
5108
+ segments.push({ type: 'text', content: fullContent.slice(currentIndex) });
5109
+ break;
5110
+ }
5111
+ if (nextLt > currentIndex) {
5112
+ segments.push({ type: 'text', content: fullContent.slice(currentIndex, nextLt) });
5113
+ }
5114
+ const maybeTag = readTagAt(fullContent, nextLt);
5115
+ if (maybeTag) {
5116
+ segments.push({ type: 'tag', content: maybeTag.tag });
5117
+ currentIndex = maybeTag.end;
5040
5118
  }
5041
5119
  else {
5042
- // Find the next HTML tag or end of string
5043
- const nextTagIndex = remainingContent.indexOf('<');
5044
- if (nextTagIndex === -1) {
5045
- // No more tags, add remaining text
5046
- segments.push({ type: 'text', content: remainingContent });
5047
- break;
5048
- }
5049
- else {
5050
- // Add text up to the next tag
5051
- segments.push({ type: 'text', content: remainingContent.substring(0, nextTagIndex) });
5052
- currentIndex += nextTagIndex;
5053
- }
5120
+ // Not a valid tag; emit the `<` as text and keep going.
5121
+ segments.push({ type: 'text', content: '<' });
5122
+ currentIndex = nextLt + 1;
5054
5123
  }
5055
5124
  }
5056
5125
  // Now animate through segments
5057
5126
  let segmentIndex = 0;
5058
5127
  let textIndex = 0;
5128
+ const nextTextStep = (text, index) => {
5129
+ if (index >= text.length)
5130
+ return { nextIndex: index, slice: '' };
5131
+ const ch = text[index];
5132
+ // Treat HTML entities as atomic "characters" so we don't type partial `&...;`.
5133
+ if (ch === '&') {
5134
+ const rest = text.slice(index);
5135
+ const entityMatch = rest.match(/^&(#\d+|#x[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]+);/);
5136
+ if (entityMatch) {
5137
+ return { nextIndex: index + entityMatch[0].length, slice: text.slice(0, index + entityMatch[0].length) };
5138
+ }
5139
+ }
5140
+ return { nextIndex: index + 1, slice: text.slice(0, index + 1) };
5141
+ };
5059
5142
  const typeNextChar = () => {
5060
5143
  if (segmentIndex >= segments.length) {
5061
5144
  // Typing complete - mark this message as animated in the persistent Set
@@ -5080,14 +5163,21 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
5080
5163
  else {
5081
5164
  // Text segments are typed character by character
5082
5165
  if (textIndex < segment.content.length) {
5083
- // Build content: all previous segments + current segment up to textIndex
5166
+ const step = nextTextStep(segment.content, textIndex);
5167
+ if (!step.slice) {
5168
+ segmentIndex++;
5169
+ textIndex = 0;
5170
+ typingIntervalRef.current = setTimeout(typeNextChar, 0);
5171
+ return;
5172
+ }
5173
+ // Build content: all previous segments + current segment slice
5084
5174
  let content = '';
5085
5175
  for (let i = 0; i < segmentIndex; i++) {
5086
5176
  content += segments[i].content;
5087
5177
  }
5088
- content += segment.content.substring(0, textIndex + 1);
5178
+ content += step.slice;
5089
5179
  setDisplayedContent(content);
5090
- textIndex++;
5180
+ textIndex = step.nextIndex;
5091
5181
  typingIntervalRef.current = setTimeout(typeNextChar, typingSpeed);
5092
5182
  }
5093
5183
  else {
@@ -5117,7 +5207,8 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
5117
5207
  __html: enhanceMessageContent(contentToDisplay)
5118
5208
  } })), message.loading && (jsxRuntime.jsx("div", { className: "fusioni-stream-messages", children: (streamMessages.length > 0 ? streamMessages : [t('chat.messages.loading')]).map((line, index) => (jsxRuntime.jsxs("div", { className: "fusioni-stream-message-item", children: [jsxRuntime.jsx("div", { className: "fusioni-stream-message-logo-wrap", children: jsxRuntime.jsx("div", { className: "fusioni-stream-message-logo-frame", children: jsxRuntime.jsx("img", { className: "fusioni-stream-message-logo-img", src: FUSIONI_LOGO_BASE64, alt: "", width: 32, height: 32 }) }) }), jsxRuntime.jsx(Spotlight, { className: "fusioni-stream-message-spotlight", text: line })] }, streamMessages.length > 0 ? `${index}-${line}` : 'loading-placeholder'))) })), !message.loading && extractUrlsFromContent(message.content).length > 0 && message.role !== 'user' && (jsxRuntime.jsx("div", { className: "fusioni-message-url-previews", children: extractUrlsFromContent(message.content).map((url, index) => (jsxRuntime.jsx(UrlPreview, { url: url, agencyId: agencyId, showCloseButton: false, compact: true, autoFetch: true, apiBaseUrl: apiBaseUrl, apiKey: apiKey }, `${url}-${index}`))) })), message.extra_data && (jsxRuntime.jsxs("div", { className: "fusioni-message-extra m2", children: [message.extra_data.document_images &&
5119
5209
  message.extra_data.document_images.length > 0 &&
5120
- onOpenGallery && (jsxRuntime.jsx(DocumentImageGrid, { images: message.extra_data.document_images, onOpenGallery: onOpenGallery, attachedImagesLabel: t('chat.attachedImages') })), message.extra_data.image && renderImage(message.extra_data.image), message.extra_data.image_ref && renderImage(message.extra_data.image_ref), message.extra_data.audio_ref && renderAudio(message.extra_data.audio_ref, message.extra_data.duration), message.extra_data.coordinates && renderMap(message.extra_data.coordinates), message.extra_data.map && (jsxRuntime.jsx("div", { className: "fusioni-message-map", children: jsxRuntime.jsx(Map$1, { lat: message.extra_data.map.lat, lng: message.extra_data.map.lng, zoom: message.extra_data.map.zoom, staticMap: true, width: 600, height: 400, apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId }) }))] })), message.extra_data?.widget === 'Confirmation' && (jsxRuntime.jsxs("div", { className: "fusioni-confirmation-widget", children: [jsxRuntime.jsx("button", { type: "button", disabled: !enableButtons, onClick: () => sendConfirmation('Confirmed', message.extra_data?.key), className: "fusioni-btn fusioni-btn-primary fusioni-btn-confirm", children: t('common.yes') }), jsxRuntime.jsx("button", { type: "button", disabled: !enableButtons, onClick: () => sendConfirmation('NotConfirmed', message.extra_data?.key), className: "fusioni-btn fusioni-btn-secondary fusioni-btn-cancel", children: t('common.no') })] })), showThoughts && message.thoughts && (jsxRuntime.jsx("div", { className: "fusioni-message-thoughts", children: jsxRuntime.jsxs("details", { children: [jsxRuntime.jsx("summary", { children: "AI Thoughts" }), jsxRuntime.jsx("p", { children: message.thoughts })] }) })), message.has_error && (jsxRuntime.jsxs("div", { className: "fusioni-message-error-indicator", children: [jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }), jsxRuntime.jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2" }), jsxRuntime.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2" })] }), jsxRuntime.jsx("span", { children: "Error occurred" })] }))] }));
5210
+ onOpenGallery && (jsxRuntime.jsx(DocumentImageGrid, { images: message.extra_data.document_images, onOpenGallery: onOpenGallery, attachedImagesLabel: t('chat.attachedImages') })), message.extra_data.document_videos &&
5211
+ message.extra_data.document_videos.length > 0 && (jsxRuntime.jsx(DocumentVideoGrid, { videos: message.extra_data.document_videos, attachedVideosLabel: t('chat.attachedVideos') })), message.extra_data.image && renderImage(message.extra_data.image), message.extra_data.image_ref && renderImage(message.extra_data.image_ref), message.extra_data.audio_ref && renderAudio(message.extra_data.audio_ref, message.extra_data.duration), message.extra_data.coordinates && renderMap(message.extra_data.coordinates), message.extra_data.map && (jsxRuntime.jsx("div", { className: "fusioni-message-map", children: jsxRuntime.jsx(Map$1, { lat: message.extra_data.map.lat, lng: message.extra_data.map.lng, zoom: message.extra_data.map.zoom, staticMap: true, width: 600, height: 400, apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId }) }))] })), message.extra_data?.widget === 'Confirmation' && (jsxRuntime.jsxs("div", { className: "fusioni-confirmation-widget", children: [jsxRuntime.jsx("button", { type: "button", disabled: !enableButtons, onClick: () => sendConfirmation('Confirmed', message.extra_data?.key), className: "fusioni-btn fusioni-btn-primary fusioni-btn-confirm", children: t('common.yes') }), jsxRuntime.jsx("button", { type: "button", disabled: !enableButtons, onClick: () => sendConfirmation('NotConfirmed', message.extra_data?.key), className: "fusioni-btn fusioni-btn-secondary fusioni-btn-cancel", children: t('common.no') })] })), showThoughts && message.thoughts && (jsxRuntime.jsx("div", { className: "fusioni-message-thoughts", children: jsxRuntime.jsxs("details", { children: [jsxRuntime.jsx("summary", { children: "AI Thoughts" }), jsxRuntime.jsx("p", { children: message.thoughts })] }) })), message.has_error && (jsxRuntime.jsxs("div", { className: "fusioni-message-error-indicator", children: [jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }), jsxRuntime.jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2" }), jsxRuntime.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2" })] }), jsxRuntime.jsx("span", { children: "Error occurred" })] }))] }));
5121
5212
  };
5122
5213
 
5123
5214
  /**
@@ -5331,12 +5422,12 @@ const MessageList = ({ messages, streamMessages, showThoughts = false, onDeleteM
5331
5422
  const isLastMessage = index === messages.length - 1;
5332
5423
  const messageKey = message.id ??
5333
5424
  `msg-fallback-${index}-${message.role}-${message.created instanceof Date ? message.created.getTime() : 0}`;
5334
- return (jsxRuntime.jsx("div", { className: "fusioni-message-wrapper", children: jsxRuntime.jsxs("div", { className: `fusioni-message ${message.role}`, children: [jsxRuntime.jsx("div", { className: "fusioni-message-avatar", children: message.role === 'user' ? (jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("path", { d: "M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("circle", { cx: "12", cy: "7", r: "4", stroke: "currentColor", strokeWidth: "2" })] })) : (jsxRuntime.jsx("img", { src: FUSIONI_LOGO_BASE64, alt: "Fusioni Logo", width: "24", height: "24" })) }), jsxRuntime.jsxs("div", { className: "fusioni-message-content", children: [jsxRuntime.jsxs("div", { className: "fusioni-message-header", children: [jsxRuntime.jsx("span", { className: "fusioni-message-role", children: message.role === 'user' ? '' : 'Fusioni' }), jsxRuntime.jsx("span", { className: "fusioni-message-time", children: formatDate(message.created) })] }), jsxRuntime.jsx("div", { className: "fusioni-message-body", children: message.role === 'user' && editingMessageId === message.id ? (jsxRuntime.jsx("div", { ref: editRef, className: "fusioni-message-text", contentEditable: true, suppressContentEditableWarning: true, spellCheck: true, onKeyDown: (event) => {
5425
+ return (jsxRuntime.jsx("div", { className: "fusioni-message-wrapper", children: jsxRuntime.jsxs("div", { className: `fusioni-message ${message.role}`, children: [jsxRuntime.jsx("div", { className: "fusioni-message-avatar", children: message.role === 'user' ? (jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("path", { d: "M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("circle", { cx: "12", cy: "7", r: "4", stroke: "currentColor", strokeWidth: "2" })] })) : (jsxRuntime.jsx("img", { src: FUSIONI_LOGO_BASE64, alt: "Fusioni Logo", width: "24", height: "24" })) }), jsxRuntime.jsxs("div", { className: "fusioni-message-content", children: [jsxRuntime.jsx("div", { className: "fusioni-message-body", children: message.role === 'user' && editingMessageId === message.id ? (jsxRuntime.jsx("div", { ref: editRef, className: "fusioni-message-text", contentEditable: true, suppressContentEditableWarning: true, spellCheck: true, onKeyDown: (event) => {
5335
5426
  if (event.key === 'Escape') {
5336
5427
  event.preventDefault();
5337
5428
  cancelEdit();
5338
5429
  }
5339
- } })) : (jsxRuntime.jsx(Message, { message: message, showThoughts: showThoughts, onDelete: onDeleteMessage, onConfirmation: onConfirmation, enableButtons: enableButtons && isLastMessage, streamMessages: message.loading ? streamMessages : [], apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId, currentLanguage: currentLanguage, onOpenGallery: openGallery })) }), showThoughts && message.thoughts && (jsxRuntime.jsx("div", { className: "fusioni-message-thoughts", children: jsxRuntime.jsxs("details", { children: [jsxRuntime.jsx("summary", { children: "Thoughts" }), jsxRuntime.jsx("p", { children: message.thoughts })] }) }))] }), message.id && (onDeleteMessage || (message.role === 'user' && onEditMessage)) && (jsxRuntime.jsx("div", { className: "fusioni-message-actions", children: message.role === 'user' && editingMessageId === message.id ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { onClick: confirmEdit, className: "fusioni-btn fusioni-btn-icon", title: "Save edit", children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), jsxRuntime.jsx("button", { onClick: cancelEdit, className: "fusioni-btn fusioni-btn-icon", title: "Cancel edit", children: jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [message.role === 'user' && onEditMessage && (jsxRuntime.jsx("button", { onClick: () => startEdit(message), className: "fusioni-btn fusioni-btn-icon", title: "Edit message", children: jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("path", { d: "M12 20H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: "M16.5 3.5C16.8978 3.10218 17.4374 2.87868 18 2.87868C18.5626 2.87868 19.1022 3.10218 19.5 3.5C19.8978 3.89782 20.1213 4.43739 20.1213 5C20.1213 5.56261 19.8978 6.10218 19.5 6.5L7 19L3 20L4 16L16.5 3.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })), onDeleteMessage && (jsxRuntime.jsx("button", { onClick: () => onDeleteMessage(message.id), className: "fusioni-btn fusioni-btn-icon fusioni-btn-danger", title: "Delete message", children: jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("path", { d: "M3 6H5H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: "M8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M19 6V20C19 20.5304 18.7893 21.0391 18.4142 21.4142C18.0391 21.7893 17.5304 22 17 22H7C6.46957 22 5.96086 21.7893 5.58579 21.4142C5.21071 21.0391 5 20.5304 5 20V6H19Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) }))] })) }))] }) }, messageKey));
5430
+ } })) : (jsxRuntime.jsx(Message, { message: message, showThoughts: showThoughts, onDelete: onDeleteMessage, onConfirmation: onConfirmation, enableButtons: enableButtons && isLastMessage, streamMessages: message.loading ? streamMessages : [], apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId, currentLanguage: currentLanguage, onOpenGallery: openGallery })) }), jsxRuntime.jsxs("div", { className: "fusioni-message-footer", children: [jsxRuntime.jsx("span", { className: "fusioni-message-time", children: formatDate(message.created) }), message.id && (onDeleteMessage || (message.role === 'user' && onEditMessage)) && (jsxRuntime.jsx("div", { className: "fusioni-message-actions", children: message.role === 'user' && editingMessageId === message.id ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { onClick: confirmEdit, className: "fusioni-btn fusioni-btn-icon", title: "Save edit", children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), jsxRuntime.jsx("button", { onClick: cancelEdit, className: "fusioni-btn fusioni-btn-icon", title: "Cancel edit", children: jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [message.role === 'user' && onEditMessage && (jsxRuntime.jsx("button", { onClick: () => startEdit(message), className: "fusioni-btn fusioni-btn-icon", title: "Edit message", children: jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("path", { d: "M12 20H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: "M16.5 3.5C16.8978 3.10218 17.4374 2.87868 18 2.87868C18.5626 2.87868 19.1022 3.10218 19.5 3.5C19.8978 3.89782 20.1213 4.43739 20.1213 5C20.1213 5.56261 19.8978 6.10218 19.5 6.5L7 19L3 20L4 16L16.5 3.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })), onDeleteMessage && (jsxRuntime.jsx("button", { onClick: () => onDeleteMessage(message.id), className: "fusioni-btn fusioni-btn-icon", title: "Delete message", children: jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsxRuntime.jsx("path", { d: "M3 6H5H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: "M8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M19 6V20C19 20.5304 18.7893 21.0391 18.4142 21.4142C18.0391 21.7893 17.5304 22 17 22H7C6.46957 22 5.96086 21.7893 5.58579 21.4142C5.21071 21.0391 5 20.5304 5 20V6H19Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) }))] })) }))] }), showThoughts && message.thoughts && (jsxRuntime.jsx("div", { className: "fusioni-message-thoughts", children: jsxRuntime.jsxs("details", { children: [jsxRuntime.jsx("summary", { children: "Thoughts" }), jsxRuntime.jsx("p", { children: message.thoughts })] }) }))] })] }) }, messageKey));
5340
5431
  }) })), jsxRuntime.jsx("div", { ref: messagesEndRef })] }) }), gallerySession &&
5341
5432
  typeof document !== 'undefined' &&
5342
5433
  reactDom.createPortal(jsxRuntime.jsx(ImageGallery, { images: gallerySession.images, initialIndex: gallerySession.index, theme: theme, onClose: () => setGallerySession(null) }, gallerySession.key), document.body)] }));
@@ -5639,7 +5730,7 @@ const ChatPanel = ({ isOpen, onClose, position = 'bottom-right', isFullscreen =
5639
5730
  };
5640
5731
  if (!isOpen)
5641
5732
  return null;
5642
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "fusioni-chat-backdrop" }), jsxRuntime.jsx("div", { ref: panelRef, className: `fusioni-chat-panel ${getPositionClasses()} ${isFullscreen ? 'fusioni-chat-panel-fullscreen' : ''}`, children: jsxRuntime.jsx("div", { className: "fusioni-chat-panel-content", children: children }) })] }));
5733
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("div", { ref: panelRef, className: `fusioni-chat-panel ${getPositionClasses()} ${isFullscreen ? 'fusioni-chat-panel-fullscreen' : ''}`, children: jsxRuntime.jsx("div", { className: "fusioni-chat-panel-content", children: children }) }) }));
5643
5734
  };
5644
5735
 
5645
5736
  const LanguageSwitcher = ({ currentLanguage, onLanguageChange, className = '' }) => {