@hef2024/llmasaservice-ui 0.19.0 → 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,8 @@ var ChatPanel = ({
1631
1675
  const continueChat = (suggestion) => {
1632
1676
  setThinkingBlocks([]);
1633
1677
  setCurrentThinkingIndex(0);
1678
+ setError(null);
1679
+ setResponse("");
1634
1680
  if (emailInput && isEmailAddress(emailInput) && !emailInputSet) {
1635
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;
1636
1682
  setEmailInputSet(true);
@@ -1725,7 +1771,11 @@ var ChatPanel = ({
1725
1771
  true,
1726
1772
  service,
1727
1773
  convId,
1728
- controller
1774
+ controller,
1775
+ void 0,
1776
+ // onComplete
1777
+ (errorMsg) => handleError(errorMsg)
1778
+ // onError
1729
1779
  );
1730
1780
  setLastPrompt(nextPromptToSend);
1731
1781
  setLastMessages(messagesAndHistory);
@@ -2044,6 +2094,15 @@ var ChatPanel = ({
2044
2094
  className: "llm-panel" + (theme === "light" ? "" : " dark-theme")
2045
2095
  },
2046
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
+ )),
2047
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(
2048
2107
  ReactMarkdown,
2049
2108
  {
@@ -2353,6 +2412,7 @@ var ChatPanel = ({
2353
2412
  setIsToolInfoModalOpen(false);
2354
2413
  setToolInfoData(null);
2355
2414
  setJustReset(true);
2415
+ setError(null);
2356
2416
  setLastController(new AbortController());
2357
2417
  buttonActionRegistry.current.clear();
2358
2418
  setTimeout(() => {
@@ -3314,9 +3374,6 @@ var DialogFooter = ({
3314
3374
  // src/AIChatPanel.tsx
3315
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" }));
3316
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" }));
3317
- 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" }));
3318
- 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" }));
3319
- 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" }));
3320
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" }));
3321
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" }));
3322
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" }));
@@ -3324,6 +3381,8 @@ var CheckIcon = () => /* @__PURE__ */ React11.createElement("svg", { xmlns: "htt
3324
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" }));
3325
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" }));
3326
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" }));
3327
3386
  var ChatInput = React11.memo(({
3328
3387
  placeholder,
3329
3388
  idle,
@@ -3627,6 +3686,8 @@ var AIChatPanel = ({
3627
3686
  const [newConversationConfirm, setNewConversationConfirm] = useState6(false);
3628
3687
  const [justReset, setJustReset] = useState6(false);
3629
3688
  const [copiedCallId, setCopiedCallId] = useState6(null);
3689
+ const [feedbackCallId, setFeedbackCallId] = useState6(null);
3690
+ const [error, setError] = useState6(null);
3630
3691
  const bottomRef = useRef5(null);
3631
3692
  const responseAreaRef = useRef5(null);
3632
3693
  const [userHasScrolled, setUserHasScrolled] = useState6(false);
@@ -3665,7 +3726,8 @@ var AIChatPanel = ({
3665
3726
  idle,
3666
3727
  lastCallId,
3667
3728
  stop,
3668
- setResponse
3729
+ setResponse,
3730
+ error: llmError
3669
3731
  } = llmResult;
3670
3732
  const toolList = llmResult.toolList || [];
3671
3733
  const toolsLoading = llmResult.toolsLoading || false;
@@ -3740,8 +3802,8 @@ var AIChatPanel = ({
3740
3802
  }
3741
3803
  console.warn("ensureConversation - No ID in response");
3742
3804
  return "";
3743
- }).catch((error) => {
3744
- console.error("Error creating new conversation", error);
3805
+ }).catch((error2) => {
3806
+ console.error("Error creating new conversation", error2);
3745
3807
  return "";
3746
3808
  });
3747
3809
  }
@@ -3833,16 +3895,59 @@ var AIChatPanel = ({
3833
3895
  }
3834
3896
  return displayPrompt;
3835
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]);
3836
3922
  const copyToClipboard = useCallback2((text, callId) => __async(void 0, null, function* () {
3837
3923
  try {
3838
3924
  const cleanText = text.replace(/<[^>]*>/g, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/#{1,6}\s/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
3839
3925
  yield navigator.clipboard.writeText(cleanText);
3840
3926
  setCopiedCallId(callId);
3841
3927
  setTimeout(() => setCopiedCallId(null), 2e3);
3928
+ yield interactionClicked(callId, "copy");
3842
3929
  } catch (err) {
3843
3930
  console.error("Failed to copy:", err);
3844
3931
  }
3845
- }), []);
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]);
3846
3951
  const scrollToBottom = useCallback2(() => {
3847
3952
  var _a;
3848
3953
  if (scrollRAFRef.current) {
@@ -3864,7 +3969,9 @@ var AIChatPanel = ({
3864
3969
  console.log("AIChatPanel.continueChat called with:", promptText);
3865
3970
  setThinkingBlocks([]);
3866
3971
  setCurrentThinkingIndex(0);
3972
+ setError(null);
3867
3973
  setUserHasScrolled(false);
3974
+ setResponse("");
3868
3975
  if (!idle) {
3869
3976
  stop(lastController);
3870
3977
  setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
@@ -3935,7 +4042,37 @@ ${followOnPrompt}`;
3935
4042
  // group_id from agent config
3936
4043
  convId,
3937
4044
  // Use the conversation ID from ensureConversation
3938
- 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
+ }
3939
4076
  );
3940
4077
  setLastMessages(messagesAndHistory);
3941
4078
  if (convId && onConversationCreated) {
@@ -3961,7 +4098,8 @@ ${followOnPrompt}`;
3961
4098
  ensureConversation,
3962
4099
  dataWithExtras,
3963
4100
  scrollToBottom,
3964
- onConversationCreated
4101
+ onConversationCreated,
4102
+ setResponse
3965
4103
  ]);
3966
4104
  const handleSuggestionClick = useCallback2((question) => {
3967
4105
  continueChat(question);
@@ -3994,6 +4132,7 @@ ${followOnPrompt}`;
3994
4132
  setJustReset(true);
3995
4133
  setLastController(new AbortController());
3996
4134
  setUserHasScrolled(false);
4135
+ setError(null);
3997
4136
  setTimeout(() => {
3998
4137
  var _a;
3999
4138
  setJustReset(false);
@@ -4021,6 +4160,7 @@ ${followOnPrompt}`;
4021
4160
  prevIdleRef.current = idle;
4022
4161
  if (wasStreaming && isNowIdle && !hasNotifiedCompletionRef.current) {
4023
4162
  hasNotifiedCompletionRef.current = true;
4163
+ setIsLoading(false);
4024
4164
  const currentHistory = latestHistoryRef.current;
4025
4165
  const currentLastKey = lastKeyRef.current;
4026
4166
  const currentLastCallId = lastCallIdRef.current;
@@ -4102,6 +4242,37 @@ ${followOnPrompt}`;
4102
4242
  continueChat(initialPrompt);
4103
4243
  }
4104
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]);
4105
4276
  const CodeBlock = useCallback2((_a) => {
4106
4277
  var _b = _a, { node, inline, className, children } = _b, props = __objRest(_b, ["node", "inline", "className", "children"]);
4107
4278
  const match = /language-(\w+)/.exec(className || "");
@@ -4115,7 +4286,13 @@ ${followOnPrompt}`;
4115
4286
  String(children).replace(/\n$/, "")
4116
4287
  ) : /* @__PURE__ */ React11.createElement("code", __spreadValues({ className }, props), children);
4117
4288
  }, [prismStyle]);
4118
- 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
+ }, []);
4119
4296
  if (!agentId || !onAgentChange) return null;
4120
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);
4121
4298
  const agentOption = agentOptions.find((opt) => opt.value === agentId);
@@ -4159,14 +4336,13 @@ ${followOnPrompt}`;
4159
4336
  onClick: () => {
4160
4337
  onAgentChange(agentId);
4161
4338
  setTimeout(() => {
4162
- var _a;
4163
- (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "auto" });
4164
- }, 50);
4339
+ scrollToBottom();
4340
+ }, 100);
4165
4341
  }
4166
4342
  },
4167
4343
  "Switch"
4168
4344
  ));
4169
- }, [onAgentChange, agentOptions, currentAgentId]);
4345
+ });
4170
4346
  const markdownComponents = useMemo2(() => ({
4171
4347
  code: CodeBlock,
4172
4348
  "agent-suggestion": (_a) => {
@@ -4209,8 +4385,16 @@ ${followOnPrompt}`;
4209
4385
  ))), /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-thinking__content" }, cleanContentForDisplay(currentBlock.content)));
4210
4386
  }, [thinkingBlocks, currentThinkingIndex, cleanContentForDisplay]);
4211
4387
  const panelClasses = ["ai-chat-panel", theme === "dark" ? "dark-theme" : ""].filter(Boolean).join(" ");
4212
- 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) => {
4213
- const isLastEntry = index === Object.keys(history).length - 1;
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) => {
4397
+ const isLastEntry = index === entries.length - 1;
4214
4398
  const isSystemMessage = prompt.startsWith("__system__:");
4215
4399
  const { cleanedText } = processThinkingTags(entry.content);
4216
4400
  const processedContent = processActions(cleanedText);
@@ -4230,31 +4414,33 @@ ${followOnPrompt}`;
4230
4414
  components: markdownComponents
4231
4415
  },
4232
4416
  processedContent
4233
- ))), idle && !isLoading && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message__actions" }, /* @__PURE__ */ React11.createElement(Tooltip, { content: copiedCallId === entry.callId ? "Copied!" : "Copy" }, /* @__PURE__ */ React11.createElement(
4234
- Button,
4417
+ ))), (!isLastEntry || !isLoading) && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-message__actions" }, /* @__PURE__ */ React11.createElement(
4418
+ "button",
4235
4419
  {
4236
- variant: "ghost",
4237
- size: "icon",
4238
- 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"
4239
4423
  },
4240
- /* @__PURE__ */ React11.createElement(CopyIcon, null)
4241
- )), thumbsUpClick && /* @__PURE__ */ React11.createElement(Tooltip, { content: "Good response" }, /* @__PURE__ */ React11.createElement(
4242
- 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",
4243
4427
  {
4244
- variant: "ghost",
4245
- size: "icon",
4246
- 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
4247
4432
  },
4248
- /* @__PURE__ */ React11.createElement(ThumbsUpIcon, null)
4249
- )), thumbsDownClick && /* @__PURE__ */ React11.createElement(Tooltip, { content: "Poor response" }, /* @__PURE__ */ React11.createElement(
4250
- 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",
4251
4436
  {
4252
- variant: "ghost",
4253
- size: "icon",
4254
- 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
4255
4441
  },
4256
- /* @__PURE__ */ React11.createElement(ThumbsDownIcon, null)
4257
- )))));
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
+ ))));
4258
4444
  }), followOnQuestionsState.length > 0 && idle && !isLoading && /* @__PURE__ */ React11.createElement("div", { className: "ai-chat-suggestions" }, followOnQuestionsState.map((question, index) => /* @__PURE__ */ React11.createElement(
4259
4445
  Button,
4260
4446
  {
@@ -4506,7 +4692,7 @@ var PlusIcon = () => /* @__PURE__ */ React12.createElement("svg", { width: "16",
4506
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" }));
4507
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" }));
4508
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" }));
4509
- 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" }));
4510
4696
  var LoadingDotIcon = () => /* @__PURE__ */ React12.createElement("span", { className: "ai-agent-panel__loading-dot" });
4511
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" }));
4512
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" }));
@@ -5790,7 +5976,7 @@ var AIAgentPanel = React12.forwardRef(({
5790
5976
  onClick: (e) => handleCloseConversation(activeConv.conversationId, e),
5791
5977
  title: "Close conversation"
5792
5978
  },
5793
- /* @__PURE__ */ React12.createElement(CloseIcon, null)
5979
+ /* @__PURE__ */ React12.createElement(CloseIcon2, null)
5794
5980
  )
5795
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(
5796
5982
  "div",