@hef2024/llmasaservice-ui 0.19.1 → 0.20.0

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.mjs CHANGED
@@ -234,6 +234,7 @@ var ChatPanel = ({
234
234
  const [alwaysApprovedTools, setAlwaysApprovedTools] = useState2([]);
235
235
  const [thinkingBlocks, setThinkingBlocks] = useState2([]);
236
236
  const [currentThinkingIndex, setCurrentThinkingIndex] = useState2(0);
237
+ const [error, setError] = useState2(null);
237
238
  const [userResizedHeight, setUserResizedHeight] = useState2(null);
238
239
  const [pendingButtonAttachments, setPendingButtonAttachments] = useState2([]);
239
240
  const actionMatchRegistry = useRef(/* @__PURE__ */ new Map());
@@ -535,10 +536,10 @@ var ChatPanel = ({
535
536
  const allTools = results.flat();
536
537
  setToolList(allTools);
537
538
  setToolsFetchError(false);
538
- } catch (error) {
539
+ } catch (error2) {
539
540
  console.error(
540
541
  "An error occurred while processing tool fetches:",
541
- error
542
+ error2
542
543
  );
543
544
  setToolList([]);
544
545
  setToolsFetchError(true);
@@ -548,7 +549,7 @@ var ChatPanel = ({
548
549
  });
549
550
  fetchAndSetTools();
550
551
  }, [mcpServers, publicAPIUrl]);
551
- const { send, response, idle, stop, lastCallId, setResponse } = useLLM({
552
+ const llmResult = useLLM({
552
553
  project_id,
553
554
  customer: currentCustomer,
554
555
  url,
@@ -561,6 +562,41 @@ var ChatPanel = ({
561
562
  };
562
563
  })
563
564
  });
565
+ const { send, response, idle, stop, lastCallId, setResponse, error: llmError } = llmResult;
566
+ const handleError = useCallback((errorMessage, historyKey) => {
567
+ console.log("[ChatPanel] Error detected:", errorMessage);
568
+ if (errorMessage.includes("413") || errorMessage.toLowerCase().includes("content too large")) {
569
+ setError({
570
+ message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
571
+ code: "413"
572
+ });
573
+ } else if (errorMessage.toLowerCase().includes("network error") || errorMessage.toLowerCase().includes("fetch")) {
574
+ setError({
575
+ message: "Network error. Please check your connection and try again.",
576
+ code: "NETWORK_ERROR"
577
+ });
578
+ } else {
579
+ setError({
580
+ message: errorMessage,
581
+ code: "UNKNOWN_ERROR"
582
+ });
583
+ }
584
+ setIsLoading(false);
585
+ const keyToUse = historyKey || lastKey;
586
+ if (keyToUse) {
587
+ setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
588
+ [keyToUse]: {
589
+ content: `Error: ${errorMessage}`,
590
+ callId: lastCallId || ""
591
+ }
592
+ }));
593
+ }
594
+ }, [lastKey, lastCallId]);
595
+ useEffect2(() => {
596
+ if (llmError && llmError.trim()) {
597
+ handleError(llmError);
598
+ }
599
+ }, [llmError, handleError]);
564
600
  const processActionsOnContent = useCallback((content, context) => {
565
601
  let workingContent = content;
566
602
  const buttonAttachments = [];
@@ -897,8 +933,8 @@ var ChatPanel = ({
897
933
  return action;
898
934
  }
899
935
  }).filter(Boolean);
900
- } catch (error) {
901
- console.error("Error parsing actions string:", error);
936
+ } catch (error2) {
937
+ console.error("Error parsing actions string:", error2);
902
938
  actions2 = [];
903
939
  }
904
940
  }
@@ -1086,8 +1122,8 @@ var ChatPanel = ({
1086
1122
  console.error(`No content returned from tool ${req.toolName}`);
1087
1123
  return null;
1088
1124
  }
1089
- } catch (error) {
1090
- console.error(`Error processing tool ${req.toolName}:`, error);
1125
+ } catch (error2) {
1126
+ console.error(`Error processing tool ${req.toolName}:`, error2);
1091
1127
  return null;
1092
1128
  }
1093
1129
  }));
