@optifye/dashboard-core 6.10.17 → 6.10.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +2051 -79
- package/dist/index.mjs +2053 -82
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -58070,6 +58070,2056 @@ var ImprovementCenterView = () => {
|
|
|
58070
58070
|
] });
|
|
58071
58071
|
};
|
|
58072
58072
|
var ImprovementCenterView_default = ImprovementCenterView;
|
|
58073
|
+
var ThreadSidebar = ({
|
|
58074
|
+
activeThreadId,
|
|
58075
|
+
onSelectThread,
|
|
58076
|
+
onNewThread,
|
|
58077
|
+
className = ""
|
|
58078
|
+
}) => {
|
|
58079
|
+
const { threads, isLoading, error, deleteThread: deleteThread2 } = useThreads();
|
|
58080
|
+
const [deletingId, setDeletingId] = React24.useState(null);
|
|
58081
|
+
const handleDelete = async (e, threadId) => {
|
|
58082
|
+
e.stopPropagation();
|
|
58083
|
+
if (confirm("Are you sure you want to delete this conversation?")) {
|
|
58084
|
+
setDeletingId(threadId);
|
|
58085
|
+
try {
|
|
58086
|
+
await deleteThread2(threadId);
|
|
58087
|
+
if (activeThreadId === threadId) {
|
|
58088
|
+
onNewThread();
|
|
58089
|
+
}
|
|
58090
|
+
} catch (error2) {
|
|
58091
|
+
console.error("Error deleting thread:", error2);
|
|
58092
|
+
alert("Failed to delete conversation. Please try again.");
|
|
58093
|
+
} finally {
|
|
58094
|
+
setDeletingId(null);
|
|
58095
|
+
}
|
|
58096
|
+
}
|
|
58097
|
+
};
|
|
58098
|
+
const formatDate2 = (dateString) => {
|
|
58099
|
+
const date = new Date(dateString);
|
|
58100
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
58101
|
+
const diffMs = now2.getTime() - date.getTime();
|
|
58102
|
+
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
58103
|
+
if (diffDays === 0) {
|
|
58104
|
+
return "Today";
|
|
58105
|
+
} else if (diffDays === 1) {
|
|
58106
|
+
return "Yesterday";
|
|
58107
|
+
} else if (diffDays < 7) {
|
|
58108
|
+
return date.toLocaleDateString("en-US", { weekday: "short" });
|
|
58109
|
+
} else {
|
|
58110
|
+
return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
58111
|
+
}
|
|
58112
|
+
};
|
|
58113
|
+
if (error) {
|
|
58114
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `p-4 text-red-600 text-sm ${className}`, children: "Failed to load conversations" });
|
|
58115
|
+
}
|
|
58116
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col h-screen bg-gray-50 border-r border-gray-200 ${className}`, children: [
|
|
58117
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 p-4 border-b border-gray-200", children: [
|
|
58118
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Chat History" }),
|
|
58119
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-1", children: "Your previous conversations" })
|
|
58120
|
+
] }),
|
|
58121
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto min-h-0", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "sm" }) }) : threads.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-gray-500 text-sm", children: "No conversations yet" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2", children: threads.map((thread) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58122
|
+
"div",
|
|
58123
|
+
{
|
|
58124
|
+
onClick: () => onSelectThread(thread.id),
|
|
58125
|
+
className: `group relative flex items-start gap-3 px-4 py-3 cursor-pointer transition-all ${activeThreadId === thread.id ? "bg-blue-50 border-l-4 border-blue-600 hover:bg-blue-100" : "hover:bg-gray-100 border-l-4 border-transparent"}`,
|
|
58126
|
+
children: [
|
|
58127
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: `w-4 h-4 mt-0.5 flex-shrink-0 ${activeThreadId === thread.id ? "text-blue-600" : "text-gray-400"}` }),
|
|
58128
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
58129
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: `text-sm font-medium truncate ${activeThreadId === thread.id ? "text-blue-900" : "text-gray-900"}`, children: thread.title || "Untitled Chat" }),
|
|
58130
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-xs mt-0.5 ${activeThreadId === thread.id ? "text-blue-700" : "text-gray-500"}`, children: formatDate2(thread.created_at) })
|
|
58131
|
+
] }),
|
|
58132
|
+
deletingId === thread.id ? /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
58133
|
+
"button",
|
|
58134
|
+
{
|
|
58135
|
+
onClick: (e) => handleDelete(e, thread.id),
|
|
58136
|
+
className: "flex-shrink-0 opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-200 rounded transition-all",
|
|
58137
|
+
title: "Delete conversation",
|
|
58138
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-3.5 h-3.5 text-gray-500" })
|
|
58139
|
+
}
|
|
58140
|
+
)
|
|
58141
|
+
]
|
|
58142
|
+
},
|
|
58143
|
+
thread.id
|
|
58144
|
+
)) }) }),
|
|
58145
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 p-4 border-t border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 text-center", children: [
|
|
58146
|
+
threads.length,
|
|
58147
|
+
" conversation",
|
|
58148
|
+
threads.length !== 1 ? "s" : ""
|
|
58149
|
+
] }) })
|
|
58150
|
+
] });
|
|
58151
|
+
};
|
|
58152
|
+
var ProfilePicture = React24__namespace.default.memo(({
|
|
58153
|
+
alt = "Axel",
|
|
58154
|
+
className = "",
|
|
58155
|
+
size = "md",
|
|
58156
|
+
animate = false
|
|
58157
|
+
}) => {
|
|
58158
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(AxelOrb, { size, animate }) });
|
|
58159
|
+
});
|
|
58160
|
+
ProfilePicture.displayName = "ProfilePicture";
|
|
58161
|
+
var GREETING_MESSAGES = [
|
|
58162
|
+
"How can I help you today?",
|
|
58163
|
+
"What would you like to know?",
|
|
58164
|
+
"Ready to optimize your operations?",
|
|
58165
|
+
"How can I assist you today?"
|
|
58166
|
+
];
|
|
58167
|
+
var getDailyGreeting = () => {
|
|
58168
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
58169
|
+
const startOfYear = new Date(now2.getFullYear(), 0, 0);
|
|
58170
|
+
const diff = now2.getTime() - startOfYear.getTime();
|
|
58171
|
+
const oneDay = 1e3 * 60 * 60 * 24;
|
|
58172
|
+
const dayOfYear = Math.floor(diff / oneDay);
|
|
58173
|
+
const index = dayOfYear % GREETING_MESSAGES.length;
|
|
58174
|
+
return GREETING_MESSAGES[index];
|
|
58175
|
+
};
|
|
58176
|
+
var AIAgentView = () => {
|
|
58177
|
+
const { navigate, pathname } = useNavigation();
|
|
58178
|
+
const config = useDashboardConfig();
|
|
58179
|
+
const entityConfig = useEntityConfig();
|
|
58180
|
+
const dateTimeConfig = useDateTimeConfig();
|
|
58181
|
+
const shiftConfig = useShiftConfig();
|
|
58182
|
+
const { formatNumber } = useFormatNumber();
|
|
58183
|
+
const [inputValue, setInputValue] = React24.useState("");
|
|
58184
|
+
const [loadingThreads, setLoadingThreads] = React24.useState(/* @__PURE__ */ new Set());
|
|
58185
|
+
const [lastError, setLastError] = React24.useState(null);
|
|
58186
|
+
const [copiedMessageId, setCopiedMessageId] = React24.useState(null);
|
|
58187
|
+
const [activeThreadId, setActiveThreadId] = React24.useState(void 0);
|
|
58188
|
+
const [isSidebarOpen, setIsSidebarOpen] = React24.useState(false);
|
|
58189
|
+
const [streamingStates, setStreamingStates] = React24.useState(/* @__PURE__ */ new Map());
|
|
58190
|
+
const [userId, setUserId] = React24.useState(null);
|
|
58191
|
+
const [pendingThreadId, setPendingThreadId] = React24.useState(null);
|
|
58192
|
+
const [isTransitioning, setIsTransitioning] = React24.useState(false);
|
|
58193
|
+
const [typedText, setTypedText] = React24.useState("");
|
|
58194
|
+
const [newChatCount, setNewChatCount] = React24.useState(0);
|
|
58195
|
+
const [greetingReset, setGreetingReset] = React24.useState(0);
|
|
58196
|
+
const [hasStartedTyping, setHasStartedTyping] = React24.useState(false);
|
|
58197
|
+
const [typingStartTime, setTypingStartTime] = React24.useState(null);
|
|
58198
|
+
const [lastTypingTime, setLastTypingTime] = React24.useState(null);
|
|
58199
|
+
const [characterCount, setCharacterCount] = React24.useState(0);
|
|
58200
|
+
const typingTimeoutRef = React24.useRef(null);
|
|
58201
|
+
const currentGreeting = React24.useMemo(() => getDailyGreeting(), [greetingReset]);
|
|
58202
|
+
const isThreadLoading = (threadId) => {
|
|
58203
|
+
return threadId ? loadingThreads.has(threadId) : false;
|
|
58204
|
+
};
|
|
58205
|
+
const getStreamingState = (threadId) => {
|
|
58206
|
+
return threadId ? streamingStates.get(threadId) || { message: "", reasoning: "" } : { message: "", reasoning: "" };
|
|
58207
|
+
};
|
|
58208
|
+
const trackTypingStart = () => {
|
|
58209
|
+
if (!hasStartedTyping) {
|
|
58210
|
+
const now2 = Date.now();
|
|
58211
|
+
setHasStartedTyping(true);
|
|
58212
|
+
setTypingStartTime(now2);
|
|
58213
|
+
setLastTypingTime(now2);
|
|
58214
|
+
trackCoreEvent("AI Agent Input Started", {
|
|
58215
|
+
line_id: lineId,
|
|
58216
|
+
company_id: companyId,
|
|
58217
|
+
shift_id: shiftId,
|
|
58218
|
+
active_thread_id: activeThreadId,
|
|
58219
|
+
has_existing_messages: messages.length > 0,
|
|
58220
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
58221
|
+
});
|
|
58222
|
+
}
|
|
58223
|
+
};
|
|
58224
|
+
const trackTypingProgress = (newValue) => {
|
|
58225
|
+
const now2 = Date.now();
|
|
58226
|
+
setLastTypingTime(now2);
|
|
58227
|
+
setCharacterCount(newValue.length);
|
|
58228
|
+
if (typingTimeoutRef.current) {
|
|
58229
|
+
clearTimeout(typingTimeoutRef.current);
|
|
58230
|
+
}
|
|
58231
|
+
typingTimeoutRef.current = setTimeout(() => {
|
|
58232
|
+
if (hasStartedTyping && typingStartTime && newValue.length > 0) {
|
|
58233
|
+
const typingDuration = now2 - typingStartTime;
|
|
58234
|
+
trackCoreEvent("AI Agent Input Typing Progress", {
|
|
58235
|
+
line_id: lineId,
|
|
58236
|
+
company_id: companyId,
|
|
58237
|
+
shift_id: shiftId,
|
|
58238
|
+
active_thread_id: activeThreadId,
|
|
58239
|
+
character_count: newValue.length,
|
|
58240
|
+
typing_duration_ms: typingDuration,
|
|
58241
|
+
has_existing_messages: messages.length > 0,
|
|
58242
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
58243
|
+
});
|
|
58244
|
+
}
|
|
58245
|
+
}, 2e3);
|
|
58246
|
+
};
|
|
58247
|
+
const trackMessageSent = (messageContent) => {
|
|
58248
|
+
if (hasStartedTyping && typingStartTime) {
|
|
58249
|
+
const now2 = Date.now();
|
|
58250
|
+
const totalTypingDuration = now2 - typingStartTime;
|
|
58251
|
+
trackCoreEvent("AI Agent Message Sent", {
|
|
58252
|
+
line_id: lineId,
|
|
58253
|
+
company_id: companyId,
|
|
58254
|
+
shift_id: shiftId,
|
|
58255
|
+
active_thread_id: activeThreadId,
|
|
58256
|
+
message_length: messageContent.length,
|
|
58257
|
+
character_count: messageContent.length,
|
|
58258
|
+
typing_duration_ms: totalTypingDuration,
|
|
58259
|
+
has_existing_messages: messages.length > 0,
|
|
58260
|
+
is_new_conversation: !activeThreadId,
|
|
58261
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
58262
|
+
});
|
|
58263
|
+
}
|
|
58264
|
+
resetTypingState();
|
|
58265
|
+
};
|
|
58266
|
+
const resetTypingState = () => {
|
|
58267
|
+
setHasStartedTyping(false);
|
|
58268
|
+
setTypingStartTime(null);
|
|
58269
|
+
setLastTypingTime(null);
|
|
58270
|
+
setCharacterCount(0);
|
|
58271
|
+
if (typingTimeoutRef.current) {
|
|
58272
|
+
clearTimeout(typingTimeoutRef.current);
|
|
58273
|
+
typingTimeoutRef.current = null;
|
|
58274
|
+
}
|
|
58275
|
+
};
|
|
58276
|
+
const textareaRef = React24.useRef(null);
|
|
58277
|
+
const messagesEndRef = React24.useRef(null);
|
|
58278
|
+
const containerRef = React24.useRef(null);
|
|
58279
|
+
const renderedContentCache = React24.useRef(/* @__PURE__ */ new Map());
|
|
58280
|
+
const { createThread, mutate: mutateThreads } = useThreads();
|
|
58281
|
+
const { messages, addMessage, setMessages } = useMessages(activeThreadId);
|
|
58282
|
+
const agnoApiUrl = config.endpoints?.agnoApiUrl || "https://fastapi-production-111f9.up.railway.app";
|
|
58283
|
+
const sseClient = React24.useMemo(() => {
|
|
58284
|
+
console.log("[AIAgentView] Using AGNO API URL:", agnoApiUrl);
|
|
58285
|
+
return new SSEChatClient(agnoApiUrl);
|
|
58286
|
+
}, [agnoApiUrl]);
|
|
58287
|
+
const getLineIdFromPath = () => {
|
|
58288
|
+
const pathParts = pathname.split("/");
|
|
58289
|
+
const lineIdIndex = pathParts.findIndex((part) => part === "ai-agent") + 1;
|
|
58290
|
+
if (lineIdIndex > 0 && lineIdIndex < pathParts.length) {
|
|
58291
|
+
return pathParts[lineIdIndex];
|
|
58292
|
+
}
|
|
58293
|
+
return entityConfig.defaultLineId || LINE_1_UUID;
|
|
58294
|
+
};
|
|
58295
|
+
const lineId = getLineIdFromPath();
|
|
58296
|
+
const { shiftId } = getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig);
|
|
58297
|
+
const companyId = entityConfig.companyId || "default-company-id";
|
|
58298
|
+
const configuredLineIds = getConfiguredLineIds(entityConfig);
|
|
58299
|
+
const lineDisplayNames = getAllLineDisplayNames(entityConfig);
|
|
58300
|
+
const allLines = configuredLineIds.map((id3) => ({
|
|
58301
|
+
id: id3,
|
|
58302
|
+
name: lineDisplayNames[id3] || `Line ${id3.substring(0, 8)}`
|
|
58303
|
+
}));
|
|
58304
|
+
const ACTIVE_THREAD_STORAGE_KEY = `ai-agent-active-thread-${lineId}`;
|
|
58305
|
+
React24.useLayoutEffect(() => {
|
|
58306
|
+
const savedThreadId = localStorage.getItem(ACTIVE_THREAD_STORAGE_KEY);
|
|
58307
|
+
if (savedThreadId && savedThreadId !== "undefined") {
|
|
58308
|
+
setActiveThreadId(savedThreadId);
|
|
58309
|
+
}
|
|
58310
|
+
}, [ACTIVE_THREAD_STORAGE_KEY]);
|
|
58311
|
+
React24.useEffect(() => {
|
|
58312
|
+
if (activeThreadId) {
|
|
58313
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
58314
|
+
} else {
|
|
58315
|
+
localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
|
|
58316
|
+
}
|
|
58317
|
+
}, [activeThreadId, ACTIVE_THREAD_STORAGE_KEY]);
|
|
58318
|
+
React24.useEffect(() => {
|
|
58319
|
+
const handleVisibilityChange = () => {
|
|
58320
|
+
if (document.visibilityState === "hidden" && activeThreadId) {
|
|
58321
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
58322
|
+
}
|
|
58323
|
+
};
|
|
58324
|
+
const handleBeforeUnload = () => {
|
|
58325
|
+
if (activeThreadId) {
|
|
58326
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
58327
|
+
}
|
|
58328
|
+
};
|
|
58329
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
58330
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
58331
|
+
return () => {
|
|
58332
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
58333
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
58334
|
+
if (activeThreadId) {
|
|
58335
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
58336
|
+
}
|
|
58337
|
+
};
|
|
58338
|
+
}, [activeThreadId, ACTIVE_THREAD_STORAGE_KEY]);
|
|
58339
|
+
React24.useEffect(() => {
|
|
58340
|
+
if (textareaRef.current) {
|
|
58341
|
+
textareaRef.current.style.height = "auto";
|
|
58342
|
+
textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`;
|
|
58343
|
+
}
|
|
58344
|
+
}, [inputValue]);
|
|
58345
|
+
const scrollToBottom = () => {
|
|
58346
|
+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
58347
|
+
};
|
|
58348
|
+
React24.useEffect(() => {
|
|
58349
|
+
if (activeThreadId && messages.length > 0) {
|
|
58350
|
+
setTimeout(scrollToBottom, 100);
|
|
58351
|
+
}
|
|
58352
|
+
}, [activeThreadId]);
|
|
58353
|
+
React24.useEffect(() => {
|
|
58354
|
+
if (messages.length === 0 && !isTransitioning) {
|
|
58355
|
+
let index = 0;
|
|
58356
|
+
setTypedText("");
|
|
58357
|
+
const typeInterval = setInterval(() => {
|
|
58358
|
+
if (index < currentGreeting.length) {
|
|
58359
|
+
setTypedText(currentGreeting.substring(0, index + 1));
|
|
58360
|
+
index++;
|
|
58361
|
+
} else {
|
|
58362
|
+
clearInterval(typeInterval);
|
|
58363
|
+
}
|
|
58364
|
+
}, 50);
|
|
58365
|
+
return () => clearInterval(typeInterval);
|
|
58366
|
+
}
|
|
58367
|
+
}, [messages.length, isTransitioning, greetingReset, currentGreeting]);
|
|
58368
|
+
React24.useEffect(() => {
|
|
58369
|
+
if (isSidebarOpen) {
|
|
58370
|
+
setNewChatCount(0);
|
|
58371
|
+
}
|
|
58372
|
+
}, [isSidebarOpen]);
|
|
58373
|
+
const copyToClipboard = async (text, messageId) => {
|
|
58374
|
+
try {
|
|
58375
|
+
await navigator.clipboard.writeText(text);
|
|
58376
|
+
setCopiedMessageId(messageId);
|
|
58377
|
+
setTimeout(() => setCopiedMessageId(null), 2e3);
|
|
58378
|
+
} catch (err) {
|
|
58379
|
+
console.error("Failed to copy text: ", err);
|
|
58380
|
+
}
|
|
58381
|
+
};
|
|
58382
|
+
const handleNewThread = () => {
|
|
58383
|
+
setActiveThreadId(void 0);
|
|
58384
|
+
setMessages([]);
|
|
58385
|
+
setInputValue("");
|
|
58386
|
+
setPendingThreadId(null);
|
|
58387
|
+
setTypedText("");
|
|
58388
|
+
setGreetingReset((prev) => prev + 1);
|
|
58389
|
+
resetTypingState();
|
|
58390
|
+
localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
|
|
58391
|
+
textareaRef.current?.focus();
|
|
58392
|
+
};
|
|
58393
|
+
React24.useEffect(() => {
|
|
58394
|
+
return () => {
|
|
58395
|
+
if (typingTimeoutRef.current) {
|
|
58396
|
+
clearTimeout(typingTimeoutRef.current);
|
|
58397
|
+
}
|
|
58398
|
+
};
|
|
58399
|
+
}, []);
|
|
58400
|
+
React24.useEffect(() => {
|
|
58401
|
+
const checkAuth = async () => {
|
|
58402
|
+
const supabase2 = _getSupabaseInstance();
|
|
58403
|
+
const { data: { session } } = await supabase2.auth.getSession();
|
|
58404
|
+
if (session?.user) {
|
|
58405
|
+
setUserId(session.user.id);
|
|
58406
|
+
console.log("[AIAgentView] User authenticated:", session.user.id);
|
|
58407
|
+
} else {
|
|
58408
|
+
console.log("[AIAgentView] No authenticated session found");
|
|
58409
|
+
}
|
|
58410
|
+
};
|
|
58411
|
+
checkAuth();
|
|
58412
|
+
const supabase = _getSupabaseInstance();
|
|
58413
|
+
const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
|
|
58414
|
+
if (session?.user) {
|
|
58415
|
+
setUserId(session.user.id);
|
|
58416
|
+
} else {
|
|
58417
|
+
setUserId(null);
|
|
58418
|
+
}
|
|
58419
|
+
});
|
|
58420
|
+
return () => {
|
|
58421
|
+
subscription.unsubscribe();
|
|
58422
|
+
};
|
|
58423
|
+
}, []);
|
|
58424
|
+
const handleSubmit = async (e) => {
|
|
58425
|
+
e.preventDefault();
|
|
58426
|
+
if (!inputValue.trim() || !userId) return;
|
|
58427
|
+
let currentThreadId = activeThreadId || `temp-${Date.now()}`;
|
|
58428
|
+
if (isThreadLoading(currentThreadId)) return;
|
|
58429
|
+
const userMessage = inputValue.trim();
|
|
58430
|
+
trackMessageSent(userMessage);
|
|
58431
|
+
if (displayMessages.length === 0) {
|
|
58432
|
+
setIsTransitioning(true);
|
|
58433
|
+
setTimeout(() => {
|
|
58434
|
+
setIsTransitioning(false);
|
|
58435
|
+
}, 800);
|
|
58436
|
+
}
|
|
58437
|
+
setInputValue("");
|
|
58438
|
+
setLoadingThreads((prev) => new Set(prev).add(currentThreadId));
|
|
58439
|
+
setLastError(null);
|
|
58440
|
+
if (!activeThreadId) {
|
|
58441
|
+
setPendingThreadId(currentThreadId);
|
|
58442
|
+
}
|
|
58443
|
+
setStreamingStates((prev) => {
|
|
58444
|
+
const newMap = new Map(prev);
|
|
58445
|
+
newMap.set(currentThreadId, { message: "", reasoning: "" });
|
|
58446
|
+
return newMap;
|
|
58447
|
+
});
|
|
58448
|
+
const tempUserMessage = {
|
|
58449
|
+
id: Date.now(),
|
|
58450
|
+
// Temporary ID
|
|
58451
|
+
thread_id: activeThreadId || "",
|
|
58452
|
+
role: "user",
|
|
58453
|
+
content: userMessage,
|
|
58454
|
+
reasoning: null,
|
|
58455
|
+
model_id: null,
|
|
58456
|
+
token_usage: null,
|
|
58457
|
+
metadata: null,
|
|
58458
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
58459
|
+
position: messages.length
|
|
58460
|
+
};
|
|
58461
|
+
setMessages((prev) => [...prev, tempUserMessage]);
|
|
58462
|
+
setTimeout(scrollToBottom, 100);
|
|
58463
|
+
try {
|
|
58464
|
+
await sseClient.sendMessage(
|
|
58465
|
+
userMessage,
|
|
58466
|
+
userId,
|
|
58467
|
+
activeThreadId || null,
|
|
58468
|
+
{
|
|
58469
|
+
companyId,
|
|
58470
|
+
lineId,
|
|
58471
|
+
shiftId,
|
|
58472
|
+
allLines
|
|
58473
|
+
},
|
|
58474
|
+
{
|
|
58475
|
+
onThreadCreated: (threadId) => {
|
|
58476
|
+
if (!activeThreadId) {
|
|
58477
|
+
const oldThreadId = currentThreadId;
|
|
58478
|
+
currentThreadId = threadId;
|
|
58479
|
+
setActiveThreadId(threadId);
|
|
58480
|
+
setPendingThreadId(null);
|
|
58481
|
+
if (!isSidebarOpen) {
|
|
58482
|
+
setNewChatCount((prev) => prev + 1);
|
|
58483
|
+
}
|
|
58484
|
+
setLoadingThreads((prev) => {
|
|
58485
|
+
const newSet = new Set(prev);
|
|
58486
|
+
if (newSet.has(oldThreadId)) {
|
|
58487
|
+
newSet.delete(oldThreadId);
|
|
58488
|
+
newSet.add(threadId);
|
|
58489
|
+
}
|
|
58490
|
+
return newSet;
|
|
58491
|
+
});
|
|
58492
|
+
setStreamingStates((prev) => {
|
|
58493
|
+
const newMap = new Map(prev);
|
|
58494
|
+
const streamingState = newMap.get(oldThreadId);
|
|
58495
|
+
if (streamingState) {
|
|
58496
|
+
newMap.delete(oldThreadId);
|
|
58497
|
+
newMap.set(threadId, streamingState);
|
|
58498
|
+
}
|
|
58499
|
+
return newMap;
|
|
58500
|
+
});
|
|
58501
|
+
mutateThreads();
|
|
58502
|
+
}
|
|
58503
|
+
},
|
|
58504
|
+
onMessage: (text) => {
|
|
58505
|
+
setStreamingStates((prev) => {
|
|
58506
|
+
const newMap = new Map(prev);
|
|
58507
|
+
const current = newMap.get(currentThreadId) || { message: "", reasoning: "" };
|
|
58508
|
+
newMap.set(currentThreadId, { ...current, message: current.message + text });
|
|
58509
|
+
return newMap;
|
|
58510
|
+
});
|
|
58511
|
+
},
|
|
58512
|
+
onComplete: async (messageId) => {
|
|
58513
|
+
if (currentThreadId && !currentThreadId.startsWith("temp-")) {
|
|
58514
|
+
const updatedMessages = await getAllThreadMessages(currentThreadId);
|
|
58515
|
+
setMessages(updatedMessages);
|
|
58516
|
+
}
|
|
58517
|
+
setStreamingStates((prev) => {
|
|
58518
|
+
const newMap = new Map(prev);
|
|
58519
|
+
newMap.delete(currentThreadId);
|
|
58520
|
+
return newMap;
|
|
58521
|
+
});
|
|
58522
|
+
setLoadingThreads((prev) => {
|
|
58523
|
+
const newSet = new Set(prev);
|
|
58524
|
+
newSet.delete(currentThreadId);
|
|
58525
|
+
return newSet;
|
|
58526
|
+
});
|
|
58527
|
+
if (!activeThreadId) {
|
|
58528
|
+
setPendingThreadId(null);
|
|
58529
|
+
}
|
|
58530
|
+
},
|
|
58531
|
+
onError: (error) => {
|
|
58532
|
+
console.error("Chat error:", error);
|
|
58533
|
+
setLastError(error);
|
|
58534
|
+
setLoadingThreads((prev) => {
|
|
58535
|
+
const newSet = new Set(prev);
|
|
58536
|
+
newSet.delete(currentThreadId);
|
|
58537
|
+
return newSet;
|
|
58538
|
+
});
|
|
58539
|
+
setStreamingStates((prev) => {
|
|
58540
|
+
const newMap = new Map(prev);
|
|
58541
|
+
newMap.delete(currentThreadId);
|
|
58542
|
+
return newMap;
|
|
58543
|
+
});
|
|
58544
|
+
if (!activeThreadId) {
|
|
58545
|
+
setPendingThreadId(null);
|
|
58546
|
+
}
|
|
58547
|
+
setMessages((prev) => prev.slice(0, -1));
|
|
58548
|
+
}
|
|
58549
|
+
}
|
|
58550
|
+
);
|
|
58551
|
+
} catch (error) {
|
|
58552
|
+
console.error("[AIAgentView] Error in chat:", error);
|
|
58553
|
+
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
58554
|
+
setLastError(errorMessage);
|
|
58555
|
+
setLoadingThreads((prev) => {
|
|
58556
|
+
const newSet = new Set(prev);
|
|
58557
|
+
newSet.delete(currentThreadId);
|
|
58558
|
+
return newSet;
|
|
58559
|
+
});
|
|
58560
|
+
setStreamingStates((prev) => {
|
|
58561
|
+
const newMap = new Map(prev);
|
|
58562
|
+
newMap.delete(currentThreadId);
|
|
58563
|
+
return newMap;
|
|
58564
|
+
});
|
|
58565
|
+
if (!activeThreadId) {
|
|
58566
|
+
setPendingThreadId(null);
|
|
58567
|
+
}
|
|
58568
|
+
setMessages((prev) => prev.slice(0, -1));
|
|
58569
|
+
}
|
|
58570
|
+
};
|
|
58571
|
+
const handleKeyDown = (e) => {
|
|
58572
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
58573
|
+
e.preventDefault();
|
|
58574
|
+
if (!isCurrentThreadLoading) {
|
|
58575
|
+
handleSubmit(e);
|
|
58576
|
+
}
|
|
58577
|
+
}
|
|
58578
|
+
};
|
|
58579
|
+
const formatMessage = (content) => {
|
|
58580
|
+
const processInlineFormatting = (text) => {
|
|
58581
|
+
text = text.replace(/\*\*(.*?)\*\*/g, '<strong class="font-semibold text-gray-900">$1</strong>');
|
|
58582
|
+
text = text.replace(/`([^`]+)`/g, '<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono text-gray-800">$1</code>');
|
|
58583
|
+
return text;
|
|
58584
|
+
};
|
|
58585
|
+
const parseTableFromText = (lines2, startIndex) => {
|
|
58586
|
+
const tableLines = [];
|
|
58587
|
+
let i = startIndex;
|
|
58588
|
+
while (i < lines2.length) {
|
|
58589
|
+
const line = lines2[i].trim();
|
|
58590
|
+
if (!line) {
|
|
58591
|
+
i++;
|
|
58592
|
+
break;
|
|
58593
|
+
}
|
|
58594
|
+
if (line.includes("|") || line.match(/^[-|=\s]+$/)) {
|
|
58595
|
+
tableLines.push(line);
|
|
58596
|
+
i++;
|
|
58597
|
+
} else {
|
|
58598
|
+
break;
|
|
58599
|
+
}
|
|
58600
|
+
}
|
|
58601
|
+
if (tableLines.length === 0) return { html: "", endIndex: startIndex };
|
|
58602
|
+
const dataLines = tableLines.filter((line) => !line.match(/^[-|=\s]+$/));
|
|
58603
|
+
if (dataLines.length === 0) return { html: "", endIndex: i };
|
|
58604
|
+
let headerRow = [];
|
|
58605
|
+
let dataRows = [];
|
|
58606
|
+
const firstLine = dataLines[0];
|
|
58607
|
+
if (firstLine.includes("|")) {
|
|
58608
|
+
const cells = firstLine.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
58609
|
+
if (cells.length >= 2) {
|
|
58610
|
+
headerRow = cells;
|
|
58611
|
+
for (let j = 1; j < dataLines.length; j++) {
|
|
58612
|
+
const row = dataLines[j];
|
|
58613
|
+
if (row.includes("|")) {
|
|
58614
|
+
const rowCells = row.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
58615
|
+
while (rowCells.length < headerRow.length) rowCells.push("");
|
|
58616
|
+
if (rowCells.length > headerRow.length) rowCells.splice(headerRow.length);
|
|
58617
|
+
dataRows.push(rowCells);
|
|
58618
|
+
}
|
|
58619
|
+
}
|
|
58620
|
+
}
|
|
58621
|
+
}
|
|
58622
|
+
if (headerRow.length === 0) {
|
|
58623
|
+
for (const line of dataLines) {
|
|
58624
|
+
if (line.includes("|")) {
|
|
58625
|
+
const rowCells = line.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
58626
|
+
if (rowCells.length >= 2) {
|
|
58627
|
+
dataRows.push(rowCells);
|
|
58628
|
+
}
|
|
58629
|
+
}
|
|
58630
|
+
}
|
|
58631
|
+
if (dataRows.length > 0 && dataRows[0].length > 0) {
|
|
58632
|
+
headerRow = dataRows[0].map((_, index) => `Column ${index + 1}`);
|
|
58633
|
+
}
|
|
58634
|
+
}
|
|
58635
|
+
if (headerRow.length > 0 && dataRows.length > 0) {
|
|
58636
|
+
let tableHtml = '<div class="overflow-x-auto my-4"><table class="min-w-full border-collapse border border-gray-300 rounded-lg shadow-sm">';
|
|
58637
|
+
tableHtml += '<thead class="bg-gray-50">';
|
|
58638
|
+
tableHtml += "<tr>";
|
|
58639
|
+
headerRow.forEach((header) => {
|
|
58640
|
+
tableHtml += `<th class="border border-gray-300 px-4 py-2 text-left font-semibold text-gray-900">${processInlineFormatting(header)}</th>`;
|
|
58641
|
+
});
|
|
58642
|
+
tableHtml += "</tr>";
|
|
58643
|
+
tableHtml += "</thead>";
|
|
58644
|
+
tableHtml += '<tbody class="bg-white divide-y divide-gray-200">';
|
|
58645
|
+
dataRows.forEach((row, rowIndex) => {
|
|
58646
|
+
tableHtml += `<tr class="${rowIndex % 2 === 0 ? "bg-white" : "bg-gray-50"}">`;
|
|
58647
|
+
row.forEach((cell) => {
|
|
58648
|
+
tableHtml += `<td class="border border-gray-300 px-4 py-2 text-gray-800">${processInlineFormatting(cell)}</td>`;
|
|
58649
|
+
});
|
|
58650
|
+
tableHtml += "</tr>";
|
|
58651
|
+
});
|
|
58652
|
+
tableHtml += "</tbody>";
|
|
58653
|
+
tableHtml += "</table></div>";
|
|
58654
|
+
return { html: tableHtml, endIndex: i };
|
|
58655
|
+
}
|
|
58656
|
+
return { html: "", endIndex: startIndex };
|
|
58657
|
+
};
|
|
58658
|
+
const processedContent = content;
|
|
58659
|
+
const lines = processedContent.split("\n");
|
|
58660
|
+
const formattedLines = [];
|
|
58661
|
+
let inList = false;
|
|
58662
|
+
for (let i = 0; i < lines.length; i++) {
|
|
58663
|
+
let line = lines[i];
|
|
58664
|
+
const trimmedLine = line.trim();
|
|
58665
|
+
if (!trimmedLine) {
|
|
58666
|
+
if (inList) {
|
|
58667
|
+
formattedLines.push("</ul>");
|
|
58668
|
+
inList = false;
|
|
58669
|
+
}
|
|
58670
|
+
formattedLines.push("<br/>");
|
|
58671
|
+
continue;
|
|
58672
|
+
}
|
|
58673
|
+
if (trimmedLine.includes("|") && (trimmedLine.match(/\|/g) || []).length >= 1) {
|
|
58674
|
+
if (inList) {
|
|
58675
|
+
formattedLines.push("</ul>");
|
|
58676
|
+
inList = false;
|
|
58677
|
+
}
|
|
58678
|
+
const tableResult = parseTableFromText(lines, i);
|
|
58679
|
+
if (tableResult.html) {
|
|
58680
|
+
formattedLines.push(tableResult.html);
|
|
58681
|
+
i = tableResult.endIndex - 1;
|
|
58682
|
+
continue;
|
|
58683
|
+
}
|
|
58684
|
+
}
|
|
58685
|
+
if (trimmedLine.startsWith("###")) {
|
|
58686
|
+
if (inList) {
|
|
58687
|
+
formattedLines.push("</ul>");
|
|
58688
|
+
inList = false;
|
|
58689
|
+
}
|
|
58690
|
+
const headerText = processInlineFormatting(trimmedLine.replace(/^###\s*/, ""));
|
|
58691
|
+
formattedLines.push(`<h3 class="text-lg font-semibold text-gray-900 mt-4 mb-2">${headerText}</h3>`);
|
|
58692
|
+
continue;
|
|
58693
|
+
} else if (trimmedLine.startsWith("##")) {
|
|
58694
|
+
if (inList) {
|
|
58695
|
+
formattedLines.push("</ul>");
|
|
58696
|
+
inList = false;
|
|
58697
|
+
}
|
|
58698
|
+
const headerText = processInlineFormatting(trimmedLine.replace(/^##\s*/, ""));
|
|
58699
|
+
formattedLines.push(`<h2 class="text-xl font-semibold text-gray-900 mt-4 mb-2">${headerText}</h2>`);
|
|
58700
|
+
continue;
|
|
58701
|
+
} else if (trimmedLine.startsWith("#")) {
|
|
58702
|
+
if (inList) {
|
|
58703
|
+
formattedLines.push("</ul>");
|
|
58704
|
+
inList = false;
|
|
58705
|
+
}
|
|
58706
|
+
const headerText = processInlineFormatting(trimmedLine.replace(/^#\s*/, ""));
|
|
58707
|
+
formattedLines.push(`<h1 class="text-3xl font-semibold text-gray-900 mt-4 mb-3">${headerText}</h1>`);
|
|
58708
|
+
continue;
|
|
58709
|
+
}
|
|
58710
|
+
const listMatch = trimmedLine.match(/^([-*•]\s+|\d+\.\s+|^\s*[-*•]\s+)/);
|
|
58711
|
+
if (listMatch) {
|
|
58712
|
+
if (!inList) {
|
|
58713
|
+
formattedLines.push('<ul class="space-y-1 mt-2 mb-2">');
|
|
58714
|
+
inList = true;
|
|
58715
|
+
}
|
|
58716
|
+
const listContent = processInlineFormatting(trimmedLine.replace(/^([-*•]\s+|\d+\.\s+|\s*[-*•]\s+)/, ""));
|
|
58717
|
+
formattedLines.push(`<li class="ml-4 text-gray-700 flex items-start"><span class="mr-2 text-gray-500">\u2022</span><span>${listContent}</span></li>`);
|
|
58718
|
+
continue;
|
|
58719
|
+
} else if (inList) {
|
|
58720
|
+
formattedLines.push("</ul>");
|
|
58721
|
+
inList = false;
|
|
58722
|
+
}
|
|
58723
|
+
if (trimmedLine.match(/^---+$/)) {
|
|
58724
|
+
formattedLines.push('<hr class="my-4 border-gray-200"/>');
|
|
58725
|
+
continue;
|
|
58726
|
+
}
|
|
58727
|
+
if (trimmedLine) {
|
|
58728
|
+
const processedLine = processInlineFormatting(line);
|
|
58729
|
+
if (trimmedLine.endsWith(":") && trimmedLine.length < 50 && !trimmedLine.includes("**")) {
|
|
58730
|
+
formattedLines.push(`<h3 class="text-lg font-semibold text-gray-900 mt-4 mb-2">${processedLine}</h3>`);
|
|
58731
|
+
} else {
|
|
58732
|
+
formattedLines.push(`<p class="text-gray-800 leading-relaxed mb-2">${processedLine}</p>`);
|
|
58733
|
+
}
|
|
58734
|
+
}
|
|
58735
|
+
}
|
|
58736
|
+
if (inList) {
|
|
58737
|
+
formattedLines.push("</ul>");
|
|
58738
|
+
}
|
|
58739
|
+
return formattedLines.join("");
|
|
58740
|
+
};
|
|
58741
|
+
const formatTime5 = (timestamp) => {
|
|
58742
|
+
const date = new Date(timestamp);
|
|
58743
|
+
return date.toLocaleTimeString([], {
|
|
58744
|
+
hour: "2-digit",
|
|
58745
|
+
minute: "2-digit",
|
|
58746
|
+
hour12: false
|
|
58747
|
+
});
|
|
58748
|
+
};
|
|
58749
|
+
const displayMessages = [...messages];
|
|
58750
|
+
const effectiveThreadId = activeThreadId || pendingThreadId || void 0;
|
|
58751
|
+
const currentStreaming = getStreamingState(effectiveThreadId);
|
|
58752
|
+
const isCurrentThreadLoading = isThreadLoading(effectiveThreadId);
|
|
58753
|
+
if (isCurrentThreadLoading && currentStreaming.message) {
|
|
58754
|
+
displayMessages.push({
|
|
58755
|
+
id: -1,
|
|
58756
|
+
// Use -1 for streaming message to identify it
|
|
58757
|
+
thread_id: activeThreadId || "",
|
|
58758
|
+
role: "assistant",
|
|
58759
|
+
content: currentStreaming.message,
|
|
58760
|
+
reasoning: currentStreaming.reasoning || null,
|
|
58761
|
+
model_id: "gpt-4o-mini",
|
|
58762
|
+
token_usage: null,
|
|
58763
|
+
metadata: null,
|
|
58764
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
58765
|
+
position: messages.length
|
|
58766
|
+
});
|
|
58767
|
+
}
|
|
58768
|
+
const renderAssistantContent = (content) => {
|
|
58769
|
+
const cached = renderedContentCache.current.get(content);
|
|
58770
|
+
if (cached) {
|
|
58771
|
+
return cached;
|
|
58772
|
+
}
|
|
58773
|
+
const parseChartPatterns = (text) => {
|
|
58774
|
+
const chartElements = [];
|
|
58775
|
+
let lastIndex = 0;
|
|
58776
|
+
console.log("[DEBUG] Parsing chart patterns from text:", text);
|
|
58777
|
+
const chartRegex = /\[\s*(?:Calling\s+|CALL\s+)?(create_[a-z_]+)\s*\(([\s\S]*?)\)\s*\]/g;
|
|
58778
|
+
let match;
|
|
58779
|
+
const processedIndices = /* @__PURE__ */ new Set();
|
|
58780
|
+
let matchCount = 0;
|
|
58781
|
+
while ((match = chartRegex.exec(text)) !== null) {
|
|
58782
|
+
matchCount++;
|
|
58783
|
+
const startIndex = match.index;
|
|
58784
|
+
const endIndex = startIndex + match[0].length;
|
|
58785
|
+
console.log(`[DEBUG] Found chart pattern #${matchCount}:`, {
|
|
58786
|
+
fullMatch: match[0],
|
|
58787
|
+
chartType: match[1],
|
|
58788
|
+
argsString: match[2],
|
|
58789
|
+
startIndex,
|
|
58790
|
+
endIndex
|
|
58791
|
+
});
|
|
58792
|
+
if (!processedIndices.has(startIndex)) {
|
|
58793
|
+
processedIndices.add(startIndex);
|
|
58794
|
+
if (startIndex > lastIndex) {
|
|
58795
|
+
const beforeText = text.substring(lastIndex, startIndex);
|
|
58796
|
+
chartElements.push(
|
|
58797
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
58798
|
+
"div",
|
|
58799
|
+
{
|
|
58800
|
+
dangerouslySetInnerHTML: { __html: formatMessage(beforeText) }
|
|
58801
|
+
},
|
|
58802
|
+
`text-${lastIndex}`
|
|
58803
|
+
)
|
|
58804
|
+
);
|
|
58805
|
+
}
|
|
58806
|
+
const chartType = match[1];
|
|
58807
|
+
const argsString = match[2];
|
|
58808
|
+
try {
|
|
58809
|
+
const args = parseChartArguments(argsString);
|
|
58810
|
+
const chartElement = renderChart(chartType, args, startIndex);
|
|
58811
|
+
if (chartElement) {
|
|
58812
|
+
console.log(`[DEBUG] Successfully rendered chart: ${chartType}`);
|
|
58813
|
+
chartElements.push(chartElement);
|
|
58814
|
+
} else {
|
|
58815
|
+
console.warn(`[DEBUG] Chart element was null for type: ${chartType}`);
|
|
58816
|
+
console.warn(`[DEBUG] Args were:`, args);
|
|
58817
|
+
chartElements.push(
|
|
58818
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
58819
|
+
"div",
|
|
58820
|
+
{
|
|
58821
|
+
className: "text-red-500 text-sm border border-red-300 bg-red-50 p-3 rounded",
|
|
58822
|
+
children: [
|
|
58823
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Chart Rendering Error:" }),
|
|
58824
|
+
" Failed to render ",
|
|
58825
|
+
chartType,
|
|
58826
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
58827
|
+
/* @__PURE__ */ jsxRuntime.jsxs("small", { children: [
|
|
58828
|
+
"Check console for details. Args: ",
|
|
58829
|
+
JSON.stringify(args, null, 2)
|
|
58830
|
+
] })
|
|
58831
|
+
]
|
|
58832
|
+
},
|
|
58833
|
+
`error-${startIndex}`
|
|
58834
|
+
)
|
|
58835
|
+
);
|
|
58836
|
+
}
|
|
58837
|
+
} catch (error) {
|
|
58838
|
+
console.error(`Failed to parse chart ${chartType}:`, error);
|
|
58839
|
+
console.error(`Args string was:`, argsString);
|
|
58840
|
+
chartElements.push(
|
|
58841
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
58842
|
+
"div",
|
|
58843
|
+
{
|
|
58844
|
+
className: "text-red-500 text-sm border border-red-300 bg-red-50 p-3 rounded",
|
|
58845
|
+
children: [
|
|
58846
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Chart Parsing Error:" }),
|
|
58847
|
+
" Failed to parse ",
|
|
58848
|
+
chartType,
|
|
58849
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
58850
|
+
/* @__PURE__ */ jsxRuntime.jsxs("small", { children: [
|
|
58851
|
+
"Error: ",
|
|
58852
|
+
error instanceof Error ? error.message : String(error)
|
|
58853
|
+
] }),
|
|
58854
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
58855
|
+
/* @__PURE__ */ jsxRuntime.jsxs("small", { children: [
|
|
58856
|
+
"Original: ",
|
|
58857
|
+
match[0]
|
|
58858
|
+
] })
|
|
58859
|
+
]
|
|
58860
|
+
},
|
|
58861
|
+
`error-${startIndex}`
|
|
58862
|
+
)
|
|
58863
|
+
);
|
|
58864
|
+
}
|
|
58865
|
+
lastIndex = endIndex;
|
|
58866
|
+
}
|
|
58867
|
+
}
|
|
58868
|
+
console.log(`[DEBUG] Total chart patterns found: ${matchCount}`);
|
|
58869
|
+
if (lastIndex < text.length) {
|
|
58870
|
+
const remainingText = text.substring(lastIndex);
|
|
58871
|
+
chartElements.push(
|
|
58872
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
58873
|
+
"div",
|
|
58874
|
+
{
|
|
58875
|
+
dangerouslySetInnerHTML: { __html: formatMessage(remainingText) }
|
|
58876
|
+
},
|
|
58877
|
+
`text-${lastIndex}`
|
|
58878
|
+
)
|
|
58879
|
+
);
|
|
58880
|
+
}
|
|
58881
|
+
if (chartElements.length === 1 && lastIndex === 0) {
|
|
58882
|
+
console.log("[DEBUG] No charts found in text, returning null");
|
|
58883
|
+
return null;
|
|
58884
|
+
}
|
|
58885
|
+
console.log(`[DEBUG] Returning ${chartElements.length} chart elements`);
|
|
58886
|
+
return chartElements;
|
|
58887
|
+
};
|
|
58888
|
+
const parseChartArguments = (argsString) => {
|
|
58889
|
+
console.log("[DEBUG] Parsing chart arguments:", argsString);
|
|
58890
|
+
const extractParameters = (str) => {
|
|
58891
|
+
const params = {};
|
|
58892
|
+
let currentPos = 0;
|
|
58893
|
+
while (currentPos < str.length) {
|
|
58894
|
+
while (currentPos < str.length && /\s|,/.test(str[currentPos])) {
|
|
58895
|
+
currentPos++;
|
|
58896
|
+
}
|
|
58897
|
+
if (currentPos >= str.length) break;
|
|
58898
|
+
const paramMatch = str.substring(currentPos).match(/^(\w+)\s*=/);
|
|
58899
|
+
if (!paramMatch) {
|
|
58900
|
+
console.warn("[DEBUG] No parameter name found at position", currentPos);
|
|
58901
|
+
break;
|
|
58902
|
+
}
|
|
58903
|
+
const paramName = paramMatch[1];
|
|
58904
|
+
currentPos += paramMatch[0].length;
|
|
58905
|
+
while (currentPos < str.length && /\s/.test(str[currentPos])) {
|
|
58906
|
+
currentPos++;
|
|
58907
|
+
}
|
|
58908
|
+
if (currentPos >= str.length) break;
|
|
58909
|
+
let value;
|
|
58910
|
+
let valueEnd;
|
|
58911
|
+
if (str[currentPos] === "[") {
|
|
58912
|
+
let bracketCount = 0;
|
|
58913
|
+
let arrayStart = currentPos;
|
|
58914
|
+
valueEnd = str.length;
|
|
58915
|
+
for (let i = currentPos; i < str.length; i++) {
|
|
58916
|
+
if (str[i] === "[") bracketCount++;
|
|
58917
|
+
else if (str[i] === "]") bracketCount--;
|
|
58918
|
+
if (bracketCount === 0) {
|
|
58919
|
+
valueEnd = i + 1;
|
|
58920
|
+
break;
|
|
58921
|
+
}
|
|
58922
|
+
}
|
|
58923
|
+
if (bracketCount !== 0) {
|
|
58924
|
+
console.error("[DEBUG] Unmatched brackets in array value");
|
|
58925
|
+
break;
|
|
58926
|
+
}
|
|
58927
|
+
const arrayStr = str.substring(arrayStart, valueEnd);
|
|
58928
|
+
console.log(`[DEBUG] Found array parameter: ${paramName} = ${arrayStr}`);
|
|
58929
|
+
try {
|
|
58930
|
+
value = JSON.parse(arrayStr);
|
|
58931
|
+
console.log(`[DEBUG] Successfully parsed array ${paramName}:`, value);
|
|
58932
|
+
} catch (e) {
|
|
58933
|
+
console.error(`[DEBUG] Failed to parse array ${paramName}:`, e);
|
|
58934
|
+
console.error(`Array value that failed:`, arrayStr);
|
|
58935
|
+
value = arrayStr;
|
|
58936
|
+
}
|
|
58937
|
+
} else if (str[currentPos] === "{") {
|
|
58938
|
+
let braceCount = 0;
|
|
58939
|
+
let objectStart = currentPos;
|
|
58940
|
+
valueEnd = str.length;
|
|
58941
|
+
for (let i = currentPos; i < str.length; i++) {
|
|
58942
|
+
if (str[i] === "{") braceCount++;
|
|
58943
|
+
else if (str[i] === "}") braceCount--;
|
|
58944
|
+
if (braceCount === 0) {
|
|
58945
|
+
valueEnd = i + 1;
|
|
58946
|
+
break;
|
|
58947
|
+
}
|
|
58948
|
+
}
|
|
58949
|
+
if (braceCount !== 0) {
|
|
58950
|
+
console.error("[DEBUG] Unmatched braces in object value");
|
|
58951
|
+
break;
|
|
58952
|
+
}
|
|
58953
|
+
const objectStr = str.substring(objectStart, valueEnd);
|
|
58954
|
+
console.log(`[DEBUG] Found object parameter: ${paramName} = ${objectStr}`);
|
|
58955
|
+
try {
|
|
58956
|
+
value = JSON.parse(objectStr);
|
|
58957
|
+
console.log(`[DEBUG] Successfully parsed object ${paramName}:`, value);
|
|
58958
|
+
} catch (e) {
|
|
58959
|
+
console.error(`[DEBUG] Failed to parse object ${paramName}:`, e);
|
|
58960
|
+
console.error(`Object value that failed:`, objectStr);
|
|
58961
|
+
value = objectStr;
|
|
58962
|
+
}
|
|
58963
|
+
} else if (str[currentPos] === '"') {
|
|
58964
|
+
let stringStart = currentPos + 1;
|
|
58965
|
+
let stringEnd = stringStart;
|
|
58966
|
+
while (stringEnd < str.length) {
|
|
58967
|
+
if (str[stringEnd] === '"' && str[stringEnd - 1] !== "\\") {
|
|
58968
|
+
break;
|
|
58969
|
+
}
|
|
58970
|
+
stringEnd++;
|
|
58971
|
+
}
|
|
58972
|
+
if (stringEnd >= str.length) {
|
|
58973
|
+
console.error("[DEBUG] Unterminated string value");
|
|
58974
|
+
valueEnd = str.length;
|
|
58975
|
+
break;
|
|
58976
|
+
}
|
|
58977
|
+
value = str.substring(stringStart, stringEnd);
|
|
58978
|
+
valueEnd = stringEnd + 1;
|
|
58979
|
+
console.log(`[DEBUG] Found string parameter: ${paramName} = "${value}"`);
|
|
58980
|
+
} else {
|
|
58981
|
+
let valueStart = currentPos;
|
|
58982
|
+
let valueEndPos = valueStart;
|
|
58983
|
+
while (valueEndPos < str.length && str[valueEndPos] !== ",") {
|
|
58984
|
+
valueEndPos++;
|
|
58985
|
+
}
|
|
58986
|
+
const rawValue = str.substring(valueStart, valueEndPos).trim();
|
|
58987
|
+
valueEnd = valueEndPos;
|
|
58988
|
+
if (rawValue === "true" || rawValue === "True") {
|
|
58989
|
+
value = true;
|
|
58990
|
+
} else if (rawValue === "false" || rawValue === "False") {
|
|
58991
|
+
value = false;
|
|
58992
|
+
} else if (rawValue === "null" || rawValue === "None") {
|
|
58993
|
+
value = null;
|
|
58994
|
+
} else if (!isNaN(Number(rawValue)) && rawValue !== "") {
|
|
58995
|
+
value = Number(rawValue);
|
|
58996
|
+
} else {
|
|
58997
|
+
value = rawValue;
|
|
58998
|
+
}
|
|
58999
|
+
console.log(`[DEBUG] Found unquoted parameter: ${paramName} = ${rawValue} (parsed as ${typeof value})`);
|
|
59000
|
+
}
|
|
59001
|
+
params[paramName] = value;
|
|
59002
|
+
currentPos = valueEnd;
|
|
59003
|
+
}
|
|
59004
|
+
return params;
|
|
59005
|
+
};
|
|
59006
|
+
const result = extractParameters(argsString);
|
|
59007
|
+
console.log("[DEBUG] Final parsed arguments:", result);
|
|
59008
|
+
return result;
|
|
59009
|
+
};
|
|
59010
|
+
const renderChart = (chartType, args, key) => {
|
|
59011
|
+
console.log(`[DEBUG] Attempting to render chart type: ${chartType}`, args);
|
|
59012
|
+
const CHART_COLORS = {
|
|
59013
|
+
primary: "#3b82f6",
|
|
59014
|
+
// blue-500
|
|
59015
|
+
secondary: "#10b981",
|
|
59016
|
+
// green-500
|
|
59017
|
+
accent: "#f59e0b",
|
|
59018
|
+
// amber-500
|
|
59019
|
+
danger: "#ef4444",
|
|
59020
|
+
// red-500
|
|
59021
|
+
violet: "#8b5cf6",
|
|
59022
|
+
// violet-500
|
|
59023
|
+
cyan: "#06b6d4",
|
|
59024
|
+
// cyan-500
|
|
59025
|
+
orange: "#f97316",
|
|
59026
|
+
// orange-500
|
|
59027
|
+
indigo: "#6366f1"
|
|
59028
|
+
// indigo-500
|
|
59029
|
+
};
|
|
59030
|
+
const CHART_COLOR_PALETTE = Object.values(CHART_COLORS);
|
|
59031
|
+
const CHART_STYLES = {
|
|
59032
|
+
grid: {
|
|
59033
|
+
strokeDasharray: "3 3",
|
|
59034
|
+
stroke: "#e5e7eb"
|
|
59035
|
+
// gray-300
|
|
59036
|
+
},
|
|
59037
|
+
axis: {
|
|
59038
|
+
tick: { fontSize: 12, fill: "#4b5563" },
|
|
59039
|
+
// gray-600
|
|
59040
|
+
stroke: "#9ca3af"
|
|
59041
|
+
// gray-400
|
|
59042
|
+
},
|
|
59043
|
+
margin: { top: 10, right: 30, left: 20, bottom: 40 },
|
|
59044
|
+
barRadius: [4, 4, 0, 0]
|
|
59045
|
+
// Top corners rounded
|
|
59046
|
+
};
|
|
59047
|
+
const CustomTooltip4 = ({ active, payload, label }) => {
|
|
59048
|
+
if (active && payload && payload.length) {
|
|
59049
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
|
|
59050
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900 mb-1", children: label }),
|
|
59051
|
+
payload.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600", style: { color: entry.color }, children: [
|
|
59052
|
+
entry.name,
|
|
59053
|
+
": ",
|
|
59054
|
+
typeof entry.value === "number" ? formatNumber(entry.value) : entry.value,
|
|
59055
|
+
args.unit || ""
|
|
59056
|
+
] }, index))
|
|
59057
|
+
] });
|
|
59058
|
+
}
|
|
59059
|
+
return null;
|
|
59060
|
+
};
|
|
59061
|
+
const DualAxisTooltip = ({ active, payload, label }) => {
|
|
59062
|
+
if (active && payload && payload.length) {
|
|
59063
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
|
|
59064
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900 mb-2", children: label }),
|
|
59065
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: payload.map((entry, index) => {
|
|
59066
|
+
const value = typeof entry.value === "number" ? formatNumber(entry.value) : entry.value;
|
|
59067
|
+
const unit = entry.dataKey === args.left_y_field ? args.left_unit || "" : entry.dataKey === args.right_y_field ? args.right_unit || "" : "";
|
|
59068
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm", style: { color: entry.color }, children: [
|
|
59069
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
59070
|
+
entry.name,
|
|
59071
|
+
":"
|
|
59072
|
+
] }),
|
|
59073
|
+
" ",
|
|
59074
|
+
value,
|
|
59075
|
+
unit
|
|
59076
|
+
] }, index);
|
|
59077
|
+
}) })
|
|
59078
|
+
] });
|
|
59079
|
+
}
|
|
59080
|
+
return null;
|
|
59081
|
+
};
|
|
59082
|
+
const formatXAxisTick = (value) => {
|
|
59083
|
+
if (typeof value === "string") {
|
|
59084
|
+
if (value.match(/^\d{2}\/\d{2}\s/)) {
|
|
59085
|
+
return value;
|
|
59086
|
+
}
|
|
59087
|
+
if (value.length > 15) {
|
|
59088
|
+
return value.substring(0, 12) + "...";
|
|
59089
|
+
}
|
|
59090
|
+
}
|
|
59091
|
+
return value;
|
|
59092
|
+
};
|
|
59093
|
+
const ChartWrapper = ({ children, title }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-6 bg-white rounded-xl shadow-sm border border-gray-200 p-6", children: [
|
|
59094
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-900 mb-4", children: title }),
|
|
59095
|
+
children
|
|
59096
|
+
] });
|
|
59097
|
+
switch (chartType) {
|
|
59098
|
+
case "create_gauge_chart":
|
|
59099
|
+
console.log("[DEBUG] Rendering gauge chart");
|
|
59100
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 w-full flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
59101
|
+
GaugeChart,
|
|
59102
|
+
{
|
|
59103
|
+
value: args.value || 0,
|
|
59104
|
+
min: args.min_value || 0,
|
|
59105
|
+
max: args.max_value || 100,
|
|
59106
|
+
target: args.target,
|
|
59107
|
+
label: args.label || "",
|
|
59108
|
+
unit: args.unit || "",
|
|
59109
|
+
thresholds: args.thresholds,
|
|
59110
|
+
className: "w-full max-w-sm"
|
|
59111
|
+
}
|
|
59112
|
+
) }) }, `gauge-${key}`);
|
|
59113
|
+
case "create_bar_chart":
|
|
59114
|
+
console.log("[DEBUG] Rendering bar chart");
|
|
59115
|
+
if (!args.data || !args.x_field || !args.y_field) {
|
|
59116
|
+
console.error("Bar chart missing required parameters:", { data: !!args.data, x_field: !!args.x_field, y_field: !!args.y_field });
|
|
59117
|
+
return null;
|
|
59118
|
+
}
|
|
59119
|
+
if (!Array.isArray(args.data)) {
|
|
59120
|
+
console.error("Bar chart data must be an array, got:", typeof args.data, args.data);
|
|
59121
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59122
|
+
"Error: Chart data must be an array. Received: ",
|
|
59123
|
+
typeof args.data
|
|
59124
|
+
] }) }, `bar-error-${key}`);
|
|
59125
|
+
}
|
|
59126
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-64", style: { minHeight: "200px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: args.data, margin: CHART_STYLES.margin, children: [
|
|
59127
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59128
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59129
|
+
recharts.XAxis,
|
|
59130
|
+
{
|
|
59131
|
+
dataKey: args.x_field,
|
|
59132
|
+
...CHART_STYLES.axis,
|
|
59133
|
+
angle: -45,
|
|
59134
|
+
textAnchor: "end",
|
|
59135
|
+
height: 60,
|
|
59136
|
+
interval: 0,
|
|
59137
|
+
tickFormatter: formatXAxisTick
|
|
59138
|
+
}
|
|
59139
|
+
),
|
|
59140
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59141
|
+
recharts.YAxis,
|
|
59142
|
+
{
|
|
59143
|
+
...CHART_STYLES.axis,
|
|
59144
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59145
|
+
}
|
|
59146
|
+
),
|
|
59147
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
|
|
59148
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59149
|
+
recharts.Bar,
|
|
59150
|
+
{
|
|
59151
|
+
dataKey: args.y_field,
|
|
59152
|
+
fill: args.color || CHART_COLORS.primary,
|
|
59153
|
+
radius: CHART_STYLES.barRadius
|
|
59154
|
+
}
|
|
59155
|
+
)
|
|
59156
|
+
] }) }) }) }, `bar-${key}`);
|
|
59157
|
+
case "create_line_chart":
|
|
59158
|
+
console.log("[DEBUG] Rendering line chart");
|
|
59159
|
+
if (!args.data || !args.x_field || !args.y_field) {
|
|
59160
|
+
console.error("Line chart missing required parameters:", { data: !!args.data, x_field: !!args.x_field, y_field: !!args.y_field });
|
|
59161
|
+
return null;
|
|
59162
|
+
}
|
|
59163
|
+
if (!Array.isArray(args.data)) {
|
|
59164
|
+
console.error("Line chart data must be an array, got:", typeof args.data, args.data);
|
|
59165
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59166
|
+
"Error: Chart data must be an array. Received: ",
|
|
59167
|
+
typeof args.data
|
|
59168
|
+
] }) }, `line-error-${key}`);
|
|
59169
|
+
}
|
|
59170
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-64", style: { minHeight: "200px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: args.data, margin: CHART_STYLES.margin, children: [
|
|
59171
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59172
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59173
|
+
recharts.XAxis,
|
|
59174
|
+
{
|
|
59175
|
+
dataKey: args.x_field,
|
|
59176
|
+
...CHART_STYLES.axis,
|
|
59177
|
+
angle: -45,
|
|
59178
|
+
textAnchor: "end",
|
|
59179
|
+
height: 60,
|
|
59180
|
+
interval: 0,
|
|
59181
|
+
tickFormatter: formatXAxisTick
|
|
59182
|
+
}
|
|
59183
|
+
),
|
|
59184
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59185
|
+
recharts.YAxis,
|
|
59186
|
+
{
|
|
59187
|
+
...CHART_STYLES.axis,
|
|
59188
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59189
|
+
}
|
|
59190
|
+
),
|
|
59191
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {}), cursor: { strokeDasharray: "3 3" } }),
|
|
59192
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59193
|
+
recharts.Line,
|
|
59194
|
+
{
|
|
59195
|
+
type: "monotone",
|
|
59196
|
+
dataKey: args.y_field,
|
|
59197
|
+
stroke: CHART_COLORS.primary,
|
|
59198
|
+
strokeWidth: 2,
|
|
59199
|
+
dot: { r: 4, fill: CHART_COLORS.primary },
|
|
59200
|
+
activeDot: { r: 6 }
|
|
59201
|
+
}
|
|
59202
|
+
)
|
|
59203
|
+
] }) }) }) }, `line-${key}`);
|
|
59204
|
+
case "create_pie_chart":
|
|
59205
|
+
console.log("[DEBUG] Rendering pie chart");
|
|
59206
|
+
if (!args.data || !args.label_field || !args.value_field) {
|
|
59207
|
+
console.error("Pie chart missing required parameters:", { data: !!args.data, label_field: !!args.label_field, value_field: !!args.value_field });
|
|
59208
|
+
console.error("Available args:", Object.keys(args));
|
|
59209
|
+
return null;
|
|
59210
|
+
}
|
|
59211
|
+
if (!Array.isArray(args.data)) {
|
|
59212
|
+
console.error("Pie chart data must be an array, got:", typeof args.data, args.data);
|
|
59213
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59214
|
+
"Error: Chart data must be an array. Received: ",
|
|
59215
|
+
typeof args.data
|
|
59216
|
+
] }) }, `pie-error-${key}`);
|
|
59217
|
+
}
|
|
59218
|
+
const pieData = args.data.map((item) => ({
|
|
59219
|
+
name: item[args.label_field],
|
|
59220
|
+
value: item[args.value_field]
|
|
59221
|
+
}));
|
|
59222
|
+
console.log("[DEBUG] Pie chart data transformed:", pieData);
|
|
59223
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 w-full max-w-md mx-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
59224
|
+
PieChart4,
|
|
59225
|
+
{
|
|
59226
|
+
data: pieData,
|
|
59227
|
+
showPercentages: args.show_percentages || false,
|
|
59228
|
+
colors: CHART_COLOR_PALETTE
|
|
59229
|
+
}
|
|
59230
|
+
) }) }, `pie-${key}`);
|
|
59231
|
+
case "create_comparison_table":
|
|
59232
|
+
console.log("[DEBUG] Rendering comparison table");
|
|
59233
|
+
if (!args.data) {
|
|
59234
|
+
console.error("Comparison table missing required data");
|
|
59235
|
+
return null;
|
|
59236
|
+
}
|
|
59237
|
+
if (!Array.isArray(args.data)) {
|
|
59238
|
+
console.error("Comparison table data must be an array, got:", typeof args.data, args.data);
|
|
59239
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59240
|
+
"Error: Table data must be an array. Received: ",
|
|
59241
|
+
typeof args.data
|
|
59242
|
+
] }) }, `table-error-${key}`);
|
|
59243
|
+
}
|
|
59244
|
+
const columns = args.columns || Object.keys(args.data[0] || {});
|
|
59245
|
+
let sortedData = [...args.data];
|
|
59246
|
+
if (args.sort_by && columns.includes(args.sort_by)) {
|
|
59247
|
+
sortedData.sort((a, b) => {
|
|
59248
|
+
const aVal = a[args.sort_by];
|
|
59249
|
+
const bVal = b[args.sort_by];
|
|
59250
|
+
const comparison = aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
|
|
59251
|
+
return args.sort_descending === false ? comparison : -comparison;
|
|
59252
|
+
});
|
|
59253
|
+
}
|
|
59254
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-lg border border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
|
|
59255
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59256
|
+
"th",
|
|
59257
|
+
{
|
|
59258
|
+
className: `px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider ${col === args.highlight_column ? "bg-blue-50" : ""}`,
|
|
59259
|
+
children: col
|
|
59260
|
+
},
|
|
59261
|
+
col
|
|
59262
|
+
)) }) }),
|
|
59263
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: sortedData.map((row, rowIdx) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: rowIdx % 2 === 0 ? "bg-white" : "bg-gray-50", children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59264
|
+
"td",
|
|
59265
|
+
{
|
|
59266
|
+
className: `px-6 py-4 whitespace-nowrap text-sm ${col === args.highlight_column ? "font-medium text-blue-600 bg-blue-50" : "text-gray-900"}`,
|
|
59267
|
+
children: typeof row[col] === "number" ? formatNumber(row[col]) : row[col]
|
|
59268
|
+
},
|
|
59269
|
+
col
|
|
59270
|
+
)) }, rowIdx)) })
|
|
59271
|
+
] }) }) }, `table-${key}`);
|
|
59272
|
+
case "create_multi_line_chart":
|
|
59273
|
+
console.log("[DEBUG] Rendering multi-line chart");
|
|
59274
|
+
if (!args.data || !args.x_field || !args.y_fields || !args.legend) {
|
|
59275
|
+
console.error("Multi-line chart missing required parameters:", {
|
|
59276
|
+
data: !!args.data,
|
|
59277
|
+
x_field: !!args.x_field,
|
|
59278
|
+
y_fields: !!args.y_fields,
|
|
59279
|
+
legend: !!args.legend
|
|
59280
|
+
});
|
|
59281
|
+
return null;
|
|
59282
|
+
}
|
|
59283
|
+
if (!Array.isArray(args.data)) {
|
|
59284
|
+
console.error("Multi-line chart data must be an array, got:", typeof args.data, args.data);
|
|
59285
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59286
|
+
"Error: Chart data must be an array. Received: ",
|
|
59287
|
+
typeof args.data
|
|
59288
|
+
] }) }, `multi-line-error-${key}`);
|
|
59289
|
+
}
|
|
59290
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: args.data, margin: CHART_STYLES.margin, children: [
|
|
59291
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59292
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59293
|
+
recharts.XAxis,
|
|
59294
|
+
{
|
|
59295
|
+
dataKey: args.x_field,
|
|
59296
|
+
...CHART_STYLES.axis,
|
|
59297
|
+
angle: -45,
|
|
59298
|
+
textAnchor: "end",
|
|
59299
|
+
height: 60,
|
|
59300
|
+
interval: 0,
|
|
59301
|
+
tickFormatter: formatXAxisTick
|
|
59302
|
+
}
|
|
59303
|
+
),
|
|
59304
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59305
|
+
recharts.YAxis,
|
|
59306
|
+
{
|
|
59307
|
+
...CHART_STYLES.axis,
|
|
59308
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59309
|
+
}
|
|
59310
|
+
),
|
|
59311
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {}), cursor: { strokeDasharray: "3 3" } }),
|
|
59312
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59313
|
+
recharts.Legend,
|
|
59314
|
+
{
|
|
59315
|
+
wrapperStyle: { paddingTop: "20px" },
|
|
59316
|
+
formatter: (value) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: value })
|
|
59317
|
+
}
|
|
59318
|
+
),
|
|
59319
|
+
args.y_fields.map((field, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59320
|
+
recharts.Line,
|
|
59321
|
+
{
|
|
59322
|
+
type: "monotone",
|
|
59323
|
+
dataKey: field,
|
|
59324
|
+
stroke: CHART_COLOR_PALETTE[index % CHART_COLOR_PALETTE.length],
|
|
59325
|
+
strokeWidth: 2,
|
|
59326
|
+
name: args.legend[index] || field,
|
|
59327
|
+
dot: { r: 4 },
|
|
59328
|
+
activeDot: { r: 6 }
|
|
59329
|
+
},
|
|
59330
|
+
field
|
|
59331
|
+
))
|
|
59332
|
+
] }) }) }) }, `multi-line-${key}`);
|
|
59333
|
+
case "create_stacked_bar_chart":
|
|
59334
|
+
console.log("[DEBUG] Rendering stacked bar chart");
|
|
59335
|
+
if (!args.data || !args.x_field || !args.stack_fields) {
|
|
59336
|
+
console.error("Stacked bar chart missing required parameters:", {
|
|
59337
|
+
data: !!args.data,
|
|
59338
|
+
x_field: !!args.x_field,
|
|
59339
|
+
stack_fields: !!args.stack_fields
|
|
59340
|
+
});
|
|
59341
|
+
return null;
|
|
59342
|
+
}
|
|
59343
|
+
if (!Array.isArray(args.data)) {
|
|
59344
|
+
console.error("Stacked bar chart data must be an array, got:", typeof args.data, args.data);
|
|
59345
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59346
|
+
"Error: Chart data must be an array. Received: ",
|
|
59347
|
+
typeof args.data
|
|
59348
|
+
] }) }, `stacked-bar-error-${key}`);
|
|
59349
|
+
}
|
|
59350
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: args.data, margin: CHART_STYLES.margin, children: [
|
|
59351
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59352
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59353
|
+
recharts.XAxis,
|
|
59354
|
+
{
|
|
59355
|
+
dataKey: args.x_field,
|
|
59356
|
+
...CHART_STYLES.axis,
|
|
59357
|
+
angle: -45,
|
|
59358
|
+
textAnchor: "end",
|
|
59359
|
+
height: 60,
|
|
59360
|
+
interval: 0,
|
|
59361
|
+
tickFormatter: formatXAxisTick
|
|
59362
|
+
}
|
|
59363
|
+
),
|
|
59364
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59365
|
+
recharts.YAxis,
|
|
59366
|
+
{
|
|
59367
|
+
...CHART_STYLES.axis,
|
|
59368
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59369
|
+
}
|
|
59370
|
+
),
|
|
59371
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
|
|
59372
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59373
|
+
recharts.Legend,
|
|
59374
|
+
{
|
|
59375
|
+
wrapperStyle: { paddingTop: "20px" },
|
|
59376
|
+
formatter: (value) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: value })
|
|
59377
|
+
}
|
|
59378
|
+
),
|
|
59379
|
+
args.stack_fields.map((field, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59380
|
+
recharts.Bar,
|
|
59381
|
+
{
|
|
59382
|
+
dataKey: field,
|
|
59383
|
+
stackId: "stack",
|
|
59384
|
+
fill: CHART_COLOR_PALETTE[index % CHART_COLOR_PALETTE.length],
|
|
59385
|
+
name: field,
|
|
59386
|
+
radius: index === args.stack_fields.length - 1 ? CHART_STYLES.barRadius : void 0
|
|
59387
|
+
},
|
|
59388
|
+
field
|
|
59389
|
+
))
|
|
59390
|
+
] }) }) }) }, `stacked-bar-${key}`);
|
|
59391
|
+
case "create_dual_axis_chart":
|
|
59392
|
+
console.log("[DEBUG] Rendering dual-axis chart");
|
|
59393
|
+
if (!args.data || !args.x_field || !args.left_y_field || !args.right_y_field) {
|
|
59394
|
+
console.error("Dual-axis chart missing required parameters:", {
|
|
59395
|
+
data: !!args.data,
|
|
59396
|
+
x_field: !!args.x_field,
|
|
59397
|
+
left_y_field: !!args.left_y_field,
|
|
59398
|
+
right_y_field: !!args.right_y_field
|
|
59399
|
+
});
|
|
59400
|
+
return null;
|
|
59401
|
+
}
|
|
59402
|
+
if (!Array.isArray(args.data)) {
|
|
59403
|
+
console.error("Dual-axis chart data must be an array, got:", typeof args.data, args.data);
|
|
59404
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59405
|
+
"Error: Chart data must be an array. Received: ",
|
|
59406
|
+
typeof args.data
|
|
59407
|
+
] }) }, `dual-axis-error-${key}`);
|
|
59408
|
+
}
|
|
59409
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
|
|
59410
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59411
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59412
|
+
recharts.XAxis,
|
|
59413
|
+
{
|
|
59414
|
+
dataKey: args.x_field,
|
|
59415
|
+
...CHART_STYLES.axis,
|
|
59416
|
+
angle: -45,
|
|
59417
|
+
textAnchor: "end",
|
|
59418
|
+
height: 100,
|
|
59419
|
+
interval: 0,
|
|
59420
|
+
tickFormatter: formatXAxisTick
|
|
59421
|
+
}
|
|
59422
|
+
),
|
|
59423
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59424
|
+
recharts.YAxis,
|
|
59425
|
+
{
|
|
59426
|
+
yAxisId: "left",
|
|
59427
|
+
orientation: "left",
|
|
59428
|
+
label: {
|
|
59429
|
+
value: args.left_label || args.left_y_field,
|
|
59430
|
+
angle: -90,
|
|
59431
|
+
position: "insideLeft",
|
|
59432
|
+
style: { textAnchor: "middle", fill: "#4b5563" }
|
|
59433
|
+
},
|
|
59434
|
+
...CHART_STYLES.axis,
|
|
59435
|
+
tickFormatter: (value) => `${formatNumber(value)}${args.left_unit || ""}`
|
|
59436
|
+
}
|
|
59437
|
+
),
|
|
59438
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59439
|
+
recharts.YAxis,
|
|
59440
|
+
{
|
|
59441
|
+
yAxisId: "right",
|
|
59442
|
+
orientation: "right",
|
|
59443
|
+
label: {
|
|
59444
|
+
value: args.right_label || args.right_y_field,
|
|
59445
|
+
angle: 90,
|
|
59446
|
+
position: "insideRight",
|
|
59447
|
+
style: { textAnchor: "middle", fill: "#4b5563" }
|
|
59448
|
+
},
|
|
59449
|
+
...CHART_STYLES.axis,
|
|
59450
|
+
tickFormatter: (value) => `${formatNumber(value)}${args.right_unit || ""}`
|
|
59451
|
+
}
|
|
59452
|
+
),
|
|
59453
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(DualAxisTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
|
|
59454
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59455
|
+
recharts.Legend,
|
|
59456
|
+
{
|
|
59457
|
+
wrapperStyle: { paddingTop: "20px" },
|
|
59458
|
+
formatter: (value) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: value })
|
|
59459
|
+
}
|
|
59460
|
+
),
|
|
59461
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59462
|
+
recharts.Bar,
|
|
59463
|
+
{
|
|
59464
|
+
yAxisId: "left",
|
|
59465
|
+
dataKey: args.left_y_field,
|
|
59466
|
+
fill: CHART_COLORS.primary,
|
|
59467
|
+
name: args.left_label || args.left_y_field,
|
|
59468
|
+
radius: CHART_STYLES.barRadius
|
|
59469
|
+
}
|
|
59470
|
+
),
|
|
59471
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59472
|
+
recharts.Line,
|
|
59473
|
+
{
|
|
59474
|
+
yAxisId: "right",
|
|
59475
|
+
type: "monotone",
|
|
59476
|
+
dataKey: args.right_y_field,
|
|
59477
|
+
stroke: CHART_COLORS.danger,
|
|
59478
|
+
strokeWidth: 3,
|
|
59479
|
+
name: args.right_label || args.right_y_field,
|
|
59480
|
+
dot: { r: 5, fill: CHART_COLORS.danger },
|
|
59481
|
+
activeDot: { r: 7 }
|
|
59482
|
+
}
|
|
59483
|
+
)
|
|
59484
|
+
] }) }) }) }, `dual-axis-${key}`);
|
|
59485
|
+
case "create_scatter_plot":
|
|
59486
|
+
console.log("[DEBUG] Rendering scatter plot");
|
|
59487
|
+
if (!args.data || !args.x_field || !args.y_field || !args.group_field) {
|
|
59488
|
+
console.error("Scatter plot missing required parameters:", {
|
|
59489
|
+
data: !!args.data,
|
|
59490
|
+
x_field: !!args.x_field,
|
|
59491
|
+
y_field: !!args.y_field,
|
|
59492
|
+
group_field: !!args.group_field
|
|
59493
|
+
});
|
|
59494
|
+
return null;
|
|
59495
|
+
}
|
|
59496
|
+
if (!Array.isArray(args.data)) {
|
|
59497
|
+
console.error("Scatter plot data must be an array, got:", typeof args.data, args.data);
|
|
59498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59499
|
+
"Error: Chart data must be an array. Received: ",
|
|
59500
|
+
typeof args.data
|
|
59501
|
+
] }) }, `scatter-error-${key}`);
|
|
59502
|
+
}
|
|
59503
|
+
const groupedData = args.data.reduce((acc, item) => {
|
|
59504
|
+
const group = item[args.group_field];
|
|
59505
|
+
if (!acc[group]) {
|
|
59506
|
+
acc[group] = [];
|
|
59507
|
+
}
|
|
59508
|
+
acc[group].push(item);
|
|
59509
|
+
return acc;
|
|
59510
|
+
}, {});
|
|
59511
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ScatterChart, { margin: CHART_STYLES.margin, children: [
|
|
59512
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59513
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59514
|
+
recharts.XAxis,
|
|
59515
|
+
{
|
|
59516
|
+
dataKey: args.x_field,
|
|
59517
|
+
type: "number",
|
|
59518
|
+
name: args.x_field,
|
|
59519
|
+
...CHART_STYLES.axis
|
|
59520
|
+
}
|
|
59521
|
+
),
|
|
59522
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59523
|
+
recharts.YAxis,
|
|
59524
|
+
{
|
|
59525
|
+
dataKey: args.y_field,
|
|
59526
|
+
type: "number",
|
|
59527
|
+
name: args.y_field,
|
|
59528
|
+
...CHART_STYLES.axis
|
|
59529
|
+
}
|
|
59530
|
+
),
|
|
59531
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59532
|
+
recharts.Tooltip,
|
|
59533
|
+
{
|
|
59534
|
+
cursor: { strokeDasharray: "3 3" },
|
|
59535
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {})
|
|
59536
|
+
}
|
|
59537
|
+
),
|
|
59538
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59539
|
+
recharts.Legend,
|
|
59540
|
+
{
|
|
59541
|
+
wrapperStyle: { paddingTop: "20px" },
|
|
59542
|
+
formatter: (value) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: value })
|
|
59543
|
+
}
|
|
59544
|
+
),
|
|
59545
|
+
Object.entries(groupedData).map(([group, data], index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59546
|
+
recharts.Scatter,
|
|
59547
|
+
{
|
|
59548
|
+
name: group,
|
|
59549
|
+
data,
|
|
59550
|
+
fill: CHART_COLOR_PALETTE[index % CHART_COLOR_PALETTE.length]
|
|
59551
|
+
},
|
|
59552
|
+
group
|
|
59553
|
+
))
|
|
59554
|
+
] }) }) }) }, `scatter-${key}`);
|
|
59555
|
+
case "create_combo_chart":
|
|
59556
|
+
console.log("[DEBUG] Rendering combo chart");
|
|
59557
|
+
if (!args.data || !args.x_field || !args.bar_field || !args.line_field) {
|
|
59558
|
+
console.error("Combo chart missing required parameters:", {
|
|
59559
|
+
data: !!args.data,
|
|
59560
|
+
x_field: !!args.x_field,
|
|
59561
|
+
bar_field: !!args.bar_field,
|
|
59562
|
+
line_field: !!args.line_field
|
|
59563
|
+
});
|
|
59564
|
+
return null;
|
|
59565
|
+
}
|
|
59566
|
+
if (!Array.isArray(args.data)) {
|
|
59567
|
+
console.error("Combo chart data must be an array, got:", typeof args.data, args.data);
|
|
59568
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59569
|
+
"Error: Chart data must be an array. Received: ",
|
|
59570
|
+
typeof args.data
|
|
59571
|
+
] }) }, `combo-error-${key}`);
|
|
59572
|
+
}
|
|
59573
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
|
|
59574
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59575
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59576
|
+
recharts.XAxis,
|
|
59577
|
+
{
|
|
59578
|
+
dataKey: args.x_field,
|
|
59579
|
+
...CHART_STYLES.axis,
|
|
59580
|
+
angle: -45,
|
|
59581
|
+
textAnchor: "end",
|
|
59582
|
+
height: 100,
|
|
59583
|
+
interval: 0,
|
|
59584
|
+
tickFormatter: formatXAxisTick
|
|
59585
|
+
}
|
|
59586
|
+
),
|
|
59587
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59588
|
+
recharts.YAxis,
|
|
59589
|
+
{
|
|
59590
|
+
yAxisId: "left",
|
|
59591
|
+
orientation: "left",
|
|
59592
|
+
...CHART_STYLES.axis,
|
|
59593
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59594
|
+
}
|
|
59595
|
+
),
|
|
59596
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59597
|
+
recharts.YAxis,
|
|
59598
|
+
{
|
|
59599
|
+
yAxisId: "right",
|
|
59600
|
+
orientation: "right",
|
|
59601
|
+
...CHART_STYLES.axis,
|
|
59602
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59603
|
+
}
|
|
59604
|
+
),
|
|
59605
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
|
|
59606
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59607
|
+
recharts.Legend,
|
|
59608
|
+
{
|
|
59609
|
+
wrapperStyle: { paddingTop: "20px" },
|
|
59610
|
+
formatter: (value) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: value })
|
|
59611
|
+
}
|
|
59612
|
+
),
|
|
59613
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59614
|
+
recharts.Bar,
|
|
59615
|
+
{
|
|
59616
|
+
yAxisId: "left",
|
|
59617
|
+
dataKey: args.bar_field,
|
|
59618
|
+
fill: CHART_COLORS.primary,
|
|
59619
|
+
name: args.bar_field,
|
|
59620
|
+
radius: CHART_STYLES.barRadius
|
|
59621
|
+
}
|
|
59622
|
+
),
|
|
59623
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59624
|
+
recharts.Line,
|
|
59625
|
+
{
|
|
59626
|
+
yAxisId: "right",
|
|
59627
|
+
type: "monotone",
|
|
59628
|
+
dataKey: args.line_field,
|
|
59629
|
+
stroke: CHART_COLORS.danger,
|
|
59630
|
+
strokeWidth: 3,
|
|
59631
|
+
name: args.line_field,
|
|
59632
|
+
dot: { r: 5 },
|
|
59633
|
+
activeDot: { r: 7 }
|
|
59634
|
+
}
|
|
59635
|
+
)
|
|
59636
|
+
] }) }) }) }, `combo-${key}`);
|
|
59637
|
+
case "create_area_chart":
|
|
59638
|
+
console.log("[DEBUG] Rendering area chart");
|
|
59639
|
+
if (!args.data || !args.x_field || !args.y_field) {
|
|
59640
|
+
console.error("Area chart missing required parameters:", {
|
|
59641
|
+
data: !!args.data,
|
|
59642
|
+
x_field: !!args.x_field,
|
|
59643
|
+
y_field: !!args.y_field
|
|
59644
|
+
});
|
|
59645
|
+
return null;
|
|
59646
|
+
}
|
|
59647
|
+
if (!Array.isArray(args.data)) {
|
|
59648
|
+
console.error("Area chart data must be an array, got:", typeof args.data, args.data);
|
|
59649
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm", children: [
|
|
59650
|
+
"Error: Chart data must be an array. Received: ",
|
|
59651
|
+
typeof args.data
|
|
59652
|
+
] }) }, `area-error-${key}`);
|
|
59653
|
+
}
|
|
59654
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
|
|
59655
|
+
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "colorGradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
59656
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "5%", stopColor: CHART_COLORS.primary, stopOpacity: 0.8 }),
|
|
59657
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "95%", stopColor: CHART_COLORS.primary, stopOpacity: 0.1 })
|
|
59658
|
+
] }) }),
|
|
59659
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...CHART_STYLES.grid }),
|
|
59660
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59661
|
+
recharts.XAxis,
|
|
59662
|
+
{
|
|
59663
|
+
dataKey: args.x_field,
|
|
59664
|
+
...CHART_STYLES.axis,
|
|
59665
|
+
angle: -45,
|
|
59666
|
+
textAnchor: "end",
|
|
59667
|
+
height: 100,
|
|
59668
|
+
interval: 0,
|
|
59669
|
+
tickFormatter: formatXAxisTick
|
|
59670
|
+
}
|
|
59671
|
+
),
|
|
59672
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59673
|
+
recharts.YAxis,
|
|
59674
|
+
{
|
|
59675
|
+
...CHART_STYLES.axis,
|
|
59676
|
+
tickFormatter: (value) => formatNumber(value)
|
|
59677
|
+
}
|
|
59678
|
+
),
|
|
59679
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip4, {}), cursor: { strokeDasharray: "3 3" } }),
|
|
59680
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59681
|
+
recharts.Legend,
|
|
59682
|
+
{
|
|
59683
|
+
wrapperStyle: { paddingTop: "20px" },
|
|
59684
|
+
formatter: (value) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: value })
|
|
59685
|
+
}
|
|
59686
|
+
),
|
|
59687
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59688
|
+
recharts.Area,
|
|
59689
|
+
{
|
|
59690
|
+
type: "monotone",
|
|
59691
|
+
dataKey: args.y_field,
|
|
59692
|
+
stroke: CHART_COLORS.primary,
|
|
59693
|
+
strokeWidth: 2,
|
|
59694
|
+
fill: args.fill !== false ? "url(#colorGradient)" : "none",
|
|
59695
|
+
name: args.y_field,
|
|
59696
|
+
dot: { r: 4, fill: CHART_COLORS.primary },
|
|
59697
|
+
activeDot: { r: 6 }
|
|
59698
|
+
}
|
|
59699
|
+
)
|
|
59700
|
+
] }) }) }) }, `area-${key}`);
|
|
59701
|
+
default:
|
|
59702
|
+
console.warn(`Unknown chart type: ${chartType}`);
|
|
59703
|
+
return null;
|
|
59704
|
+
}
|
|
59705
|
+
};
|
|
59706
|
+
const chartContent = parseChartPatterns(content);
|
|
59707
|
+
let finalNode;
|
|
59708
|
+
if (chartContent) {
|
|
59709
|
+
finalNode = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "formatted-content", children: chartContent });
|
|
59710
|
+
} else {
|
|
59711
|
+
finalNode = /* @__PURE__ */ jsxRuntime.jsx(
|
|
59712
|
+
"div",
|
|
59713
|
+
{
|
|
59714
|
+
className: "formatted-content",
|
|
59715
|
+
dangerouslySetInnerHTML: { __html: formatMessage(content) }
|
|
59716
|
+
}
|
|
59717
|
+
);
|
|
59718
|
+
}
|
|
59719
|
+
renderedContentCache.current.set(content, finalNode);
|
|
59720
|
+
return finalNode;
|
|
59721
|
+
};
|
|
59722
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-screen bg-white", children: [
|
|
59723
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: {
|
|
59724
|
+
__html: `
|
|
59725
|
+
@keyframes slideDown {
|
|
59726
|
+
0% {
|
|
59727
|
+
transform: translateY(-40vh);
|
|
59728
|
+
opacity: 1;
|
|
59729
|
+
}
|
|
59730
|
+
100% {
|
|
59731
|
+
transform: translateY(0);
|
|
59732
|
+
opacity: 1;
|
|
59733
|
+
}
|
|
59734
|
+
}
|
|
59735
|
+
|
|
59736
|
+
@keyframes waveLoad {
|
|
59737
|
+
0% {
|
|
59738
|
+
background-position: -200% 0;
|
|
59739
|
+
}
|
|
59740
|
+
100% {
|
|
59741
|
+
background-position: 200% 0;
|
|
59742
|
+
}
|
|
59743
|
+
}
|
|
59744
|
+
|
|
59745
|
+
.thinking-wave {
|
|
59746
|
+
background: linear-gradient(
|
|
59747
|
+
90deg,
|
|
59748
|
+
#6b7280 0%,
|
|
59749
|
+
#6b7280 40%,
|
|
59750
|
+
#3b82f6 50%,
|
|
59751
|
+
#6b7280 60%,
|
|
59752
|
+
#6b7280 100%
|
|
59753
|
+
);
|
|
59754
|
+
background-size: 200% 100%;
|
|
59755
|
+
-webkit-background-clip: text;
|
|
59756
|
+
background-clip: text;
|
|
59757
|
+
-webkit-text-fill-color: transparent;
|
|
59758
|
+
animation: waveLoad 3s ease-in-out infinite;
|
|
59759
|
+
}
|
|
59760
|
+
`
|
|
59761
|
+
} }),
|
|
59762
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex-1 flex flex-col h-screen transition-all duration-300 ${isSidebarOpen ? "lg:mr-80 mr-0" : "mr-0"}`, children: [
|
|
59763
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex-shrink-0 bg-white px-3 sm:px-6 md:px-8 py-2 sm:py-5 md:py-6 shadow-sm border-b border-gray-200/80 sticky top-0 z-10", children: [
|
|
59764
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
59765
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59766
|
+
"button",
|
|
59767
|
+
{
|
|
59768
|
+
onClick: () => navigate("/"),
|
|
59769
|
+
className: "p-2 -ml-2 rounded-full active:bg-gray-100 transition-colors",
|
|
59770
|
+
"aria-label": "Navigate back",
|
|
59771
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5 text-gray-700", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
59772
|
+
}
|
|
59773
|
+
),
|
|
59774
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
|
|
59775
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
59776
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-base font-semibold text-gray-900", children: "Chat with Axel" }),
|
|
59777
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-2 w-2", children: [
|
|
59778
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
|
|
59779
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
|
|
59780
|
+
] })
|
|
59781
|
+
] }),
|
|
59782
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-500", children: /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {}) })
|
|
59783
|
+
] }),
|
|
59784
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
59785
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59786
|
+
"button",
|
|
59787
|
+
{
|
|
59788
|
+
onClick: handleNewThread,
|
|
59789
|
+
className: "p-2 rounded-full active:bg-gray-100 transition-colors",
|
|
59790
|
+
"aria-label": "New chat",
|
|
59791
|
+
title: "New chat",
|
|
59792
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "w-5 h-5 text-gray-700" })
|
|
59793
|
+
}
|
|
59794
|
+
),
|
|
59795
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59796
|
+
"button",
|
|
59797
|
+
{
|
|
59798
|
+
onClick: () => setIsSidebarOpen(!isSidebarOpen),
|
|
59799
|
+
className: "relative p-2 -mr-2 rounded-full active:bg-gray-100 transition-colors",
|
|
59800
|
+
"aria-label": "Toggle chat history",
|
|
59801
|
+
title: isSidebarOpen ? "Hide history" : "Show history",
|
|
59802
|
+
children: isSidebarOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-5 h-5 text-gray-700" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
59803
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "w-5 h-5 text-gray-700" }),
|
|
59804
|
+
newChatCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-1 right-1 bg-red-500 text-white text-[9px] rounded-full w-4 h-4 flex items-center justify-center font-medium", children: newChatCount })
|
|
59805
|
+
] })
|
|
59806
|
+
}
|
|
59807
|
+
)
|
|
59808
|
+
] })
|
|
59809
|
+
] }) }),
|
|
59810
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden sm:flex items-center justify-between relative", children: [
|
|
59811
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
59812
|
+
BackButtonMinimal,
|
|
59813
|
+
{
|
|
59814
|
+
onClick: () => navigate("/"),
|
|
59815
|
+
text: "Back",
|
|
59816
|
+
size: "default",
|
|
59817
|
+
"aria-label": "Navigate back to dashboard"
|
|
59818
|
+
}
|
|
59819
|
+
) }),
|
|
59820
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 text-center mx-auto", children: [
|
|
59821
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-3 mb-1", children: [
|
|
59822
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl md:text-2xl lg:text-3xl font-semibold text-gray-900", children: "Chat with Axel" }),
|
|
59823
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-1.5 md:h-2 md:w-2 rounded-full bg-green-500 animate-pulse ring-2 ring-green-500/30 ring-offset-1" })
|
|
59824
|
+
] }),
|
|
59825
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-500", children: /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {}) }) })
|
|
59826
|
+
] }),
|
|
59827
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 flex items-center gap-2", children: [
|
|
59828
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
59829
|
+
"button",
|
|
59830
|
+
{
|
|
59831
|
+
onClick: handleNewThread,
|
|
59832
|
+
className: "flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium",
|
|
59833
|
+
children: [
|
|
59834
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "w-4 h-4" }),
|
|
59835
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "New Chat" })
|
|
59836
|
+
]
|
|
59837
|
+
}
|
|
59838
|
+
),
|
|
59839
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59840
|
+
"button",
|
|
59841
|
+
{
|
|
59842
|
+
onClick: () => setIsSidebarOpen(!isSidebarOpen),
|
|
59843
|
+
className: "relative flex items-center gap-2 px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors text-sm font-medium",
|
|
59844
|
+
"aria-label": "Toggle chat history",
|
|
59845
|
+
children: isSidebarOpen ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
59846
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" }),
|
|
59847
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Hide History" })
|
|
59848
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
59849
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "w-4 h-4" }),
|
|
59850
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Chat History" }),
|
|
59851
|
+
newChatCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 bg-red-500 text-white text-xs rounded-full px-2 py-0.5 font-medium", children: newChatCount })
|
|
59852
|
+
] })
|
|
59853
|
+
}
|
|
59854
|
+
)
|
|
59855
|
+
] })
|
|
59856
|
+
] })
|
|
59857
|
+
] }),
|
|
59858
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59859
|
+
"main",
|
|
59860
|
+
{
|
|
59861
|
+
ref: containerRef,
|
|
59862
|
+
className: `flex-1 bg-gray-50/50 min-h-0 ${displayMessages.length === 0 && !isTransitioning ? "flex items-center justify-center" : "overflow-y-auto"}`,
|
|
59863
|
+
children: !activeThreadId && displayMessages.length === 0 && !isTransitioning ? (
|
|
59864
|
+
/* Centered welcome and input for new chat */
|
|
59865
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-3xl mx-auto px-3 sm:px-4 md:px-6 flex flex-col items-center justify-center space-y-8 sm:space-y-12 -mt-8 sm:-mt-16", children: [
|
|
59866
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
59867
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center mb-4 sm:mb-6 md:mb-8", children: /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", size: "2xl", animate: true }) }),
|
|
59868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "text-lg sm:text-xl md:text-2xl lg:text-3xl font-semibold text-gray-900 px-2 sm:px-4", children: [
|
|
59869
|
+
typedText,
|
|
59870
|
+
typedText.length < currentGreeting.length && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-pulse", children: "|" })
|
|
59871
|
+
] })
|
|
59872
|
+
] }),
|
|
59873
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
59874
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative bg-white rounded-2xl sm:rounded-3xl shadow-lg border border-gray-200 focus-within:border-gray-300 transition-all duration-200", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-end gap-2 p-3 sm:p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 relative", children: [
|
|
59875
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59876
|
+
"textarea",
|
|
59877
|
+
{
|
|
59878
|
+
ref: textareaRef,
|
|
59879
|
+
value: inputValue,
|
|
59880
|
+
onChange: (e) => {
|
|
59881
|
+
const newValue = e.target.value;
|
|
59882
|
+
setInputValue(newValue);
|
|
59883
|
+
if (newValue.length > 0 && !hasStartedTyping) {
|
|
59884
|
+
trackTypingStart();
|
|
59885
|
+
}
|
|
59886
|
+
if (newValue.length > 0) {
|
|
59887
|
+
trackTypingProgress(newValue);
|
|
59888
|
+
}
|
|
59889
|
+
if (newValue.length === 0) {
|
|
59890
|
+
resetTypingState();
|
|
59891
|
+
}
|
|
59892
|
+
},
|
|
59893
|
+
onKeyDown: handleKeyDown,
|
|
59894
|
+
onFocus: () => {
|
|
59895
|
+
trackCoreEvent("AI Agent Input Focused", {
|
|
59896
|
+
line_id: lineId,
|
|
59897
|
+
company_id: companyId,
|
|
59898
|
+
shift_id: shiftId,
|
|
59899
|
+
active_thread_id: activeThreadId,
|
|
59900
|
+
has_existing_messages: messages.length > 0,
|
|
59901
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
59902
|
+
});
|
|
59903
|
+
},
|
|
59904
|
+
placeholder: "Ask me anything about your shop-floor",
|
|
59905
|
+
className: "w-full resize-none bg-transparent px-3 sm:px-4 py-3 sm:py-2 pr-12 sm:pr-14 focus:outline-none placeholder-gray-500 text-gray-900 text-sm sm:text-base leading-relaxed",
|
|
59906
|
+
rows: 1,
|
|
59907
|
+
style: { minHeight: "40px", maxHeight: "120px" }
|
|
59908
|
+
}
|
|
59909
|
+
),
|
|
59910
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 sm:right-3 bottom-2 sm:bottom-2 flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
59911
|
+
"button",
|
|
59912
|
+
{
|
|
59913
|
+
type: "submit",
|
|
59914
|
+
disabled: !inputValue.trim() || isCurrentThreadLoading,
|
|
59915
|
+
className: "inline-flex items-center justify-center w-8 h-8 sm:w-9 sm:h-9 bg-gray-900 text-white rounded-full hover:bg-gray-800 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-gray-500/20",
|
|
59916
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-4 h-4" })
|
|
59917
|
+
}
|
|
59918
|
+
) })
|
|
59919
|
+
] }) }) }),
|
|
59920
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4 mt-2 text-xs text-gray-400", children: [
|
|
59921
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center", children: isCurrentThreadLoading ? "You can type your next message while Axel responds" : "Press Enter to send \u2022 Shift+Enter for new line" }),
|
|
59922
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
59923
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isCurrentThreadLoading ? "bg-orange-500" : "bg-green-500"}` }),
|
|
59924
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: isCurrentThreadLoading ? "Responding..." : "Connected" })
|
|
59925
|
+
] })
|
|
59926
|
+
] })
|
|
59927
|
+
] }) })
|
|
59928
|
+
] })
|
|
59929
|
+
) : isTransitioning ? (
|
|
59930
|
+
/* Transition state - show user message first, then thinking */
|
|
59931
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-4xl mx-auto px-3 sm:px-4 md:px-6 py-4 sm:py-6 pb-24 sm:pb-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 sm:space-y-6", children: [
|
|
59932
|
+
displayMessages.map((message, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
59933
|
+
"div",
|
|
59934
|
+
{
|
|
59935
|
+
className: `flex gap-2 sm:gap-3 md:gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
|
|
59936
|
+
children: [
|
|
59937
|
+
message.role === "assistant" && /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, {}),
|
|
59938
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `max-w-none w-full group ${message.role === "user" ? "order-1" : ""}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
59939
|
+
"div",
|
|
59940
|
+
{
|
|
59941
|
+
className: `relative px-3 sm:px-4 md:px-5 py-3 sm:py-4 rounded-xl sm:rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-600 text-white max-w-[90%] sm:max-w-[85%] ml-auto" : "bg-white border border-gray-200/80 max-w-full"}`,
|
|
59942
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
|
|
59943
|
+
message.role === "assistant" ? message.id === -1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
59944
|
+
"div",
|
|
59945
|
+
{
|
|
59946
|
+
className: "formatted-content",
|
|
59947
|
+
dangerouslySetInnerHTML: { __html: formatMessage(message.content) }
|
|
59948
|
+
}
|
|
59949
|
+
) : renderAssistantContent(message.content) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
|
|
59950
|
+
message.id === -1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
|
|
59951
|
+
] })
|
|
59952
|
+
}
|
|
59953
|
+
) })
|
|
59954
|
+
]
|
|
59955
|
+
},
|
|
59956
|
+
message.id === -1 ? "streaming-message" : `${message.id}-${index}`
|
|
59957
|
+
)),
|
|
59958
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
59959
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, {}),
|
|
59960
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
|
|
59961
|
+
] })
|
|
59962
|
+
] }) })
|
|
59963
|
+
) : (
|
|
59964
|
+
/* Regular chat view with messages */
|
|
59965
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-4xl mx-auto px-3 sm:px-4 md:px-6 py-3 sm:py-6 pb-20 sm:pb-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 sm:space-y-6", children: [
|
|
59966
|
+
displayMessages.map((message, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
59967
|
+
"div",
|
|
59968
|
+
{
|
|
59969
|
+
className: `flex gap-2 sm:gap-3 md:gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
|
|
59970
|
+
children: [
|
|
59971
|
+
message.role === "assistant" && /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, {}),
|
|
59972
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `max-w-none w-full group ${message.role === "user" ? "order-1" : ""}`, children: [
|
|
59973
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
59974
|
+
"div",
|
|
59975
|
+
{
|
|
59976
|
+
className: `relative px-3 sm:px-4 md:px-5 py-2.5 sm:py-4 rounded-2xl sm:rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-500 sm:bg-blue-600 text-white max-w-[85%] sm:max-w-[85%] ml-auto" : "bg-gray-100 sm:bg-white sm:border sm:border-gray-200/80 max-w-full"}`,
|
|
59977
|
+
children: [
|
|
59978
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
|
|
59979
|
+
message.role === "assistant" ? message.id === -1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
59980
|
+
"div",
|
|
59981
|
+
{
|
|
59982
|
+
className: "formatted-content",
|
|
59983
|
+
dangerouslySetInnerHTML: { __html: formatMessage(message.content) }
|
|
59984
|
+
}
|
|
59985
|
+
) : renderAssistantContent(message.content) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
|
|
59986
|
+
message.id === -1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
|
|
59987
|
+
] }),
|
|
59988
|
+
message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
59989
|
+
"button",
|
|
59990
|
+
{
|
|
59991
|
+
onClick: () => copyToClipboard(message.content, message.id.toString()),
|
|
59992
|
+
className: "absolute top-2 sm:top-3 right-2 sm:right-3 opacity-100 sm:opacity-0 group-hover:opacity-100 transition-opacity duration-200 p-1 sm:p-1.5 hover:bg-gray-100 rounded-lg",
|
|
59993
|
+
title: "Copy message",
|
|
59994
|
+
children: copiedMessageId === message.id.toString() ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4 text-green-600" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4 text-gray-500" })
|
|
59995
|
+
}
|
|
59996
|
+
),
|
|
59997
|
+
message.reasoning && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "mt-3 pt-3 border-t border-gray-200", children: [
|
|
59998
|
+
/* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer text-sm text-gray-600 hover:text-gray-800", children: "View reasoning" }),
|
|
59999
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-sm text-gray-600", children: message.reasoning })
|
|
60000
|
+
] })
|
|
60001
|
+
]
|
|
60002
|
+
}
|
|
60003
|
+
),
|
|
60004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `mt-1.5 sm:mt-2 flex items-center gap-2 text-xs text-gray-400 ${message.role === "user" ? "justify-end" : "justify-start"}`, children: [
|
|
60005
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime5(message.created_at) }),
|
|
60006
|
+
message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
60007
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-1 h-1 bg-gray-300 rounded-full" }),
|
|
60008
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Axel" })
|
|
60009
|
+
] })
|
|
60010
|
+
] })
|
|
60011
|
+
] })
|
|
60012
|
+
]
|
|
60013
|
+
},
|
|
60014
|
+
message.id === -1 ? "streaming-message" : `${message.id}-${index}`
|
|
60015
|
+
)),
|
|
60016
|
+
lastError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
60017
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-xl bg-red-100 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-6 h-6 text-red-600" }) }) }),
|
|
60018
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-red-50 border border-red-200 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: [
|
|
60019
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-red-800 text-sm", children: lastError }),
|
|
60020
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60021
|
+
"button",
|
|
60022
|
+
{
|
|
60023
|
+
onClick: () => setLastError(null),
|
|
60024
|
+
className: "mt-2 text-xs text-red-600 hover:text-red-800 underline",
|
|
60025
|
+
children: "Dismiss"
|
|
60026
|
+
}
|
|
60027
|
+
)
|
|
60028
|
+
] })
|
|
60029
|
+
] }),
|
|
60030
|
+
isCurrentThreadLoading && !currentStreaming.message && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
60031
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, {}),
|
|
60032
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
|
|
60033
|
+
] }),
|
|
60034
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
|
|
60035
|
+
] }) })
|
|
60036
|
+
)
|
|
60037
|
+
}
|
|
60038
|
+
),
|
|
60039
|
+
(displayMessages.length > 0 || isTransitioning) && /* @__PURE__ */ jsxRuntime.jsx("footer", { className: `fixed bottom-0 left-0 right-0 bg-gradient-to-t from-white via-white/95 to-transparent sm:from-gray-50/50 sm:to-transparent pointer-events-none ${isSidebarOpen ? "lg:right-80" : "right-0"}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-4xl mx-auto p-2 sm:p-4 md:p-6 pointer-events-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
60040
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60041
|
+
"div",
|
|
60042
|
+
{
|
|
60043
|
+
className: `relative bg-white rounded-xl sm:rounded-3xl shadow-md sm:shadow-lg border border-gray-200 focus-within:border-blue-400 sm:focus-within:border-gray-300 transition-all duration-200 ${isTransitioning ? "animate-slide-down" : ""}`,
|
|
60044
|
+
style: isTransitioning ? {
|
|
60045
|
+
animation: "slideDown 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards"
|
|
60046
|
+
} : {},
|
|
60047
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-end gap-1 sm:gap-2 p-2 sm:p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 relative", children: [
|
|
60048
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60049
|
+
"textarea",
|
|
60050
|
+
{
|
|
60051
|
+
ref: textareaRef,
|
|
60052
|
+
value: inputValue,
|
|
60053
|
+
onChange: (e) => {
|
|
60054
|
+
const newValue = e.target.value;
|
|
60055
|
+
setInputValue(newValue);
|
|
60056
|
+
if (newValue.length > 0 && !hasStartedTyping) {
|
|
60057
|
+
trackTypingStart();
|
|
60058
|
+
}
|
|
60059
|
+
if (newValue.length > 0) {
|
|
60060
|
+
trackTypingProgress(newValue);
|
|
60061
|
+
}
|
|
60062
|
+
if (newValue.length === 0) {
|
|
60063
|
+
resetTypingState();
|
|
60064
|
+
}
|
|
60065
|
+
},
|
|
60066
|
+
onKeyDown: handleKeyDown,
|
|
60067
|
+
onFocus: () => {
|
|
60068
|
+
trackCoreEvent("AI Agent Input Focused", {
|
|
60069
|
+
line_id: lineId,
|
|
60070
|
+
company_id: companyId,
|
|
60071
|
+
shift_id: shiftId,
|
|
60072
|
+
active_thread_id: activeThreadId,
|
|
60073
|
+
has_existing_messages: messages.length > 0,
|
|
60074
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
60075
|
+
});
|
|
60076
|
+
},
|
|
60077
|
+
placeholder: "Message Axel...",
|
|
60078
|
+
className: "w-full resize-none bg-transparent px-2 sm:px-4 py-2 sm:py-2 pr-10 sm:pr-14 focus:outline-none placeholder-gray-400 sm:placeholder-gray-500 text-gray-900 text-sm sm:text-base leading-relaxed",
|
|
60079
|
+
rows: 1,
|
|
60080
|
+
style: { minHeight: "36px", maxHeight: "120px" }
|
|
60081
|
+
}
|
|
60082
|
+
),
|
|
60083
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-1 sm:right-3 bottom-1 sm:bottom-2 flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
60084
|
+
"button",
|
|
60085
|
+
{
|
|
60086
|
+
type: "submit",
|
|
60087
|
+
disabled: !inputValue.trim() || isCurrentThreadLoading,
|
|
60088
|
+
className: "inline-flex items-center justify-center w-7 h-7 sm:w-9 sm:h-9 bg-blue-500 sm:bg-gray-900 text-white rounded-full active:scale-95 sm:hover:bg-gray-800 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-blue-400/20 sm:focus:ring-gray-500/20",
|
|
60089
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4" })
|
|
60090
|
+
}
|
|
60091
|
+
) })
|
|
60092
|
+
] }) })
|
|
60093
|
+
}
|
|
60094
|
+
),
|
|
60095
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden sm:flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4 mt-2 text-xs text-gray-400", children: [
|
|
60096
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center", children: isCurrentThreadLoading ? "You can type your next message while Axel responds" : "Press Enter to send \u2022 Shift+Enter for new line" }),
|
|
60097
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
60098
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isCurrentThreadLoading ? "bg-orange-500" : "bg-green-500"}` }),
|
|
60099
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: isCurrentThreadLoading ? "Responding..." : "Connected" })
|
|
60100
|
+
] })
|
|
60101
|
+
] })
|
|
60102
|
+
] }) }) })
|
|
60103
|
+
] }),
|
|
60104
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `fixed inset-0 sm:inset-auto sm:right-0 sm:top-0 z-20 h-screen transition-transform duration-300 ease-in-out ${isSidebarOpen ? "translate-x-0" : "translate-x-full"}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full sm:w-96 lg:w-80 h-full bg-white sm:border-l sm:border-gray-200 shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
60105
|
+
ThreadSidebar,
|
|
60106
|
+
{
|
|
60107
|
+
activeThreadId,
|
|
60108
|
+
onSelectThread: setActiveThreadId,
|
|
60109
|
+
onNewThread: handleNewThread,
|
|
60110
|
+
className: "h-full"
|
|
60111
|
+
}
|
|
60112
|
+
) }) }),
|
|
60113
|
+
isSidebarOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
60114
|
+
"div",
|
|
60115
|
+
{
|
|
60116
|
+
className: "fixed inset-0 bg-black bg-opacity-30 z-10 lg:hidden",
|
|
60117
|
+
onClick: () => setIsSidebarOpen(false)
|
|
60118
|
+
}
|
|
60119
|
+
)
|
|
60120
|
+
] });
|
|
60121
|
+
};
|
|
60122
|
+
var AIAgentView_default = AIAgentView;
|
|
58073
60123
|
var S3Service = class {
|
|
58074
60124
|
constructor(config) {
|
|
58075
60125
|
this.s3Client = null;
|
|
@@ -58524,87 +60574,9 @@ var streamProxyConfig = {
|
|
|
58524
60574
|
responseLimit: false
|
|
58525
60575
|
}
|
|
58526
60576
|
};
|
|
58527
|
-
var ThreadSidebar = ({
|
|
58528
|
-
activeThreadId,
|
|
58529
|
-
onSelectThread,
|
|
58530
|
-
onNewThread,
|
|
58531
|
-
className = ""
|
|
58532
|
-
}) => {
|
|
58533
|
-
const { threads, isLoading, error, deleteThread: deleteThread2 } = useThreads();
|
|
58534
|
-
const [deletingId, setDeletingId] = React24.useState(null);
|
|
58535
|
-
const handleDelete = async (e, threadId) => {
|
|
58536
|
-
e.stopPropagation();
|
|
58537
|
-
if (confirm("Are you sure you want to delete this conversation?")) {
|
|
58538
|
-
setDeletingId(threadId);
|
|
58539
|
-
try {
|
|
58540
|
-
await deleteThread2(threadId);
|
|
58541
|
-
if (activeThreadId === threadId) {
|
|
58542
|
-
onNewThread();
|
|
58543
|
-
}
|
|
58544
|
-
} catch (error2) {
|
|
58545
|
-
console.error("Error deleting thread:", error2);
|
|
58546
|
-
alert("Failed to delete conversation. Please try again.");
|
|
58547
|
-
} finally {
|
|
58548
|
-
setDeletingId(null);
|
|
58549
|
-
}
|
|
58550
|
-
}
|
|
58551
|
-
};
|
|
58552
|
-
const formatDate2 = (dateString) => {
|
|
58553
|
-
const date = new Date(dateString);
|
|
58554
|
-
const now2 = /* @__PURE__ */ new Date();
|
|
58555
|
-
const diffMs = now2.getTime() - date.getTime();
|
|
58556
|
-
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
58557
|
-
if (diffDays === 0) {
|
|
58558
|
-
return "Today";
|
|
58559
|
-
} else if (diffDays === 1) {
|
|
58560
|
-
return "Yesterday";
|
|
58561
|
-
} else if (diffDays < 7) {
|
|
58562
|
-
return date.toLocaleDateString("en-US", { weekday: "short" });
|
|
58563
|
-
} else {
|
|
58564
|
-
return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
58565
|
-
}
|
|
58566
|
-
};
|
|
58567
|
-
if (error) {
|
|
58568
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `p-4 text-red-600 text-sm ${className}`, children: "Failed to load conversations" });
|
|
58569
|
-
}
|
|
58570
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col h-screen bg-gray-50 border-r border-gray-200 ${className}`, children: [
|
|
58571
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 p-4 border-b border-gray-200", children: [
|
|
58572
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Chat History" }),
|
|
58573
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-1", children: "Your previous conversations" })
|
|
58574
|
-
] }),
|
|
58575
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto min-h-0", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "sm" }) }) : threads.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-gray-500 text-sm", children: "No conversations yet" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2", children: threads.map((thread) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58576
|
-
"div",
|
|
58577
|
-
{
|
|
58578
|
-
onClick: () => onSelectThread(thread.id),
|
|
58579
|
-
className: `group relative flex items-start gap-3 px-4 py-3 cursor-pointer transition-all ${activeThreadId === thread.id ? "bg-blue-50 border-l-4 border-blue-600 hover:bg-blue-100" : "hover:bg-gray-100 border-l-4 border-transparent"}`,
|
|
58580
|
-
children: [
|
|
58581
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: `w-4 h-4 mt-0.5 flex-shrink-0 ${activeThreadId === thread.id ? "text-blue-600" : "text-gray-400"}` }),
|
|
58582
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
58583
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: `text-sm font-medium truncate ${activeThreadId === thread.id ? "text-blue-900" : "text-gray-900"}`, children: thread.title || "Untitled Chat" }),
|
|
58584
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-xs mt-0.5 ${activeThreadId === thread.id ? "text-blue-700" : "text-gray-500"}`, children: formatDate2(thread.created_at) })
|
|
58585
|
-
] }),
|
|
58586
|
-
deletingId === thread.id ? /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
58587
|
-
"button",
|
|
58588
|
-
{
|
|
58589
|
-
onClick: (e) => handleDelete(e, thread.id),
|
|
58590
|
-
className: "flex-shrink-0 opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-200 rounded transition-all",
|
|
58591
|
-
title: "Delete conversation",
|
|
58592
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-3.5 h-3.5 text-gray-500" })
|
|
58593
|
-
}
|
|
58594
|
-
)
|
|
58595
|
-
]
|
|
58596
|
-
},
|
|
58597
|
-
thread.id
|
|
58598
|
-
)) }) }),
|
|
58599
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 p-4 border-t border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 text-center", children: [
|
|
58600
|
-
threads.length,
|
|
58601
|
-
" conversation",
|
|
58602
|
-
threads.length !== 1 ? "s" : ""
|
|
58603
|
-
] }) })
|
|
58604
|
-
] });
|
|
58605
|
-
};
|
|
58606
60577
|
|
|
58607
60578
|
exports.ACTION_NAMES = ACTION_NAMES;
|
|
60579
|
+
exports.AIAgentView = AIAgentView_default;
|
|
58608
60580
|
exports.AcceptInvite = AcceptInvite;
|
|
58609
60581
|
exports.AcceptInviteView = AcceptInviteView_default;
|
|
58610
60582
|
exports.AdvancedFilterDialog = AdvancedFilterDialog;
|