@gendive/chatllm 0.17.22 → 0.17.24

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.
@@ -1257,7 +1257,7 @@ var useProject = (options) => {
1257
1257
  }
1258
1258
  };
1259
1259
  loadProjects();
1260
- }, [useExternalStorage, onLoadProjects, onError, storageKey]);
1260
+ }, [enabled, useExternalStorage, onLoadProjects, onError, storageKey]);
1261
1261
  const createProject = (0, import_react4.useCallback)(
1262
1262
  async (data) => {
1263
1263
  const now = Date.now();
@@ -1499,11 +1499,6 @@ var parsePollFromContent = (content) => {
1499
1499
  allowOther,
1500
1500
  required: false
1501
1501
  };
1502
- console.log("[pollParser] Parsed poll:", {
1503
- question: pollQuestion.question,
1504
- optionsCount: pollQuestion.options.length,
1505
- options: pollQuestion.options.map((o) => o.label)
1506
- });
1507
1502
  polls.push(pollQuestion);
1508
1503
  }
1509
1504
  cleanContent = cleanContent.replace(match[0], "");
@@ -1511,7 +1506,6 @@ var parsePollFromContent = (content) => {
1511
1506
  if (polls.length === 0) {
1512
1507
  return { pollBlock: null, cleanContent: content };
1513
1508
  }
1514
- console.log("[pollParser] Total polls parsed:", polls.length, polls.map((p) => p.question));
1515
1509
  cleanContent = cleanContent.replace(/\n{3,}/g, "\n\n");
1516
1510
  return {
1517
1511
  pollBlock: {
@@ -1796,7 +1790,8 @@ var useChatUI = (options) => {
1796
1790
  }),
1797
1791
  [globalMemoryConfig, storageKey]
1798
1792
  );
1799
- const globalMemory = useGlobalMemoryEnabled ? useGlobalMemory(memoryOptions) : null;
1793
+ const globalMemoryRaw = useGlobalMemory(memoryOptions);
1794
+ const globalMemory = useGlobalMemoryEnabled ? globalMemoryRaw : null;
1800
1795
  const stableToolCall = (0, import_react5.useCallback)(
1801
1796
  (name, params) => onToolCallRef.current(name, params),
1802
1797
  []
@@ -2415,7 +2410,7 @@ ${finalContent}`;
2415
2410
  ...userContentParts && { contentParts: userContentParts }
2416
2411
  };
2417
2412
  const capturedSessionId = sessionId;
2418
- const currentSession2 = sessions.find((s) => s.id === capturedSessionId);
2413
+ const currentSession2 = sessionsRef.current.find((s) => s.id === capturedSessionId);
2419
2414
  const existingMessages = currentSession2?.messages || [];
2420
2415
  const isFirstMessage = !existingMessages.length;
2421
2416
  const contextSummary = currentSession2?.compressionState?.contextSummary || currentSession2?.contextSummary;
@@ -2432,6 +2427,9 @@ ${finalContent}`;
2432
2427
  setInput("");
2433
2428
  setQuotedText(null);
2434
2429
  setSelectedAction(null);
2430
+ attachments.forEach((a) => {
2431
+ if (a.previewUrl) URL.revokeObjectURL(a.previewUrl);
2432
+ });
2435
2433
  setAttachments([]);
2436
2434
  setSessions(
2437
2435
  (prev) => prev.map((s) => {
@@ -2803,6 +2801,26 @@ ${attachmentContext}
2803
2801
  } catch {
2804
2802
  }
2805
2803
  }
2804
+ const saveMessagesOnEarlyReturn = () => {
2805
+ if (!useExternalStorage || !capturedSessionId) return;
2806
+ queueMicrotask(() => {
2807
+ const latestSession = sessionsRef.current.find((s) => s.id === capturedSessionId);
2808
+ if (!latestSession) return;
2809
+ const latestMessages = latestSession.messages;
2810
+ const assistantMsg = [...latestMessages].reverse().find((m) => m.role === "assistant");
2811
+ const userMsg = latestMessages.find((m) => m.role === "user" && m.content === finalContent);
2812
+ const assistantContent = assistantMsg?.content || "";
2813
+ if (assistantContent && onSaveMessagesRef.current) {
2814
+ onSaveMessagesRef.current(capturedSessionId, [
2815
+ { role: "user", message: finalContent, ...userMsg?.contentParts && { contentParts: userMsg.contentParts } },
2816
+ { role: "assistant", message: assistantContent, ...assistantMsg?.contentParts && { contentParts: assistantMsg.contentParts } }
2817
+ ]).catch((e) => console.error("[useChatUI] Failed to save messages:", e));
2818
+ }
2819
+ if (latestSession.messages.length > 0) {
2820
+ writeSessionCache(storageKey, latestSession);
2821
+ }
2822
+ });
2823
+ };
2806
2824
  if (!shouldSkipSkillParsing) {
2807
2825
  const assistantContent = accumulatedContent;
2808
2826
  const { skillCall: detectedSkill, cleanContent: skillCleanContent } = parseSkillCallFromContent(assistantContent);
@@ -2906,6 +2924,7 @@ ${attachmentContext}
2906
2924
  })
2907
2925
  );
2908
2926
  if (resultType === "image" || resultType === "file") {
2927
+ saveMessagesOnEarlyReturn();
2909
2928
  setIsLoading(false);
2910
2929
  abortControllerRef.current = null;
2911
2930
  return;
@@ -2916,11 +2935,13 @@ ${attachmentContext}
2916
2935
  shouldContinue = decision === "continue";
2917
2936
  }
2918
2937
  if (!shouldContinue) {
2938
+ saveMessagesOnEarlyReturn();
2919
2939
  setIsLoading(false);
2920
2940
  abortControllerRef.current = null;
2921
2941
  return;
2922
2942
  }
2923
2943
  skipNextSkillParsingRef.current = true;
2944
+ saveMessagesOnEarlyReturn();
2924
2945
  const feedbackPrompt = resultType === "error" ? `\uB3C4\uAD6C "${toolName}" \uC2E4\uD589 \uC911 \uC624\uB958 \uBC1C\uC0DD: ${result.content}
2925
2946
 
2926
2947
  \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC624\uB958\uB97C \uC548\uB0B4\uD574\uC8FC\uC138\uC694. skill_use \uD0DC\uADF8\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uB9C8\uC138\uC694.` : `\uB3C4\uAD6C "${toolName}" \uACB0\uACFC:
@@ -2956,6 +2977,7 @@ ${result.content}
2956
2977
  })
2957
2978
  );
2958
2979
  if (streamedReport) {
2980
+ saveMessagesOnEarlyReturn();
2959
2981
  setIsLoading(false);
2960
2982
  abortControllerRef.current = null;
2961
2983
  return;
@@ -2966,11 +2988,13 @@ ${result.content}
2966
2988
  shouldContinueSkill = decision === "continue";
2967
2989
  }
2968
2990
  if (!shouldContinueSkill) {
2991
+ saveMessagesOnEarlyReturn();
2969
2992
  setIsLoading(false);
2970
2993
  abortControllerRef.current = null;
2971
2994
  return;
2972
2995
  }
2973
2996
  skipNextSkillParsingRef.current = true;
2997
+ saveMessagesOnEarlyReturn();
2974
2998
  const resultPrompt = `\uC2A4\uD0AC "${detectedSkill.name}" \uC2E4\uD589 \uACB0\uACFC:
2975
2999
 
2976
3000
  ${result.content}
@@ -6507,6 +6531,7 @@ var MarkdownRenderer = ({
6507
6531
  if (hasUnfinishedPoll) {
6508
6532
  processedContent += "\n\xA7POLL_LOADING\xA7";
6509
6533
  }
6534
+ processedContent = processedContent.replace(/<skill_use[^>]*>[\s\S]*?<\/skill_use>/gi, "");
6510
6535
  processedContent = processedContent.replace(UNCLOSED_SKILL_TAG_REGEX, "");
6511
6536
  const codeBlocks = [];
6512
6537
  processedContent = processedContent.replace(CODE_BLOCK_REGEX, (match, lang, code) => {
@@ -6838,7 +6863,7 @@ var MarkdownRenderer = ({
6838
6863
  flushBlockquote();
6839
6864
  flushTable();
6840
6865
  return elements;
6841
- }, [content, onChoiceClick, sources]);
6866
+ }, [content, onChoiceClick, sources, showThinking, thinkingDefaultOpen]);
6842
6867
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6843
6868
  "div",
6844
6869
  {
@@ -7236,7 +7261,10 @@ var PollCard = ({
7236
7261
  (0, import_react13.useEffect)(() => {
7237
7262
  if (typeof window === "undefined") return;
7238
7263
  const handleKeyDown = (e) => {
7239
- if (e.key === "Escape") handleSkip();
7264
+ if (e.key !== "Escape") return;
7265
+ const modalOpen = document.querySelector(".chatllm-settings-overlay, .chatllm-disclaimer-overlay, .chatllm-project-settings-overlay");
7266
+ if (modalOpen) return;
7267
+ handleSkip();
7240
7268
  };
7241
7269
  window.addEventListener("keydown", handleKeyDown);
7242
7270
  return () => window.removeEventListener("keydown", handleKeyDown);
@@ -8208,13 +8236,6 @@ var MessageBubble = ({
8208
8236
  const displayContent = isAssistant && relevantAlternatives && relevantAlternatives.length > 0 && relevantActiveIndex > 0 ? relevantAlternatives[relevantActiveIndex - 1]?.content || message.content : message.content;
8209
8237
  const displayModel = isAssistant && relevantAlternatives && relevantAlternatives.length > 0 && relevantActiveIndex > 0 ? relevantAlternatives[relevantActiveIndex - 1]?.model : message.model;
8210
8238
  const displaySources = isAssistant && relevantAlternatives && relevantAlternatives.length > 0 && relevantActiveIndex > 0 ? relevantAlternatives[relevantActiveIndex - 1]?.sources : message.sources;
8211
- const handleMouseUp = () => {
8212
- if (!onQuote) return;
8213
- const selection = typeof window !== "undefined" ? window.getSelection() : null;
8214
- const text = selection?.toString().trim();
8215
- if (text && text.length > 0) {
8216
- }
8217
- };
8218
8239
  if (isUser) {
8219
8240
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
8220
8241
  "div",
@@ -8228,7 +8249,6 @@ var MessageBubble = ({
8228
8249
  },
8229
8250
  onMouseEnter: () => setShowActions(true),
8230
8251
  onMouseLeave: () => setShowActions(false),
8231
- onMouseUp: handleMouseUp,
8232
8252
  children: [
8233
8253
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
8234
8254
  "div",
@@ -8349,7 +8369,6 @@ var MessageBubble = ({
8349
8369
  },
8350
8370
  onMouseEnter: () => setShowActions(true),
8351
8371
  onMouseLeave: () => setShowActions(false),
8352
- onMouseUp: handleMouseUp,
8353
8372
  children: [
8354
8373
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
8355
8374
  "div",
@@ -8452,7 +8471,7 @@ var MessageBubble = ({
8452
8471
  ]
8453
8472
  }
8454
8473
  ),
8455
- message.contentParts?.length && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
8474
+ !!message.contentParts?.length && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
8456
8475
  ContentPartRenderer,
8457
8476
  {
8458
8477
  parts: message.contentParts,
@@ -9089,6 +9108,9 @@ var SettingsModal = ({
9089
9108
  }) => {
9090
9109
  const [activeTab, setActiveTab] = (0, import_react18.useState)("general");
9091
9110
  const [localApiKey, setLocalApiKey] = (0, import_react18.useState)(apiKey);
9111
+ (0, import_react18.useEffect)(() => {
9112
+ setLocalApiKey(apiKey);
9113
+ }, [apiKey]);
9092
9114
  if (!isOpen) return null;
9093
9115
  const updateResponseStyle = (key, value) => {
9094
9116
  onPersonalizationChange({