@chatwidgetai/chat-widget 0.2.9 → 0.3.1
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/ai-chat-widget.umd.js +1546 -331
- package/dist/ai-chat-widget.umd.js.map +1 -1
- package/dist/api/client.d.ts +2 -2
- package/dist/api/client.d.ts.map +1 -1
- package/dist/components/ChatWidget.d.ts +2 -1
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/components/ChatWindow.d.ts +0 -1
- package/dist/components/ChatWindow.d.ts.map +1 -1
- package/dist/components/DataPolicyView.d.ts +14 -0
- package/dist/components/DataPolicyView.d.ts.map +1 -0
- package/dist/hooks/useChat/action-handler.d.ts +6 -0
- package/dist/hooks/useChat/action-handler.d.ts.map +1 -0
- package/dist/hooks/useChat/action-lifecycle.d.ts +19 -0
- package/dist/hooks/useChat/action-lifecycle.d.ts.map +1 -0
- package/dist/hooks/useChat/error-utils.d.ts +7 -0
- package/dist/hooks/useChat/error-utils.d.ts.map +1 -0
- package/dist/hooks/{useChat.d.ts → useChat/index.d.ts} +2 -2
- package/dist/hooks/useChat/index.d.ts.map +1 -0
- package/dist/hooks/useChat/message-hydration.d.ts +4 -0
- package/dist/hooks/useChat/message-hydration.d.ts.map +1 -0
- package/dist/hooks/useChat/stream-handlers.d.ts +27 -0
- package/dist/hooks/useChat/stream-handlers.d.ts.map +1 -0
- package/dist/hooks/useChat/stream-state.d.ts +8 -0
- package/dist/hooks/useChat/stream-state.d.ts.map +1 -0
- package/dist/hooks/useChat/types.d.ts +26 -0
- package/dist/hooks/useChat/types.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +1546 -331
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1546 -331
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +10 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/sse-parser.d.ts.map +1 -1
- package/package.json +7 -3
- package/dist/hooks/useChat.d.ts.map +0 -1
|
@@ -16696,11 +16696,14 @@
|
|
|
16696
16696
|
const reader = response.body.getReader();
|
|
16697
16697
|
const decoder = new TextDecoder();
|
|
16698
16698
|
let buffer = "";
|
|
16699
|
+
let eventCount = 0;
|
|
16699
16700
|
try {
|
|
16700
16701
|
while (true) {
|
|
16701
16702
|
const { done, value } = await reader.read();
|
|
16702
|
-
if (done)
|
|
16703
|
+
if (done) {
|
|
16704
|
+
console.log(`[SSE Parser] Stream ended normally after ${eventCount} events`);
|
|
16703
16705
|
break;
|
|
16706
|
+
}
|
|
16704
16707
|
buffer += decoder.decode(value, { stream: true });
|
|
16705
16708
|
const chunks = buffer.split("\n\n");
|
|
16706
16709
|
buffer = chunks.pop() || "";
|
|
@@ -16712,6 +16715,7 @@
|
|
|
16712
16715
|
const data = JSON.parse(line.slice(6));
|
|
16713
16716
|
if (validator) {
|
|
16714
16717
|
if (validator(data)) {
|
|
16718
|
+
eventCount++;
|
|
16715
16719
|
yield data;
|
|
16716
16720
|
}
|
|
16717
16721
|
else {
|
|
@@ -16719,6 +16723,7 @@
|
|
|
16719
16723
|
}
|
|
16720
16724
|
}
|
|
16721
16725
|
else {
|
|
16726
|
+
eventCount++;
|
|
16722
16727
|
yield data;
|
|
16723
16728
|
}
|
|
16724
16729
|
}
|
|
@@ -16731,6 +16736,10 @@
|
|
|
16731
16736
|
}
|
|
16732
16737
|
}
|
|
16733
16738
|
}
|
|
16739
|
+
catch (error) {
|
|
16740
|
+
console.error(`[SSE Parser] Stream error after ${eventCount} events:`, error);
|
|
16741
|
+
throw error;
|
|
16742
|
+
}
|
|
16734
16743
|
finally {
|
|
16735
16744
|
reader.releaseLock();
|
|
16736
16745
|
}
|
|
@@ -16864,7 +16873,7 @@
|
|
|
16864
16873
|
const result = await response.json();
|
|
16865
16874
|
return result.file;
|
|
16866
16875
|
}
|
|
16867
|
-
async *sendAgentMessageStream(conversationId, message, fileIds) {
|
|
16876
|
+
async *sendAgentMessageStream(conversationId, message, fileIds, signal) {
|
|
16868
16877
|
const headers = {
|
|
16869
16878
|
'Content-Type': 'application/json',
|
|
16870
16879
|
};
|
|
@@ -16880,6 +16889,7 @@
|
|
|
16880
16889
|
fileIds,
|
|
16881
16890
|
timeZone: this.getTimeZone(),
|
|
16882
16891
|
}),
|
|
16892
|
+
signal,
|
|
16883
16893
|
});
|
|
16884
16894
|
if (!response.ok) {
|
|
16885
16895
|
throw await buildApiError(response, 'Failed to send agent message');
|
|
@@ -16888,7 +16898,7 @@
|
|
|
16888
16898
|
return typeof data === 'object' && data !== null && 'type' in data;
|
|
16889
16899
|
});
|
|
16890
16900
|
}
|
|
16891
|
-
async *continueAgentMessageStream(conversationId, toolCallId, state) {
|
|
16901
|
+
async *continueAgentMessageStream(conversationId, toolCallId, state, signal) {
|
|
16892
16902
|
const headers = {
|
|
16893
16903
|
'Content-Type': 'application/json',
|
|
16894
16904
|
};
|
|
@@ -16904,6 +16914,7 @@
|
|
|
16904
16914
|
state,
|
|
16905
16915
|
timeZone: this.getTimeZone(),
|
|
16906
16916
|
}),
|
|
16917
|
+
signal,
|
|
16907
16918
|
});
|
|
16908
16919
|
if (!response.ok) {
|
|
16909
16920
|
throw await buildApiError(response, 'Failed to continue agent');
|
|
@@ -43804,18 +43815,14 @@
|
|
|
43804
43815
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
43805
43816
|
.join(' ');
|
|
43806
43817
|
};
|
|
43807
|
-
const GearIcon = ({ spinning = false }) => (jsxRuntimeExports.jsxs("svg", { className: `ai-chat-tool-gear ${spinning ? 'spinning' : ''}`, width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z" }), jsxRuntimeExports.jsx("path", { d: "M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z" }), jsxRuntimeExports.jsx("path", { d: "M12 2v2" }), jsxRuntimeExports.jsx("path", { d: "M12 22v-2" }), jsxRuntimeExports.jsx("path", { d: "m17 20.66-1-1.73" }), jsxRuntimeExports.jsx("path", { d: "M11 10.27 7 3.34" }), jsxRuntimeExports.jsx("path", { d: "m20.66 17-1.73-1" }), jsxRuntimeExports.jsx("path", { d: "m3.34 7 1.73 1" }), jsxRuntimeExports.jsx("path", { d: "M14 12h8" }), jsxRuntimeExports.jsx("path", { d: "M2 12h2" }), jsxRuntimeExports.jsx("path", { d: "m20.66 7-1.73 1" }), jsxRuntimeExports.jsx("path", { d: "m3.34 17 1.73-1" }), jsxRuntimeExports.jsx("path", { d: "m17 3.34-1 1.73" }), jsxRuntimeExports.jsx("path", { d: "m11 13.73-4 6.93" })] }));
|
|
43808
|
-
const CheckIcon$2 = () => (jsxRuntimeExports.jsx("svg", { className: "ai-chat-tool-check", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
43809
|
-
const ErrorIcon = () => (jsxRuntimeExports.jsx("svg", { className: "ai-chat-tool-error", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }));
|
|
43810
43818
|
function ToolIndicator({ badges, className = '' }) {
|
|
43811
|
-
|
|
43812
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-tool-row ${className}`, children: [jsxRuntimeExports.jsx(GearIcon, { spinning: isAnyLoading }), jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-badges", children: badges.map((badge) => (jsxRuntimeExports.jsxs("div", { className: `ai-chat-tool-badge ${badge.status}`, children: [badge.status !== 'loading' && (badge.status === 'error' ? jsxRuntimeExports.jsx(ErrorIcon, {}) : jsxRuntimeExports.jsx(CheckIcon$2, {})), jsxRuntimeExports.jsx("span", { className: "tool-name", children: formatToolName(badge.name) })] }, badge.id))) })] }));
|
|
43819
|
+
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-row ${className}`, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-badges", children: badges.map((badge) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-badge ${badge.status}`, children: jsxRuntimeExports.jsx("span", { className: "tool-name", children: formatToolName(badge.name) }) }, badge.id))) }) }));
|
|
43813
43820
|
}
|
|
43814
43821
|
|
|
43815
43822
|
// SVG Icon components
|
|
43816
43823
|
const ThumbsUpIcon = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }) }));
|
|
43817
43824
|
const ThumbsDownIcon = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" }) }));
|
|
43818
|
-
const CheckIcon$
|
|
43825
|
+
const CheckIcon$2 = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
43819
43826
|
const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
|
|
43820
43827
|
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
43821
43828
|
const [submitted, setSubmitted] = reactExports.useState(false);
|
|
@@ -43836,17 +43843,10 @@
|
|
|
43836
43843
|
setIsSubmitting(false);
|
|
43837
43844
|
}
|
|
43838
43845
|
};
|
|
43839
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntimeExports.jsx(ThumbsUpIcon, {}) }), jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'negative' ? 'active' : ''}`, onClick: () => handleFeedback('negative'), disabled: isDisabled, "aria-label": "Not helpful", title: "This was not helpful", children: jsxRuntimeExports.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntimeExports.jsx(CheckIcon$
|
|
43840
|
-
};
|
|
43841
|
-
|
|
43842
|
-
const Sources = ({ sources, displayMode = 'with-score' }) => {
|
|
43843
|
-
const [isExpanded, setIsExpanded] = reactExports.useState(false);
|
|
43844
|
-
if (!sources || sources.length === 0 || displayMode === 'none')
|
|
43845
|
-
return null;
|
|
43846
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-sources", children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-sources-toggle", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-sources-icon", children: isExpanded ? '▼' : '▶' }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-sources-title", children: [sources.length, " source", sources.length > 1 ? 's' : ''] })] }), isExpanded && displayMode !== 'minimal' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-sources-list", children: sources.map((source, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-item", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-number", children: [index + 1, "."] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-details", children: [displayMode === 'with-score' && source.score && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), (displayMode === 'with-content' || displayMode === 'full') && source.doc.pageContent && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-content", children: [source.doc.pageContent.substring(0, 100), source.doc.pageContent.length > 100 ? '...' : ''] })), displayMode === 'full' && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [source.score && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), source.doc.metadata && Object.keys(source.doc.metadata).length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-source-metadata", children: Object.entries(source.doc.metadata).map(([key, value]) => (jsxRuntimeExports.jsxs("span", { className: "ai-chat-source-meta-item", children: [key, ": ", String(value)] }, key))) }))] }))] })] }, `${source.kbId}-${source.doc.id}-${index}`))) }))] }));
|
|
43846
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntimeExports.jsx(ThumbsUpIcon, {}) }), jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'negative' ? 'active' : ''}`, onClick: () => handleFeedback('negative'), disabled: isDisabled, "aria-label": "Not helpful", title: "This was not helpful", children: jsxRuntimeExports.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntimeExports.jsx(CheckIcon$2, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-text", children: "Thanks for feedback" })] }))] }));
|
|
43847
43847
|
};
|
|
43848
43848
|
|
|
43849
|
-
const Message = ({ message, showTimestamp = true, enableFeedback = true,
|
|
43849
|
+
const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
|
|
43850
43850
|
const formatTime = (timestamp) => {
|
|
43851
43851
|
const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
|
|
43852
43852
|
return date.toLocaleTimeString('en-US', {
|
|
@@ -43866,15 +43866,15 @@
|
|
|
43866
43866
|
return null;
|
|
43867
43867
|
}
|
|
43868
43868
|
// AI message rendering
|
|
43869
|
+
// Note: Actions are rendered by ToolMessageGroup for tool messages, not here
|
|
43869
43870
|
if (isAssistant) {
|
|
43870
43871
|
const aiContent = message.message.content || '';
|
|
43871
43872
|
const hasContent = aiContent.trim().length > 0;
|
|
43872
43873
|
if (!hasContent)
|
|
43873
43874
|
return null;
|
|
43874
|
-
|
|
43875
|
-
|
|
43876
|
-
|
|
43877
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-content", children: [isError && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-error-indicator", children: [jsxRuntimeExports.jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "error-text", children: "Error" })] })), jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], children: aiContent })] }), actionRenderer && message.action && actionRenderer(message), showTimestamp && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] })), showSources && message.sources?.length > 0 && (jsxRuntimeExports.jsx(Sources, { sources: message.sources, displayMode: sourceDisplayMode }))] }));
|
|
43875
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], components: {
|
|
43876
|
+
table: ({ children, ...props }) => (jsxRuntimeExports.jsx("div", { className: "table-wrapper", children: jsxRuntimeExports.jsx("div", { className: "table-scroll", children: jsxRuntimeExports.jsx("table", { ...props, children: children }) }) })),
|
|
43877
|
+
}, children: aiContent }) }), showTimestamp && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] }))] }));
|
|
43878
43878
|
}
|
|
43879
43879
|
// System message rendering
|
|
43880
43880
|
if (isSystem) {
|
|
@@ -43888,30 +43888,85 @@
|
|
|
43888
43888
|
return null;
|
|
43889
43889
|
};
|
|
43890
43890
|
|
|
43891
|
-
|
|
43891
|
+
// Centralized action state logic
|
|
43892
|
+
function isActionComplete(state) {
|
|
43893
|
+
if (!state)
|
|
43894
|
+
return false;
|
|
43895
|
+
const TERMINAL_STATUSES = [
|
|
43896
|
+
'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
|
|
43897
|
+
'displaying', 'clicked', 'contacted', 'submitted', 'sent'
|
|
43898
|
+
];
|
|
43899
|
+
const status = state.status;
|
|
43900
|
+
if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
|
|
43901
|
+
return true;
|
|
43902
|
+
}
|
|
43903
|
+
// For non-halting actions (query_contact_directory, etc.) with results/success
|
|
43904
|
+
if (!status && (state.success !== undefined || state.results !== undefined)) {
|
|
43905
|
+
return true;
|
|
43906
|
+
}
|
|
43907
|
+
return false;
|
|
43908
|
+
}
|
|
43909
|
+
function isActionLoading(message) {
|
|
43910
|
+
if (!message.action)
|
|
43911
|
+
return false;
|
|
43912
|
+
if (message.action.done)
|
|
43913
|
+
return false;
|
|
43914
|
+
if (message.isStreaming)
|
|
43915
|
+
return true;
|
|
43916
|
+
const state = message.action.state;
|
|
43917
|
+
return !isActionComplete(state);
|
|
43918
|
+
}
|
|
43919
|
+
const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant }) => {
|
|
43892
43920
|
const actionMessages = messages.filter(message => message.action);
|
|
43921
|
+
// Debug logging
|
|
43922
|
+
console.log('[DEBUG ToolMessageGroup] ========================================');
|
|
43923
|
+
console.log('[DEBUG ToolMessageGroup] Total messages:', messages.length);
|
|
43924
|
+
console.log('[DEBUG ToolMessageGroup] Messages with action:', actionMessages.length);
|
|
43925
|
+
console.log('[DEBUG ToolMessageGroup] hasGetActionRenderer:', !!getActionRenderer);
|
|
43926
|
+
messages.forEach((msg, i) => {
|
|
43927
|
+
console.log(`[DEBUG ToolMessageGroup] Message ${i}:`, {
|
|
43928
|
+
id: msg.id,
|
|
43929
|
+
role: msg.message.role,
|
|
43930
|
+
hasAction: !!msg.action,
|
|
43931
|
+
actionImpl: msg.action?.implementation,
|
|
43932
|
+
toolExecuting: msg.toolExecuting,
|
|
43933
|
+
});
|
|
43934
|
+
});
|
|
43935
|
+
actionMessages.forEach((msg, i) => {
|
|
43936
|
+
const impl = msg.action?.implementation || '';
|
|
43937
|
+
const renderer = getActionRenderer?.(impl);
|
|
43938
|
+
console.log(`[DEBUG ToolMessageGroup] Action ${i}:`, {
|
|
43939
|
+
implementation: impl,
|
|
43940
|
+
hasRenderer: !!renderer,
|
|
43941
|
+
rendererType: renderer ? typeof renderer : 'undefined',
|
|
43942
|
+
state: msg.action?.state,
|
|
43943
|
+
});
|
|
43944
|
+
});
|
|
43945
|
+
// If tool indicator is hidden AND there are no action cards to render, don't render anything
|
|
43946
|
+
if (!showToolIndicator && actionMessages.length === 0) {
|
|
43947
|
+
return null;
|
|
43948
|
+
}
|
|
43893
43949
|
const badges = messages.map((message) => {
|
|
43894
43950
|
const toolName = message.toolExecuting || message.message.name || 'Tool';
|
|
43895
43951
|
const hasError = message.isError || false;
|
|
43896
|
-
const
|
|
43897
|
-
const actionStatus = actionState?.status;
|
|
43898
|
-
const terminalStatuses = ['completed', 'booked', 'scheduled', 'failed', 'cancelled'];
|
|
43899
|
-
const isTerminalStatus = actionStatus && terminalStatuses.includes(actionStatus);
|
|
43900
|
-
const isDone = message.action ? (message.action.done ?? isTerminalStatus ?? false) : !message.isStreaming;
|
|
43901
|
-
const isLoading = !isDone;
|
|
43952
|
+
const loading = isActionLoading(message);
|
|
43902
43953
|
return {
|
|
43903
43954
|
id: message.id,
|
|
43904
43955
|
name: toolName,
|
|
43905
|
-
status:
|
|
43956
|
+
status: loading ? 'loading' : hasError ? 'error' : 'completed',
|
|
43906
43957
|
};
|
|
43907
43958
|
});
|
|
43908
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message tool", children: [jsxRuntimeExports.jsx(ToolIndicator, { badges: badges }), actionMessages.map((message) => {
|
|
43909
|
-
if (!message.action || !getActionRenderer)
|
|
43959
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message tool", children: [showToolIndicator && jsxRuntimeExports.jsx(ToolIndicator, { badges: badges }), actionMessages.map((message) => {
|
|
43960
|
+
if (!message.action || !getActionRenderer) {
|
|
43961
|
+
console.log('[ToolMessageGroup] Skipping - no action or renderer:', { hasAction: !!message.action, hasGetRenderer: !!getActionRenderer });
|
|
43910
43962
|
return null;
|
|
43963
|
+
}
|
|
43911
43964
|
const renderer = getActionRenderer(message.action.implementation);
|
|
43912
|
-
if (!renderer)
|
|
43965
|
+
if (!renderer) {
|
|
43966
|
+
console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
|
|
43913
43967
|
return null;
|
|
43914
|
-
|
|
43968
|
+
}
|
|
43969
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant) }, `action-${message.id}`));
|
|
43915
43970
|
})] }));
|
|
43916
43971
|
};
|
|
43917
43972
|
|
|
@@ -43973,12 +44028,16 @@
|
|
|
43973
44028
|
};
|
|
43974
44029
|
|
|
43975
44030
|
const MessageList = (props) => {
|
|
43976
|
-
const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true,
|
|
44031
|
+
const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onFeedback, onScrollStateChange, getActionRenderer, variant, } = props;
|
|
43977
44032
|
const containerRef = reactExports.useRef(null);
|
|
43978
44033
|
const messagesEndRef = reactExports.useRef(null);
|
|
43979
44034
|
const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
|
|
43980
44035
|
const prevMessageCountRef = reactExports.useRef(0);
|
|
43981
|
-
const hasActiveAction = reactExports.useMemo(() =>
|
|
44036
|
+
const hasActiveAction = reactExports.useMemo(() => {
|
|
44037
|
+
// Find the last tool message and check if its action is still active (not done)
|
|
44038
|
+
const lastToolMsg = [...messages].reverse().find(msg => msg.message.role === 'tool');
|
|
44039
|
+
return lastToolMsg?.action && lastToolMsg.action.done !== true;
|
|
44040
|
+
}, [messages]);
|
|
43982
44041
|
const checkScrollPosition = reactExports.useCallback(() => {
|
|
43983
44042
|
const c = containerRef.current;
|
|
43984
44043
|
if (!c)
|
|
@@ -44014,39 +44073,70 @@
|
|
|
44014
44073
|
checkScrollPosition();
|
|
44015
44074
|
}, [messages, isTyping, checkScrollPosition]);
|
|
44016
44075
|
const groupedMessages = reactExports.useMemo(() => {
|
|
44076
|
+
console.log('[DEBUG MessageList] ========================================');
|
|
44077
|
+
console.log('[DEBUG MessageList] Processing messages:', messages.length);
|
|
44078
|
+
messages.forEach((m, i) => {
|
|
44079
|
+
console.log(`[DEBUG MessageList] Message ${i}:`, {
|
|
44080
|
+
id: m.id,
|
|
44081
|
+
role: m.message.role,
|
|
44082
|
+
hasAction: !!m.action,
|
|
44083
|
+
actionImpl: m.action?.implementation,
|
|
44084
|
+
content: (m.message.content || '').substring(0, 50),
|
|
44085
|
+
});
|
|
44086
|
+
});
|
|
44017
44087
|
const result = [];
|
|
44018
44088
|
let toolGroup = [];
|
|
44019
|
-
const flush = () => {
|
|
44020
|
-
|
|
44021
|
-
|
|
44022
|
-
|
|
44089
|
+
const flush = () => {
|
|
44090
|
+
if (toolGroup.length) {
|
|
44091
|
+
console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
|
|
44092
|
+
result.push({ type: 'tool-group', messages: [...toolGroup] });
|
|
44093
|
+
toolGroup = [];
|
|
44094
|
+
}
|
|
44095
|
+
};
|
|
44023
44096
|
for (const m of messages) {
|
|
44024
|
-
if (m.message.role === 'tool')
|
|
44097
|
+
if (m.message.role === 'tool') {
|
|
44098
|
+
console.log('[DEBUG MessageList] Adding to tool group:', m.id);
|
|
44025
44099
|
toolGroup.push(m);
|
|
44100
|
+
}
|
|
44026
44101
|
else if (m.message.role === 'user') {
|
|
44027
44102
|
flush();
|
|
44028
44103
|
result.push({ type: 'message', message: m });
|
|
44029
44104
|
}
|
|
44030
|
-
else if (m.message.role === 'assistant'
|
|
44031
|
-
|
|
44032
|
-
|
|
44105
|
+
else if (m.message.role === 'assistant') {
|
|
44106
|
+
// Include assistant messages if they have content OR are still streaming (content may arrive)
|
|
44107
|
+
const hasContent = (m.message.content || '').trim().length > 0;
|
|
44108
|
+
if (hasContent || m.isStreaming) {
|
|
44109
|
+
flush();
|
|
44110
|
+
result.push({ type: 'message', message: m });
|
|
44111
|
+
}
|
|
44112
|
+
// Don't flush on empty assistant messages - let tools continue grouping
|
|
44033
44113
|
}
|
|
44034
|
-
else
|
|
44114
|
+
else {
|
|
44035
44115
|
flush();
|
|
44036
44116
|
result.push({ type: 'message', message: m });
|
|
44037
44117
|
}
|
|
44038
44118
|
}
|
|
44039
44119
|
flush();
|
|
44120
|
+
console.log('[DEBUG MessageList] Final grouped result:', result.length, 'items');
|
|
44121
|
+
result.forEach((item, i) => {
|
|
44122
|
+
if (item.type === 'tool-group') {
|
|
44123
|
+
console.log(`[DEBUG MessageList] Group ${i}: tool-group with ${item.messages.length} messages`);
|
|
44124
|
+
}
|
|
44125
|
+
else {
|
|
44126
|
+
console.log(`[DEBUG MessageList] Group ${i}: message (${item.message.message.role})`);
|
|
44127
|
+
}
|
|
44128
|
+
});
|
|
44040
44129
|
return result;
|
|
44041
44130
|
}, [messages]);
|
|
44042
44131
|
const hasSuggestions = messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
|
|
44043
44132
|
const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
|
|
44044
44133
|
return (jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "ai-chat-messages", role: "log", "aria-live": "polite", children: [showWelcome && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle }), welcomeMessage && jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }), hasSuggestions && jsxRuntimeExports.jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: onSuggestedQuestionClick })] })), groupedMessages.map((item, i) => {
|
|
44045
|
-
if (item.type === 'tool-group')
|
|
44046
|
-
return jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer }, `tg-${i}`);
|
|
44134
|
+
if (item.type === 'tool-group') {
|
|
44135
|
+
return jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant }, `tg-${i}`);
|
|
44136
|
+
}
|
|
44047
44137
|
const isLast = i === groupedMessages.length - 1;
|
|
44048
44138
|
const hasFollowUp = item.message.message.role === 'assistant' && item.message.suggestions?.length && isLast && !isTyping;
|
|
44049
|
-
return (jsxRuntimeExports.jsxs(React.Fragment, { children: [jsxRuntimeExports.jsx(Message, { message: item.message, showTimestamp: showTimestamps,
|
|
44139
|
+
return (jsxRuntimeExports.jsxs(React.Fragment, { children: [jsxRuntimeExports.jsx(Message, { message: item.message, showTimestamp: showTimestamps, onFeedback: onFeedback, getActionRenderer: getActionRenderer, accentColor: accentColor }), hasFollowUp && onSuggestedQuestionClick && jsxRuntimeExports.jsx(FollowUpSuggestions, { suggestions: item.message.suggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })] }, item.message.id));
|
|
44050
44140
|
}), isTyping && showTypingIndicator && !hasActiveAction && messages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
|
|
44051
44141
|
};
|
|
44052
44142
|
|
|
@@ -44061,7 +44151,7 @@
|
|
|
44061
44151
|
return (bytes / 1024).toFixed(1) + ' KB';
|
|
44062
44152
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
44063
44153
|
};
|
|
44064
|
-
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
|
|
44154
|
+
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, }) => {
|
|
44065
44155
|
const [value, setValue] = reactExports.useState('');
|
|
44066
44156
|
const [selectedFiles, setSelectedFiles] = reactExports.useState([]);
|
|
44067
44157
|
const textareaRef = reactExports.useRef(null);
|
|
@@ -44096,10 +44186,10 @@
|
|
|
44096
44186
|
}
|
|
44097
44187
|
};
|
|
44098
44188
|
const canSend = value.trim() || selectedFiles.length > 0;
|
|
44099
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntimeExports.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 2, wrap: "soft", "aria-label": "Message input" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] })] }));
|
|
44189
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntimeExports.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 2, wrap: "soft", "aria-label": "Message input" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] }), showDataPolicy && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy", children: [jsxRuntimeExports.jsx("span", { children: "KI-generierte Antworten k\u00F6nnen unzutreffend sein." }), onDataPolicyClick && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [' ', jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Datenschutzhinweis" })] }))] }))] }));
|
|
44100
44190
|
};
|
|
44101
44191
|
|
|
44102
|
-
function groupSlotsByDate(slots) {
|
|
44192
|
+
function groupSlotsByDate$1(slots) {
|
|
44103
44193
|
const grouped = new Map();
|
|
44104
44194
|
for (const slot of slots) {
|
|
44105
44195
|
if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
|
|
@@ -44113,7 +44203,7 @@
|
|
|
44113
44203
|
}
|
|
44114
44204
|
return grouped;
|
|
44115
44205
|
}
|
|
44116
|
-
function formatDate(dateStr) {
|
|
44206
|
+
function formatDate$1(dateStr) {
|
|
44117
44207
|
try {
|
|
44118
44208
|
const date = new Date(dateStr);
|
|
44119
44209
|
return new Intl.DateTimeFormat("en-US", {
|
|
@@ -44126,16 +44216,16 @@
|
|
|
44126
44216
|
return dateStr;
|
|
44127
44217
|
}
|
|
44128
44218
|
}
|
|
44129
|
-
function CalendarIcon() {
|
|
44219
|
+
function CalendarIcon$1() {
|
|
44130
44220
|
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z", clipRule: "evenodd" }) }));
|
|
44131
44221
|
}
|
|
44132
|
-
function CheckIcon() {
|
|
44222
|
+
function CheckIcon$1() {
|
|
44133
44223
|
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }));
|
|
44134
44224
|
}
|
|
44135
|
-
function ExternalLinkIcon() {
|
|
44225
|
+
function ExternalLinkIcon$2() {
|
|
44136
44226
|
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
44137
44227
|
}
|
|
44138
|
-
function Skeleton({ width, height, borderRadius = '4px' }) {
|
|
44228
|
+
function Skeleton$1({ width, height, borderRadius = '4px' }) {
|
|
44139
44229
|
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
|
|
44140
44230
|
}
|
|
44141
44231
|
function GoogleCalendarCard({ action, onComplete, accentColor, className = '' }) {
|
|
@@ -44152,13 +44242,12 @@
|
|
|
44152
44242
|
: [];
|
|
44153
44243
|
const allowTopic = state.allowTopic !== false;
|
|
44154
44244
|
const isBooked = state.status === "booked";
|
|
44155
|
-
const slotsByDate = groupSlotsByDate(availableSlots);
|
|
44245
|
+
const slotsByDate = groupSlotsByDate$1(availableSlots);
|
|
44156
44246
|
const dates = Array.from(slotsByDate.keys()).sort();
|
|
44157
44247
|
const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
|
|
44158
44248
|
const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
|
|
44159
44249
|
const [topic, setTopic] = reactExports.useState("");
|
|
44160
44250
|
const [error, setError] = reactExports.useState(null);
|
|
44161
|
-
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
44162
44251
|
const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
|
|
44163
44252
|
const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
|
|
44164
44253
|
const onConfirm = () => {
|
|
@@ -44171,8 +44260,245 @@
|
|
|
44171
44260
|
return;
|
|
44172
44261
|
}
|
|
44173
44262
|
setError(null);
|
|
44263
|
+
onComplete?.(action.toolCallId, {
|
|
44264
|
+
...action.state,
|
|
44265
|
+
selectedSlot: {
|
|
44266
|
+
startTime: selectedSlot.startTime,
|
|
44267
|
+
endTime: selectedSlot.endTime,
|
|
44268
|
+
},
|
|
44269
|
+
topic: allowTopic ? topic.trim() : null,
|
|
44270
|
+
});
|
|
44271
|
+
};
|
|
44272
|
+
// Booked state
|
|
44273
|
+
if (isBooked) {
|
|
44274
|
+
const bookedSlot = state.selectedSlot;
|
|
44275
|
+
const bookedTopic = state.topic;
|
|
44276
|
+
const eventLink = state.bookedEventLink;
|
|
44277
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon$1, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Google Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$2, {})] }))] })] }));
|
|
44278
|
+
}
|
|
44279
|
+
// Skeleton loading state - show when waiting for backend after user confirms
|
|
44280
|
+
const isWaitingForBackend = !action.done && state.selectedSlot && !isBooked;
|
|
44281
|
+
if (isWaitingForBackend) {
|
|
44282
|
+
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton$1, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
|
|
44283
|
+
}
|
|
44284
|
+
// Booking form
|
|
44285
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-google-calendar ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon$1, {}), "Schedule an Appointment"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
|
|
44286
|
+
setSelectedDate(date);
|
|
44287
|
+
setSelectedSlot(null);
|
|
44288
|
+
}, children: formatDate$1(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), error && jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: error }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: onConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
|
|
44289
|
+
}
|
|
44290
|
+
|
|
44291
|
+
function groupSlotsByDate(slots) {
|
|
44292
|
+
const grouped = new Map();
|
|
44293
|
+
for (const slot of slots) {
|
|
44294
|
+
if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
|
|
44295
|
+
continue;
|
|
44296
|
+
}
|
|
44297
|
+
const date = slot.startTime.slice(0, 10);
|
|
44298
|
+
if (!grouped.has(date)) {
|
|
44299
|
+
grouped.set(date, []);
|
|
44300
|
+
}
|
|
44301
|
+
grouped.get(date).push(slot);
|
|
44302
|
+
}
|
|
44303
|
+
return grouped;
|
|
44304
|
+
}
|
|
44305
|
+
function formatDate(dateStr) {
|
|
44306
|
+
try {
|
|
44307
|
+
const date = new Date(dateStr);
|
|
44308
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
44309
|
+
weekday: "short",
|
|
44310
|
+
month: "short",
|
|
44311
|
+
day: "numeric",
|
|
44312
|
+
}).format(date);
|
|
44313
|
+
}
|
|
44314
|
+
catch {
|
|
44315
|
+
return dateStr;
|
|
44316
|
+
}
|
|
44317
|
+
}
|
|
44318
|
+
function CalendarIcon() {
|
|
44319
|
+
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z", clipRule: "evenodd" }) }));
|
|
44320
|
+
}
|
|
44321
|
+
function MailIcon() {
|
|
44322
|
+
return (jsxRuntimeExports.jsxs("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: [jsxRuntimeExports.jsx("path", { d: "M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" }), jsxRuntimeExports.jsx("path", { d: "M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" })] }));
|
|
44323
|
+
}
|
|
44324
|
+
function CheckIcon() {
|
|
44325
|
+
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }));
|
|
44326
|
+
}
|
|
44327
|
+
function ErrorIcon() {
|
|
44328
|
+
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-error", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }));
|
|
44329
|
+
}
|
|
44330
|
+
function ExternalLinkIcon$1() {
|
|
44331
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
44332
|
+
}
|
|
44333
|
+
function Skeleton({ width, height, borderRadius = '4px' }) {
|
|
44334
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
|
|
44335
|
+
}
|
|
44336
|
+
function PinInputGroup({ values, onChange, disabled }) {
|
|
44337
|
+
const inputRefs = reactExports.useRef([]);
|
|
44338
|
+
const handleChange = (index, value) => {
|
|
44339
|
+
// Only allow digits
|
|
44340
|
+
const digit = value.replace(/[^0-9]/g, '');
|
|
44341
|
+
const newValues = [...values];
|
|
44342
|
+
newValues[index] = digit.slice(-1);
|
|
44343
|
+
onChange(newValues);
|
|
44344
|
+
// Auto-focus next input
|
|
44345
|
+
if (digit && index < 5) {
|
|
44346
|
+
inputRefs.current[index + 1]?.focus();
|
|
44347
|
+
}
|
|
44348
|
+
};
|
|
44349
|
+
const handleKeyDown = (index, e) => {
|
|
44350
|
+
if (e.key === 'Backspace' && !values[index] && index > 0) {
|
|
44351
|
+
inputRefs.current[index - 1]?.focus();
|
|
44352
|
+
}
|
|
44353
|
+
};
|
|
44354
|
+
const handlePaste = (e) => {
|
|
44355
|
+
e.preventDefault();
|
|
44356
|
+
const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
|
|
44357
|
+
const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
|
|
44358
|
+
onChange(newValues);
|
|
44359
|
+
// Focus the next empty input or the last one
|
|
44360
|
+
const nextIndex = Math.min(pastedData.length, 5);
|
|
44361
|
+
inputRefs.current[nextIndex]?.focus();
|
|
44362
|
+
};
|
|
44363
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntimeExports.jsx("input", { ref: (el) => {
|
|
44364
|
+
inputRefs.current[index] = el;
|
|
44365
|
+
}, type: "text", inputMode: "numeric", maxLength: 1, className: "ai-chat-pin-input", value: value, onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onPaste: handlePaste, disabled: disabled, autoFocus: index === 0 }, index))) }));
|
|
44366
|
+
}
|
|
44367
|
+
function MicrosoftCalendarCard({ action, onComplete, accentColor, className = '' }) {
|
|
44368
|
+
const state = action.state;
|
|
44369
|
+
const phase = state.phase || "awaiting_email";
|
|
44370
|
+
const allowTopic = state.allowTopic !== false;
|
|
44371
|
+
const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
|
|
44372
|
+
// Debug: Log state changes
|
|
44373
|
+
const prevStateRef = reactExports.useRef(null);
|
|
44374
|
+
reactExports.useEffect(() => {
|
|
44375
|
+
if (JSON.stringify(prevStateRef.current) !== JSON.stringify(state)) {
|
|
44376
|
+
console.log('[MicrosoftCalendarCard] State updated:', {
|
|
44377
|
+
phase: state.phase,
|
|
44378
|
+
hasError: !!state.errorMessage,
|
|
44379
|
+
error: state.errorMessage,
|
|
44380
|
+
slotsCount: state.availableSlots?.length || 0
|
|
44381
|
+
});
|
|
44382
|
+
prevStateRef.current = state;
|
|
44383
|
+
}
|
|
44384
|
+
}, [state]);
|
|
44385
|
+
// Email phase state
|
|
44386
|
+
const [email, setEmail] = reactExports.useState("");
|
|
44387
|
+
const [emailError, setEmailError] = reactExports.useState(null);
|
|
44388
|
+
// OTP phase state
|
|
44389
|
+
const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
|
|
44390
|
+
const [otpError, setOtpError] = reactExports.useState(null);
|
|
44391
|
+
// Loading states
|
|
44392
|
+
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
44393
|
+
// Reset loading state when phase changes (backend has responded)
|
|
44394
|
+
// Use useEffect for reliable re-rendering
|
|
44395
|
+
reactExports.useEffect(() => {
|
|
44396
|
+
console.log('[MicrosoftCalendarCard] Phase changed to:', phase);
|
|
44397
|
+
setIsSubmitting(false);
|
|
44398
|
+
// Clear errors when transitioning to new phase
|
|
44399
|
+
if (phase === "awaiting_email") {
|
|
44400
|
+
setEmailError(null);
|
|
44401
|
+
setOtpError(null);
|
|
44402
|
+
setSelectionError(null);
|
|
44403
|
+
}
|
|
44404
|
+
else if (phase === "awaiting_otp") {
|
|
44405
|
+
setOtpError(state.errorMessage || null);
|
|
44406
|
+
setEmailError(null);
|
|
44407
|
+
setSelectionError(null);
|
|
44408
|
+
// Clear OTP input for fresh attempt
|
|
44409
|
+
setOtpValues(Array(6).fill(''));
|
|
44410
|
+
}
|
|
44411
|
+
else if (phase === "awaiting_options") {
|
|
44412
|
+
setEmailError(null);
|
|
44413
|
+
setOtpError(null);
|
|
44414
|
+
setSelectionError(null);
|
|
44415
|
+
}
|
|
44416
|
+
else if (phase === "awaiting_booking") {
|
|
44417
|
+
setSelectionError(state.errorMessage || null);
|
|
44418
|
+
setEmailError(null);
|
|
44419
|
+
setOtpError(null);
|
|
44420
|
+
}
|
|
44421
|
+
else if (phase === "booked" || phase === "cancelled" || phase === "error") {
|
|
44422
|
+
setEmailError(null);
|
|
44423
|
+
setOtpError(null);
|
|
44424
|
+
setSelectionError(null);
|
|
44425
|
+
setSelectedId(null); // Reset selection
|
|
44426
|
+
}
|
|
44427
|
+
}, [phase, state.errorMessage]);
|
|
44428
|
+
// Selection phase state
|
|
44429
|
+
const rawSlots = state.availableSlots;
|
|
44430
|
+
const availableSlots = Array.isArray(rawSlots)
|
|
44431
|
+
? rawSlots.filter((slot) => slot !== null &&
|
|
44432
|
+
slot !== undefined &&
|
|
44433
|
+
typeof slot === "object" &&
|
|
44434
|
+
"startTime" in slot &&
|
|
44435
|
+
"endTime" in slot &&
|
|
44436
|
+
typeof slot.startTime === "string" &&
|
|
44437
|
+
typeof slot.endTime === "string")
|
|
44438
|
+
: [];
|
|
44439
|
+
const slotsByDate = groupSlotsByDate(availableSlots);
|
|
44440
|
+
const dates = Array.from(slotsByDate.keys()).sort();
|
|
44441
|
+
const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
|
|
44442
|
+
const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
|
|
44443
|
+
const [topic, setTopic] = reactExports.useState("");
|
|
44444
|
+
const [selectionError, setSelectionError] = reactExports.useState(null);
|
|
44445
|
+
// Cancellation phase state
|
|
44446
|
+
const [selectedId, setSelectedId] = reactExports.useState(null);
|
|
44447
|
+
const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
|
|
44448
|
+
// Phase 1: Email Input
|
|
44449
|
+
const handleEmailSubmit = () => {
|
|
44450
|
+
const trimmedEmail = email.trim();
|
|
44451
|
+
if (!trimmedEmail) {
|
|
44452
|
+
setEmailError("Please enter your email address");
|
|
44453
|
+
return;
|
|
44454
|
+
}
|
|
44455
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
|
|
44456
|
+
setEmailError("Please enter a valid email address");
|
|
44457
|
+
return;
|
|
44458
|
+
}
|
|
44459
|
+
setEmailError(null);
|
|
44460
|
+
setIsSubmitting(true);
|
|
44461
|
+
console.log('[MicrosoftCalendarCard] Submitting email:', trimmedEmail);
|
|
44462
|
+
setTimeout(() => {
|
|
44463
|
+
onComplete?.(action.toolCallId, {
|
|
44464
|
+
...action.state,
|
|
44465
|
+
email: trimmedEmail,
|
|
44466
|
+
});
|
|
44467
|
+
}, 50);
|
|
44468
|
+
};
|
|
44469
|
+
// Phase 2: OTP Verification
|
|
44470
|
+
const handleOtpSubmit = () => {
|
|
44471
|
+
const otpCode = otpValues.join('');
|
|
44472
|
+
if (otpCode.length !== 6) {
|
|
44473
|
+
setOtpError("Please enter the 6-digit code");
|
|
44474
|
+
return;
|
|
44475
|
+
}
|
|
44476
|
+
setOtpError(null);
|
|
44477
|
+
setIsSubmitting(true);
|
|
44478
|
+
console.log('[MicrosoftCalendarCard] Submitting OTP code');
|
|
44479
|
+
setTimeout(() => {
|
|
44480
|
+
onComplete?.(action.toolCallId, {
|
|
44481
|
+
...action.state,
|
|
44482
|
+
otpCode,
|
|
44483
|
+
});
|
|
44484
|
+
}, 50);
|
|
44485
|
+
};
|
|
44486
|
+
// Phase 3: Appointment Selection
|
|
44487
|
+
const handleAppointmentConfirm = () => {
|
|
44488
|
+
if (!selectedSlot) {
|
|
44489
|
+
setSelectionError("Please select a time slot");
|
|
44490
|
+
return;
|
|
44491
|
+
}
|
|
44492
|
+
if (allowTopic && !topic.trim()) {
|
|
44493
|
+
setSelectionError("Please enter a meeting topic");
|
|
44494
|
+
return;
|
|
44495
|
+
}
|
|
44496
|
+
setSelectionError(null);
|
|
44174
44497
|
setIsSubmitting(true);
|
|
44175
|
-
|
|
44498
|
+
console.log('[MicrosoftCalendarCard] Confirming appointment:', {
|
|
44499
|
+
slot: selectedSlot,
|
|
44500
|
+
topic: topic.trim()
|
|
44501
|
+
});
|
|
44176
44502
|
setTimeout(() => {
|
|
44177
44503
|
onComplete?.(action.toolCallId, {
|
|
44178
44504
|
...action.state,
|
|
@@ -44184,22 +44510,566 @@
|
|
|
44184
44510
|
});
|
|
44185
44511
|
}, 50);
|
|
44186
44512
|
};
|
|
44187
|
-
//
|
|
44188
|
-
|
|
44513
|
+
// Handle "Use different email" button
|
|
44514
|
+
const handleUseDifferentEmail = () => {
|
|
44515
|
+
setEmail("");
|
|
44516
|
+
setEmailError(null);
|
|
44517
|
+
setOtpValues(Array(6).fill(''));
|
|
44518
|
+
setOtpError(null);
|
|
44519
|
+
onComplete?.(action.toolCallId, {
|
|
44520
|
+
phase: "awaiting_email",
|
|
44521
|
+
email: null,
|
|
44522
|
+
otpVerified: false,
|
|
44523
|
+
otpAttempts: 0,
|
|
44524
|
+
availableSlots: [],
|
|
44525
|
+
selectedSlot: null,
|
|
44526
|
+
topic: null,
|
|
44527
|
+
bookedEventId: null,
|
|
44528
|
+
bookedEventLink: null,
|
|
44529
|
+
allowTopic,
|
|
44530
|
+
errorMessage: null,
|
|
44531
|
+
});
|
|
44532
|
+
};
|
|
44533
|
+
// Phase 5: Booked Confirmation
|
|
44534
|
+
if (phase === "booked") {
|
|
44189
44535
|
const bookedSlot = state.selectedSlot;
|
|
44190
44536
|
const bookedTopic = state.topic;
|
|
44191
44537
|
const eventLink = state.bookedEventLink;
|
|
44192
|
-
|
|
44193
|
-
|
|
44194
|
-
|
|
44538
|
+
const bookedEmail = state.email;
|
|
44539
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), bookedEmail && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["A calendar invitation has been sent to ", bookedEmail] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Outlook Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$1, {})] }))] })] }));
|
|
44540
|
+
}
|
|
44541
|
+
// Phase 6: Cancelled Confirmation
|
|
44542
|
+
if (phase === "cancelled") {
|
|
44543
|
+
const cancelledSubject = state.cancelledEventSubject;
|
|
44544
|
+
const userEmail = state.email;
|
|
44545
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Cancelled"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [cancelledSubject && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "CANCELLED" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: cancelledSubject })] })), userEmail && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["A cancellation notice has been sent to ", userEmail] }))] })] }));
|
|
44546
|
+
}
|
|
44547
|
+
// Error State
|
|
44548
|
+
if (phase === "error") {
|
|
44549
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-error ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(ErrorIcon, {}), "Error"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error-message", children: state.errorMessage || "An error occurred. Please try again." }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
|
|
44550
|
+
setEmail("");
|
|
44551
|
+
setEmailError(null);
|
|
44552
|
+
setOtpValues(Array(6).fill(''));
|
|
44553
|
+
setOtpError(null);
|
|
44554
|
+
onComplete?.(action.toolCallId, {
|
|
44555
|
+
phase: "awaiting_email",
|
|
44556
|
+
email: null,
|
|
44557
|
+
otpVerified: false,
|
|
44558
|
+
otpAttempts: 0,
|
|
44559
|
+
availableSlots: [],
|
|
44560
|
+
selectedSlot: null,
|
|
44561
|
+
topic: null,
|
|
44562
|
+
bookedEventId: null,
|
|
44563
|
+
bookedEventLink: null,
|
|
44564
|
+
allowTopic,
|
|
44565
|
+
errorMessage: null,
|
|
44566
|
+
});
|
|
44567
|
+
}, children: "Start Over" })] })] }));
|
|
44568
|
+
}
|
|
44569
|
+
// Loading State
|
|
44195
44570
|
if (isSubmitting) {
|
|
44196
|
-
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.
|
|
44571
|
+
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
|
|
44572
|
+
}
|
|
44573
|
+
// Phase 1: Email Input
|
|
44574
|
+
if (phase === "awaiting_email") {
|
|
44575
|
+
const displayError = state.errorMessage || emailError;
|
|
44576
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Schedule an Appointment"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "We'll send a verification code to your email" }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `email-${action.toolCallId}`, className: "ai-chat-action-label", children: "Email Address" }), jsxRuntimeExports.jsx("input", { id: `email-${action.toolCallId}`, type: "email", className: "ai-chat-action-input", placeholder: "your@email.com", value: email, onChange: (e) => {
|
|
44577
|
+
setEmail(e.target.value);
|
|
44578
|
+
setEmailError(null);
|
|
44579
|
+
}, onKeyPress: (e) => {
|
|
44580
|
+
if (e.key === 'Enter') {
|
|
44581
|
+
handleEmailSubmit();
|
|
44582
|
+
}
|
|
44583
|
+
}, autoFocus: true })] }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleEmailSubmit, children: "Continue" })] })] }));
|
|
44584
|
+
}
|
|
44585
|
+
// Phase 2: OTP Input
|
|
44586
|
+
if (phase === "awaiting_otp") {
|
|
44587
|
+
const displayError = state.errorMessage || otpError;
|
|
44588
|
+
const userEmail = state.email;
|
|
44589
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(MailIcon, {}), "Verify Your Email"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["We sent a 6-digit code to ", jsxRuntimeExports.jsx("strong", { children: userEmail })] }), jsxRuntimeExports.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
|
|
44590
|
+
setOtpValues(newValues);
|
|
44591
|
+
setOtpError(null);
|
|
44592
|
+
// Auto-submit when all 6 digits are entered
|
|
44593
|
+
if (newValues.every(v => v.length === 1)) {
|
|
44594
|
+
console.log('[MicrosoftCalendarCard] Auto-submitting OTP (all 6 digits entered)');
|
|
44595
|
+
setIsSubmitting(true);
|
|
44596
|
+
const code = newValues.join('');
|
|
44597
|
+
setTimeout(() => {
|
|
44598
|
+
onComplete?.(action.toolCallId, {
|
|
44599
|
+
...action.state,
|
|
44600
|
+
otpCode: code,
|
|
44601
|
+
});
|
|
44602
|
+
}, 100);
|
|
44603
|
+
}
|
|
44604
|
+
}, disabled: isSubmitting }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, children: "Verify Code" }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: handleUseDifferentEmail, children: "Use different email" })] })] }));
|
|
44605
|
+
}
|
|
44606
|
+
// Phase 3: Options Menu (with inline cancel buttons and confirmation)
|
|
44607
|
+
if (phase === "awaiting_options") {
|
|
44608
|
+
const userAppointments = state.userAppointments || [];
|
|
44609
|
+
const maxAppointments = state.maxAppointmentsPerUser || 3;
|
|
44610
|
+
const appointmentCount = userAppointments.length;
|
|
44611
|
+
const canBook = appointmentCount < maxAppointments;
|
|
44612
|
+
const hasAppointments = appointmentCount > 0;
|
|
44613
|
+
const displayError = state.errorMessage || selectionError;
|
|
44614
|
+
// If confirming cancellation, show confirmation dialog
|
|
44615
|
+
if (selectedId) {
|
|
44616
|
+
const appointmentToCancel = userAppointments.find(appt => appt.id === selectedId);
|
|
44617
|
+
if (!appointmentToCancel) {
|
|
44618
|
+
setSelectedId(null); // Reset if appointment not found
|
|
44619
|
+
}
|
|
44620
|
+
else {
|
|
44621
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Confirm Cancellation"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "Are you sure you want to cancel this appointment?" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-item", style: { marginBottom: '16px' }, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-subject", children: appointmentToCancel.subject }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-time", children: appointmentToCancel.displayTime })] }) }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-button-group", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
|
|
44622
|
+
setIsSubmitting(true);
|
|
44623
|
+
onComplete?.(action.toolCallId, {
|
|
44624
|
+
...action.state,
|
|
44625
|
+
selectedOption: "cancel",
|
|
44626
|
+
selectedAppointmentId: selectedId,
|
|
44627
|
+
});
|
|
44628
|
+
}, disabled: isSubmitting, children: isSubmitting ? 'Cancelling...' : 'Confirm Cancellation' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
|
|
44629
|
+
setSelectedId(null);
|
|
44630
|
+
setSelectionError(null);
|
|
44631
|
+
}, disabled: isSubmitting, children: "Go Back" })] })] })] }));
|
|
44632
|
+
}
|
|
44633
|
+
}
|
|
44634
|
+
// Normal view with inline cancel buttons
|
|
44635
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Manage Your Appointments"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["You have ", appointmentCount, " active appointment", appointmentCount !== 1 ? 's' : '', canBook && ` (${maxAppointments - appointmentCount} slot${maxAppointments - appointmentCount !== 1 ? 's' : ''} remaining)`] }), hasAppointments && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-list", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-label", children: "Your Upcoming Appointments" }), userAppointments.map((appt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-item", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-subject", children: appt.subject }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-time", children: appt.displayTime })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
|
|
44636
|
+
setSelectedId(appt.id);
|
|
44637
|
+
setSelectionError(null);
|
|
44638
|
+
}, children: "Cancel" })] }, appt.id)))] })), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), canBook && (jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
|
|
44639
|
+
setIsSubmitting(true);
|
|
44640
|
+
onComplete?.(action.toolCallId, {
|
|
44641
|
+
...action.state,
|
|
44642
|
+
selectedOption: "book",
|
|
44643
|
+
});
|
|
44644
|
+
}, disabled: isSubmitting, children: isSubmitting ? 'Loading...' : 'Book New Appointment' })), !canBook && !hasAppointments && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No appointments found." }))] })] }));
|
|
44645
|
+
}
|
|
44646
|
+
// Phase 4: Appointment Selection (Booking)
|
|
44647
|
+
if (phase === "awaiting_booking") {
|
|
44648
|
+
const displayError = state.errorMessage || selectionError;
|
|
44649
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Select Appointment Time"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
|
|
44650
|
+
setSelectedDate(date);
|
|
44651
|
+
setSelectedSlot(null);
|
|
44652
|
+
}, children: formatDate(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleAppointmentConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
|
|
44653
|
+
}
|
|
44654
|
+
// Fallback
|
|
44655
|
+
return null;
|
|
44656
|
+
}
|
|
44657
|
+
|
|
44658
|
+
function truncate(text, maxLength) {
|
|
44659
|
+
if (text.length <= maxLength)
|
|
44660
|
+
return text;
|
|
44661
|
+
return text.slice(0, maxLength).trim() + '...';
|
|
44662
|
+
}
|
|
44663
|
+
function ExternalLinkIcon() {
|
|
44664
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
44665
|
+
}
|
|
44666
|
+
function SingleLinkPreview({ link, onLinkClick, accentColor }) {
|
|
44667
|
+
const domain = (() => {
|
|
44668
|
+
if (!link.url)
|
|
44669
|
+
return '';
|
|
44670
|
+
try {
|
|
44671
|
+
return new URL(link.url).hostname.replace('www.', '');
|
|
44672
|
+
}
|
|
44673
|
+
catch {
|
|
44674
|
+
return link.url;
|
|
44675
|
+
}
|
|
44676
|
+
})();
|
|
44677
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
44678
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-card ai-chat-link-preview", onClick: onLinkClick, style: style, role: "link", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onLinkClick(), children: [link.image && (jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__image", children: jsxRuntimeExports.jsx("img", { src: link.image, alt: link.title, onError: (e) => {
|
|
44679
|
+
e.currentTarget.parentElement.style.display = 'none';
|
|
44680
|
+
} }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__site", children: [link.favicon && (jsxRuntimeExports.jsx("img", { src: link.favicon, alt: "", className: "ai-chat-link-preview__favicon", onError: (e) => {
|
|
44681
|
+
e.currentTarget.style.display = 'none';
|
|
44682
|
+
} })), jsxRuntimeExports.jsx("span", { className: "ai-chat-link-preview__domain", children: link.siteName || domain })] }), jsxRuntimeExports.jsx("h4", { className: "ai-chat-link-preview__title", children: link.title }), link.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__description", children: truncate(link.description, 120) }))] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntimeExports.jsx(ExternalLinkIcon, {}) })] }));
|
|
44683
|
+
}
|
|
44684
|
+
function LinkPreviewCard({ action, onComplete, accentColor }) {
|
|
44685
|
+
const rawState = action.state;
|
|
44686
|
+
const hasCompletedRef = reactExports.useRef(false);
|
|
44687
|
+
// Provide safe defaults if state is missing
|
|
44688
|
+
const state = {
|
|
44689
|
+
links: rawState?.links || [],
|
|
44690
|
+
context: rawState?.context,
|
|
44691
|
+
status: rawState?.status || 'displaying',
|
|
44692
|
+
error: rawState?.error,
|
|
44693
|
+
};
|
|
44694
|
+
const isError = state.status === 'error';
|
|
44695
|
+
// Auto-complete on mount so AI can continue generating text response
|
|
44696
|
+
reactExports.useEffect(() => {
|
|
44697
|
+
if (!action.done && !hasCompletedRef.current && onComplete && state.links.length > 0) {
|
|
44698
|
+
hasCompletedRef.current = true;
|
|
44699
|
+
// Signal completion immediately - the card is displayed, AI can continue
|
|
44700
|
+
onComplete(action.toolCallId, { ...state, status: 'displaying' });
|
|
44701
|
+
}
|
|
44702
|
+
}, [action.done, action.toolCallId, onComplete, state]);
|
|
44703
|
+
const handleLinkClick = (url) => {
|
|
44704
|
+
if (url) {
|
|
44705
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
44706
|
+
}
|
|
44707
|
+
onComplete?.(action.toolCallId, { ...state, status: 'clicked' });
|
|
44708
|
+
};
|
|
44709
|
+
if (isError) {
|
|
44710
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-card ai-chat-link-preview ai-chat-link-preview--error", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__error-text", children: state.error || 'Failed to load preview' }) }) }));
|
|
44197
44711
|
}
|
|
44198
|
-
|
|
44199
|
-
|
|
44200
|
-
|
|
44201
|
-
|
|
44202
|
-
|
|
44712
|
+
if (state.links.length === 0) {
|
|
44713
|
+
return null;
|
|
44714
|
+
}
|
|
44715
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview-container", children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__context", style: { marginBottom: '8px', fontSize: '0.9em', color: 'var(--ai-chat-fg-muted)' }, children: state.context })), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview-grid", style: {
|
|
44716
|
+
display: 'grid',
|
|
44717
|
+
gridTemplateColumns: state.links.length === 1 ? '1fr' : state.links.length === 2 ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',
|
|
44718
|
+
gap: '12px',
|
|
44719
|
+
}, children: state.links.map((link, index) => (jsxRuntimeExports.jsx(SingleLinkPreview, { link: link, onLinkClick: () => handleLinkClick(link.url), accentColor: accentColor }, index))) })] }));
|
|
44720
|
+
}
|
|
44721
|
+
|
|
44722
|
+
function PlayIcon() {
|
|
44723
|
+
return (jsxRuntimeExports.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", children: jsxRuntimeExports.jsx("path", { d: "M8 5v14l11-7z" }) }));
|
|
44724
|
+
}
|
|
44725
|
+
function getProviderLabel(provider) {
|
|
44726
|
+
switch (provider) {
|
|
44727
|
+
case 'youtube':
|
|
44728
|
+
return 'YouTube';
|
|
44729
|
+
case 'vimeo':
|
|
44730
|
+
return 'Vimeo';
|
|
44731
|
+
case 'loom':
|
|
44732
|
+
return 'Loom';
|
|
44733
|
+
case 'direct':
|
|
44734
|
+
return 'Video';
|
|
44735
|
+
default:
|
|
44736
|
+
return 'Video';
|
|
44737
|
+
}
|
|
44738
|
+
}
|
|
44739
|
+
function VideoPlayerCard({ action, onComplete, accentColor }) {
|
|
44740
|
+
const rawState = action.state;
|
|
44741
|
+
const hasCompletedRef = reactExports.useRef(false);
|
|
44742
|
+
const [isPlaying, setIsPlaying] = reactExports.useState(false);
|
|
44743
|
+
// Provide safe defaults if state is missing
|
|
44744
|
+
const state = {
|
|
44745
|
+
url: rawState?.url || '',
|
|
44746
|
+
title: rawState?.title,
|
|
44747
|
+
context: rawState?.context,
|
|
44748
|
+
provider: rawState?.provider || 'direct',
|
|
44749
|
+
embedUrl: rawState?.embedUrl || '',
|
|
44750
|
+
thumbnailUrl: rawState?.thumbnailUrl,
|
|
44751
|
+
videoId: rawState?.videoId,
|
|
44752
|
+
status: rawState?.status || 'displaying',
|
|
44753
|
+
error: rawState?.error,
|
|
44754
|
+
};
|
|
44755
|
+
const isError = state.status === 'error';
|
|
44756
|
+
// Auto-complete on mount so AI can continue generating text response
|
|
44757
|
+
reactExports.useEffect(() => {
|
|
44758
|
+
if (!action.done && !hasCompletedRef.current && onComplete && state.embedUrl) {
|
|
44759
|
+
hasCompletedRef.current = true;
|
|
44760
|
+
onComplete(action.toolCallId, { ...state, status: 'displaying' });
|
|
44761
|
+
}
|
|
44762
|
+
}, [action.done, action.toolCallId, onComplete, state]);
|
|
44763
|
+
const handlePlay = () => {
|
|
44764
|
+
setIsPlaying(true);
|
|
44765
|
+
onComplete?.(action.toolCallId, { ...state, status: 'played' });
|
|
44766
|
+
};
|
|
44767
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
44768
|
+
// Build embed URL with autoplay when playing
|
|
44769
|
+
const getEmbedSrc = () => {
|
|
44770
|
+
if (!isPlaying)
|
|
44771
|
+
return '';
|
|
44772
|
+
let src = state.embedUrl;
|
|
44773
|
+
const separator = src.includes('?') ? '&' : '?';
|
|
44774
|
+
switch (state.provider) {
|
|
44775
|
+
case 'youtube':
|
|
44776
|
+
return `${src}${separator}autoplay=1&rel=0`;
|
|
44777
|
+
case 'vimeo':
|
|
44778
|
+
return `${src}${separator}autoplay=1`;
|
|
44779
|
+
case 'loom':
|
|
44780
|
+
return `${src}${separator}autoplay=1`;
|
|
44781
|
+
default:
|
|
44782
|
+
return src;
|
|
44783
|
+
}
|
|
44784
|
+
};
|
|
44785
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-card ai-chat-video-player", style: style, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__container", children: isError ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__error", children: jsxRuntimeExports.jsx("span", { children: state.error || 'Could not load video' }) })) : !isPlaying && state.thumbnailUrl ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player__thumbnail", onClick: handlePlay, children: [jsxRuntimeExports.jsx("img", { src: state.thumbnailUrl, alt: state.title || 'Video thumbnail' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntimeExports.jsx(PlayIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : !isPlaying ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player__placeholder", onClick: handlePlay, children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntimeExports.jsx(PlayIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-video-player__click-text", children: "Click to play" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : state.provider === 'direct' ? (jsxRuntimeExports.jsx("video", { src: state.embedUrl, controls: true, autoPlay: true, className: "ai-chat-video-player__video" })) : (jsxRuntimeExports.jsx("iframe", { src: getEmbedSrc(), className: "ai-chat-video-player__iframe", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true, title: state.title || 'Video player' })) }), state.context && (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__context", children: state.context }))] }));
|
|
44786
|
+
}
|
|
44787
|
+
|
|
44788
|
+
function MapPinIcon() {
|
|
44789
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }), jsxRuntimeExports.jsx("circle", { cx: "12", cy: "10", r: "3" })] }));
|
|
44790
|
+
}
|
|
44791
|
+
function PhoneIcon() {
|
|
44792
|
+
return (jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }));
|
|
44793
|
+
}
|
|
44794
|
+
function ClockIcon() {
|
|
44795
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }), jsxRuntimeExports.jsx("polyline", { points: "12 6 12 12 16 14" })] }));
|
|
44796
|
+
}
|
|
44797
|
+
function NavigationIcon() {
|
|
44798
|
+
return (jsxRuntimeExports.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polygon", { points: "3 11 22 2 13 21 11 13 3 11" }) }));
|
|
44799
|
+
}
|
|
44800
|
+
function GlobeIcon() {
|
|
44801
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }), jsxRuntimeExports.jsx("line", { x1: "2", y1: "12", x2: "22", y2: "12" }), jsxRuntimeExports.jsx("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })] }));
|
|
44802
|
+
}
|
|
44803
|
+
function ChevronIcon({ direction }) {
|
|
44804
|
+
return (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { transform: direction === 'up' ? 'rotate(180deg)' : 'none' }, children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) }));
|
|
44805
|
+
}
|
|
44806
|
+
function getOpenStatus(hours) {
|
|
44807
|
+
if (!hours || hours.length === 0)
|
|
44808
|
+
return null;
|
|
44809
|
+
const now = new Date();
|
|
44810
|
+
const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
44811
|
+
const today = dayNames[now.getDay()];
|
|
44812
|
+
const todayHours = hours.find(h => h.day === today);
|
|
44813
|
+
if (!todayHours || todayHours.closed)
|
|
44814
|
+
return false;
|
|
44815
|
+
const currentTime = now.getHours() * 100 + now.getMinutes();
|
|
44816
|
+
const openTime = parseInt(todayHours.open.replace(':', ''));
|
|
44817
|
+
const closeTime = parseInt(todayHours.close.replace(':', ''));
|
|
44818
|
+
return currentTime >= openTime && currentTime < closeTime;
|
|
44819
|
+
}
|
|
44820
|
+
function HoursDisplay({ hours, compact = false }) {
|
|
44821
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
44822
|
+
const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
44823
|
+
const today = dayNames[new Date().getDay()];
|
|
44824
|
+
const todayHours = hours.find(h => h.day === today);
|
|
44825
|
+
if (compact && !expanded) {
|
|
44826
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__hours", children: [jsxRuntimeExports.jsx(ClockIcon, {}), jsxRuntimeExports.jsx("span", { children: todayHours?.closed ? 'Closed today' : `${todayHours?.open} - ${todayHours?.close}` })] }));
|
|
44827
|
+
}
|
|
44828
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__hours", children: [jsxRuntimeExports.jsx(ClockIcon, {}), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__hours-list", children: [jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setExpanded(!expanded), className: "ai-chat-location-card__hours-toggle", children: ["Today: ", todayHours?.closed ? 'Closed' : `${todayHours?.open} - ${todayHours?.close}`, jsxRuntimeExports.jsx(ChevronIcon, { direction: expanded ? 'up' : 'down' })] }), expanded && (jsxRuntimeExports.jsx("ul", { className: "ai-chat-location-card__hours-full", children: hours.map(h => (jsxRuntimeExports.jsxs("li", { className: h.day === today ? 'ai-chat-location-card__hours-today' : '', children: [jsxRuntimeExports.jsx("span", { children: h.day }), jsxRuntimeExports.jsx("span", { children: h.closed ? 'Closed' : `${h.open} - ${h.close}` })] }, h.day))) }))] })] }));
|
|
44829
|
+
}
|
|
44830
|
+
function LocationItem({ location, settings, accentColor, onDirections, showMap = true, compact = false, }) {
|
|
44831
|
+
const openStatus = getOpenStatus(location.hours);
|
|
44832
|
+
const mapHeight = settings.mapHeight || 180;
|
|
44833
|
+
const mapZoom = settings.mapZoom || 15;
|
|
44834
|
+
const getMapEmbedUrl = () => {
|
|
44835
|
+
const query = location.lat && location.lng
|
|
44836
|
+
? `${location.lat},${location.lng}`
|
|
44837
|
+
: encodeURIComponent(location.address);
|
|
44838
|
+
return `https://www.google.com/maps/embed/v1/place?key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8&q=${query}&zoom=${mapZoom}`;
|
|
44839
|
+
};
|
|
44840
|
+
const handleCall = () => {
|
|
44841
|
+
if (location.phone) {
|
|
44842
|
+
window.location.href = `tel:${location.phone}`;
|
|
44843
|
+
}
|
|
44844
|
+
};
|
|
44845
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
44846
|
+
// Use smaller map height in compact mode
|
|
44847
|
+
const effectiveMapHeight = compact ? Math.min(mapHeight, 140) : mapHeight;
|
|
44848
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-location-card ${compact ? 'ai-chat-location-card--compact' : ''}`, style: style, children: [showMap && settings.showMap !== false && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card__map", style: { height: effectiveMapHeight }, children: jsxRuntimeExports.jsx("iframe", { src: getMapEmbedUrl(), allowFullScreen: true, loading: "lazy", referrerPolicy: "no-referrer-when-downgrade", title: `Map of ${location.name}` }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__header", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-location-card__name", children: location.name }), location.type && (jsxRuntimeExports.jsx("span", { className: "ai-chat-location-card__type", children: location.type })), openStatus !== null && (jsxRuntimeExports.jsx("span", { className: `ai-chat-location-card__status ai-chat-location-card__status--${openStatus ? 'open' : 'closed'}`, children: openStatus ? 'Open' : 'Closed' }))] }), jsxRuntimeExports.jsxs("p", { className: "ai-chat-location-card__address", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), location.address] }), location.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-location-card__description", children: location.description })), settings.showHours !== false && location.hours && location.hours.length > 0 && (jsxRuntimeExports.jsx(HoursDisplay, { hours: location.hours, compact: compact })), settings.showPhone !== false && location.phone && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__phone", onClick: handleCall, children: [jsxRuntimeExports.jsx(PhoneIcon, {}), location.phone] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__actions", children: [settings.showDirectionsButton !== false && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__button", style: accentColor ? { backgroundColor: accentColor } : undefined, onClick: onDirections, children: [jsxRuntimeExports.jsx(NavigationIcon, {}), compact ? 'Directions' : 'Get Directions'] })), !compact && location.website && (jsxRuntimeExports.jsxs("a", { href: location.website, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-location-card__link", children: [jsxRuntimeExports.jsx(GlobeIcon, {}), "Website"] }))] })] })] }));
|
|
44849
|
+
}
|
|
44850
|
+
function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
|
|
44851
|
+
const rawState = action.state;
|
|
44852
|
+
const hasCompletedRef = reactExports.useRef(false);
|
|
44853
|
+
const state = {
|
|
44854
|
+
locations: rawState?.locations || [],
|
|
44855
|
+
settings: rawState?.settings || {},
|
|
44856
|
+
matchInfo: rawState?.matchInfo,
|
|
44857
|
+
status: rawState?.status || 'displaying',
|
|
44858
|
+
};
|
|
44859
|
+
const { locations, settings } = state;
|
|
44860
|
+
const layout = settings.multiLocationLayout || 'stack';
|
|
44861
|
+
const isSingleLocation = locations.length === 1;
|
|
44862
|
+
const stackColumns = Math.min(Math.max(locations.length, 1), maxColumns);
|
|
44863
|
+
reactExports.useEffect(() => {
|
|
44864
|
+
if (!action.done && !hasCompletedRef.current && onComplete && locations.length > 0) {
|
|
44865
|
+
hasCompletedRef.current = true;
|
|
44866
|
+
onComplete(action.toolCallId, { ...state, status: 'displaying' });
|
|
44867
|
+
}
|
|
44868
|
+
}, [action.done, action.toolCallId, onComplete, state, locations.length]);
|
|
44869
|
+
const handleDirections = (location) => {
|
|
44870
|
+
const url = location.lat && location.lng
|
|
44871
|
+
? `https://www.google.com/maps/dir/?api=1&destination=${location.lat},${location.lng}`
|
|
44872
|
+
: `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(location.address)}`;
|
|
44873
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
44874
|
+
onComplete?.(action.toolCallId, { ...state, status: 'directions_opened' });
|
|
44875
|
+
};
|
|
44876
|
+
if (locations.length === 0) {
|
|
44877
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card ai-chat-location-card--error", children: jsxRuntimeExports.jsx("p", { children: "No locations to display" }) }));
|
|
44878
|
+
}
|
|
44879
|
+
if (isSingleLocation) {
|
|
44880
|
+
return (jsxRuntimeExports.jsx(LocationItem, { location: locations[0], settings: settings, accentColor: accentColor, onDirections: () => handleDirections(locations[0]), showMap: true }));
|
|
44881
|
+
}
|
|
44882
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-location-card-list ai-chat-location-card-list--${layout}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card-list__header", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), jsxRuntimeExports.jsxs("span", { children: [locations.length, " Locations"] })] }), layout === 'stack' && (jsxRuntimeExports.jsx("div", { className: `ai-chat-location-card-list__stack ai-chat-location-card-list__stack--cols-${stackColumns}`, children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: settings.showMap !== false, compact: locations.length > 2 }, location.id))) })), layout === 'grid' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__grid", children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: false, compact: true }, location.id))) })), layout === 'carousel' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__carousel", children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: true, compact: false }, location.id))) }))] }));
|
|
44883
|
+
}
|
|
44884
|
+
|
|
44885
|
+
function UsersIcon() {
|
|
44886
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }), jsxRuntimeExports.jsx("circle", { cx: "9", cy: "7", r: "4" }), jsxRuntimeExports.jsx("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87" }), jsxRuntimeExports.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })] }));
|
|
44887
|
+
}
|
|
44888
|
+
const AVATAR_COLORS = [
|
|
44889
|
+
{ bg: '#E8F5E9', text: '#2E7D32' }, // Green
|
|
44890
|
+
{ bg: '#E3F2FD', text: '#1565C0' }, // Blue
|
|
44891
|
+
{ bg: '#FFF3E0', text: '#E65100' }, // Orange
|
|
44892
|
+
{ bg: '#F3E5F5', text: '#7B1FA2' }, // Purple
|
|
44893
|
+
{ bg: '#FFEBEE', text: '#C62828' }, // Red
|
|
44894
|
+
{ bg: '#E0F7FA', text: '#00838F' }, // Cyan
|
|
44895
|
+
{ bg: '#FFF8E1', text: '#F9A825' }, // Amber
|
|
44896
|
+
{ bg: '#FCE4EC', text: '#AD1457' }, // Pink
|
|
44897
|
+
];
|
|
44898
|
+
function getInitials(name) {
|
|
44899
|
+
const parts = name.trim().split(/\s+/);
|
|
44900
|
+
if (parts.length === 1) {
|
|
44901
|
+
return parts[0].substring(0, 2).toUpperCase();
|
|
44902
|
+
}
|
|
44903
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
44904
|
+
}
|
|
44905
|
+
function getColorFromName(name) {
|
|
44906
|
+
let hash = 0;
|
|
44907
|
+
for (let i = 0; i < name.length; i++) {
|
|
44908
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
44909
|
+
}
|
|
44910
|
+
return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
|
|
44911
|
+
}
|
|
44912
|
+
function ContactItem({ contact, settings, accentColor, onEmail, onPhone, compact = false, layout = 'vertical', }) {
|
|
44913
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
44914
|
+
const layoutClass = layout === 'horizontal'
|
|
44915
|
+
? 'ai-chat-contact-card--horizontal'
|
|
44916
|
+
: 'ai-chat-contact-card--vertical';
|
|
44917
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-contact-card ${layoutClass} ${compact ? 'ai-chat-contact-card--compact' : ''}`, style: style, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__image-section", children: [contact.profilePictureUrl ? (jsxRuntimeExports.jsx("img", { src: contact.profilePictureUrl, alt: contact.name, className: "ai-chat-contact-card__image", onError: (e) => {
|
|
44918
|
+
e.currentTarget.style.display = 'none';
|
|
44919
|
+
const placeholder = e.currentTarget.parentElement?.querySelector('.ai-chat-contact-card__initials');
|
|
44920
|
+
if (placeholder) {
|
|
44921
|
+
placeholder.style.display = 'flex';
|
|
44922
|
+
}
|
|
44923
|
+
} })) : null, (() => {
|
|
44924
|
+
const colors = getColorFromName(contact.name);
|
|
44925
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-contact-card__initials", style: {
|
|
44926
|
+
display: contact.profilePictureUrl ? 'none' : 'flex',
|
|
44927
|
+
backgroundColor: colors.bg,
|
|
44928
|
+
color: colors.text,
|
|
44929
|
+
}, children: getInitials(contact.name) }));
|
|
44930
|
+
})()] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__info", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-contact-card__name", children: contact.name }), settings.showRole !== false && contact.role && (jsxRuntimeExports.jsx("p", { className: "ai-chat-contact-card__role", children: contact.role })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__details", children: [settings.showEmail !== false && contact.email && (jsxRuntimeExports.jsx("a", { href: `mailto:${contact.email}`, className: "ai-chat-contact-card__detail", onClick: onEmail, children: contact.email })), settings.showPhone !== false && contact.phone && (jsxRuntimeExports.jsx("a", { href: `tel:${contact.phone}`, className: "ai-chat-contact-card__detail", onClick: onPhone, children: contact.phone }))] }), settings.showResponsibilities !== false && contact.responsibilities && contact.responsibilities.length > 0 && !compact && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__responsibilities", children: [contact.responsibilities.slice(0, 3).map((resp, idx) => (jsxRuntimeExports.jsx("span", { className: "ai-chat-contact-card__responsibility-tag", children: resp }, idx))), contact.responsibilities.length > 3 && (jsxRuntimeExports.jsxs("span", { className: "ai-chat-contact-card__responsibility-more", children: ["+", contact.responsibilities.length - 3, " more"] }))] }))] })] }));
|
|
44931
|
+
}
|
|
44932
|
+
function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
|
|
44933
|
+
const rawState = action.state;
|
|
44934
|
+
const hasCompletedRef = reactExports.useRef(false);
|
|
44935
|
+
const state = {
|
|
44936
|
+
contacts: rawState?.contacts || [],
|
|
44937
|
+
settings: rawState?.settings || {},
|
|
44938
|
+
query: rawState?.query,
|
|
44939
|
+
status: rawState?.status || 'displaying',
|
|
44940
|
+
};
|
|
44941
|
+
const { contacts, settings } = state;
|
|
44942
|
+
const isSingleContact = contacts.length === 1;
|
|
44943
|
+
const stackColumns = Math.min(Math.max(contacts.length, 1), maxColumns);
|
|
44944
|
+
reactExports.useEffect(() => {
|
|
44945
|
+
if (!action.done && !hasCompletedRef.current && onComplete) {
|
|
44946
|
+
hasCompletedRef.current = true;
|
|
44947
|
+
onComplete(action.toolCallId, { ...state, status: 'displaying' });
|
|
44948
|
+
}
|
|
44949
|
+
}, [action.done, action.toolCallId, onComplete, state]);
|
|
44950
|
+
const handleContact = () => {
|
|
44951
|
+
onComplete?.(action.toolCallId, { ...state, status: 'contacted' });
|
|
44952
|
+
};
|
|
44953
|
+
if (contacts.length === 0) {
|
|
44954
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card ai-chat-contact-card--empty", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-contact-card__empty-icon", children: jsxRuntimeExports.jsx(UsersIcon, {}) }), jsxRuntimeExports.jsxs("p", { className: "ai-chat-contact-card__empty-text", children: ["No contacts found", state.query ? ` for "${state.query}"` : ''] })] }));
|
|
44955
|
+
}
|
|
44956
|
+
if (isSingleContact) {
|
|
44957
|
+
return (jsxRuntimeExports.jsx(ContactItem, { contact: contacts[0], settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, layout: settings.layout || 'horizontal' }));
|
|
44958
|
+
}
|
|
44959
|
+
const isWidget = maxColumns === 1;
|
|
44960
|
+
const stackClassName = isWidget
|
|
44961
|
+
? 'ai-chat-contact-card-list__stack ai-chat-contact-card-list__stack--widget'
|
|
44962
|
+
: 'ai-chat-contact-card-list__stack';
|
|
44963
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card-list", style: { containerType: 'inline-size' }, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card-list__header", children: [jsxRuntimeExports.jsx(UsersIcon, {}), jsxRuntimeExports.jsxs("span", { children: [contacts.length, " Contacts"] })] }), jsxRuntimeExports.jsx("div", { className: stackClassName, style: isWidget ? undefined : {
|
|
44964
|
+
gridTemplateColumns: `repeat(${stackColumns}, minmax(0, 1fr))`,
|
|
44965
|
+
}, children: contacts.map((contact) => (jsxRuntimeExports.jsx(ContactItem, { contact: contact, settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, compact: true, layout: settings.layout || 'vertical' }, contact.id))) })] }));
|
|
44966
|
+
}
|
|
44967
|
+
|
|
44968
|
+
function FormCard({ action, onComplete, accentColor }) {
|
|
44969
|
+
const state = action.state;
|
|
44970
|
+
const [currentStep, setCurrentStep] = reactExports.useState(0);
|
|
44971
|
+
const [answers, setAnswers] = reactExports.useState({});
|
|
44972
|
+
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
44973
|
+
const questions = state.questions || [];
|
|
44974
|
+
const currentQuestion = questions[currentStep];
|
|
44975
|
+
const totalQuestions = questions.length;
|
|
44976
|
+
const handleAnswerChange = (questionId, value) => {
|
|
44977
|
+
setAnswers((prev) => ({ ...prev, [questionId]: value }));
|
|
44978
|
+
};
|
|
44979
|
+
const handleNext = () => {
|
|
44980
|
+
if (currentStep < totalQuestions - 1) {
|
|
44981
|
+
setCurrentStep((prev) => prev + 1);
|
|
44982
|
+
}
|
|
44983
|
+
};
|
|
44984
|
+
const handlePrev = () => {
|
|
44985
|
+
if (currentStep > 0) {
|
|
44986
|
+
setCurrentStep((prev) => prev - 1);
|
|
44987
|
+
}
|
|
44988
|
+
};
|
|
44989
|
+
const handleSubmit = () => {
|
|
44990
|
+
if (!onComplete)
|
|
44991
|
+
return;
|
|
44992
|
+
setIsSubmitting(true);
|
|
44993
|
+
const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
|
|
44994
|
+
questionId,
|
|
44995
|
+
value,
|
|
44996
|
+
}));
|
|
44997
|
+
onComplete(action.toolCallId, {
|
|
44998
|
+
...state,
|
|
44999
|
+
status: 'submitted',
|
|
45000
|
+
answers: formattedAnswers,
|
|
45001
|
+
});
|
|
45002
|
+
};
|
|
45003
|
+
const handleSkip = () => {
|
|
45004
|
+
if (!onComplete || !state.settings.allowSkip)
|
|
45005
|
+
return;
|
|
45006
|
+
onComplete(action.toolCallId, {
|
|
45007
|
+
...state,
|
|
45008
|
+
status: 'skipped',
|
|
45009
|
+
});
|
|
45010
|
+
};
|
|
45011
|
+
const isCurrentAnswered = () => {
|
|
45012
|
+
if (!currentQuestion)
|
|
45013
|
+
return false;
|
|
45014
|
+
const answer = answers[currentQuestion.id];
|
|
45015
|
+
if (!answer)
|
|
45016
|
+
return !currentQuestion.required;
|
|
45017
|
+
if (Array.isArray(answer))
|
|
45018
|
+
return answer.length > 0 || !currentQuestion.required;
|
|
45019
|
+
return answer.trim() !== '' || !currentQuestion.required;
|
|
45020
|
+
};
|
|
45021
|
+
const canSubmit = () => {
|
|
45022
|
+
return questions.every((q) => {
|
|
45023
|
+
const answer = answers[q.id];
|
|
45024
|
+
if (!q.required)
|
|
45025
|
+
return true;
|
|
45026
|
+
if (!answer)
|
|
45027
|
+
return false;
|
|
45028
|
+
if (Array.isArray(answer))
|
|
45029
|
+
return answer.length > 0;
|
|
45030
|
+
return answer.trim() !== '';
|
|
45031
|
+
});
|
|
45032
|
+
};
|
|
45033
|
+
// Error state
|
|
45034
|
+
if (state.status === 'error') {
|
|
45035
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: "Form Error" })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__error", children: state.error || 'Could not load form' })] }));
|
|
45036
|
+
}
|
|
45037
|
+
// Submitted state
|
|
45038
|
+
if (state.status === 'submitted' || action.done) {
|
|
45039
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--submitted", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\u2713" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__success", children: state.settings.successMessage || 'Thank you for your response!' })] }));
|
|
45040
|
+
}
|
|
45041
|
+
// Skipped state
|
|
45042
|
+
if (state.status === 'skipped') {
|
|
45043
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--skipped", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\u21B7" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__skipped-text", children: "Form skipped" })] }));
|
|
45044
|
+
}
|
|
45045
|
+
// No questions
|
|
45046
|
+
if (totalQuestions === 0) {
|
|
45047
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--empty", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__empty-text", children: "This form has no questions." })] }));
|
|
45048
|
+
}
|
|
45049
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), state.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__description", children: state.description })), state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__context", children: state.context })), state.settings.showProgress && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__progress", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__progress-bar", style: {
|
|
45050
|
+
width: `${((currentStep + 1) / totalQuestions) * 100}%`,
|
|
45051
|
+
backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
|
|
45052
|
+
} }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-form-card__progress-text", children: [currentStep + 1, " of ", totalQuestions] })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__question", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-form-card__question-text", children: [currentQuestion.text, currentQuestion.required && jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__required", children: "*" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__answer", children: [currentQuestion.type === 'text' && (jsxRuntimeExports.jsx("textarea", { className: "ai-chat-form-card__textarea", placeholder: currentQuestion.placeholder || 'Type your answer...', value: answers[currentQuestion.id] || '', onChange: (e) => handleAnswerChange(currentQuestion.id, e.target.value), rows: 3 })), currentQuestion.type === 'single_choice' && currentQuestion.options && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => (jsxRuntimeExports.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntimeExports.jsx("input", { type: "radio", name: currentQuestion.id, value: option.value, checked: answers[currentQuestion.id] === option.value, onChange: () => handleAnswerChange(currentQuestion.id, option.value) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id))) })), currentQuestion.type === 'multiple_choice' && currentQuestion.options && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => {
|
|
45053
|
+
const currentAnswers = answers[currentQuestion.id] || [];
|
|
45054
|
+
const isChecked = currentAnswers.includes(option.value);
|
|
45055
|
+
return (jsxRuntimeExports.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", value: option.value, checked: isChecked, onChange: () => {
|
|
45056
|
+
const newAnswers = isChecked
|
|
45057
|
+
? currentAnswers.filter((v) => v !== option.value)
|
|
45058
|
+
: [...currentAnswers, option.value];
|
|
45059
|
+
handleAnswerChange(currentQuestion.id, newAnswers);
|
|
45060
|
+
} }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id));
|
|
45061
|
+
}) })), currentQuestion.type === 'rating' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__rating", children: Array.from({ length: (currentQuestion.maxRating || 5) - (currentQuestion.minRating || 1) + 1 }, (_, i) => (currentQuestion.minRating || 1) + i).map((rating) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-form-card__rating-btn ${answers[currentQuestion.id] === String(rating) ? 'ai-chat-form-card__rating-btn--selected' : ''}`, onClick: () => handleAnswerChange(currentQuestion.id, String(rating)), style: {
|
|
45062
|
+
borderColor: answers[currentQuestion.id] === String(rating)
|
|
45063
|
+
? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
|
|
45064
|
+
: undefined,
|
|
45065
|
+
backgroundColor: answers[currentQuestion.id] === String(rating)
|
|
45066
|
+
? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
|
|
45067
|
+
: undefined,
|
|
45068
|
+
}, children: rating }, rating))) }))] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__actions", children: [currentStep > 0 && (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--secondary", onClick: handlePrev, children: "Back" })), state.settings.allowSkip && currentStep === 0 && (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--ghost", onClick: handleSkip, children: "Skip" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__actions-spacer" }), currentStep < totalQuestions - 1 ? (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--primary", onClick: handleNext, disabled: !isCurrentAnswered(), style: {
|
|
45069
|
+
backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
|
|
45070
|
+
}, children: "Next" })) : (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--primary", onClick: handleSubmit, disabled: !canSubmit() || isSubmitting, style: {
|
|
45071
|
+
backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
|
|
45072
|
+
}, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
|
|
44203
45073
|
}
|
|
44204
45074
|
|
|
44205
45075
|
const pendingResolvers = new Map();
|
|
@@ -44212,12 +45082,6 @@
|
|
|
44212
45082
|
function getActionRenderer(implementation) {
|
|
44213
45083
|
return actionRenderers[implementation];
|
|
44214
45084
|
}
|
|
44215
|
-
function getActionPrompt(implementation) {
|
|
44216
|
-
if (implementation === "google-calendar-appointment") {
|
|
44217
|
-
return "Select a date to continue.";
|
|
44218
|
-
}
|
|
44219
|
-
return "Action input required.";
|
|
44220
|
-
}
|
|
44221
45085
|
function waitForActionState(toolCallId) {
|
|
44222
45086
|
return new Promise((resolve) => {
|
|
44223
45087
|
pendingResolvers.set(toolCallId, resolve);
|
|
@@ -44244,26 +45108,272 @@
|
|
|
44244
45108
|
resumeCallbacks.delete(toolCallId);
|
|
44245
45109
|
}
|
|
44246
45110
|
|
|
44247
|
-
|
|
44248
|
-
|
|
44249
|
-
|
|
45111
|
+
function registerGoogleCalendarHandler() {
|
|
45112
|
+
frontendActionHandlers["google-calendar-appointment"] = async (_input, _state, context) => {
|
|
45113
|
+
return waitForActionState(context.toolCallId);
|
|
45114
|
+
};
|
|
45115
|
+
}
|
|
44250
45116
|
|
|
44251
|
-
|
|
44252
|
-
|
|
44253
|
-
|
|
44254
|
-
|
|
44255
|
-
|
|
44256
|
-
|
|
45117
|
+
/**
|
|
45118
|
+
* Register google-calendar-appointment action handler and renderer.
|
|
45119
|
+
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45120
|
+
*/
|
|
45121
|
+
function registerGoogleCalendarAction() {
|
|
45122
|
+
// Register the handler
|
|
45123
|
+
registerGoogleCalendarHandler();
|
|
45124
|
+
// Register the renderer
|
|
45125
|
+
actionRenderers["google-calendar-appointment"] = (message, accentColor) => {
|
|
45126
|
+
const action = message.action;
|
|
45127
|
+
if (!action)
|
|
45128
|
+
return null;
|
|
45129
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45130
|
+
resolveActionState(toolCallId, newState);
|
|
45131
|
+
};
|
|
45132
|
+
return (jsxRuntimeExports.jsx(GoogleCalendarCard, { action: {
|
|
45133
|
+
implementation: action.implementation,
|
|
45134
|
+
toolCallId: action.toolCallId,
|
|
45135
|
+
actionId: action.actionId,
|
|
45136
|
+
input: action.input,
|
|
45137
|
+
state: action.state,
|
|
45138
|
+
done: action.done ?? false,
|
|
45139
|
+
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
44257
45140
|
};
|
|
44258
|
-
|
|
44259
|
-
|
|
44260
|
-
|
|
44261
|
-
|
|
44262
|
-
|
|
44263
|
-
|
|
44264
|
-
|
|
44265
|
-
|
|
44266
|
-
|
|
45141
|
+
}
|
|
45142
|
+
|
|
45143
|
+
function registerMicrosoftCalendarHandler() {
|
|
45144
|
+
frontendActionHandlers["microsoft-calendar-appointment"] = async (_input, _state, context) => {
|
|
45145
|
+
return waitForActionState(context.toolCallId);
|
|
45146
|
+
};
|
|
45147
|
+
}
|
|
45148
|
+
|
|
45149
|
+
/**
|
|
45150
|
+
* Register microsoft-calendar-appointment action handler and renderer.
|
|
45151
|
+
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45152
|
+
*/
|
|
45153
|
+
function registerMicrosoftCalendarAction() {
|
|
45154
|
+
// Register the handler
|
|
45155
|
+
registerMicrosoftCalendarHandler();
|
|
45156
|
+
// Register the renderer
|
|
45157
|
+
actionRenderers["microsoft-calendar-appointment"] = (message, accentColor) => {
|
|
45158
|
+
const action = message.action;
|
|
45159
|
+
if (!action)
|
|
45160
|
+
return null;
|
|
45161
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45162
|
+
resolveActionState(toolCallId, newState);
|
|
45163
|
+
};
|
|
45164
|
+
return (jsxRuntimeExports.jsx(MicrosoftCalendarCard, { action: {
|
|
45165
|
+
implementation: action.implementation,
|
|
45166
|
+
toolCallId: action.toolCallId,
|
|
45167
|
+
actionId: action.actionId,
|
|
45168
|
+
input: action.input,
|
|
45169
|
+
state: action.state,
|
|
45170
|
+
done: action.done ?? false,
|
|
45171
|
+
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45172
|
+
};
|
|
45173
|
+
}
|
|
45174
|
+
|
|
45175
|
+
/**
|
|
45176
|
+
* Register link-preview action handler and renderer.
|
|
45177
|
+
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45178
|
+
*/
|
|
45179
|
+
function registerLinkPreviewAction() {
|
|
45180
|
+
// Handler - auto-completes immediately since no user input is needed
|
|
45181
|
+
frontendActionHandlers["link-preview"] = async (_input, state, _context) => {
|
|
45182
|
+
return { ...state, status: "displaying" };
|
|
45183
|
+
};
|
|
45184
|
+
// Renderer - displays the link preview card
|
|
45185
|
+
actionRenderers["link-preview"] = (message, accentColor) => {
|
|
45186
|
+
const action = message.action;
|
|
45187
|
+
if (!action)
|
|
45188
|
+
return null;
|
|
45189
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45190
|
+
resolveActionState(toolCallId, newState);
|
|
45191
|
+
};
|
|
45192
|
+
// Check if action state indicates it's already complete (displaying or clicked)
|
|
45193
|
+
const state = action.state;
|
|
45194
|
+
const status = state?.status;
|
|
45195
|
+
const isDone = action.done || status === "displaying" || status === "clicked";
|
|
45196
|
+
return (jsxRuntimeExports.jsx(LinkPreviewCard, { action: {
|
|
45197
|
+
implementation: action.implementation,
|
|
45198
|
+
toolCallId: action.toolCallId,
|
|
45199
|
+
actionId: action.actionId,
|
|
45200
|
+
input: action.input,
|
|
45201
|
+
state: action.state,
|
|
45202
|
+
done: isDone,
|
|
45203
|
+
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45204
|
+
};
|
|
45205
|
+
}
|
|
45206
|
+
|
|
45207
|
+
/**
|
|
45208
|
+
* Register video-player action handler and renderer.
|
|
45209
|
+
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45210
|
+
*/
|
|
45211
|
+
function registerVideoPlayerAction() {
|
|
45212
|
+
// Handler - auto-completes immediately since no user input is needed
|
|
45213
|
+
frontendActionHandlers["video-player"] = async (_input, state, _context) => {
|
|
45214
|
+
return { ...state, status: "displaying" };
|
|
45215
|
+
};
|
|
45216
|
+
// Renderer - displays the embedded video player card
|
|
45217
|
+
actionRenderers["video-player"] = (message, accentColor) => {
|
|
45218
|
+
const action = message.action;
|
|
45219
|
+
if (!action)
|
|
45220
|
+
return null;
|
|
45221
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45222
|
+
resolveActionState(toolCallId, newState);
|
|
45223
|
+
};
|
|
45224
|
+
// Check if action state indicates it's already complete (displaying or played)
|
|
45225
|
+
const state = action.state;
|
|
45226
|
+
const status = state?.status;
|
|
45227
|
+
const isDone = action.done || status === "displaying" || status === "played";
|
|
45228
|
+
return (jsxRuntimeExports.jsx(VideoPlayerCard, { action: {
|
|
45229
|
+
implementation: action.implementation,
|
|
45230
|
+
toolCallId: action.toolCallId,
|
|
45231
|
+
actionId: action.actionId,
|
|
45232
|
+
input: action.input,
|
|
45233
|
+
state: action.state,
|
|
45234
|
+
done: isDone,
|
|
45235
|
+
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45236
|
+
};
|
|
45237
|
+
}
|
|
45238
|
+
|
|
45239
|
+
/**
|
|
45240
|
+
* Register location-card action handler and renderer.
|
|
45241
|
+
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45242
|
+
*/
|
|
45243
|
+
function registerLocationCardAction() {
|
|
45244
|
+
// Handler - auto-completes immediately since no user input is needed
|
|
45245
|
+
frontendActionHandlers["location-card"] = async (_input, state, _context) => {
|
|
45246
|
+
return { ...state, status: "displaying" };
|
|
45247
|
+
};
|
|
45248
|
+
// Renderer - displays the location card
|
|
45249
|
+
actionRenderers["location-card"] = (message, accentColor, variant) => {
|
|
45250
|
+
const action = message.action;
|
|
45251
|
+
if (!action)
|
|
45252
|
+
return null;
|
|
45253
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45254
|
+
resolveActionState(toolCallId, newState);
|
|
45255
|
+
};
|
|
45256
|
+
// Check if action state indicates it's already complete
|
|
45257
|
+
const state = action.state;
|
|
45258
|
+
const status = state?.status;
|
|
45259
|
+
const isDone = action.done || status === "displaying" || status === "directions_opened";
|
|
45260
|
+
return (jsxRuntimeExports.jsx(LocationCard, { action: {
|
|
45261
|
+
implementation: action.implementation,
|
|
45262
|
+
toolCallId: action.toolCallId,
|
|
45263
|
+
actionId: action.actionId,
|
|
45264
|
+
input: action.input,
|
|
45265
|
+
state: action.state,
|
|
45266
|
+
done: isDone,
|
|
45267
|
+
}, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
|
|
45268
|
+
};
|
|
45269
|
+
}
|
|
45270
|
+
|
|
45271
|
+
function registerContactCardAction() {
|
|
45272
|
+
// Handler - auto-completes immediately since no user input is needed
|
|
45273
|
+
frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
|
|
45274
|
+
return { ...state, status: 'displaying' };
|
|
45275
|
+
};
|
|
45276
|
+
// Renderer - displays the contact card
|
|
45277
|
+
actionRenderers['contact-card'] = (message, accentColor, variant) => {
|
|
45278
|
+
const action = message.action;
|
|
45279
|
+
if (!action)
|
|
45280
|
+
return null;
|
|
45281
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45282
|
+
resolveActionState(toolCallId, newState);
|
|
45283
|
+
};
|
|
45284
|
+
// Check if action state indicates it's already complete
|
|
45285
|
+
const state = action.state;
|
|
45286
|
+
const status = state?.status;
|
|
45287
|
+
const isDone = action.done || status === 'displaying' || status === 'contacted';
|
|
45288
|
+
return (jsxRuntimeExports.jsx(ContactCard, { action: {
|
|
45289
|
+
implementation: action.implementation,
|
|
45290
|
+
toolCallId: action.toolCallId,
|
|
45291
|
+
actionId: action.actionId,
|
|
45292
|
+
input: action.input,
|
|
45293
|
+
state: action.state,
|
|
45294
|
+
done: isDone,
|
|
45295
|
+
}, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
|
|
45296
|
+
};
|
|
45297
|
+
}
|
|
45298
|
+
|
|
45299
|
+
function registerQueryContactDirectoryAction() {
|
|
45300
|
+
// Handler - auto-completes immediately since no user input is needed
|
|
45301
|
+
frontendActionHandlers['query-contact-directory'] = async (_input, state, _context) => {
|
|
45302
|
+
return { ...state, status: 'displaying' };
|
|
45303
|
+
};
|
|
45304
|
+
// Renderer - displays the contact card with search results
|
|
45305
|
+
actionRenderers['query-contact-directory'] = (message, accentColor, variant) => {
|
|
45306
|
+
const action = message.action;
|
|
45307
|
+
if (!action)
|
|
45308
|
+
return null;
|
|
45309
|
+
// Handle completion - triggers agent to continue with text response
|
|
45310
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45311
|
+
resolveActionState(toolCallId, newState);
|
|
45312
|
+
};
|
|
45313
|
+
// Check if action state indicates it's already complete
|
|
45314
|
+
const state = action.state;
|
|
45315
|
+
const status = state?.status;
|
|
45316
|
+
const isDone = action.done || status === 'displaying' || status === 'contacted';
|
|
45317
|
+
return (jsxRuntimeExports.jsx(ContactCard, { action: {
|
|
45318
|
+
implementation: action.implementation,
|
|
45319
|
+
toolCallId: action.toolCallId,
|
|
45320
|
+
actionId: action.actionId,
|
|
45321
|
+
input: action.input,
|
|
45322
|
+
state: action.state,
|
|
45323
|
+
done: isDone,
|
|
45324
|
+
}, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
|
|
45325
|
+
};
|
|
45326
|
+
}
|
|
45327
|
+
|
|
45328
|
+
function registerDisplayFormAction() {
|
|
45329
|
+
// Handler - handles form submission and state updates
|
|
45330
|
+
frontendActionHandlers['display-form'] = async (_input, _state, context) => {
|
|
45331
|
+
return waitForActionState(context.toolCallId);
|
|
45332
|
+
};
|
|
45333
|
+
// Renderer - displays the form card
|
|
45334
|
+
actionRenderers['display-form'] = (message, accentColor, variant) => {
|
|
45335
|
+
const action = message.action;
|
|
45336
|
+
if (!action)
|
|
45337
|
+
return null;
|
|
45338
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45339
|
+
resolveActionState(toolCallId, newState);
|
|
45340
|
+
};
|
|
45341
|
+
// Check if action state indicates it's already complete
|
|
45342
|
+
const state = action.state;
|
|
45343
|
+
const status = state?.status;
|
|
45344
|
+
const isDone = action.done || status === 'completed' || status === 'submitted';
|
|
45345
|
+
return (jsxRuntimeExports.jsx(FormCard, { action: {
|
|
45346
|
+
implementation: action.implementation,
|
|
45347
|
+
toolCallId: action.toolCallId,
|
|
45348
|
+
actionId: action.actionId,
|
|
45349
|
+
input: action.input,
|
|
45350
|
+
state: action.state,
|
|
45351
|
+
done: isDone,
|
|
45352
|
+
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45353
|
+
};
|
|
45354
|
+
}
|
|
45355
|
+
|
|
45356
|
+
// Track if handlers have been initialized
|
|
45357
|
+
let initialized = false;
|
|
45358
|
+
/**
|
|
45359
|
+
* Initialize all action handlers.
|
|
45360
|
+
* Call this to ensure handlers are registered (prevents tree-shaking in production builds).
|
|
45361
|
+
* Safe to call multiple times - will only register once.
|
|
45362
|
+
*/
|
|
45363
|
+
function initializeActionHandlers() {
|
|
45364
|
+
if (initialized)
|
|
45365
|
+
return;
|
|
45366
|
+
initialized = true;
|
|
45367
|
+
// Explicitly call each registration function to prevent tree-shaking
|
|
45368
|
+
registerGoogleCalendarAction();
|
|
45369
|
+
registerMicrosoftCalendarAction();
|
|
45370
|
+
registerLinkPreviewAction();
|
|
45371
|
+
registerVideoPlayerAction();
|
|
45372
|
+
registerLocationCardAction();
|
|
45373
|
+
registerQueryContactDirectoryAction();
|
|
45374
|
+
registerContactCardAction();
|
|
45375
|
+
registerDisplayFormAction();
|
|
45376
|
+
}
|
|
44267
45377
|
|
|
44268
45378
|
/**
|
|
44269
45379
|
* Local Storage Utilities
|
|
@@ -44482,10 +45592,6 @@
|
|
|
44482
45592
|
}
|
|
44483
45593
|
}
|
|
44484
45594
|
|
|
44485
|
-
/**
|
|
44486
|
-
* useChat Hook
|
|
44487
|
-
* Main state management for chat functionality
|
|
44488
|
-
*/
|
|
44489
45595
|
function hydrateToolNames(messages) {
|
|
44490
45596
|
const toolCallNameById = new Map();
|
|
44491
45597
|
for (const entry of messages) {
|
|
@@ -44529,81 +45635,77 @@
|
|
|
44529
45635
|
};
|
|
44530
45636
|
});
|
|
44531
45637
|
}
|
|
44532
|
-
function hydrateActionContent(messages) {
|
|
44533
|
-
return messages.map((entry) => {
|
|
44534
|
-
if (entry.message.role !== "assistant" || !entry.action) {
|
|
44535
|
-
return entry;
|
|
44536
|
-
}
|
|
44537
|
-
const content = typeof entry.message.content === "string" ? entry.message.content : "";
|
|
44538
|
-
if (content.trim().length > 0) {
|
|
44539
|
-
return entry;
|
|
44540
|
-
}
|
|
44541
|
-
return {
|
|
44542
|
-
...entry,
|
|
44543
|
-
message: { ...entry.message, content: getActionPrompt(entry.action.implementation) },
|
|
44544
|
-
};
|
|
44545
|
-
});
|
|
44546
|
-
}
|
|
44547
45638
|
function hydrateMessages(messages) {
|
|
44548
|
-
return
|
|
45639
|
+
return hydrateToolNames(messages);
|
|
44549
45640
|
}
|
|
44550
|
-
|
|
44551
|
-
|
|
44552
|
-
|
|
44553
|
-
|
|
44554
|
-
|
|
44555
|
-
|
|
44556
|
-
|
|
44557
|
-
|
|
44558
|
-
|
|
44559
|
-
|
|
44560
|
-
|
|
44561
|
-
|
|
44562
|
-
|
|
44563
|
-
|
|
44564
|
-
|
|
44565
|
-
|
|
44566
|
-
}
|
|
44567
|
-
: m),
|
|
44568
|
-
isTyping: true,
|
|
44569
|
-
}));
|
|
44570
|
-
const streamState = createStreamState();
|
|
44571
|
-
// Continue the agent stream with the new state
|
|
44572
|
-
for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
|
|
44573
|
-
if (event.type === "done") {
|
|
44574
|
-
finalizeToolMessage(streamState, setState, toolCallId, toolName);
|
|
44575
|
-
streamState.sources = event.sources;
|
|
44576
|
-
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
44577
|
-
finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
|
|
44578
|
-
continue;
|
|
44579
|
-
}
|
|
44580
|
-
if (event.type === "error") {
|
|
44581
|
-
const errorMessage = {
|
|
44582
|
-
id: generateMessageId(),
|
|
44583
|
-
message: {
|
|
44584
|
-
role: "assistant",
|
|
44585
|
-
content: "Sorry, an error occurred. Please try again later.",
|
|
44586
|
-
},
|
|
44587
|
-
timestamp: new Date().toISOString(),
|
|
44588
|
-
sources: [],
|
|
44589
|
-
isError: true,
|
|
44590
|
-
};
|
|
44591
|
-
upsertMessage(setState, errorMessage, false);
|
|
44592
|
-
setState(prev => ({ ...prev, isTyping: false }));
|
|
44593
|
-
return;
|
|
44594
|
-
}
|
|
44595
|
-
handleStreamEvent(event, streamState, onMessageUpdate, setState);
|
|
44596
|
-
}
|
|
44597
|
-
setState(prev => ({ ...prev, isTyping: false }));
|
|
45641
|
+
|
|
45642
|
+
function deriveErrorInfo(error) {
|
|
45643
|
+
if (error instanceof ApiError) {
|
|
45644
|
+
const retryAfterSeconds = typeof error.retryAfterMs === 'number'
|
|
45645
|
+
? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
|
|
45646
|
+
: undefined;
|
|
45647
|
+
const lowerMessage = (error.message || '').toLowerCase();
|
|
45648
|
+
let message;
|
|
45649
|
+
switch (error.status) {
|
|
45650
|
+
case 429: {
|
|
45651
|
+
const isPerUser = lowerMessage.includes('user');
|
|
45652
|
+
const base = isPerUser
|
|
45653
|
+
? 'You have reached the per-user rate limit.'
|
|
45654
|
+
: 'This widget has received too many requests.';
|
|
45655
|
+
if (retryAfterSeconds) {
|
|
45656
|
+
message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
|
|
44598
45657
|
}
|
|
44599
|
-
|
|
44600
|
-
|
|
44601
|
-
|
|
45658
|
+
else {
|
|
45659
|
+
message = `${base} Please wait a moment and try again.`;
|
|
45660
|
+
}
|
|
45661
|
+
break;
|
|
45662
|
+
}
|
|
45663
|
+
case 401:
|
|
45664
|
+
message = 'Authentication failed. Please refresh the page or verify your API key.';
|
|
45665
|
+
break;
|
|
45666
|
+
case 403:
|
|
45667
|
+
message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
|
|
45668
|
+
break;
|
|
45669
|
+
case 404:
|
|
45670
|
+
if (lowerMessage.includes('not active')) {
|
|
45671
|
+
message = 'This widget is currently inactive. Please contact the site owner.';
|
|
45672
|
+
}
|
|
45673
|
+
else {
|
|
45674
|
+
message = 'We could not find this widget. It may have been removed.';
|
|
45675
|
+
}
|
|
45676
|
+
break;
|
|
45677
|
+
default:
|
|
45678
|
+
if (error.status >= 500) {
|
|
45679
|
+
message = 'The server encountered an error. Please try again shortly.';
|
|
45680
|
+
}
|
|
45681
|
+
else if (error.status > 0) {
|
|
45682
|
+
message = error.message || 'Something went wrong. Please try again.';
|
|
45683
|
+
}
|
|
45684
|
+
else {
|
|
45685
|
+
message = error.message || 'Unable to connect to the server. Please check your internet connection.';
|
|
44602
45686
|
}
|
|
44603
|
-
});
|
|
44604
45687
|
}
|
|
45688
|
+
return { message, retryAfterSeconds, status: error.status };
|
|
44605
45689
|
}
|
|
45690
|
+
if (error instanceof Error) {
|
|
45691
|
+
const lower = error.message.toLowerCase();
|
|
45692
|
+
if (lower.includes('network')) {
|
|
45693
|
+
return { message: 'Unable to connect to the server. Please check your internet connection.' };
|
|
45694
|
+
}
|
|
45695
|
+
if (lower.includes('timeout')) {
|
|
45696
|
+
return { message: 'The request timed out. Please try again.' };
|
|
45697
|
+
}
|
|
45698
|
+
if (lower.includes('unauthorized') || lower.includes('401')) {
|
|
45699
|
+
return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
|
|
45700
|
+
}
|
|
45701
|
+
if (lower.includes('internal server error') || lower.includes('500')) {
|
|
45702
|
+
return { message: 'The server encountered an error. Please try again shortly.' };
|
|
45703
|
+
}
|
|
45704
|
+
return { message: error.message || 'Something went wrong. Please try again.' };
|
|
45705
|
+
}
|
|
45706
|
+
return { message: 'Something went wrong. Please try again.' };
|
|
44606
45707
|
}
|
|
45708
|
+
|
|
44607
45709
|
function createStreamState() {
|
|
44608
45710
|
return {
|
|
44609
45711
|
currentContent: "",
|
|
@@ -44612,6 +45714,7 @@
|
|
|
44612
45714
|
newMessageIds: new Set(),
|
|
44613
45715
|
sources: [],
|
|
44614
45716
|
toolCallToActionId: {},
|
|
45717
|
+
requestId: generateMessageId(),
|
|
44615
45718
|
};
|
|
44616
45719
|
}
|
|
44617
45720
|
function upsertMessage(setState, message, isTyping) {
|
|
@@ -44647,15 +45750,40 @@
|
|
|
44647
45750
|
return msg;
|
|
44648
45751
|
}
|
|
44649
45752
|
// Attach suggestions only to the last assistant message
|
|
44650
|
-
|
|
44651
|
-
|
|
44652
|
-
|
|
44653
|
-
return { ...msg, sources, toolCallToActionId };
|
|
45753
|
+
const withSuggestions = index === lastAssistantIndex && suggestions && suggestions.length > 0
|
|
45754
|
+
? { suggestions }
|
|
45755
|
+
: {};
|
|
45756
|
+
return { ...msg, sources, toolCallToActionId, ...withSuggestions };
|
|
44654
45757
|
}),
|
|
44655
45758
|
isTyping: false,
|
|
44656
45759
|
};
|
|
44657
45760
|
});
|
|
44658
45761
|
}
|
|
45762
|
+
function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
|
|
45763
|
+
setState(prev => {
|
|
45764
|
+
const messages = prev.messages.map((entry) => {
|
|
45765
|
+
const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
|
|
45766
|
+
if (!matchesToolCall) {
|
|
45767
|
+
return entry;
|
|
45768
|
+
}
|
|
45769
|
+
const existingName = entry.message.name || toolName;
|
|
45770
|
+
return {
|
|
45771
|
+
...entry,
|
|
45772
|
+
message: {
|
|
45773
|
+
role: "tool",
|
|
45774
|
+
content: typeof entry.message.content === "string" ? entry.message.content : "",
|
|
45775
|
+
tool_call_id: toolCallId,
|
|
45776
|
+
name: existingName,
|
|
45777
|
+
},
|
|
45778
|
+
isStreaming: false,
|
|
45779
|
+
toolExecuting: existingName,
|
|
45780
|
+
};
|
|
45781
|
+
});
|
|
45782
|
+
return { ...prev, messages, isTyping: false, isLoading: false };
|
|
45783
|
+
});
|
|
45784
|
+
streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
|
|
45785
|
+
}
|
|
45786
|
+
|
|
44659
45787
|
function handleContentEvent(event, streamState, onMessageUpdate, setState) {
|
|
44660
45788
|
streamState.currentContent += event.content;
|
|
44661
45789
|
const assistantMessage = {
|
|
@@ -44702,8 +45830,6 @@
|
|
|
44702
45830
|
}
|
|
44703
45831
|
function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
|
|
44704
45832
|
streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
|
|
44705
|
-
// Update state and mark action as done in a single setState call
|
|
44706
|
-
// Keep isTyping: true because the agent may continue generating content after tool completion
|
|
44707
45833
|
setState(prev => {
|
|
44708
45834
|
const messages = prev.messages.map((msg) => {
|
|
44709
45835
|
const matchesToolCall = msg.message.role === "tool" && msg.message.tool_call_id === event.tool_call_id;
|
|
@@ -44711,7 +45837,26 @@
|
|
|
44711
45837
|
return msg;
|
|
44712
45838
|
}
|
|
44713
45839
|
const existingName = msg.message.name || event.tool_name;
|
|
44714
|
-
|
|
45840
|
+
let action = msg.action;
|
|
45841
|
+
if (event.action_id && event.implementation) {
|
|
45842
|
+
action = {
|
|
45843
|
+
implementation: event.implementation,
|
|
45844
|
+
toolCallId: event.tool_call_id,
|
|
45845
|
+
actionId: event.action_id,
|
|
45846
|
+
input: (event.input || {}),
|
|
45847
|
+
state: (event.state || {}),
|
|
45848
|
+
done: event.done,
|
|
45849
|
+
};
|
|
45850
|
+
}
|
|
45851
|
+
else if (action) {
|
|
45852
|
+
action = {
|
|
45853
|
+
...action,
|
|
45854
|
+
input: event.input ? event.input : action.input,
|
|
45855
|
+
state: event.state ? event.state : action.state,
|
|
45856
|
+
done: event.done,
|
|
45857
|
+
};
|
|
45858
|
+
}
|
|
45859
|
+
const updatedMsg = {
|
|
44715
45860
|
...msg,
|
|
44716
45861
|
message: {
|
|
44717
45862
|
role: "tool",
|
|
@@ -44721,14 +45866,10 @@
|
|
|
44721
45866
|
},
|
|
44722
45867
|
isStreaming: false,
|
|
44723
45868
|
toolExecuting: existingName,
|
|
44724
|
-
action
|
|
44725
|
-
...msg.action,
|
|
44726
|
-
state: event.state || msg.action.state,
|
|
44727
|
-
done: true, // Mark action as completed
|
|
44728
|
-
} : undefined,
|
|
45869
|
+
action,
|
|
44729
45870
|
};
|
|
45871
|
+
return updatedMsg;
|
|
44730
45872
|
});
|
|
44731
|
-
// Keep typing indicator visible - it will be hidden by done/finalizeStreamMessages
|
|
44732
45873
|
return { ...prev, messages, isTyping: true, isLoading: false };
|
|
44733
45874
|
});
|
|
44734
45875
|
}
|
|
@@ -44760,34 +45901,6 @@
|
|
|
44760
45901
|
return { ...prev, messages, isTyping: true, isLoading: false };
|
|
44761
45902
|
});
|
|
44762
45903
|
}
|
|
44763
|
-
function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
|
|
44764
|
-
setState(prev => {
|
|
44765
|
-
const messages = prev.messages.map((entry) => {
|
|
44766
|
-
const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
|
|
44767
|
-
if (!matchesToolCall) {
|
|
44768
|
-
return entry;
|
|
44769
|
-
}
|
|
44770
|
-
const existingName = entry.message.name || toolName;
|
|
44771
|
-
return {
|
|
44772
|
-
...entry,
|
|
44773
|
-
message: {
|
|
44774
|
-
role: "tool",
|
|
44775
|
-
content: typeof entry.message.content === "string" ? entry.message.content : "",
|
|
44776
|
-
tool_call_id: toolCallId,
|
|
44777
|
-
name: existingName,
|
|
44778
|
-
},
|
|
44779
|
-
isStreaming: false,
|
|
44780
|
-
toolExecuting: existingName,
|
|
44781
|
-
action: entry.action ? {
|
|
44782
|
-
...entry.action,
|
|
44783
|
-
done: true, // Mark action as completed
|
|
44784
|
-
} : undefined,
|
|
44785
|
-
};
|
|
44786
|
-
});
|
|
44787
|
-
return { ...prev, messages, isTyping: false, isLoading: false };
|
|
44788
|
-
});
|
|
44789
|
-
streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
|
|
44790
|
-
}
|
|
44791
45904
|
function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
|
|
44792
45905
|
streamState.sources = event.sources;
|
|
44793
45906
|
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
@@ -44846,6 +45959,7 @@
|
|
|
44846
45959
|
console.warn('[Chat] Unknown event type:', event.type);
|
|
44847
45960
|
}
|
|
44848
45961
|
}
|
|
45962
|
+
|
|
44849
45963
|
async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
|
|
44850
45964
|
let pendingEvent = initialEvent;
|
|
44851
45965
|
while (pendingEvent) {
|
|
@@ -44872,7 +45986,7 @@
|
|
|
44872
45986
|
actionId: pendingEvent.action_id,
|
|
44873
45987
|
input: pendingEvent.input,
|
|
44874
45988
|
state: pendingEvent.state,
|
|
44875
|
-
done: false,
|
|
45989
|
+
done: pendingEvent.done ?? false,
|
|
44876
45990
|
},
|
|
44877
45991
|
};
|
|
44878
45992
|
if (streamState.activeToolCallCount === 0) {
|
|
@@ -44886,7 +46000,7 @@
|
|
|
44886
46000
|
id: generateMessageId(),
|
|
44887
46001
|
message: {
|
|
44888
46002
|
role: "assistant",
|
|
44889
|
-
content: "Sorry, an error occurred.
|
|
46003
|
+
content: "Sorry, an error occurred.",
|
|
44890
46004
|
},
|
|
44891
46005
|
timestamp: new Date().toISOString(),
|
|
44892
46006
|
sources: [],
|
|
@@ -44910,7 +46024,7 @@
|
|
|
44910
46024
|
console.error("[Widget] Frontend action failed:", error);
|
|
44911
46025
|
const errorMessageEntry = {
|
|
44912
46026
|
id: generateMessageId(),
|
|
44913
|
-
message: { role: "assistant", content: "Sorry, an error occurred.
|
|
46027
|
+
message: { role: "assistant", content: "Sorry, an error occurred." },
|
|
44914
46028
|
timestamp: new Date().toISOString(),
|
|
44915
46029
|
sources: [],
|
|
44916
46030
|
isError: true,
|
|
@@ -44922,12 +46036,7 @@
|
|
|
44922
46036
|
pendingEvent = null;
|
|
44923
46037
|
const updatedToolMessage = {
|
|
44924
46038
|
...toolMessage,
|
|
44925
|
-
action: toolMessage.action
|
|
44926
|
-
? {
|
|
44927
|
-
...toolMessage.action,
|
|
44928
|
-
state: nextState,
|
|
44929
|
-
}
|
|
44930
|
-
: undefined,
|
|
46039
|
+
action: toolMessage.action ? { ...toolMessage.action, state: nextState } : toolMessage.action,
|
|
44931
46040
|
};
|
|
44932
46041
|
upsertMessage(setState, updatedToolMessage, true);
|
|
44933
46042
|
let streamEnded = false;
|
|
@@ -44937,22 +46046,20 @@
|
|
|
44937
46046
|
break;
|
|
44938
46047
|
}
|
|
44939
46048
|
if (event.type === "done") {
|
|
44940
|
-
//
|
|
44941
|
-
// updated by tool_end event or by the user's frontend action.
|
|
46049
|
+
// Finalize tool message and stream messages
|
|
44942
46050
|
finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
|
|
44943
|
-
// Handle the done event but skip the tool finalization part since we already did it
|
|
44944
46051
|
streamState.sources = event.sources;
|
|
44945
46052
|
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
44946
46053
|
finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
|
|
44947
46054
|
streamEnded = true;
|
|
44948
|
-
continue;
|
|
46055
|
+
continue;
|
|
44949
46056
|
}
|
|
44950
46057
|
if (event.type === "error") {
|
|
44951
46058
|
const errorMessage = {
|
|
44952
46059
|
id: generateMessageId(),
|
|
44953
46060
|
message: {
|
|
44954
46061
|
role: "assistant",
|
|
44955
|
-
content: "Sorry, an error occurred.
|
|
46062
|
+
content: "Sorry, an error occurred.",
|
|
44956
46063
|
},
|
|
44957
46064
|
timestamp: new Date().toISOString(),
|
|
44958
46065
|
sources: [],
|
|
@@ -44963,73 +46070,79 @@
|
|
|
44963
46070
|
}
|
|
44964
46071
|
handleStreamEvent(event, streamState, onMessageUpdate, setState);
|
|
44965
46072
|
}
|
|
44966
|
-
// If stream ended without a done event
|
|
46073
|
+
// If stream ended without a done event, finalize the tool message
|
|
44967
46074
|
if (!streamEnded && !pendingEvent) {
|
|
44968
46075
|
finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
|
|
44969
46076
|
}
|
|
44970
46077
|
}
|
|
44971
46078
|
}
|
|
44972
|
-
function
|
|
44973
|
-
|
|
44974
|
-
|
|
44975
|
-
|
|
44976
|
-
|
|
44977
|
-
|
|
44978
|
-
|
|
44979
|
-
|
|
44980
|
-
|
|
44981
|
-
|
|
44982
|
-
|
|
44983
|
-
|
|
44984
|
-
|
|
44985
|
-
|
|
44986
|
-
|
|
44987
|
-
|
|
44988
|
-
|
|
44989
|
-
|
|
44990
|
-
|
|
44991
|
-
|
|
44992
|
-
|
|
44993
|
-
|
|
44994
|
-
|
|
44995
|
-
|
|
44996
|
-
|
|
44997
|
-
|
|
44998
|
-
|
|
44999
|
-
|
|
45000
|
-
|
|
45001
|
-
|
|
45002
|
-
|
|
45003
|
-
|
|
45004
|
-
|
|
45005
|
-
|
|
45006
|
-
|
|
45007
|
-
|
|
46079
|
+
function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate, createStreamState, registerCallback) {
|
|
46080
|
+
// Find all incomplete actions and register resume callbacks
|
|
46081
|
+
for (const message of messages) {
|
|
46082
|
+
if (message.action && !message.action.done) {
|
|
46083
|
+
const toolCallId = message.action.toolCallId;
|
|
46084
|
+
const toolName = message.message.name || message.toolExecuting || "tool";
|
|
46085
|
+
registerCallback(toolCallId, async (newState) => {
|
|
46086
|
+
// When user interacts with the action after reload, continue the stream
|
|
46087
|
+
try {
|
|
46088
|
+
// Update the action message with the new state and check completion
|
|
46089
|
+
setState(prev => ({
|
|
46090
|
+
...prev,
|
|
46091
|
+
messages: prev.messages.map(m => {
|
|
46092
|
+
if (m.action?.toolCallId !== toolCallId) {
|
|
46093
|
+
return m;
|
|
46094
|
+
}
|
|
46095
|
+
if (!m.action) {
|
|
46096
|
+
return m;
|
|
46097
|
+
}
|
|
46098
|
+
return { ...m, action: { ...m.action, state: newState } };
|
|
46099
|
+
}),
|
|
46100
|
+
isTyping: true,
|
|
46101
|
+
}));
|
|
46102
|
+
const streamState = createStreamState();
|
|
46103
|
+
// Continue the agent stream with the new state
|
|
46104
|
+
for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
|
|
46105
|
+
if (event.type === "done") {
|
|
46106
|
+
finalizeToolMessage(streamState, setState, toolCallId, toolName);
|
|
46107
|
+
streamState.sources = event.sources;
|
|
46108
|
+
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
46109
|
+
finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
|
|
46110
|
+
continue;
|
|
46111
|
+
}
|
|
46112
|
+
if (event.type === "error") {
|
|
46113
|
+
const errorMessage = {
|
|
46114
|
+
id: generateMessageId(),
|
|
46115
|
+
message: {
|
|
46116
|
+
role: "assistant",
|
|
46117
|
+
content: "Sorry, an error occurred. Please try again later.",
|
|
46118
|
+
},
|
|
46119
|
+
timestamp: new Date().toISOString(),
|
|
46120
|
+
sources: [],
|
|
46121
|
+
isError: true,
|
|
46122
|
+
};
|
|
46123
|
+
upsertMessage(setState, errorMessage, false);
|
|
46124
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
46125
|
+
return;
|
|
46126
|
+
}
|
|
46127
|
+
handleStreamEvent(event, streamState, onMessageUpdate, setState);
|
|
46128
|
+
}
|
|
46129
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
45008
46130
|
}
|
|
45009
|
-
|
|
45010
|
-
|
|
46131
|
+
catch (error) {
|
|
46132
|
+
console.error("[Action Resume] Failed to continue stream:", error);
|
|
46133
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
45011
46134
|
}
|
|
46135
|
+
});
|
|
45012
46136
|
}
|
|
45013
|
-
return { message, retryAfterSeconds, status: error.status };
|
|
45014
|
-
}
|
|
45015
|
-
if (error instanceof Error) {
|
|
45016
|
-
const lower = error.message.toLowerCase();
|
|
45017
|
-
if (lower.includes('network')) {
|
|
45018
|
-
return { message: 'Unable to connect to the server. Please check your internet connection.' };
|
|
45019
|
-
}
|
|
45020
|
-
if (lower.includes('timeout')) {
|
|
45021
|
-
return { message: 'The request timed out. Please try again.' };
|
|
45022
|
-
}
|
|
45023
|
-
if (lower.includes('unauthorized') || lower.includes('401')) {
|
|
45024
|
-
return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
|
|
45025
|
-
}
|
|
45026
|
-
if (lower.includes('internal server error') || lower.includes('500')) {
|
|
45027
|
-
return { message: 'The server encountered an error. Please try again shortly.' };
|
|
45028
|
-
}
|
|
45029
|
-
return { message: error.message || 'Something went wrong. Please try again.' };
|
|
45030
46137
|
}
|
|
45031
|
-
return { message: 'Something went wrong. Please try again.' };
|
|
45032
46138
|
}
|
|
46139
|
+
|
|
46140
|
+
/**
|
|
46141
|
+
* useChat Hook
|
|
46142
|
+
* Main state management for chat functionality
|
|
46143
|
+
*/
|
|
46144
|
+
// Initialize action handlers immediately to prevent tree-shaking
|
|
46145
|
+
initializeActionHandlers();
|
|
45033
46146
|
function useChat(options) {
|
|
45034
46147
|
const { widgetId, apiUrl, currentRoute, onMessage, onError, skipInitialization = false, } = options;
|
|
45035
46148
|
const [state, setState] = reactExports.useState({
|
|
@@ -45038,23 +46151,24 @@
|
|
|
45038
46151
|
isLoading: false,
|
|
45039
46152
|
isTyping: false,
|
|
45040
46153
|
error: null,
|
|
45041
|
-
conversationId: '',
|
|
46154
|
+
conversationId: '',
|
|
45042
46155
|
config: null,
|
|
45043
46156
|
});
|
|
45044
46157
|
const stateRef = reactExports.useRef(state);
|
|
45045
46158
|
reactExports.useEffect(() => {
|
|
45046
46159
|
stateRef.current = state;
|
|
45047
46160
|
}, [state]);
|
|
45048
|
-
// Chat history state
|
|
45049
46161
|
const [conversations, setConversations] = reactExports.useState([]);
|
|
46162
|
+
const abortControllerRef = reactExports.useRef(null);
|
|
46163
|
+
const currentRequestIdRef = reactExports.useRef(null);
|
|
46164
|
+
const lastNewChatTimeRef = reactExports.useRef(0);
|
|
46165
|
+
const NEW_CHAT_COOLDOWN_MS = 5000;
|
|
45050
46166
|
const apiClient = reactExports.useRef(new WidgetApiClient({ widgetId, apiUrl, currentRoute }));
|
|
45051
|
-
// Update API client when currentRoute changes
|
|
45052
46167
|
reactExports.useEffect(() => {
|
|
45053
46168
|
apiClient.current = new WidgetApiClient({ widgetId, apiUrl, currentRoute });
|
|
45054
46169
|
}, [widgetId, apiUrl, currentRoute]);
|
|
45055
46170
|
// Load configuration on mount and hydrate with existing conversation if available
|
|
45056
46171
|
reactExports.useEffect(() => {
|
|
45057
|
-
// Skip initialization in preview mode
|
|
45058
46172
|
if (skipInitialization) {
|
|
45059
46173
|
return;
|
|
45060
46174
|
}
|
|
@@ -45091,7 +46205,7 @@
|
|
|
45091
46205
|
}));
|
|
45092
46206
|
// Setup resume callbacks for incomplete actions
|
|
45093
46207
|
if (conversationId) {
|
|
45094
|
-
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }));
|
|
46208
|
+
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
|
|
45095
46209
|
}
|
|
45096
46210
|
}
|
|
45097
46211
|
catch (error) {
|
|
@@ -45108,7 +46222,6 @@
|
|
|
45108
46222
|
initialize();
|
|
45109
46223
|
return () => {
|
|
45110
46224
|
isMounted = false;
|
|
45111
|
-
// Cleanup resume callbacks
|
|
45112
46225
|
state.messages.forEach(message => {
|
|
45113
46226
|
if (message.action?.toolCallId) {
|
|
45114
46227
|
unregisterActionResumeCallback(message.action.toolCallId);
|
|
@@ -45131,7 +46244,15 @@
|
|
|
45131
46244
|
const hasFiles = !!files && files.length > 0;
|
|
45132
46245
|
if (!trimmedContent && !hasFiles)
|
|
45133
46246
|
return;
|
|
45134
|
-
|
|
46247
|
+
if (stateRef.current.isTyping) {
|
|
46248
|
+
console.warn('[Widget] Cannot send message while streaming is in progress');
|
|
46249
|
+
return;
|
|
46250
|
+
}
|
|
46251
|
+
if (abortControllerRef.current) {
|
|
46252
|
+
abortControllerRef.current.abort();
|
|
46253
|
+
abortControllerRef.current = null;
|
|
46254
|
+
}
|
|
46255
|
+
abortControllerRef.current = new AbortController();
|
|
45135
46256
|
const displayContent = trimmedContent.replace(/^\[EXECUTE_ACTION:[^\]]+\]\s*/, '');
|
|
45136
46257
|
const userMessage = {
|
|
45137
46258
|
id: generateMessageId(),
|
|
@@ -45142,12 +46263,11 @@
|
|
|
45142
46263
|
timestamp: new Date().toISOString(),
|
|
45143
46264
|
sources: [],
|
|
45144
46265
|
};
|
|
45145
|
-
// Add user message immediately
|
|
45146
46266
|
setState(prev => ({
|
|
45147
46267
|
...prev,
|
|
45148
46268
|
messages: [...prev.messages, userMessage],
|
|
45149
|
-
isLoading: false,
|
|
45150
|
-
isTyping: true,
|
|
46269
|
+
isLoading: false,
|
|
46270
|
+
isTyping: true,
|
|
45151
46271
|
error: null,
|
|
45152
46272
|
}));
|
|
45153
46273
|
onMessage?.(userMessage);
|
|
@@ -45187,16 +46307,29 @@
|
|
|
45187
46307
|
}
|
|
45188
46308
|
catch (uploadError) {
|
|
45189
46309
|
console.error('Failed to upload file:', uploadError);
|
|
45190
|
-
// Continue with other files
|
|
45191
46310
|
}
|
|
45192
46311
|
}
|
|
45193
46312
|
}
|
|
45194
|
-
// Stream the response
|
|
45195
46313
|
let lastStreamedMessage = null;
|
|
45196
46314
|
const streamState = createStreamState();
|
|
45197
|
-
|
|
46315
|
+
currentRequestIdRef.current = streamState.requestId;
|
|
46316
|
+
const currentAbortController = abortControllerRef.current;
|
|
46317
|
+
const streamConversationId = conversationId;
|
|
46318
|
+
const streamRequestId = streamState.requestId;
|
|
46319
|
+
const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds, currentAbortController?.signal);
|
|
45198
46320
|
for await (const event of stream) {
|
|
46321
|
+
if (currentAbortController?.signal.aborted ||
|
|
46322
|
+
stateRef.current.conversationId !== streamConversationId ||
|
|
46323
|
+
currentRequestIdRef.current !== streamRequestId) {
|
|
46324
|
+
console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
|
|
46325
|
+
break;
|
|
46326
|
+
}
|
|
45199
46327
|
if (event.type === "action_request") {
|
|
46328
|
+
if (currentAbortController?.signal.aborted ||
|
|
46329
|
+
stateRef.current.conversationId !== streamConversationId ||
|
|
46330
|
+
currentRequestIdRef.current !== streamRequestId) {
|
|
46331
|
+
break;
|
|
46332
|
+
}
|
|
45200
46333
|
await handleActionLoop(apiClient.current, event, streamState, (message) => {
|
|
45201
46334
|
lastStreamedMessage = message;
|
|
45202
46335
|
}, setState, widgetId, conversationId, () => stateRef.current.messages);
|
|
@@ -45206,25 +46339,26 @@
|
|
|
45206
46339
|
lastStreamedMessage = message;
|
|
45207
46340
|
}, setState);
|
|
45208
46341
|
}
|
|
45209
|
-
|
|
46342
|
+
if (currentAbortController?.signal.aborted ||
|
|
46343
|
+
stateRef.current.conversationId !== streamConversationId ||
|
|
46344
|
+
currentRequestIdRef.current !== streamRequestId) {
|
|
46345
|
+
console.log('[Widget] Stream was aborted or superseded, skipping finalization');
|
|
46346
|
+
return;
|
|
46347
|
+
}
|
|
45210
46348
|
setState(prev => ({
|
|
45211
46349
|
...prev,
|
|
45212
46350
|
isLoading: false,
|
|
45213
46351
|
isTyping: false,
|
|
45214
46352
|
}));
|
|
45215
|
-
// Notify about final message
|
|
45216
46353
|
if (lastStreamedMessage) {
|
|
45217
46354
|
onMessage?.(lastStreamedMessage);
|
|
45218
46355
|
}
|
|
45219
|
-
// Generate follow-up suggestions asynchronously
|
|
45220
46356
|
const enableFollowUps = state.config?.settings.enableFollowUpSuggestions !== false;
|
|
45221
46357
|
const actionIds = state.config?.actions || [];
|
|
45222
46358
|
if (enableFollowUps) {
|
|
45223
|
-
// Don't await - let it run in background
|
|
45224
46359
|
apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
|
|
45225
46360
|
.then(suggestions => {
|
|
45226
46361
|
if (suggestions.length > 0) {
|
|
45227
|
-
// Attach suggestions to the last assistant message
|
|
45228
46362
|
setState(prev => {
|
|
45229
46363
|
const messages = [...prev.messages];
|
|
45230
46364
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -45253,7 +46387,7 @@
|
|
|
45253
46387
|
},
|
|
45254
46388
|
timestamp: new Date().toISOString(),
|
|
45255
46389
|
sources: [],
|
|
45256
|
-
isError: !fallbackMessage,
|
|
46390
|
+
isError: !fallbackMessage,
|
|
45257
46391
|
};
|
|
45258
46392
|
setState(prev => ({
|
|
45259
46393
|
...prev,
|
|
@@ -45265,9 +46399,6 @@
|
|
|
45265
46399
|
onError?.(err);
|
|
45266
46400
|
}
|
|
45267
46401
|
}, [state.conversationId, state.config, state.messages, onMessage, onError]);
|
|
45268
|
-
/**
|
|
45269
|
-
* Clear all messages
|
|
45270
|
-
*/
|
|
45271
46402
|
const clearMessages = reactExports.useCallback(() => {
|
|
45272
46403
|
setState(prev => ({
|
|
45273
46404
|
...prev,
|
|
@@ -45280,9 +46411,6 @@
|
|
|
45280
46411
|
clearConversation(widgetId);
|
|
45281
46412
|
}
|
|
45282
46413
|
}, [widgetId, state.config?.settings.persistConversation]);
|
|
45283
|
-
/**
|
|
45284
|
-
* Submit feedback for a message
|
|
45285
|
-
*/
|
|
45286
46414
|
const submitFeedback = reactExports.useCallback(async (messageId, feedback) => {
|
|
45287
46415
|
try {
|
|
45288
46416
|
const message = state.messages.find(msg => msg.id === messageId);
|
|
@@ -45292,7 +46420,6 @@
|
|
|
45292
46420
|
: undefined;
|
|
45293
46421
|
console.log('Submitting feedback:', { conversationId: state.conversationId, messageId, feedback });
|
|
45294
46422
|
await apiClient.current.submitFeedback(state.conversationId, messageId, feedback, meta);
|
|
45295
|
-
// Update message with feedback
|
|
45296
46423
|
setState(prev => ({
|
|
45297
46424
|
...prev,
|
|
45298
46425
|
messages: prev.messages.map(msg => msg.id === messageId
|
|
@@ -45307,9 +46434,6 @@
|
|
|
45307
46434
|
onError?.(err);
|
|
45308
46435
|
}
|
|
45309
46436
|
}, [state.conversationId, onError]);
|
|
45310
|
-
/**
|
|
45311
|
-
* Load conversation history list from localStorage
|
|
45312
|
-
*/
|
|
45313
46437
|
const loadConversations = reactExports.useCallback(() => {
|
|
45314
46438
|
const persistConversation = state.config?.settings.persistConversation ?? true;
|
|
45315
46439
|
if (!persistConversation || !isStorageAvailable()) {
|
|
@@ -45326,8 +46450,11 @@
|
|
|
45326
46450
|
})));
|
|
45327
46451
|
}, [widgetId, state.config?.settings.persistConversation]);
|
|
45328
46452
|
const switchConversation = reactExports.useCallback(async (conversationId) => {
|
|
46453
|
+
if (abortControllerRef.current) {
|
|
46454
|
+
abortControllerRef.current.abort();
|
|
46455
|
+
abortControllerRef.current = null;
|
|
46456
|
+
}
|
|
45329
46457
|
const persistConversation = state.config?.settings.persistConversation ?? true;
|
|
45330
|
-
// First try to load from localStorage
|
|
45331
46458
|
if (persistConversation && isStorageAvailable()) {
|
|
45332
46459
|
const stored = loadConversationById(widgetId, conversationId);
|
|
45333
46460
|
if (stored) {
|
|
@@ -45335,16 +46462,17 @@
|
|
|
45335
46462
|
...prev,
|
|
45336
46463
|
conversationId: stored.conversationId,
|
|
45337
46464
|
messages: hydrateMessages(stored.messages),
|
|
46465
|
+
isTyping: false,
|
|
46466
|
+
isLoading: false,
|
|
45338
46467
|
}));
|
|
45339
46468
|
setActiveConversation(widgetId, conversationId);
|
|
45340
46469
|
return;
|
|
45341
46470
|
}
|
|
45342
46471
|
}
|
|
45343
|
-
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
46472
|
+
setState(prev => ({ ...prev, isLoading: true, isTyping: false, error: null }));
|
|
45344
46473
|
try {
|
|
45345
46474
|
const conversation = await apiClient.current.getOrCreateConversation(conversationId);
|
|
45346
46475
|
const hydratedMessages = hydrateMessages(conversation.messages);
|
|
45347
|
-
// Clear old resume callbacks
|
|
45348
46476
|
state.messages.forEach(message => {
|
|
45349
46477
|
if (message.action?.toolCallId) {
|
|
45350
46478
|
unregisterActionResumeCallback(message.action.toolCallId);
|
|
@@ -45356,9 +46484,7 @@
|
|
|
45356
46484
|
messages: hydratedMessages,
|
|
45357
46485
|
isLoading: false,
|
|
45358
46486
|
}));
|
|
45359
|
-
|
|
45360
|
-
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }));
|
|
45361
|
-
// Save to local storage
|
|
46487
|
+
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
|
|
45362
46488
|
if (persistConversation && isStorageAvailable()) {
|
|
45363
46489
|
saveConversation(widgetId, conversation.id, hydratedMessages);
|
|
45364
46490
|
}
|
|
@@ -45369,11 +46495,23 @@
|
|
|
45369
46495
|
}
|
|
45370
46496
|
}, [widgetId, state.config?.settings.persistConversation]);
|
|
45371
46497
|
const startNewConversation = reactExports.useCallback(() => {
|
|
46498
|
+
const now = Date.now();
|
|
46499
|
+
if (now - lastNewChatTimeRef.current < NEW_CHAT_COOLDOWN_MS) {
|
|
46500
|
+
console.warn('[Widget] New chat rate limited - please wait');
|
|
46501
|
+
return;
|
|
46502
|
+
}
|
|
46503
|
+
lastNewChatTimeRef.current = now;
|
|
46504
|
+
if (abortControllerRef.current) {
|
|
46505
|
+
abortControllerRef.current.abort();
|
|
46506
|
+
abortControllerRef.current = null;
|
|
46507
|
+
}
|
|
45372
46508
|
setState(prev => ({
|
|
45373
46509
|
...prev,
|
|
45374
46510
|
messages: [],
|
|
45375
46511
|
conversationId: '',
|
|
45376
46512
|
error: null,
|
|
46513
|
+
isTyping: false,
|
|
46514
|
+
isLoading: false,
|
|
45377
46515
|
}));
|
|
45378
46516
|
const persistConversation = state.config?.settings.persistConversation ?? true;
|
|
45379
46517
|
if (persistConversation && isStorageAvailable()) {
|
|
@@ -45385,11 +46523,8 @@
|
|
|
45385
46523
|
if (!persistConversation || !isStorageAvailable()) {
|
|
45386
46524
|
return;
|
|
45387
46525
|
}
|
|
45388
|
-
// Delete from storage
|
|
45389
46526
|
deleteConversation(widgetId, conversationId);
|
|
45390
|
-
// Update local state
|
|
45391
46527
|
setConversations(prev => prev.filter(c => c.id !== conversationId));
|
|
45392
|
-
// If we deleted the current conversation, clear it
|
|
45393
46528
|
if (state.conversationId === conversationId) {
|
|
45394
46529
|
setState(prev => ({
|
|
45395
46530
|
...prev,
|
|
@@ -45409,7 +46544,6 @@
|
|
|
45409
46544
|
sendMessage,
|
|
45410
46545
|
clearMessages,
|
|
45411
46546
|
submitFeedback,
|
|
45412
|
-
// Chat history features
|
|
45413
46547
|
conversations,
|
|
45414
46548
|
loadConversations,
|
|
45415
46549
|
switchConversation,
|
|
@@ -45418,11 +46552,20 @@
|
|
|
45418
46552
|
};
|
|
45419
46553
|
}
|
|
45420
46554
|
|
|
46555
|
+
const ShieldIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }), jsxRuntimeExports.jsx("path", { d: "M9 12l2 2 4-4" })] }));
|
|
46556
|
+
const DataPolicyView = ({ config, widgetName, }) => {
|
|
46557
|
+
const headerTitle = widgetName || config?.appearance?.headerTitle || 'AI Assistant';
|
|
46558
|
+
const hasFileUpload = config?.settings?.enableFileUpload ?? false;
|
|
46559
|
+
const persistsConversation = config?.settings?.persistConversation ?? true;
|
|
46560
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-view", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-intro", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-icon", children: jsxRuntimeExports.jsx(ShieldIcon, {}) }), jsxRuntimeExports.jsxs("p", { children: ["Dieser Datenschutzhinweis informiert dich gem\u00E4\u00DF Art. 13 DSGVO dar\u00FCber, wie ", jsxRuntimeExports.jsx("strong", { children: headerTitle }), " Daten verarbeitet, wenn du diesen Chat nutzt. Bitte beachte, dass der konkrete Umfang der Verarbeitung vom Betreiber dieser Website/Anwendung (dem Verantwortlichen) sowie von den jeweils aktivierten Funktionen abh\u00E4ngt."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Verantwortlicher / Kontakt" }), jsxRuntimeExports.jsx("p", { children: "Verantwortlicher im Sinne von Art. 4 Nr. 7 DSGVO ist der Betreiber dieser Website/Anwendung. Die Kontaktdaten (und ggf. die Kontaktdaten eines Datenschutzbeauftragten) findest du in der Datenschutzerkl\u00E4rung bzw. im Impressum der Website, in die dieses Chat-Widget eingebunden ist." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Verarbeitete Daten (Kategorien)" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Chat-Inhalte:" }), " Nachrichten (Text) sowie ggf. Kontextinformationen, die du im Chat angibst. Diese Inhalte werden verarbeitet, um Antworten zu generieren und die Unterhaltung bereitzustellen."] }), hasFileUpload && (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Hochgeladene Dateien:" }), " Dateien, die du an den Chat \u00FCbermittelst, werden zur Bearbeitung des Anliegens verarbeitet. Die Verarbeitung kann das Extrahieren von Text/Informationen umfassen."] })), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Technische Nutzungsdaten:" }), " z.B. Zeitstempel, Sitzungs-/Request-Informationen sowie technische Metadaten, die f\u00FCr den Betrieb, die Sicherheit (Missbrauchspr\u00E4vention) und Fehleranalyse erforderlich sind."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Zwecke und Rechtsgrundlagen" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Bereitstellung des Chats und Beantwortung von Anfragen" }), " (Art. 6 Abs. 1 lit. b DSGVO, soweit Vertrags-/vorvertragliche Ma\u00DFnahmen; andernfalls Art. 6 Abs. 1 lit. f DSGVO \u2013 berechtigtes Interesse an effizienter Kommunikation und Support)."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Qualit\u00E4tssicherung, Betrieb und Sicherheit" }), " (Art. 6 Abs. 1 lit. f DSGVO), z.B. zur Stabilit\u00E4t, Missbrauchserkennung und Fehlerbehebung."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Einwilligungsbasierte Verarbeitung" }), " kann erfolgen, sofern der Betreiber dies vorsieht (Art. 6 Abs. 1 lit. a DSGVO)."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Empf\u00E4nger und Auftragsverarbeiter" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Hosting/IT-Dienstleister:" }), " Der Betreiber kann Dienstleister f\u00FCr Hosting, Logging, Monitoring und Infrastruktur einsetzen."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "KI-Dienstleister:" }), " Zur Generierung von Antworten k\u00F6nnen Chat-Inhalte an KI-Modelle bzw. Anbieter von KI-Infrastruktur \u00FCbertragen werden. Soweit erforderlich, erfolgt dies auf Grundlage eines Auftragsverarbeitungsvertrags (Art. 28 DSGVO)."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Drittlandtransfer:" }), " Falls Empf\u00E4nger au\u00DFerhalb der EU/des EWR sitzen, kann ein Transfer in Drittl\u00E4nder stattfinden. In diesem Fall werden geeignete Garantien (z.B. EU-Standardvertragsklauseln) eingesetzt, soweit erforderlich."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Speicherdauer" }), jsxRuntimeExports.jsxs("ul", { children: [persistsConversation ? (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Chatverlauf:" }), " Der Chatverlauf kann gespeichert werden, um die Unterhaltung \u00FCber mehrere Sitzungen hinweg fortzusetzen."] })) : (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Chatverlauf:" }), " Der Chatverlauf wird nicht dauerhaft gespeichert und wird beim Schlie\u00DFen des Chats beendet."] })), hasFileUpload && (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Dateien:" }), " Hochgeladene Dateien werden nur so lange verarbeitet, wie dies f\u00FCr die Bearbeitung erforderlich ist, und anschlie\u00DFend gel\u00F6scht, sofern keine l\u00E4ngere Speicherung gesetzlich erforderlich ist."] })), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Technische Protokolle:" }), " Technische Logdaten k\u00F6nnen f\u00FCr einen begrenzten Zeitraum gespeichert werden, um den sicheren Betrieb zu gew\u00E4hrleisten."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Deine Rechte (Betroffenenrechte)" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Auskunft" }), " (Art. 15 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Berichtigung" }), " (Art. 16 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "L\u00F6schung" }), " (Art. 17 DSGVO) und ", jsxRuntimeExports.jsx("strong", { children: "Einschr\u00E4nkung der Verarbeitung" }), " (Art. 18 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Daten\u00FCbertragbarkeit" }), " (Art. 20 DSGVO), soweit anwendbar"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Widerspruch" }), " gegen Verarbeitungen auf Grundlage berechtigter Interessen (Art. 21 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Beschwerderecht" }), " bei einer Datenschutzaufsichtsbeh\u00F6rde (Art. 77 DSGVO)"] })] }), jsxRuntimeExports.jsx("p", { children: "Hinweis: Ohne eindeutige Identifikationsmerkmale kann der Betreiber einzelne Chatverl\u00E4ufe ggf. nicht einer Person zuordnen. F\u00FCr Anfragen wende dich bitte an den Betreiber dieser Website/Anwendung." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Wichtiger Hinweis" }), jsxRuntimeExports.jsx("p", { className: "ai-chat-data-policy-warning", children: "Bitte gib keine besonderen Kategorien personenbezogener Daten (z.B. Gesundheitsdaten), Passw\u00F6rter, Kreditkarten-/Bankdaten oder vertrauliche Gesch\u00E4ftsgeheimnisse in den Chat ein. KI-generierte Antworten k\u00F6nnen unzutreffend sein und sollten vor einer Nutzung eigenverantwortlich gepr\u00FCft werden." })] })] }) }));
|
|
46561
|
+
};
|
|
46562
|
+
|
|
45421
46563
|
const MenuIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "4", y1: "10", x2: "20", y2: "10" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "20", y2: "14" })] }));
|
|
45422
46564
|
const PlusIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), jsxRuntimeExports.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })] }));
|
|
45423
46565
|
const TrashIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M3 6h18" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), jsxRuntimeExports.jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })] }));
|
|
45424
46566
|
const CloseIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
|
|
45425
|
-
const
|
|
46567
|
+
const BackIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M19 12H5" }), jsxRuntimeExports.jsx("path", { d: "M12 19l-7-7 7-7" })] }));
|
|
46568
|
+
const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick,
|
|
45426
46569
|
// Chat history props (only active when persistConversation is true)
|
|
45427
46570
|
conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
|
|
45428
46571
|
// Override props for live preview
|
|
@@ -45439,6 +46582,8 @@
|
|
|
45439
46582
|
const inputPlaceholder = placeholderOverride ?? appearance?.placeholder ?? 'Ask me anything...';
|
|
45440
46583
|
// Track if history panel is open
|
|
45441
46584
|
const [showHistory, setShowHistory] = reactExports.useState(false);
|
|
46585
|
+
// Track if data policy view is open
|
|
46586
|
+
const [showDataPolicy, setShowDataPolicy] = reactExports.useState(false);
|
|
45442
46587
|
// Scroll button state (managed by MessageList)
|
|
45443
46588
|
const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
|
|
45444
46589
|
const [scrollToBottom, setScrollToBottom] = reactExports.useState(null);
|
|
@@ -45448,6 +46593,13 @@
|
|
|
45448
46593
|
}, []);
|
|
45449
46594
|
// History exit animation when starting a new chat from overview
|
|
45450
46595
|
const [isHistoryExiting, setIsHistoryExiting] = reactExports.useState(false);
|
|
46596
|
+
// Handle data policy click
|
|
46597
|
+
const handleDataPolicyClick = reactExports.useCallback(() => {
|
|
46598
|
+
setShowDataPolicy(true);
|
|
46599
|
+
}, []);
|
|
46600
|
+
const handleDataPolicyBack = reactExports.useCallback(() => {
|
|
46601
|
+
setShowDataPolicy(false);
|
|
46602
|
+
}, []);
|
|
45451
46603
|
// Load conversations when history panel opens
|
|
45452
46604
|
const handleOpenHistory = () => {
|
|
45453
46605
|
setShowHistory(true);
|
|
@@ -45495,10 +46647,22 @@
|
|
|
45495
46647
|
// The backend will detect and trigger the action based on the message
|
|
45496
46648
|
onSendMessage(question);
|
|
45497
46649
|
};
|
|
45498
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''}`, children: showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntimeExports.jsx(CloseIcon, {}) })] })] })) }),
|
|
46650
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''} ${showDataPolicy ? 'is-data-policy' : ''}`, children: showDataPolicy ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleDataPolicyBack, "aria-label": "Back to chat", children: jsxRuntimeExports.jsx(BackIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: "Datenschutzhinweis" })] })) : showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntimeExports.jsx(CloseIcon, {}) })] })] })) }), showDataPolicy ? (jsxRuntimeExports.jsx(DataPolicyView, { config: config, onBack: handleDataPolicyBack, widgetName: headerTitle })) : showHistory ? (
|
|
46651
|
+
/* History Panel */
|
|
46652
|
+
jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-item-content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), onDeleteConversation && (jsxRuntimeExports.jsx("button", { className: "ai-chat-history-item-delete", onClick: (e) => {
|
|
45499
46653
|
e.stopPropagation();
|
|
45500
46654
|
onDeleteConversation(conv.id);
|
|
45501
|
-
}, "aria-label": "Delete conversation", children: jsxRuntimeExports.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
46655
|
+
}, "aria-label": "Delete conversation", children: jsxRuntimeExports.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), (() => {
|
|
46656
|
+
console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
|
|
46657
|
+
messages.forEach((m, i) => {
|
|
46658
|
+
console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
|
|
46659
|
+
});
|
|
46660
|
+
console.log('[DEBUG ChatWindow] getActionRenderer available:', !!getActionRenderer);
|
|
46661
|
+
if (getActionRenderer) {
|
|
46662
|
+
console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
|
|
46663
|
+
}
|
|
46664
|
+
return null;
|
|
46665
|
+
})(), jsxRuntimeExports.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, showToolCalls: settings?.showToolCalls, enableFeedback: settings?.enableFeedback, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, accentColor: appearance?.primaryColor, onSuggestedQuestionClick: handleQuestionClick, onActionClick: onActionClick, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer }), jsxRuntimeExports.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : (isTyping ? 'Waiting for response...' : inputPlaceholder), disabled: isLoading || isTyping || isLimitReached, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] }))] }));
|
|
45502
46666
|
};
|
|
45503
46667
|
|
|
45504
46668
|
/**
|
|
@@ -45904,7 +47068,7 @@
|
|
|
45904
47068
|
if ( ref === void 0 ) ref = {};
|
|
45905
47069
|
var insertAt = ref.insertAt;
|
|
45906
47070
|
|
|
45907
|
-
if (typeof document === 'undefined') { return; }
|
|
47071
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
45908
47072
|
|
|
45909
47073
|
var head = document.head || document.getElementsByTagName('head')[0];
|
|
45910
47074
|
var style = document.createElement('style');
|
|
@@ -45927,7 +47091,10 @@
|
|
|
45927
47091
|
}
|
|
45928
47092
|
}
|
|
45929
47093
|
|
|
45930
|
-
var css_248z = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}.ai-chat-message.streaming .ai-chat-message-content:after{animation:ai-chat-cursor-blink .8s infinite;content:\"▋\";margin-left:2px;opacity:.7}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-cursor-blink{0%,50%{opacity:1}51%,to{opacity:0}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-gear.spinning{animation:ai-chat-spin 1.5s linear infinite}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:none;border-radius:var(--radius-lg,12px);box-sizing:border-box;margin-top:var(--space-sm,8px);max-width:100%;padding:var(--space-md,16px);transition:all var(--duration-normal,.25s) ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-booked{background:var(--bg-secondary,#f4f4f4);border:none}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-date-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}.ai-chat-action-date-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-date-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn,.chakra-ui-dark .ai-chat-action-date-btn,.dark .ai-chat-action-date-btn,[data-theme=dark] .ai-chat-action-date-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn:hover,.chakra-ui-dark .ai-chat-action-date-btn:hover,.dark .ai-chat-action-date-btn:hover,[data-theme=dark] .ai-chat-action-date-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-date-btn.active,.chakra-ui-dark .ai-chat-action-date-btn.active,.dark .ai-chat-action-date-btn.active,[data-theme=dark] .ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-time-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}.ai-chat-action-time-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-time-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn,.chakra-ui-dark .ai-chat-action-time-btn,.dark .ai-chat-action-time-btn,[data-theme=dark] .ai-chat-action-time-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn:hover,.chakra-ui-dark .ai-chat-action-time-btn:hover,.dark .ai-chat-action-time-btn:hover,[data-theme=dark] .ai-chat-action-time-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-time-btn.active,.chakra-ui-dark .ai-chat-action-time-btn.active,.dark .ai-chat-action-time-btn.active,[data-theme=dark] .ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}@media (max-width:480px){.ai-chat-widget-container.is-open{height:100vh!important;inset:0!important;width:100vw!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border-radius:0!important;height:100%!important;inset:0!important;max-height:100%!important;max-width:100%!important;position:absolute!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;visibility:hidden!important}.ai-chat-header{padding-top:max(16px,env(safe-area-inset-top))}.ai-chat-input-container{padding-bottom:max(20px,env(safe-area-inset-bottom))}}.ai-chat-window{animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium,.ai-chat-window.size-small{max-height:calc(100vh - 100px);max-width:calc(100vw - 40px)}.ai-chat-window.size-medium{height:600px;width:420px}.ai-chat-window.size-large{height:700px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:18px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:opacity var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#fff) 50%,var(--bg-primary,#fff) 100%);bottom:0;left:0;padding-top:30px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#282625) 50%,var(--bg-primary,#282625) 100%)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px);padding-top:30px}.ai-chat-input-wrapper{align-items:flex-end;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:var(--text-md,15px)!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;align-self:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:var(--space-lg,24px) var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%}.ai-chat-message.tool{align-self:flex-start;margin:0 -16px;max-width:100%;padding:0;width:calc(100% + 32px)}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);overflow-wrap:break-word;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);color:var(--agent-text,#000);padding:0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:var(--space-sm) 0;padding-left:var(--space-lg)}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);margin:var(--space-sm) 0;width:100%}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border:1px solid var(--border-subtle);padding:var(--space-sm);text-align:left}.ai-chat-message.assistant .ai-chat-message-content th{font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;border:none;border-radius:var(--radius-preset-badge,18px);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:opacity .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-follow-up-item,.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-md) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,44px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,8px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;margin-left:auto;margin-right:var(--space-2xs,2px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:32px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0 16px}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0 16px;width:100%}.ai-chat-sources{background:rgba(0,0,0,.02);border-radius:6px;font-size:var(--text-xs);margin-top:var(--space-sm);overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:var(--space-sm) 10px;text-align:left;transition:background var(--duration-fast) ease;width:100%}.ai-chat-sources-toggle:hover{background:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform var(--duration-fast) ease}.ai-chat-sources-title{color:var(--text-primary);flex:1;font-size:11px;font-weight:var(--font-weight-semibold);letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:var(--text-muted);display:flex;gap:var(--space-sm);padding:var(--space-sm) 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--btn-primary-bg);flex-shrink:0;font-weight:var(--font-weight-semibold)}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:var(--space-xs)}.ai-chat-source-score{color:var(--text-placeholder);font-size:11px}.ai-chat-source-content{color:var(--text-muted);font-size:11px;font-style:italic;line-height:var(--line-height-normal)}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background:rgba(0,0,0,.05);border-radius:3px;color:var(--text-muted);font-size:10px;padding:2px 6px}";
|
|
47094
|
+
var css_248z$1 = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}.ai-chat-message.streaming .ai-chat-message-content:after{animation:ai-chat-cursor-blink .8s infinite;content:\"▋\";margin-left:2px;opacity:.7}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-cursor-blink{0%,50%{opacity:1}51%,to{opacity:0}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-row{padding:0 16px}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-pin-input-group{align-items:center;display:flex;flex-wrap:nowrap;gap:8px;justify-content:center;margin:4px 0 8px}.ai-chat-pin-input{align-items:center;appearance:none;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);display:inline-flex;flex:0 0 42px;font-family:inherit;font-size:18px;font-weight:600;height:46px;justify-content:center;line-height:1;max-width:42px;min-width:42px;outline:none;padding:0;text-align:center;transition:border-color .2s ease,box-shadow .2s ease;width:42px}.ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-pin-input:disabled{cursor:not-allowed;opacity:.6}.ai-chat-widget.dark .ai-chat-pin-input,.chakra-ui-dark .ai-chat-pin-input,.dark .ai-chat-pin-input,[data-theme=dark] .ai-chat-pin-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-pin-input:focus,.chakra-ui-dark .ai-chat-pin-input:focus,.dark .ai-chat-pin-input:focus,[data-theme=dark] .ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button-secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:9999px;color:var(--text-secondary,#6b7280);cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500);padding:10px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-button-secondary:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-action-button-secondary,.chakra-ui-dark .ai-chat-action-button-secondary,.dark .ai-chat-action-button-secondary,[data-theme=dark] .ai-chat-action-button-secondary{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#e5e7eb}.ai-chat-widget.dark .ai-chat-action-button-secondary:hover:not(:disabled),.chakra-ui-dark .ai-chat-action-button-secondary:hover:not(:disabled),.dark .ai-chat-action-button-secondary:hover:not(:disabled),[data-theme=dark] .ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.2);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-appointment-list,.ai-chat-action-button-group{display:flex;flex-direction:column;gap:8px}.ai-chat-action-appointment-item{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-appointment-item,.chakra-ui-dark .ai-chat-action-appointment-item,.dark .ai-chat-action-appointment-item,[data-theme=dark] .ai-chat-action-appointment-item{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.08)}.ai-chat-action-appointment-info{display:flex;flex-direction:column;gap:2px;min-width:0}.ai-chat-action-appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-action-appointment-subject,.chakra-ui-dark .ai-chat-action-appointment-subject,.dark .ai-chat-action-appointment-subject,[data-theme=dark] .ai-chat-action-appointment-subject{color:#fff}.ai-chat-action-appointment-time{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-action-appointment-item .ai-chat-action-button-secondary{font-size:12px;padding:6px 12px;width:auto}.ai-chat-action-error-message{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:12px}.ai-chat-widget.dark .ai-chat-action-error-message,.chakra-ui-dark .ai-chat-action-error-message,.dark .ai-chat-action-error-message,[data-theme=dark] .ai-chat-action-error-message{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:var(--widget-z-index,2147483647)}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-widget-container.container-mode{position:absolute}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}.ai-chat-window{animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium,.ai-chat-window.size-small{max-height:calc(100vh - 100px);max-width:calc(100vw - 40px)}.ai-chat-window.size-medium{height:600px;width:420px}.ai-chat-window.size-large{height:700px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:12px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:opacity var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-welcome-bubble{animation:ai-chat-bubble-fade-in .3s ease-out;background:var(--button-color,var(--btn-primary-bg,#07f));border:none;border-radius:12px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--button-icon-color,var(--btn-primary-text,#fff));cursor:pointer;font-size:14px;font-weight:500;line-height:1.4;padding:12px 16px;position:absolute;width:200px;z-index:0}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{bottom:68px;right:0;text-align:right}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{bottom:68px;left:0;right:auto;text-align:left}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{right:0;text-align:right;top:68px}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{left:0;right:auto;text-align:left;top:68px}.ai-chat-welcome-bubble:hover{filter:brightness(1.1)}@keyframes ai-chat-bubble-fade-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble,.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-down}@keyframes ai-chat-bubble-fade-in-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0;left:0;padding:8px 0 16px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px)}.ai-chat-input-wrapper{align-items:flex-end;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:var(--text-md,15px)!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;align-self:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-data-policy{bottom:2px;color:var(--text-muted,#71717a);font-size:9px;left:0;line-height:1.4;opacity:.5;pointer-events:auto;position:absolute;right:0;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy{color:var(--text-muted,#a1a1aa)}.ai-chat-data-policy-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-data-policy-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-data-policy-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-data-policy-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:0 var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%;width:100%}.ai-chat-message.tool{align-self:stretch;max-width:none;padding:0}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);overflow-wrap:break-word;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);box-sizing:border-box;color:var(--agent-text,#000);padding:0;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:var(--space-sm) 0;padding-left:var(--space-lg)}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:var(--radius-md,8px);box-sizing:border-box;display:block;margin:var(--space-sm) var(--space-sm);max-width:100%;overflow:hidden;width:auto}.ai-chat-message.assistant .ai-chat-message-content .table-scroll{max-width:100%;overflow-x:auto;overflow-y:hidden;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);min-width:100%;width:max-content}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.1));border-right:1px solid var(--border-subtle,rgba(0,0,0,.1));padding:var(--space-sm);text-align:left}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content td:last-child,.ai-chat-message.assistant .ai-chat-message-content th:last-child{border-right:none}.ai-chat-message.assistant .ai-chat-message-content tr:last-child td{border-bottom:none}.ai-chat-message.assistant .ai-chat-message-content th{background:rgba(0,0,0,.03);font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;border:none;border-radius:var(--radius-preset-badge,18px);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:opacity .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-follow-up-item,.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type,.dark .ai-chat-follow-up-item.question-type,[data-color-mode=dark] .ai-chat-follow-up-item.question-type,[data-theme=dark] .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover,.dark .ai-chat-follow-up-item.question-type:hover,[data-color-mode=dark] .ai-chat-follow-up-item.question-type:hover,[data-theme=dark] .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-xs) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,36px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,4px) 0 var(--space-md,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,6px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-left:auto;margin-right:var(--space-xs,4px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:24px}.ai-chat-history-item-delete svg{height:14px;width:14px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#fff;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0;width:100%}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin-top:4px;padding:16px;transition:all .2s ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-action-booked{background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}.ai-chat-action-date-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}.ai-chat-action-date-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-date-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn,.chakra-ui-dark .ai-chat-action-date-btn,.dark .ai-chat-action-date-btn,[data-theme=dark] .ai-chat-action-date-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn:hover,.chakra-ui-dark .ai-chat-action-date-btn:hover,.dark .ai-chat-action-date-btn:hover,[data-theme=dark] .ai-chat-action-date-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-date-btn.active,.chakra-ui-dark .ai-chat-action-date-btn.active,.dark .ai-chat-action-date-btn.active,[data-theme=dark] .ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-time-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}.ai-chat-action-time-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-time-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn,.chakra-ui-dark .ai-chat-action-time-btn,.dark .ai-chat-action-time-btn,[data-theme=dark] .ai-chat-action-time-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn:hover,.chakra-ui-dark .ai-chat-action-time-btn:hover,.dark .ai-chat-action-time-btn:hover,[data-theme=dark] .ai-chat-action-time-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-time-btn.active,.chakra-ui-dark .ai-chat-action-time-btn.active,.dark .ai-chat-action-time-btn.active,[data-theme=dark] .ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-link-preview{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);cursor:pointer;display:flex;flex-direction:column;margin-top:4px;overflow:hidden;padding:0!important;position:relative;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 8px rgba(0,0,0,.1);transform:translateY(-1px)}.ai-chat-link-preview:focus{border-color:var(--action-accent);box-shadow:0 0 0 2px rgba(59,130,246,.2);outline:none}.ai-chat-widget.dark .ai-chat-link-preview,.chakra-ui-dark .ai-chat-link-preview,.dark .ai-chat-link-preview,[data-theme=dark] .ai-chat-link-preview{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-widget.dark .ai-chat-link-preview:hover,.chakra-ui-dark .ai-chat-link-preview:hover,.dark .ai-chat-link-preview:hover,[data-theme=dark] .ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 12px rgba(0,0,0,.3)}.ai-chat-link-preview__image{aspect-ratio:1.91/1;background:var(--bg-muted,#e5e7eb);overflow:hidden;width:100%}.ai-chat-widget.dark .ai-chat-link-preview__image,.chakra-ui-dark .ai-chat-link-preview__image,.dark .ai-chat-link-preview__image,[data-theme=dark] .ai-chat-link-preview__image{background:hsla(0,0%,100%,.05)}.ai-chat-link-preview__image img{height:100%;object-fit:cover;width:100%}.ai-chat-link-preview__content{flex:1;padding:8px 10px}.ai-chat-link-preview__site{align-items:center;display:flex;gap:6px;margin-bottom:6px}.ai-chat-link-preview__favicon{border-radius:2px;flex-shrink:0;height:16px;width:16px}.ai-chat-link-preview__domain{color:var(--text-muted,#71717a);font-size:12px;letter-spacing:.5px;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.ai-chat-link-preview__title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-primary,#3e3e3e);display:-webkit-box;font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px;overflow:hidden}.ai-chat-widget.dark .ai-chat-link-preview__title,.chakra-ui-dark .ai-chat-link-preview__title,.dark .ai-chat-link-preview__title,[data-theme=dark] .ai-chat-link-preview__title{color:#fff}.ai-chat-link-preview__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#71717a);display:-webkit-box;font-size:13px;line-height:1.4;margin:0;overflow:hidden}.ai-chat-link-preview__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:8px 0 0;padding-top:8px}.ai-chat-widget.dark .ai-chat-link-preview__context,.chakra-ui-dark .ai-chat-link-preview__context,.dark .ai-chat-link-preview__context,[data-theme=dark] .ai-chat-link-preview__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-link-preview__arrow{align-items:center;background:var(--bg-primary,#fff);border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.1);color:var(--text-muted,#71717a);display:flex;height:28px;justify-content:center;opacity:0;position:absolute;right:12px;top:12px;transition:opacity .2s,background .2s;width:28px}.ai-chat-link-preview:hover .ai-chat-link-preview__arrow{opacity:1}.ai-chat-widget.dark .ai-chat-link-preview__arrow,.chakra-ui-dark .ai-chat-link-preview__arrow,.dark .ai-chat-link-preview__arrow,[data-theme=dark] .ai-chat-link-preview__arrow{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-link-preview--error{border-color:rgba(239,68,68,.3)}.ai-chat-link-preview--error:hover{border-color:rgba(239,68,68,.5)}.ai-chat-link-preview__error-text{color:#dc2626;font-size:12px;margin:4px 0 0}.ai-chat-widget.dark .ai-chat-link-preview__error-text,.chakra-ui-dark .ai-chat-link-preview__error-text,.dark .ai-chat-link-preview__error-text,[data-theme=dark] .ai-chat-link-preview__error-text{color:#fca5a5}.ai-chat-video-player{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;gap:0;margin-top:4px;overflow:hidden;padding:0!important}.ai-chat-widget.dark .ai-chat-video-player,.chakra-ui-dark .ai-chat-video-player,.dark .ai-chat-video-player,[data-theme=dark] .ai-chat-video-player{background:var(--bg-secondary,#3a3a3a)}.ai-chat-video-player__header{align-items:center;color:var(--action-accent,var(--primary-color,#3b82f6));display:flex;gap:8px}.ai-chat-video-player__title{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600}.ai-chat-widget.dark .ai-chat-video-player__title,.chakra-ui-dark .ai-chat-video-player__title,.dark .ai-chat-video-player__title,[data-theme=dark] .ai-chat-video-player__title{color:#fff}.ai-chat-video-player__container{aspect-ratio:16/9;background:#000;border-radius:8px;overflow:hidden;position:relative;width:100%}.ai-chat-video-player__thumbnail{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-video-player__thumbnail img{height:100%;object-fit:cover;width:100%}.ai-chat-video-player__placeholder{align-items:center;background:linear-gradient(135deg,#1a1a2e,#16213e);cursor:pointer;display:flex;flex-direction:column;gap:8px;height:100%;justify-content:center;position:relative;width:100%}.ai-chat-video-player__click-text{color:hsla(0,0%,100%,.7);font-size:13px}.ai-chat-video-player__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:64px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:64px}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn{left:auto;position:relative;top:auto;transform:none}.ai-chat-video-player__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn:hover{transform:scale(1.05)}.ai-chat-video-player__provider-badge{background:rgba(0,0,0,.8);border-radius:4px;bottom:8px;color:#fff;font-size:11px;font-weight:600;letter-spacing:.5px;padding:4px 8px;position:absolute;right:8px;text-transform:uppercase}.ai-chat-video-player__iframe,.ai-chat-video-player__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-video-player__error{align-items:center;background:rgba(239,68,68,.1);color:#dc2626;display:flex;font-size:13px;height:100%;justify-content:center;padding:16px;text-align:center;width:100%}.ai-chat-widget.dark .ai-chat-video-player__error,.chakra-ui-dark .ai-chat-video-player__error,.dark .ai-chat-video-player__error,[data-theme=dark] .ai-chat-video-player__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-video-player__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin-top:4px;padding-top:8px}.ai-chat-widget.dark .ai-chat-video-player__context,.chakra-ui-dark .ai-chat-video-player__context,.dark .ai-chat-video-player__context,[data-theme=dark] .ai-chat-video-player__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-location-card{background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:12px;overflow:hidden;padding:0}.ai-chat-widget.dark .ai-chat-location-card,.chakra-ui-dark .ai-chat-location-card,.dark .ai-chat-location-card,[data-theme=dark] .ai-chat-location-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-location-card--compact{border-radius:10px}.ai-chat-location-card--error{color:var(--text-muted,#71717a);padding:16px;text-align:center}.ai-chat-location-card__map{background:var(--bg-muted,#f4f4f5);position:relative;width:100%}.ai-chat-widget.dark .ai-chat-location-card__map,.chakra-ui-dark .ai-chat-location-card__map,.dark .ai-chat-location-card__map,[data-theme=dark] .ai-chat-location-card__map{background:rgba(0,0,0,.2)}.ai-chat-location-card__map iframe{border:none;display:block;height:100%;width:100%}.ai-chat-location-card__content{padding:12px}.ai-chat-location-card--compact .ai-chat-location-card__content{padding:10px}.ai-chat-location-card__header{align-items:center;display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.ai-chat-location-card__name{color:var(--text-primary,#18181b);flex:1;font-size:16px;font-weight:600;margin:0;min-width:0}.ai-chat-widget.dark .ai-chat-location-card__name,.chakra-ui-dark .ai-chat-location-card__name,.dark .ai-chat-location-card__name,[data-theme=dark] .ai-chat-location-card__name{color:#fff}.ai-chat-location-card--compact .ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__type{background:var(--bg-muted,#f4f4f5);border-radius:10px;color:var(--text-muted,#71717a);font-size:11px;font-weight:500;letter-spacing:.5px;padding:2px 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-location-card__type,.chakra-ui-dark .ai-chat-location-card__type,.dark .ai-chat-location-card__type,[data-theme=dark] .ai-chat-location-card__type{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.ai-chat-location-card__status{border-radius:12px;font-size:12px;font-weight:500;padding:2px 8px}.ai-chat-location-card__status--open{background:#dcfce7;color:#16a34a}.ai-chat-location-card__status--closed{background:#fef2f2;color:#dc2626}.ai-chat-widget.dark .ai-chat-location-card__status--open,.chakra-ui-dark .ai-chat-location-card__status--open,.dark .ai-chat-location-card__status--open,[data-theme=dark] .ai-chat-location-card__status--open{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-widget.dark .ai-chat-location-card__status--closed,.chakra-ui-dark .ai-chat-location-card__status--closed,.dark .ai-chat-location-card__status--closed,[data-theme=dark] .ai-chat-location-card__status--closed{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-location-card__address{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__address svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__hours{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;margin-bottom:8px}.ai-chat-location-card__hours svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__hours-list{flex:1}.ai-chat-location-card__hours-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;font:inherit;gap:4px;padding:0}.ai-chat-location-card__hours-toggle:hover{text-decoration:underline}.ai-chat-location-card__hours-full{list-style:none;margin:8px 0 0;padding:0}.ai-chat-location-card__hours-full li{display:flex;font-size:12px;justify-content:space-between;padding:4px 0}.ai-chat-location-card__hours-today{color:var(--text-primary,#18181b);font-weight:600}.ai-chat-widget.dark .ai-chat-location-card__hours-today,.chakra-ui-dark .ai-chat-location-card__hours-today,.dark .ai-chat-location-card__hours-today,[data-theme=dark] .ai-chat-location-card__hours-today{color:#fff}.ai-chat-location-card__phone{align-items:center;background:none;border:none;color:var(--action-accent,#3b82f6);cursor:pointer;display:flex;font-size:13px;gap:6px;margin-bottom:12px;padding:0}.ai-chat-location-card__phone:hover{text-decoration:underline}.ai-chat-location-card__actions{display:flex;gap:8px;justify-content:flex-start;width:100%}.ai-chat-location-card__button{align-items:center;background:var(--action-accent,#3b82f6);border:none;border-radius:20px;color:#fff;cursor:pointer;display:flex;flex:1;font-size:13px;font-weight:500;gap:6px;justify-content:center;padding:10px 16px;transition:opacity .2s}.ai-chat-location-card__button:hover{opacity:.9}.ai-chat-location-card--compact .ai-chat-location-card__button{font-size:12px;padding:8px 12px}.ai-chat-location-card__link{align-items:center;background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:20px;color:var(--text-primary,#18181b);display:flex;font-size:13px;gap:6px;padding:10px 16px;text-decoration:none;transition:border-color .2s}.ai-chat-widget.dark .ai-chat-location-card__link,.chakra-ui-dark .ai-chat-location-card__link,.dark .ai-chat-location-card__link,[data-theme=dark] .ai-chat-location-card__link{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-location-card__link:hover{border-color:var(--action-accent,#3b82f6)}.ai-chat-location-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-location-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:4px;padding:0 4px}.ai-chat-location-card-list__stack{display:grid;gap:12px;grid-template-columns:1fr}.ai-chat-location-card-list__stack--cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:1000px){.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:640px){.ai-chat-location-card-list__stack--cols-2,.ai-chat-location-card-list__stack--cols-3{grid-template-columns:1fr}}.ai-chat-location-card-list__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:400px){.ai-chat-location-card-list__grid{grid-template-columns:1fr}}.ai-chat-location-card-list__carousel{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;scroll-snap-type:x mandatory;scrollbar-width:none}.ai-chat-location-card-list__carousel::-webkit-scrollbar{display:none}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 280px;scroll-snap-align:start}.ai-chat-contact-card{background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;overflow:hidden;padding:0;position:relative}.ai-chat-widget.dark .ai-chat-contact-card,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card,.chakra-ui-dark .ai-chat-contact-card,.dark .ai-chat-contact-card,[data-theme=dark] .ai-chat-contact-card,html.dark .ai-chat-contact-card{background:#4a4a4a;border-color:hsla(0,0%,100%,.08)}.ai-chat-contact-card-list{gap:12px;width:100%}.ai-chat-contact-card--compact{border-radius:12px}.ai-chat-contact-card--empty{align-items:center;background:var(--bg-secondary,#f4f4f5);display:flex;flex-direction:column;gap:8px;justify-content:center;padding:24px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-contact-card--empty,.chakra-ui-dark .ai-chat-contact-card--empty,.dark .ai-chat-contact-card--empty,[data-theme=dark] .ai-chat-contact-card--empty{background:#3a3a3a}.ai-chat-contact-card__empty-icon{color:var(--text-muted,#71717a);opacity:.6}.ai-chat-contact-card__empty-text{color:var(--text-muted,#71717a);font-size:14px;margin:0}.ai-chat-contact-card--vertical{display:flex;flex-direction:column}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-section{aspect-ratio:3/2;overflow:hidden;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder svg{height:48px;width:48px}.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:16px;text-align:center}.ai-chat-contact-card--horizontal{display:flex;flex-direction:row}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{height:160px;min-width:140px;overflow:hidden;width:140px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__image-section{height:120px;min-width:100px;width:100px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder svg{height:36px;width:36px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info{display:flex;flex:1;flex-direction:column;justify-content:center;padding:16px}.ai-chat-contact-card__name{color:var(--action-accent,#ef4444);font-size:18px;font-weight:600;line-height:1.3;margin:0}.ai-chat-contact-card--compact .ai-chat-contact-card__name{font-size:15px}.ai-chat-contact-card__role{color:rgba(0,0,0,.7);font-size:14px;font-weight:400;margin:2px 0 0}.ai-chat-widget.dark .ai-chat-contact-card__role,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__role,.chakra-ui-dark .ai-chat-contact-card__role,.dark .ai-chat-contact-card__role,[data-theme=dark] .ai-chat-contact-card__role,html.dark .ai-chat-contact-card__role{color:hsla(0,0%,100%,.9)}.ai-chat-contact-card--compact .ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__details{display:flex;flex-direction:column;gap:2px;margin-top:12px}.ai-chat-contact-card__detail{color:rgba(0,0,0,.6);display:block;font-size:14px;line-height:1.5;margin:0;text-decoration:none}.ai-chat-contact-card__detail:hover{color:#000;text-decoration:underline}.ai-chat-widget.dark .ai-chat-contact-card__detail,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail,.chakra-ui-dark .ai-chat-contact-card__detail,.dark .ai-chat-contact-card__detail,[data-theme=dark] .ai-chat-contact-card__detail,html.dark .ai-chat-contact-card__detail{color:hsla(0,0%,100%,.7)}.ai-chat-widget.dark .ai-chat-contact-card__detail:hover,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail:hover,.chakra-ui-dark .ai-chat-contact-card__detail:hover,.dark .ai-chat-contact-card__detail:hover,[data-theme=dark] .ai-chat-contact-card__detail:hover,html.dark .ai-chat-contact-card__detail:hover{color:#fff}.ai-chat-contact-card--compact .ai-chat-contact-card__detail{font-size:13px}.ai-chat-contact-card__responsibilities{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.ai-chat-contact-card__responsibility-tag{background:rgba(0,0,0,.08);border-radius:10px;color:rgba(0,0,0,.8);font-size:11px;font-weight:500;padding:3px 10px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-tag,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-tag,.chakra-ui-dark .ai-chat-contact-card__responsibility-tag,.dark .ai-chat-contact-card__responsibility-tag,[data-theme=dark] .ai-chat-contact-card__responsibility-tag,html.dark .ai-chat-contact-card__responsibility-tag{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9)}.ai-chat-contact-card__responsibility-more{color:rgba(0,0,0,.5);font-size:11px;padding:3px 4px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-more,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-more,.chakra-ui-dark .ai-chat-contact-card__responsibility-more,.dark .ai-chat-contact-card__responsibility-more,[data-theme=dark] .ai-chat-contact-card__responsibility-more,html.dark .ai-chat-contact-card__responsibility-more{color:hsla(0,0%,100%,.5)}.ai-chat-contact-card__actions{display:flex;gap:8px;padding:0 12px 12px}.ai-chat-contact-card--compact .ai-chat-contact-card__actions{gap:6px;padding:0 10px 10px}.ai-chat-contact-card__button{align-items:center;border:none;border-radius:9999px;cursor:pointer;display:flex;font-size:14px;font-weight:600;gap:8px;justify-content:center;padding:12px 20px;transition:all .15s ease;white-space:nowrap}.ai-chat-contact-card--compact .ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card__button:hover{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-contact-card__button:active{transform:translateY(0)}.ai-chat-contact-card__button--primary{background:var(--action-accent,#3b82f6);color:#fff;flex:1}.ai-chat-contact-card__button--primary:hover{background:color-mix(in srgb,var(--action-accent,#3b82f6) 90%,#000)}.ai-chat-contact-card__button--secondary{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-primary,#18181b);flex:1}.ai-chat-contact-card__button--secondary:hover{background:var(--bg-hover,#e4e4e7)}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary,.chakra-ui-dark .ai-chat-contact-card__button--secondary,.dark .ai-chat-contact-card__button--secondary,[data-theme=dark] .ai-chat-contact-card__button--secondary{background:hsla(0,0%,100%,.1);border-color:hsla(0,0%,100%,.15);color:#fff}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary:hover,.chakra-ui-dark .ai-chat-contact-card__button--secondary:hover,.dark .ai-chat-contact-card__button--secondary:hover,[data-theme=dark] .ai-chat-contact-card__button--secondary:hover{background:hsla(0,0%,100%,.15)}.ai-chat-contact-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-contact-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:2px;margin-top:8px;padding:0 4px}.ai-chat-contact-card-list__stack{display:grid;gap:12px;grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:900px){.ai-chat-contact-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:600px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr}}.ai-chat-contact-card-list__stack--widget{grid-template-columns:1fr}@container (min-width: 380px){.ai-chat-contact-card-list__stack--widget{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:520px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr!important}.ai-chat-contact-card--horizontal{flex-direction:column}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{aspect-ratio:3/2;height:auto;min-width:100%;width:100%}}.ai-chat-contact-card__initials{align-items:center;display:flex;font-size:48px;font-weight:600;height:100%;justify-content:center;letter-spacing:.05em;text-transform:uppercase;width:100%}.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:32px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__initials{font-size:28px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:22px}.ai-chat-form-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin:6px 0;overflow:hidden;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-form-card,.chakra-ui-dark .ai-chat-form-card,.dark .ai-chat-form-card,[data-theme=dark] .ai-chat-form-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-form-card--empty,.ai-chat-form-card--error,.ai-chat-form-card--skipped,.ai-chat-form-card--submitted{padding:12px 16px}.ai-chat-form-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-form-card__icon{font-size:18px}.ai-chat-form-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-form-card__title,.chakra-ui-dark .ai-chat-form-card__title,.dark .ai-chat-form-card__title,[data-theme=dark] .ai-chat-form-card__title{color:#fff}.ai-chat-form-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 12px}.ai-chat-form-card__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:0 0 12px}.ai-chat-form-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__error,.chakra-ui-dark .ai-chat-form-card__error,.dark .ai-chat-form-card__error,[data-theme=dark] .ai-chat-form-card__error{color:#fca5a5}.ai-chat-form-card__success{color:#16a34a;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__success,.chakra-ui-dark .ai-chat-form-card__success,.dark .ai-chat-form-card__success,[data-theme=dark] .ai-chat-form-card__success{color:#4ade80}.ai-chat-form-card__empty-text,.ai-chat-form-card__skipped-text{color:var(--text-muted,#71717a);font-size:13px;margin:0}.ai-chat-form-card__progress{align-items:center;display:flex;gap:12px;margin-bottom:16px}.ai-chat-form-card__progress-bar{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:2px;flex:1;height:4px;transition:width .3s ease}.ai-chat-form-card__progress-text{color:var(--text-muted,#71717a);font-size:12px;white-space:nowrap}.ai-chat-form-card__question{margin-bottom:16px}.ai-chat-form-card__question-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;line-height:1.4;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-form-card__question-text,.chakra-ui-dark .ai-chat-form-card__question-text,.dark .ai-chat-form-card__question-text,[data-theme=dark] .ai-chat-form-card__question-text{color:#fff}.ai-chat-form-card__required{color:#dc2626;margin-left:2px}.ai-chat-form-card__answer{margin-top:8px}.ai-chat-form-card__textarea{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;min-height:80px;outline:none;padding:10px 12px;resize:vertical;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-form-card__textarea::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-form-card__textarea,.chakra-ui-dark .ai-chat-form-card__textarea,.dark .ai-chat-form-card__textarea,[data-theme=dark] .ai-chat-form-card__textarea{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__textarea:focus,.chakra-ui-dark .ai-chat-form-card__textarea:focus,.dark .ai-chat-form-card__textarea:focus,[data-theme=dark] .ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-form-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-form-card__option{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);cursor:pointer;display:flex;gap:10px;padding:10px 12px;transition:border-color .15s,background .15s}.ai-chat-form-card__option:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__option,.chakra-ui-dark .ai-chat-form-card__option,.dark .ai-chat-form-card__option,[data-theme=dark] .ai-chat-form-card__option{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-form-card__option:hover,.chakra-ui-dark .ai-chat-form-card__option:hover,.dark .ai-chat-form-card__option:hover,[data-theme=dark] .ai-chat-form-card__option:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__option input{accent-color:var(--action-accent,var(--primary-color,#3b82f6));margin:0}.ai-chat-form-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px}.ai-chat-widget.dark .ai-chat-form-card__option-text,.chakra-ui-dark .ai-chat-form-card__option-text,.dark .ai-chat-form-card__option-text,[data-theme=dark] .ai-chat-form-card__option-text{color:#fff}.ai-chat-form-card__rating{display:flex;flex-wrap:wrap;gap:8px}.ai-chat-form-card__rating-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;display:flex;font-size:14px;font-weight:500;height:40px;justify-content:center;transition:all .15s ease;width:40px}.ai-chat-form-card__rating-btn--selected,.ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn,.chakra-ui-dark .ai-chat-form-card__rating-btn,.dark .ai-chat-form-card__rating-btn,[data-theme=dark] .ai-chat-form-card__rating-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn:hover,.chakra-ui-dark .ai-chat-form-card__rating-btn:hover,.dark .ai-chat-form-card__rating-btn:hover,[data-theme=dark] .ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__rating-btn--selected,.chakra-ui-dark .ai-chat-form-card__rating-btn--selected,.dark .ai-chat-form-card__rating-btn--selected,[data-theme=dark] .ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__actions{align-items:center;border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));display:flex;gap:8px;margin-top:16px;padding-top:16px}.ai-chat-widget.dark .ai-chat-form-card__actions,.chakra-ui-dark .ai-chat-form-card__actions,.dark .ai-chat-form-card__actions,[data-theme=dark] .ai-chat-form-card__actions{border-color:hsla(0,0%,100%,.08)}.ai-chat-form-card__actions-spacer{flex:1}.ai-chat-form-card__btn{border:none;border-radius:9999px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:8px 16px;transition:all .2s ease}.ai-chat-form-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-form-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-form-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-form-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__btn--secondary,.chakra-ui-dark .ai-chat-form-card__btn--secondary,.dark .ai-chat-form-card__btn--secondary,[data-theme=dark] .ai-chat-form-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-form-card__btn--ghost{background:transparent;color:var(--text-muted,#71717a)}.ai-chat-form-card__btn--ghost:hover:not(:disabled){background:rgba(0,0,0,.05);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.chakra-ui-dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),[data-theme=dark] .ai-chat-form-card__btn--ghost:hover:not(:disabled){background:hsla(0,0%,100%,.05);color:#fff}.chat-fullpage{--fp-max-width:800px;--fp-padding-x:16px;--fp-padding-top-mobile:64px;--fp-padding-top-desktop:16px;--fp-padding-bottom:200px;--fp-input-bottom:0}.chat-fullpage .ai-chat-messages{background:transparent;height:100%;margin:0 auto;max-width:var(--fp-max-width);padding:var(--fp-padding-top-desktop) var(--fp-padding-x) var(--fp-padding-bottom)}@media (max-width:768px){.chat-fullpage .ai-chat-messages{padding-top:var(--fp-padding-top-mobile)}}.chat-fullpage .ai-chat-message{animation:none}.chat-fullpage .ai-chat-message.user{max-width:85%}.chat-fullpage .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#f4f4f5);border-radius:24px;color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#27272a);color:#fff}.chat-fullpage .ai-chat-message.assistant{width:100%}.chat-fullpage .ai-chat-message.assistant .ai-chat-message-content{color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.assistant .ai-chat-message-content{color:#fff}.chat-fullpage .ai-chat-message.tool{margin:0;padding:0;width:100%}.chat-fullpage .ai-chat-welcome{align-items:center;display:flex;flex-direction:column;gap:24px;justify-content:center;min-height:60vh;padding:24px;text-align:center}.chat-fullpage .ai-chat-welcome-title{font-size:32px;font-weight:600}.chat-fullpage .ai-chat-welcome-text{color:var(--text-muted,#71717a);font-size:18px;max-width:400px}.chat-fullpage .ai-chat-input-container{background:transparent;bottom:0;left:0;padding:16px 16px calc(16px + env(safe-area-inset-bottom));position:fixed;right:0;z-index:20}.chat-fullpage .ai-chat-input-container:after{background:var(--bg-primary,#fff);bottom:0;content:\"\";height:calc(40% + 16px);left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.chat-fullpage.dark .ai-chat-input-container:after{background:var(--bg-primary,#18181b)}@media (min-width:769px){.chat-fullpage .ai-chat-input-container{background:transparent;bottom:var(--fp-input-bottom);left:50%;max-width:var(--fp-max-width);padding:0;position:absolute;right:auto;transform:translateX(-50%);width:100%}}.chat-fullpage .ai-chat-input-wrapper{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-muted,#e4e4e7);border-radius:24px;box-shadow:0 1px 8px rgba(0,0,0,.06);margin:0 auto;max-width:var(--fp-max-width)}.chat-fullpage.dark .ai-chat-input-wrapper{background:var(--bg-muted,#27272a);border-color:var(--border-muted,#3f3f46);box-shadow:0 1px 12px rgba(0,0,0,.25)}.chat-fullpage .ai-chat-scroll-button{bottom:100px}@media (min-width:769px){.chat-fullpage .ai-chat-scroll-button{bottom:90px}}.chat-fullpage .ai-chat-suggested-questions{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:600px}.chat-fullpage .ai-chat-suggested-question{border-radius:9999px;font-size:14px;padding:8px 16px}.chat-fullpage .ai-chat-follow-up-suggestions{margin-top:12px}.chat-fullpage .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:#000}.chat-fullpage .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5)}.chat-fullpage.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:#fff}.chat-fullpage.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46)}.chat-fullpage .ai-chat-typing{padding:8px 16px}@media (max-width:480px){body.ai-chat-widget-open{height:100%!important;overflow:hidden!important;position:fixed!important;touch-action:none!important;width:100%!important}.ai-chat-widget-container.is-open{height:100vh!important;height:100dvh!important;width:100vw!important;z-index:var(--widget-z-index,2147483647)!important}.ai-chat-widget-container.is-open,.ai-chat-widget-container.is-open .ai-chat-window{bottom:0!important;left:0!important;position:fixed!important;right:0!important;top:0!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;height:100%!important;max-height:100%!important;max-width:100%!important;outline:none!important;transform:none!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;pointer-events:none!important;visibility:hidden!important}.ai-chat-widget-container.is-open .ai-chat-header{border-radius:0!important;flex-shrink:0;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));padding-top:max(12px,env(safe-area-inset-top));position:relative;z-index:100}.ai-chat-widget-container.is-open .ai-chat-messages{-webkit-overflow-scrolling:touch;flex:1;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding-bottom:120px;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));touch-action:pan-y}.ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0!important;left:0!important;padding:8px max(12px,env(safe-area-inset-right)) max(16px,calc(env(safe-area-inset-bottom) + 8px)) max(12px,env(safe-area-inset-left));position:fixed!important;right:0!important;z-index:100}.ai-chat-widget.dark .ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-widget-container.is-open .ai-chat-input-container:after{display:none}.ai-chat-widget-container.is-open .ai-chat-input-wrapper{margin:0;max-width:100%}.ai-chat-widget-container.is-open .ai-chat-scroll-button{bottom:calc(80px + env(safe-area-inset-bottom))}.ai-chat-widget-container.is-open .ai-chat-welcome{padding:16px 0}.ai-chat-widget-container.is-open .ai-chat-welcome-title{font-size:24px}.ai-chat-widget-container.is-open .ai-chat-suggested-questions{align-items:stretch;flex-direction:column}.ai-chat-widget-container.is-open .ai-chat-suggested-question{text-align:center;width:100%}}@media (min-width:481px) and (max-width:768px){.ai-chat-widget-container.is-open .ai-chat-window{border-radius:22px 22px 44px 44px;max-height:calc(100vh - 100px);max-width:calc(100vw - 32px)}}";
|
|
47095
|
+
styleInject(css_248z$1);
|
|
47096
|
+
|
|
47097
|
+
var css_248z = ".ai-chat-data-policy-view{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.ai-chat-data-policy-content{-webkit-overflow-scrolling:touch;flex:1;overflow-y:auto;padding:20px 16px 40px}.ai-chat-data-policy-intro{align-items:center;background:var(--bg-subtle,rgba(0,0,0,.02));border-radius:12px;display:flex;flex-direction:column;margin-bottom:20px;padding:16px;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy-intro{background:var(--bg-subtle,hsla(0,0%,100%,.04))}.ai-chat-data-policy-icon{align-items:center;background:var(--primary-color,#07f);border-radius:12px;color:#fff;display:flex;height:48px;justify-content:center;margin-bottom:12px;width:48px}.ai-chat-data-policy-intro p{color:var(--text-secondary,#52525b);font-size:13px;line-height:1.5;margin:0}.ai-chat-widget.dark .ai-chat-data-policy-intro p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-intro strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-intro strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section{margin-bottom:20px}.ai-chat-data-policy-section h3{color:var(--text-primary,#18181b);font-size:13px;font-weight:600;letter-spacing:.02em;margin:0 0 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section ul{list-style:none;margin:0;padding:0}.ai-chat-data-policy-section li{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.5;padding:8px 0 8px 16px;position:relative}.ai-chat-widget.dark .ai-chat-data-policy-section li{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-section li:before{background:var(--text-muted,#a1a1aa);border-radius:50%;content:\"\";height:4px;left:0;position:absolute;top:14px;width:4px}.ai-chat-data-policy-section li strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-section li strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.5;margin:0}.ai-chat-widget.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-warning{background:rgba(234,179,8,.1);border:1px solid rgba(234,179,8,.3);border-radius:8px;color:#92400e!important;padding:12px}.ai-chat-widget.dark .ai-chat-data-policy-warning{background:rgba(234,179,8,.15);border-color:rgba(234,179,8,.25);color:#fbbf24!important}";
|
|
45931
47098
|
styleInject(css_248z);
|
|
45932
47099
|
|
|
45933
47100
|
// Icon components mapping
|
|
@@ -45935,9 +47102,10 @@
|
|
|
45935
47102
|
FiMessageCircle: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) })),
|
|
45936
47103
|
FiChevronDown: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) })),
|
|
45937
47104
|
};
|
|
45938
|
-
const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
|
|
47105
|
+
const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
|
|
45939
47106
|
const [isOpen, setIsOpen] = reactExports.useState(defaultOpen);
|
|
45940
47107
|
const [autoDetectedTheme, setAutoDetectedTheme] = reactExports.useState('light');
|
|
47108
|
+
const [showWelcomeBubble, setShowWelcomeBubble] = reactExports.useState(false);
|
|
45941
47109
|
const widgetRef = reactExports.useRef(null);
|
|
45942
47110
|
const containerRef = reactExports.useRef(null);
|
|
45943
47111
|
// Determine mode
|
|
@@ -45959,10 +47127,9 @@
|
|
|
45959
47127
|
showChatHistory: true,
|
|
45960
47128
|
showTimestamps: true,
|
|
45961
47129
|
showTypingIndicator: true,
|
|
47130
|
+
showToolCalls: false,
|
|
45962
47131
|
enableFileUpload: false,
|
|
45963
47132
|
enableFeedback: true,
|
|
45964
|
-
showSources: false,
|
|
45965
|
-
sourceDisplayMode: 'none',
|
|
45966
47133
|
},
|
|
45967
47134
|
behavior: {
|
|
45968
47135
|
agentic: false,
|
|
@@ -45999,7 +47166,6 @@
|
|
|
45999
47166
|
const messages = previewMode ? [] : chatHook.messages;
|
|
46000
47167
|
const isLoading = previewMode ? false : chatHook.isLoading;
|
|
46001
47168
|
const isTyping = previewMode ? false : chatHook.isTyping;
|
|
46002
|
-
const error = previewMode ? null : chatHook.error;
|
|
46003
47169
|
const config = previewMode ? mergedPreviewConfig : chatHook.config;
|
|
46004
47170
|
const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
|
|
46005
47171
|
const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
|
|
@@ -46034,8 +47200,13 @@
|
|
|
46034
47200
|
mediaQuery.removeEventListener('change', handleMediaChange);
|
|
46035
47201
|
};
|
|
46036
47202
|
}, [config]);
|
|
46037
|
-
//
|
|
47203
|
+
// Check if device is mobile
|
|
47204
|
+
const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
|
|
47205
|
+
// Handle auto-open (only for bubble mode, disabled on mobile)
|
|
46038
47206
|
reactExports.useEffect(() => {
|
|
47207
|
+
// Never auto-open on mobile devices
|
|
47208
|
+
if (isMobile)
|
|
47209
|
+
return undefined;
|
|
46039
47210
|
if (!isEmbedded && config?.settings.autoOpen) {
|
|
46040
47211
|
const delay = config.settings.autoOpenDelay || 0;
|
|
46041
47212
|
const timer = setTimeout(() => {
|
|
@@ -46045,7 +47216,7 @@
|
|
|
46045
47216
|
return () => clearTimeout(timer);
|
|
46046
47217
|
}
|
|
46047
47218
|
return undefined;
|
|
46048
|
-
}, [config, onOpen, isEmbedded]);
|
|
47219
|
+
}, [config, onOpen, isEmbedded, isMobile]);
|
|
46049
47220
|
// Handle close on Escape key (only for bubble mode)
|
|
46050
47221
|
reactExports.useEffect(() => {
|
|
46051
47222
|
if (!isOpen || isEmbedded)
|
|
@@ -46059,6 +47230,37 @@
|
|
|
46059
47230
|
document.addEventListener('keydown', handleEscapeKey);
|
|
46060
47231
|
return () => document.removeEventListener('keydown', handleEscapeKey);
|
|
46061
47232
|
}, [isOpen, onClose, isEmbedded]);
|
|
47233
|
+
// Handle body scroll lock on mobile when widget is open
|
|
47234
|
+
reactExports.useEffect(() => {
|
|
47235
|
+
if (!isOpen || isEmbedded)
|
|
47236
|
+
return;
|
|
47237
|
+
// Only apply scroll lock on mobile
|
|
47238
|
+
const checkMobile = window.innerWidth <= 480;
|
|
47239
|
+
if (!checkMobile)
|
|
47240
|
+
return;
|
|
47241
|
+
// Add class to body to lock scrolling
|
|
47242
|
+
document.body.classList.add('ai-chat-widget-open');
|
|
47243
|
+
return () => {
|
|
47244
|
+
document.body.classList.remove('ai-chat-widget-open');
|
|
47245
|
+
};
|
|
47246
|
+
}, [isOpen, isEmbedded]);
|
|
47247
|
+
// Handle welcome bubble visibility per session
|
|
47248
|
+
// Shows on each new session if welcomeBubbleText is configured
|
|
47249
|
+
reactExports.useEffect(() => {
|
|
47250
|
+
if (isEmbedded || previewMode)
|
|
47251
|
+
return;
|
|
47252
|
+
const bubbleText = welcomeBubbleText ?? config?.appearance?.welcomeBubbleText;
|
|
47253
|
+
if (!bubbleText) {
|
|
47254
|
+
setShowWelcomeBubble(false);
|
|
47255
|
+
return;
|
|
47256
|
+
}
|
|
47257
|
+
// Check if bubble was already dismissed this session
|
|
47258
|
+
const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
|
|
47259
|
+
const wasDismissed = sessionStorage.getItem(storageKey) === 'true';
|
|
47260
|
+
if (!wasDismissed && !isOpen) {
|
|
47261
|
+
setShowWelcomeBubble(true);
|
|
47262
|
+
}
|
|
47263
|
+
}, [widgetId, welcomeBubbleText, config, isOpen, isEmbedded, previewMode]);
|
|
46062
47264
|
// Determine theme - use prop override if provided, otherwise auto-detect
|
|
46063
47265
|
const appearanceConfig = config?.appearance;
|
|
46064
47266
|
const effectiveTheme = theme ?? autoDetectedTheme;
|
|
@@ -46072,6 +47274,7 @@
|
|
|
46072
47274
|
const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
|
|
46073
47275
|
const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
|
|
46074
47276
|
const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
|
|
47277
|
+
const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? '';
|
|
46075
47278
|
// Generate styles using simplified theme system
|
|
46076
47279
|
const simpleAppearance = {
|
|
46077
47280
|
accentColor};
|
|
@@ -46093,6 +47296,18 @@
|
|
|
46093
47296
|
return;
|
|
46094
47297
|
const newState = !isOpen;
|
|
46095
47298
|
setIsOpen(newState);
|
|
47299
|
+
// Dismiss welcome bubble when chat is opened
|
|
47300
|
+
if (newState && showWelcomeBubble) {
|
|
47301
|
+
setShowWelcomeBubble(false);
|
|
47302
|
+
// Store in sessionStorage so it doesn't show again this session
|
|
47303
|
+
const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
|
|
47304
|
+
try {
|
|
47305
|
+
sessionStorage.setItem(storageKey, 'true');
|
|
47306
|
+
}
|
|
47307
|
+
catch {
|
|
47308
|
+
// Ignore storage errors
|
|
47309
|
+
}
|
|
47310
|
+
}
|
|
46096
47311
|
if (newState) {
|
|
46097
47312
|
onOpen?.();
|
|
46098
47313
|
}
|
|
@@ -46123,13 +47338,13 @@
|
|
|
46123
47338
|
const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
|
|
46124
47339
|
// Embedded mode renders directly without wrapper positioning
|
|
46125
47340
|
if (isEmbedded) {
|
|
46126
|
-
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping,
|
|
47341
|
+
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: sendMessage, onClose: () => { }, onFeedback: handleFeedback, onActionClick: handleActionClick, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
|
|
46127
47342
|
}
|
|
46128
|
-
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping,
|
|
47343
|
+
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''} ${containerMode ? 'container-mode' : ''}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick,
|
|
46129
47344
|
// Chat history props (only active when persistConversation is true)
|
|
46130
47345
|
conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId,
|
|
46131
47346
|
// Override props for live preview
|
|
46132
|
-
headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] }) }));
|
|
47347
|
+
headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), !isOpen && effectiveWelcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-bubble", onClick: handleToggle, children: jsxRuntimeExports.jsx("span", { children: effectiveWelcomeBubbleText }) })), jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] }) }));
|
|
46133
47348
|
};
|
|
46134
47349
|
|
|
46135
47350
|
/**
|