@@ -1129,10 +1165,14 @@ var ChatPanel = ({
1129
1165
  true,
1130
1166
  service,
1131
1167
  currentConversation,
1132
- lastController
1168
+ lastController,
1169
+ void 0,
1170
+ // onComplete
1171
+ (errorMsg) => handleError(errorMsg)
1172
+ // onError
1133
1173
  );
1134
- } catch (error) {
1135
- console.error("Error in processing all tools:", error);
1174
+ } catch (error2) {
1175
+ console.error("Error in processing all tools:", error2);
1136
1176
  setIsLoading(false);
1137
1177
  }
1138
1178
  });
@@ -1264,8 +1304,8 @@ var ChatPanel = ({
1264
1304
  if (typeof interactionClicked === "function") {
1265
1305
  interactionClicked(lastCallId, "action");
1266
1306
  }
1267
- } catch (error) {
1268
- console.error("Error executing clickCode:", error);
1307
+ } catch (error2) {
1308
+ console.error("Error executing clickCode:", error2);
1269
1309
  }
1270
1310
  }
1271
1311
  };
@@ -1360,10 +1400,10 @@ var ChatPanel = ({
1360
1400
  if (typeof interactionClicked === "function") {
1361
1401
  interactionClicked(lastCallId, "action");
1362
1402
  }
1363
- } catch (error) {
1403
+ } catch (error2) {
1364
1404
  console.error(
1365
1405
  "Error executing clickCode via delegation:",
1366
- error
1406
+ error2
1367
1407
  );
1368
1408
  }
1369
1409
  }
@@ -1475,7 +1515,11 @@ var ChatPanel = ({
1475
1515
  true,
1476
1516
  service,
1477
1517
  convId,
1478
- controller
1518
+ controller,
1519
+ void 0,
1520
+ // onComplete
1521
+ (errorMsg) => handleError(errorMsg)
1522
+ // onError
1479
1523
  );
1480
1524
  setLastPrompt(initialPrompt);
1481
1525
  setLastMessages(messages);
@@ -1571,8 +1615,8 @@ var ChatPanel = ({
1571
1615
  return newConvo.id;
1572
1616
  }
1573
1617
  return "";
1574
- }).catch((error) => {
1575
- console.error("Error creating new conversation", error);
1618
+ }).catch((error2) => {
1619
+ console.error("Error creating new conversation", error2);
1576
1620
  return "";
1577
1621
  });
1578
1622
  }
@@ -1621,7 +1665,7 @@ var ChatPanel = ({
1621
1665
  customerEmail: updatedValues.customer_user_email
1622
1666
  })
1623
1667
  }).catch(
1624
- (error) => console.error("Failed to update conversation:", error)
1668
+ (error2) => console.error("Failed to update conversation:", error2)
1625
1669
  );
1626
1670
  }
1627
1671
  });
@@ -1631,6 +1675,7 @@ var ChatPanel = ({
1631
1675
  const continueChat = (suggestion) => {
1632
1676
  setThinkingBlocks([]);
1633
1677
  setCurrentThinkingIndex(0);
1678
+ setError(null);
1634
1679
  setResponse("");
1635
1680
  if (emailInput && isEmailAddress(emailInput) && !emailInputSet) {
1636
1681
  const newId = (currentCustomer == null ? void 0 : currentCustomer.customer_id) && currentCustomer.customer_id !== "" && currentCustomer.customer_id !== (currentCustomer == null ? void 0 : currentCustomer.customer_user_email) ? currentCustomer.customer_id : emailInput;
@@ -1726,7 +1771,11 @@ var ChatPanel = ({
1726
1771
  true,
1727
1772
  service,
1728
1773
  convId,
1729
- controller
1774
+ controller,
1775
+ void 0,
1776
+ // onComplete
1777
+ (errorMsg) => handleError(errorMsg)
1778
+ // onError
1730
1779
  );
1731
1780
  setLastPrompt(nextPromptToSend);
1732
1781
  setLastMessages(messagesAndHistory);
@@ -2045,6 +2094,15 @@ var ChatPanel = ({
2045
2094
  className: "llm-panel" + (theme === "light" ? "" : " dark-theme")
2046
2095
  },
2047
2096
  title && title !== "" ? /* @__PURE__ */ React3.createElement("div", { className: "title" }, title) : null,
2097
+ error && /* @__PURE__ */ React3.createElement("div", { className: "error-banner" }, /* @__PURE__ */ React3.createElement("div", { className: "error-banner__icon" }, /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React3.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React3.createElement("line", { x1: "12", x2: "12", y1: "8", y2: "12" }), /* @__PURE__ */ React3.createElement("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" }))), /* @__PURE__ */ React3.createElement("div", { className: "error-banner__content" }, /* @__PURE__ */ React3.createElement("div", { className: "error-banner__message" }, error.message), error.code === "413" && /* @__PURE__ */ React3.createElement("div", { className: "error-banner__hint" }, "Try starting a new conversation or reducing the amount of information being sent.")), /* @__PURE__ */ React3.createElement(
2098
+ "button",
2099
+ {
2100
+ className: "error-banner__close",
2101
+ onClick: () => setError(null),
2102
+ "aria-label": "Dismiss error"
2103
+ },
2104
+ /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React3.createElement("line", { x1: "18", x2: "6", y1: "6", y2: "18" }), /* @__PURE__ */ React3.createElement("line", { x1: "6", x2: "18", y1: "6", y2: "18" }))
2105
+ )),
2048
2106
  /* @__PURE__ */ React3.createElement("div", { className: "responseArea", ref: responseAreaRef }, initialMessage && initialMessage !== "" ? /* @__PURE__ */ React3.createElement("div", { className: "history-entry" }, /* @__PURE__ */ React3.createElement("div", { className: "response" }, /* @__PURE__ */ React3.createElement(
2049
2107
  ReactMarkdown,
2050
2108
  {
@@ -2354,6 +2412,7 @@ var ChatPanel = ({
2354
2412
  setIsToolInfoModalOpen(false);
2355
2413
  setToolInfoData(null);
2356
2414
  setJustReset(true);
2415
+ setError(null);
2357
2416
  setLastController(new AbortController());
2358
2417
  buttonActionRegistry.current.clear();
2359
2418
  setTimeout(() => {
@@ -3315,9 +3374,6 @@ var DialogFooter = ({
3315
3374
  // src/AIChatPanel.tsx
3316
3375
  var ArrowUpIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M12 19V5M5 12l7-7 7 7" }));
3317
3376
  var StopIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "ai-chat-icon" }, /* @__PURE__ */ React11.createElement("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }));
3318
- var CopyIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), /* @__PURE__ */ React11.createElement("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" }));
3319
- var ThumbsUpIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }));
3320
- var ThumbsDownIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" }));
3321
3377
  var ChevronDownIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "m6 9 6 6 6-6" }));
3322
3378
  var ChevronUpIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "m18 15-6-6-6 6" }));
3323
3379
  var AgentIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M12 8V4H8" }), /* @__PURE__ */ React11.createElement("rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }), /* @__PURE__ */ React11.createElement("path", { d: "M2 14h2" }), /* @__PURE__ */ React11.createElement("path", { d: "M20 14h2" }), /* @__PURE__ */ React11.createElement("path", { d: "M15 13v2" }), /* @__PURE__ */ React11.createElement("path", { d: "M9 13v2" }));
@@ -3325,6 +3381,8 @@ var CheckIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "htt
3325
3381
  var BrainIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z" }), /* @__PURE__ */ React11.createElement("path", { d: "M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z" }));
3326
3382
  var SearchIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("circle", { cx: "11", cy: "11", r: "8" }), /* @__PURE__ */ React11.createElement("path", { d: "m21 21-4.3-4.3" }));
3327
3383
  var LLMAsAServiceLogo = () => /* @__PURE__ */ React11.createElement("svg", { width: "16", height: "16", viewBox: "0 0 72 72", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React11.createElement("ellipse", { cx: "14.0868", cy: "59.2146", rx: "7.8261", ry: "7.7854", fill: "#2487D8" }), /* @__PURE__ */ React11.createElement("ellipse", { cx: "24.9013", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ React11.createElement("ellipse", { cx: "45.391", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ React11.createElement("ellipse", { cx: "65.8813", cy: "43.0776", rx: "6.11858", ry: "6.08676", fill: "#2487D8" }), /* @__PURE__ */ React11.createElement("ellipse", { cx: "35.1461", cy: "26.5327", rx: "4.41103", ry: "4.3878", fill: "#2487D8" }), /* @__PURE__ */ React11.createElement("ellipse", { cx: "55.6364", cy: "26.5327", rx: "4.41103", ry: "4.3878", fill: "#2487D8" }), /* @__PURE__ */ React11.createElement("ellipse", { cx: "45.391", cy: "10.3959", rx: "2.70351", ry: "2.68919", fill: "#2487D8" }));
3384
+ var AlertCircleIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React11.createElement("line", { x1: "12", x2: "12", y1: "8", y2: "12" }), /* @__PURE__ */ React11.createElement("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" }));
3385
+ var CloseIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("line", { x1: "18", x2: "6", y1: "6", y2: "18" }), /* @__PURE__ */ React11.createElement("line", { x1: "6", x2: "18", y1: "6", y2: "18" }));
3328
3386
  var ChatInput = React11.memo(({
3329
3387
  placeholder,
3330
3388
  idle,
@@ -3628,6 +3686,8 @@ var AIChatPanel = ({
3628
3686
  const [newConversationConfirm, setNewConversationConfirm] = useState6(false);
3629
3687
  const [justReset, setJustReset] = useState6(false);
3630
3688
  const [copiedCallId, setCopiedCallId] = useState6(null);
3689
+ const [feedbackCallId, setFeedbackCallId] = useState6(null);
3690
+ const [error, setError] = useState6(null);
3631
3691
  const bottomRef = useRef5(null);
3632
3692
  const responseAreaRef = useRef5(null);
3633
3693
  const [userHasScrolled, setUserHasScrolled] = useState6(false);
@@ -3666,7 +3726,8 @@ var AIChatPanel = ({
3666
3726
  idle,
3667
3727
  lastCallId,
3668
3728
  stop,
3669
- setResponse
3729
+ setResponse,
3730
+ error: llmError
3670
3731
  } = llmResult;
3671
3732
  const toolList = llmResult.toolList || [];
3672
3733
  const toolsLoading = llmResult.toolsLoading || false;
@@ -3741,8 +3802,8 @@ var AIChatPanel = ({
3741
3802
  }
3742
3803
  console.warn("ensureConversation - No ID in response");
3743
3804
  return "";
3744
- }).catch((error) => {
3745
- console.error("Error creating new conversation", error);
3805
+ }).catch((error2) => {
3806
+ console.error("Error creating new conversation", error2);
3746
3807
  return "";
3747
3808
  });
3748
3809
  }
@@ -3834,16 +3895,59 @@ var AIChatPanel = ({
3834
3895
  }
3835
3896
  return displayPrompt;
3836
3897
  }, [hideRagContextInPrompt]);
3898
+ const interactionClicked = useCallback2((callId, action, emailaddress = "", comment = "") => __async(void 0, null, function* () {
3899
+ var _a, _b;
3900
+ console.log(`[AIChatPanel] Interaction: ${action} for callId: ${callId}`);
3901
+ const convId = currentConversation || (yield ensureConversation());
3902
+ const finalCallId = callId || convId;
3903
+ const isEmailAddress = (str) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str);
3904
+ const email = emailaddress && emailaddress !== "" ? emailaddress : isEmailAddress((_a = customer == null ? void 0 : customer.customer_user_email) != null ? _a : "") ? customer == null ? void 0 : customer.customer_user_email : isEmailAddress((_b = customer == null ? void 0 : customer.customer_id) != null ? _b : "") ? customer == null ? void 0 : customer.customer_id : "";
3905
+ try {
3906
+ yield fetch(`${publicAPIUrl}/feedback/${finalCallId}/${action}`, {
3907
+ method: "POST",
3908
+ headers: {
3909
+ "Content-Type": "application/json"
3910
+ },
3911
+ body: JSON.stringify({
3912
+ project_id: project_id != null ? project_id : "",
3913
+ conversation_id: convId != null ? convId : "",
3914
+ email,
3915
+ comment
3916
+ })
3917
+ });
3918
+ } catch (err) {
3919
+ console.error("[AIChatPanel] Failed to send feedback:", err);
3920
+ }
3921
+ }), [currentConversation, ensureConversation, customer, project_id, publicAPIUrl]);
3837
3922
  const copyToClipboard = useCallback2((text, callId) => __async(void 0, null, function* () {
3838
3923
  try {
3839
3924
  const cleanText = text.replace(/<[^>]*>/g, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/#{1,6}\s/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
3840
3925
  yield navigator.clipboard.writeText(cleanText);
3841
3926
  setCopiedCallId(callId);
3842
3927
  setTimeout(() => setCopiedCallId(null), 2e3);
3928
+ yield interactionClicked(callId, "copy");
3843
3929
  } catch (err) {
3844
3930
  console.error("Failed to copy:", err);
3845
3931
  }
3846
- }), []);
3932
+ }), [interactionClicked]);
3933
+ const handleThumbsUp = useCallback2((callId) => __async(void 0, null, function* () {
3934
+ console.log("[AIChatPanel] Thumbs up clicked:", callId);
3935
+ setFeedbackCallId({ callId, type: "up" });
3936
+ setTimeout(() => setFeedbackCallId(null), 2e3);
3937
+ yield interactionClicked(callId, "thumbsup");
3938
+ if (thumbsUpClick) {
3939
+ thumbsUpClick(callId);
3940
+ }
3941
+ }), [thumbsUpClick, interactionClicked]);
3942
+ const handleThumbsDown = useCallback2((callId) => __async(void 0, null, function* () {
3943
+ console.log("[AIChatPanel] Thumbs down clicked:", callId);
3944
+ setFeedbackCallId({ callId, type: "down" });
3945
+ setTimeout(() => setFeedbackCallId(null), 2e3);
3946
+ yield interactionClicked(callId, "thumbsdown");
3947
+ if (thumbsDownClick) {
3948
+ thumbsDownClick(callId);
3949
+ }
3950
+ }), [thumbsDownClick, interactionClicked]);
3847
3951
  const scrollToBottom = useCallback2(() => {
3848
3952
  var _a;
3849
3953
  if (scrollRAFRef.current) {
@@ -3865,6 +3969,7 @@ var AIChatPanel = ({
3865
3969
  console.log("AIChatPanel.continueChat called with:", promptText);
3866
3970
  setThinkingBlocks([]);
3867
3971
  setCurrentThinkingIndex(0);
3972
+ setError(null);
3868
3973
  setUserHasScrolled(false);
3869
3974
  setResponse("");
3870
3975
  if (!idle) {
@@ -3937,7 +4042,37 @@ ${followOnPrompt}`;
3937
4042
  // group_id from agent config
3938
4043
  convId,
3939
4044
  // Use the conversation ID from ensureConversation
3940
- newController
4045
+ newController,
4046
+ void 0,
4047
+ // onComplete
4048
+ (errorMsg) => {
4049
+ console.log("[AIChatPanel] Error callback triggered:", errorMsg);
4050
+ if (errorMsg.includes("413") || errorMsg.toLowerCase().includes("content too large")) {
4051
+ setError({
4052
+ message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
4053
+ code: "413"
4054
+ });
4055
+ } else if (errorMsg.toLowerCase().includes("network error") || errorMsg.toLowerCase().includes("fetch")) {
4056
+ setError({
4057
+ message: "Network error. Please check your connection and try again.",
4058
+ code: "NETWORK_ERROR"
4059
+ });
4060
+ } else {
4061
+ setError({
4062
+ message: errorMsg,
4063
+ code: "UNKNOWN_ERROR"
4064
+ });
4065
+ }
4066
+ setIsLoading(false);
4067
+ if (promptKey) {
4068
+ setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
4069
+ [promptKey]: {
4070
+ content: `Error: ${errorMsg}`,
4071
+ callId: lastCallId || ""
4072
+ }
4073
+ }));
4074
+ }
4075
+ }
3941
4076
  );
3942
4077
  setLastMessages(messagesAndHistory);
3943
4078
  if (convId && onConversationCreated) {
@@ -3997,6 +4132,7 @@ ${followOnPrompt}`;
3997
4132
  setJustReset(true);
3998
4133
  setLastController(new AbortController());
3999
4134
  setUserHasScrolled(false);
4135
+ setError(null);
4000
4136
  setTimeout(() => {
4001
4137
  var _a;
4002
4138
  setJustReset(false);
@@ -4024,6 +4160,7 @@ ${followOnPrompt}`;
4024
4160
  prevIdleRef.current = idle;
4025
4161
  if (wasStreaming && isNowIdle && !hasNotifiedCompletionRef.current) {
4026
4162
  hasNotifiedCompletionRef.current = true;
4163
+ setIsLoading(false);
4027
4164
  const currentHistory = latestHistoryRef.current;
4028
4165
  const currentLastKey = lastKeyRef.current;
4029
4166
  const currentLastCallId = lastCallIdRef.current;
@@ -4105,6 +4242,37 @@ ${followOnPrompt}`;
4105
4242
  continueChat(initialPrompt);
4106
4243
  }
4107
4244
  }, [initialPrompt, continueChat]);
4245
+ useEffect7(() => {
4246
+ if (llmError && llmError.trim()) {
4247
+ console.log("[AIChatPanel] Error detected:", llmError);
4248
+ const errorMessage = llmError;
4249
+ if (errorMessage.includes("413") || errorMessage.toLowerCase().includes("content too large")) {
4250
+ setError({
4251
+ message: "The context is too large to process. Please start a new conversation or reduce the amount of context.",
4252
+ code: "413"
4253
+ });
4254
+ } else if (errorMessage.toLowerCase().includes("network error") || errorMessage.toLowerCase().includes("fetch")) {
4255
+ setError({
4256
+ message: "Network error. Please check your connection and try again.",
4257
+ code: "NETWORK_ERROR"
4258
+ });
4259
+ } else {
4260
+ setError({
4261
+ message: errorMessage,
4262
+ code: "UNKNOWN_ERROR"
4263
+ });
4264
+ }
4265
+ setIsLoading(false);
4266
+ if (lastKey) {
4267
+ setHistory((prev) => __spreadProps(__spreadValues({}, prev), {
4268
+ [lastKey]: {
4269
+ content: `Error: ${errorMessage}`,
4270
+ callId: lastCallId || ""
4271
+ }
4272
+ }));
4273
+ }
4274
+ }
4275
+ }, [llmError, lastKey, lastCallId]);
4108
4276
  const CodeBlock = useCallback2((_a) => {
4109
4277
  var _b = _a, { node, inline, className, children } = _b, props = __objRest(_b, ["node", "inline", "className", "children"]);
4110
4278
  const match = /language-(\w+)/.exec(className || "");
@@ -4118,7 +4286,13 @@ ${followOnPrompt}`;
4118
4286
  String(children).replace(/\n$/, "")
4119
4287
  ) : /* @__PURE__ */ React11.createElement("code", __spreadValues({ className }, props), children);
4120
4288
  }, [prismStyle]);
4121
- const AgentSuggestionCard = useCallback2(({ agentId, agentName, reason }) => {
4289
+ const AgentSuggestionCard = React11.memo(({ agentId, agentName, reason }) => {
4290
+ useEffect7(() => {
4291
+ const timer = setTimeout(() => {
4292
+ scrollToBottom();
4293
+ }, 100);
4294
+ return () => clearTimeout(timer);
4295
+ }, []);
4122
4296
  if (!agentId || !onAgentChange) return null;
4123
4297
  const isValidUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(agentId);
4124
4298
  const agentOption = agentOptions.find((opt) => opt.value === agentId);
@@ -4162,14 +4336,13 @@ ${followOnPrompt}`;
4162
4336
  onClick: () => {
4163
4337
  onAgentChange(agentId);
4164
4338
  setTimeout(() => {
4165
- var _a;
4166
- (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "auto" });
4167
- }, 50);
4339
+ scrollToBottom();
4340
+ }, 100);
4168
4341
  }
4169
4342
  },
4170
4343
  "Switch"
4171
4344
  ));
4172
- }, [onAgentChange, agentOptions, currentAgentId]);
4345
+ });
4173
4346
  const markdownComponents = useMemo2(() => ({
4174
4347
  code: CodeBlock,
4175
4348
  "agent-suggestion": (_a) => {
@@ -4212,7 +4385,15 @@ ${followOnPrompt}`;
4212
4385
  ))), /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-thinking__content" }, cleanContentForDisplay(currentBlock.content)));
4213
4386
  }, [thinkingBlocks, currentThinkingIndex, cleanContentForDisplay]);
4214
4387
  const panelClasses = ["ai-chat-panel", theme === "dark" ? "dark-theme" : ""].filter(Boolean).join(" ");
4215
- return /* @__PURE__ */ React11.createElement("div", { className: panelClasses }, title && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-panel__title" }, title), /* @__PURE__ */ React11.createElement(ScrollArea, { className: "ai-chat-panel__messages", ref: responseAreaRef }, initialMessage && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message ai-chat-message--assistant" }, /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message__content" }, /* @__PURE__ */ React11.createElement(ReactMarkdown2, { remarkPlugins: [remarkGfm2], rehypePlugins: [rehypeRaw2] }, initialMessage))), Object.entries(history).map(([prompt, entry], index, entries) => {
4388
+ return /* @__PURE__ */ React11.createElement("div", { className: panelClasses }, title && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-panel__title" }, title), error && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-error-banner" }, /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-error-banner__icon" }, /* @__PURE__ */ React11.createElement(AlertCircleIcon, null)), /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-error-banner__content" }, /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-error-banner__message" }, error.message), error.code === "413" && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-error-banner__hint" }, "Try starting a new conversation or reducing the amount of information being sent.")), /* @__PURE__ */ React11.createElement(
4389
+ "button",
4390
+ {
4391
+ className: "ai-chat-error-banner__close",
4392
+ onClick: () => setError(null),
4393
+ "aria-label": "Dismiss error"
4394
+ },
4395
+ /* @__PURE__ */ React11.createElement(CloseIcon, null)
4396
+ )), /* @__PURE__ */ React11.createElement(ScrollArea, { className: "ai-chat-panel__messages", ref: responseAreaRef }, initialMessage && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message ai-chat-message--assistant" }, /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message__content" }, /* @__PURE__ */ React11.createElement(ReactMarkdown2, { remarkPlugins: [remarkGfm2], rehypePlugins: [rehypeRaw2] }, initialMessage))), Object.entries(history).map(([prompt, entry], index, entries) => {
4216
4397
  const isLastEntry = index === entries.length - 1;
4217
4398
  const isSystemMessage = prompt.startsWith("__system__:");
4218
4399
  const { cleanedText } = processThinkingTags(entry.content);
@@ -4233,31 +4414,33 @@ ${followOnPrompt}`;
4233
4414
  components: markdownComponents
4234
4415
  },
4235
4416
  processedContent
4236
- ))), idle && !isLoading && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message__actions" }, /* @__PURE__ */ React11.createElement(Tooltip, { content: copiedCallId === entry.callId ? "Copied!" : "Copy" }, /* @__PURE__ */ React11.createElement(
4237
- Button,
4417
+ ))), (!isLastEntry || !isLoading) && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message__actions" }, /* @__PURE__ */ React11.createElement(
4418
+ "button",
4238
4419
  {
4239
- variant: "ghost",
4240
- size: "icon",
4241
- onClick: () => copyToClipboard(entry.content, entry.callId)
4420
+ className: "ai-chat-action-button",
4421
+ onClick: () => copyToClipboard(entry.content, entry.callId),
4422
+ title: copiedCallId === entry.callId ? "Copied!" : "Copy"
4242
4423
  },
4243
- /* @__PURE__ */ React11.createElement(CopyIcon, null)
4244
- )), thumbsUpClick && /* @__PURE__ */ React11.createElement(Tooltip, { content: "Good response" }, /* @__PURE__ */ React11.createElement(
4245
- Button,
4424
+ copiedCallId === entry.callId ? /* @__PURE__ */ React11.createElement("span", { style: { fontSize: "11px", fontWeight: 500 } }, "Copied!") : /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), /* @__PURE__ */ React11.createElement("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" }))
4425
+ ), /* @__PURE__ */ React11.createElement(
4426
+ "button",
4246
4427
  {
4247
- variant: "ghost",
4248
- size: "icon",
4249
- onClick: () => thumbsUpClick(entry.callId)
4428
+ className: "ai-chat-action-button",
4429
+ onClick: () => handleThumbsUp(entry.callId),
4430
+ title: (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "up" ? "Thanks!" : "Good response",
4431
+ style: (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "up" ? { color: "#22c55e" } : void 0
4250
4432
  },
4251
- /* @__PURE__ */ React11.createElement(ThumbsUpIcon, null)
4252
- )), thumbsDownClick && /* @__PURE__ */ React11.createElement(Tooltip, { content: "Poor response" }, /* @__PURE__ */ React11.createElement(
4253
- Button,
4433
+ (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "up" ? /* @__PURE__ */ React11.createElement("span", { style: { fontSize: "11px", fontWeight: 500 } }, "Thanks!") : /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }))
4434
+ ), /* @__PURE__ */ React11.createElement(
4435
+ "button",
4254
4436
  {
4255
- variant: "ghost",
4256
- size: "icon",
4257
- onClick: () => thumbsDownClick(entry.callId)
4437
+ className: "ai-chat-action-button",
4438
+ onClick: () => handleThumbsDown(entry.callId),
4439
+ title: (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "down" ? "Thanks!" : "Poor response",
4440
+ style: (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "down" ? { color: "#ef4444" } : void 0
4258
4441
  },
4259
- /* @__PURE__ */ React11.createElement(ThumbsDownIcon, null)
4260
- )))));
4442
+ (feedbackCallId == null ? void 0 : feedbackCallId.callId) === entry.callId && (feedbackCallId == null ? void 0 : feedbackCallId.type) === "down" ? /* @__PURE__ */ React11.createElement("span", { style: { fontSize: "11px", fontWeight: 500 } }, "Thanks!") : /* @__PURE__ */ React11.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "ai-chat-icon-sm" }, /* @__PURE__ */ React11.createElement("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" }))
4443
+ ))));
4261
4444
  }), followOnQuestionsState.length > 0 && idle && !isLoading && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-suggestions" }, followOnQuestionsState.map((question, index) => /* @__PURE__ */ React11.createElement(
4262
4445
  Button,
4263
4446
  {
@@ -4509,7 +4692,7 @@ var PlusIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "16",
4509
4692
  var ChevronLeftIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("path", { d: "M10 12L6 8l4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
4510
4693
  var ChevronRightIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("path", { d: "M6 12l4-4-4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
4511
4694
  var MessageIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("path", { d: "M14 10a1.333 1.333 0 0 1-1.333 1.333H4L2 14V3.333A1.333 1.333 0 0 1 3.333 2h9.334A1.333 1.333 0 0 1 14 3.333V10Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
4512
- var CloseIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("path", { d: "M9 3L3 9M3 3l6 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
4695
+ var CloseIcon2 = () => /* @__PURE__ */ React12.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("path", { d: "M9 3L3 9M3 3l6 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }));
4513
4696
  var LoadingDotIcon = () => /* @__PURE__ */ React12.createElement("span", { className: "ai-agent-panel__loading-dot" });
4514
4697
  var SidebarIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("rect", { x: "2", y: "2", width: "12", height: "12", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }), /* @__PURE__ */ React12.createElement("path", { d: "M6 2v12", stroke: "currentColor", strokeWidth: "1.5" }));
4515
4698
  var SparkleIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React12.createElement("path", { d: "M8 1v3M8 12v3M3 8H0M16 8h-3M12.95 3.05l-2.12 2.12M5.17 10.83l-2.12 2.12M12.95 12.95l-2.12-2.12M5.17 5.17L3.05 3.05", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }), /* @__PURE__ */ React12.createElement("circle", { cx: "8", cy: "8", r: "2", fill: "currentColor" }));
@@ -5793,7 +5976,7 @@ var AIAgentPanel = React12.forwardRef(({
5793
5976
  onClick: (e) => handleCloseConversation(activeConv.conversationId, e),
5794
5977
  title: "Close conversation"
5795
5978
  },
5796
- /* @__PURE__ */ React12.createElement(CloseIcon, null)
5979
+ /* @__PURE__ */ React12.createElement(CloseIcon2, null)
5797
5980
  )
5798
5981
  ))), conversationsLoading ? /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__loading" }, /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ React12.createElement("span", null, "Loading conversations...")) : conversationsError ? /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__empty" }, /* @__PURE__ */ React12.createElement("p", null, "Error: ", conversationsError), /* @__PURE__ */ React12.createElement(Button, { variant: "secondary", size: "sm", onClick: handleRefreshConversations }, "Retry")) : groupedConversations.length === 0 && activeConversationsList.length === 0 ? /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__empty" }, /* @__PURE__ */ React12.createElement(MessageIcon, null), /* @__PURE__ */ React12.createElement("p", null, "No conversations yet"), /* @__PURE__ */ React12.createElement("p", { className: "ai-agent-panel__empty-hint" }, "Start chatting to create your first conversation")) : /* @__PURE__ */ React12.createElement(React12.Fragment, null, activeConversationsList.length > 0 && groupedConversations.some((g) => g.count > 0) && /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__group-divider" }), groupedConversations.map((group) => /* @__PURE__ */ React12.createElement("div", { key: group.label, className: "ai-agent-panel__group" }, /* @__PURE__ */ React12.createElement(
5799
5982
  "div",