@gendive/chatllm 0.12.0 → 0.12.2

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.
@@ -512,7 +512,10 @@ function useInfoExtraction(options) {
512
512
  if (data === "[DONE]") continue;
513
513
  try {
514
514
  const parsed = JSON.parse(data);
515
- if (parsed.content) fullResponse += parsed.content;
515
+ {
516
+ const chunk = parsed.content ?? parsed.text ?? "";
517
+ if (chunk) fullResponse += chunk;
518
+ }
516
519
  } catch {
517
520
  }
518
521
  }
@@ -672,7 +675,7 @@ var callLLMStream = async (prompt, opts, onChunk) => {
672
675
  if (data === "[DONE]") continue;
673
676
  try {
674
677
  const parsed = JSON.parse(data);
675
- const content = parsed.choices?.[0]?.delta?.content || parsed.delta?.content || parsed.message?.content || "";
678
+ const content = parsed.choices?.[0]?.delta?.content || parsed.delta?.content || parsed.message?.content || parsed.content || parsed.text || "";
676
679
  if (content) {
677
680
  fullContent += content;
678
681
  onChunk(content);
@@ -1207,6 +1210,37 @@ var formatPollResponse = (question, selectedOptions, otherText) => {
1207
1210
  return `${selectedLabels.join(", ")}\uC744(\uB97C) \uC120\uD0DD\uD588\uC2B5\uB2C8\uB2E4. \uC774 \uC120\uD0DD\uC744 \uBC14\uD0D5\uC73C\uB85C \uC9C4\uD589\uD574\uC8FC\uC138\uC694.`;
1208
1211
  };
1209
1212
 
1213
+ // src/react/utils/sessionCache.ts
1214
+ var buildCacheKey = (storageKey, sessionId) => `${storageKey}_cache_${sessionId}`;
1215
+ var writeSessionCache = (storageKey, session) => {
1216
+ if (typeof window === "undefined") return;
1217
+ try {
1218
+ const key = buildCacheKey(storageKey, session.id);
1219
+ localStorage.setItem(key, JSON.stringify(session));
1220
+ } catch (error) {
1221
+ console.warn("[sessionCache] Failed to write cache:", error);
1222
+ }
1223
+ };
1224
+ var readSessionCache = (storageKey, sessionId) => {
1225
+ if (typeof window === "undefined") return null;
1226
+ try {
1227
+ const key = buildCacheKey(storageKey, sessionId);
1228
+ const data = localStorage.getItem(key);
1229
+ if (!data) return null;
1230
+ return JSON.parse(data);
1231
+ } catch {
1232
+ return null;
1233
+ }
1234
+ };
1235
+ var removeSessionCache = (storageKey, sessionId) => {
1236
+ if (typeof window === "undefined") return;
1237
+ try {
1238
+ const key = buildCacheKey(storageKey, sessionId);
1239
+ localStorage.removeItem(key);
1240
+ } catch {
1241
+ }
1242
+ };
1243
+
1210
1244
  // src/react/hooks/useChatUI.ts
1211
1245
  var DEFAULT_STORAGE_KEY = "chatllm_sessions";
1212
1246
  var DEFAULT_COMPRESSION_THRESHOLD = 20;
@@ -1278,6 +1312,10 @@ var useChatUI = (options) => {
1278
1312
  const [deepResearchProgress, setDeepResearchProgress] = (0, import_react4.useState)(
1279
1313
  null
1280
1314
  );
1315
+ const sessionsRef = (0, import_react4.useRef)(sessions);
1316
+ (0, import_react4.useEffect)(() => {
1317
+ sessionsRef.current = sessions;
1318
+ }, [sessions]);
1281
1319
  const abortControllerRef = (0, import_react4.useRef)(null);
1282
1320
  const skipNextPollParsingRef = (0, import_react4.useRef)(false);
1283
1321
  const skipNextSkillParsingRef = (0, import_react4.useRef)(false);
@@ -1489,7 +1527,10 @@ ${conversationText}
1489
1527
  if (data === "[DONE]") continue;
1490
1528
  try {
1491
1529
  const parsed = JSON.parse(data);
1492
- if (parsed.content) summary += parsed.content;
1530
+ {
1531
+ const chunk = parsed.content ?? parsed.text ?? "";
1532
+ if (chunk) summary += chunk;
1533
+ }
1493
1534
  } catch {
1494
1535
  }
1495
1536
  }
@@ -1545,7 +1586,10 @@ ${newConversation}
1545
1586
  if (data === "[DONE]") continue;
1546
1587
  try {
1547
1588
  const parsed = JSON.parse(data);
1548
- if (parsed.content) summary += parsed.content;
1589
+ {
1590
+ const chunk = parsed.content ?? parsed.text ?? "";
1591
+ if (chunk) summary += chunk;
1592
+ }
1549
1593
  } catch {
1550
1594
  }
1551
1595
  }
@@ -1601,7 +1645,7 @@ ${newConversation}
1601
1645
  setIsSessionLoading(true);
1602
1646
  try {
1603
1647
  const sessionDetail = await onLoadSession(id);
1604
- const loadedMessages = sessionDetail.messages.map((m, idx) => ({
1648
+ let loadedMessages = sessionDetail.messages.map((m, idx) => ({
1605
1649
  id: m.id || generateId2("msg"),
1606
1650
  role: typeof m.role === "string" ? m.role.toLowerCase() : m.role,
1607
1651
  // API는 message 필드, 내부는 content 필드 사용
@@ -1611,18 +1655,54 @@ ${newConversation}
1611
1655
  alternatives: m.alternatives,
1612
1656
  sources: m.sources
1613
1657
  }));
1658
+ let resolvedTitle = sessionDetail.title;
1659
+ if (loadedMessages.length === 0) {
1660
+ const cached = readSessionCache(storageKey, id);
1661
+ if (cached && cached.messages.length > 0) {
1662
+ console.warn("[useChatUI] Server returned empty messages, using localStorage cache");
1663
+ loadedMessages = cached.messages;
1664
+ if (!resolvedTitle && cached.title) {
1665
+ resolvedTitle = cached.title;
1666
+ }
1667
+ }
1668
+ }
1614
1669
  setSessions(
1615
1670
  (prev) => prev.map(
1616
- (s) => s.id === id ? { ...s, title: sessionDetail.title, messages: loadedMessages, updatedAt: Date.now() } : s
1671
+ (s) => s.id === id ? { ...s, title: resolvedTitle, messages: loadedMessages, updatedAt: Date.now() } : s
1617
1672
  )
1618
1673
  );
1619
1674
  setCurrentSessionId(id);
1675
+ if (loadedMessages.length > 0) {
1676
+ const existingSession2 = sessions.find((s) => s.id === id);
1677
+ writeSessionCache(storageKey, {
1678
+ id,
1679
+ title: resolvedTitle,
1680
+ messages: loadedMessages,
1681
+ model: existingSession2?.model || initialModel || models[0]?.id || "",
1682
+ createdAt: existingSession2?.createdAt || Date.now(),
1683
+ updatedAt: Date.now()
1684
+ });
1685
+ }
1620
1686
  const existingSession = sessions.find((s) => s.id === id);
1621
1687
  if (existingSession) {
1622
1688
  setSelectedModel(existingSession.model);
1623
1689
  }
1624
1690
  } catch (error) {
1625
1691
  onError?.(error instanceof Error ? error : new Error("Failed to load session"));
1692
+ const cached = readSessionCache(storageKey, id);
1693
+ if (cached && cached.messages.length > 0) {
1694
+ console.warn("[useChatUI] onLoadSession failed, using localStorage cache");
1695
+ setSessions(
1696
+ (prev) => prev.map(
1697
+ (s) => s.id === id ? { ...s, title: cached.title || s.title, messages: cached.messages, updatedAt: Date.now() } : s
1698
+ )
1699
+ );
1700
+ setCurrentSessionId(id);
1701
+ const existingSession = sessions.find((s) => s.id === id);
1702
+ if (existingSession) {
1703
+ setSelectedModel(existingSession.model);
1704
+ }
1705
+ }
1626
1706
  } finally {
1627
1707
  setIsSessionLoading(false);
1628
1708
  }
@@ -1633,11 +1713,12 @@ ${newConversation}
1633
1713
  setCurrentSessionId(id);
1634
1714
  setSelectedModel(session.model);
1635
1715
  }
1636
- }, [sessions, useExternalStorage, onLoadSession, onError]);
1716
+ }, [sessions, useExternalStorage, onLoadSession, onError, storageKey, initialModel, models]);
1637
1717
  const deleteSession = (0, import_react4.useCallback)(async (id) => {
1638
1718
  if (useExternalStorage && onDeleteSessionCallback) {
1639
1719
  try {
1640
1720
  await onDeleteSessionCallback(id);
1721
+ removeSessionCache(storageKey, id);
1641
1722
  setSessions((prev) => {
1642
1723
  const filtered = prev.filter((s) => s.id !== id);
1643
1724
  if (currentSessionId === id) {
@@ -1945,7 +2026,7 @@ ${currentContextSummary}` },
1945
2026
  }
1946
2027
  try {
1947
2028
  const parsed = JSON.parse(data);
1948
- const content2 = parsed.message?.content || parsed.content || "";
2029
+ const content2 = parsed.message?.content || parsed.content || parsed.text || "";
1949
2030
  const thinking = parsed.message?.thinking || "";
1950
2031
  if (content2 || thinking) {
1951
2032
  if (content2) accumulatedContent += content2;
@@ -1985,7 +2066,7 @@ ${currentContextSummary}` },
1985
2066
  if (buffer.trim()) {
1986
2067
  try {
1987
2068
  const parsed = JSON.parse(buffer);
1988
- const content2 = parsed.message?.content || parsed.content;
2069
+ const content2 = parsed.message?.content || parsed.content || parsed.text;
1989
2070
  if (content2) {
1990
2071
  accumulatedContent += content2;
1991
2072
  setSessions(
@@ -2128,20 +2209,23 @@ ${result.content}
2128
2209
  };
2129
2210
  })
2130
2211
  );
2131
- if (useExternalStorage && onSaveMessages && capturedSessionId) {
2132
- const updatedSession = sessions.find((s) => s.id === capturedSessionId);
2133
- const assistantContent = updatedSession?.messages.find(
2134
- (m) => m.id === assistantMessageId
2135
- )?.content || "";
2136
- if (assistantContent) {
2212
+ if (useExternalStorage && capturedSessionId) {
2213
+ const assistantContentForSave = accumulatedContent;
2214
+ if (assistantContentForSave && onSaveMessages) {
2137
2215
  const messagesToSave = [
2138
2216
  { role: "USER", message: finalContent },
2139
- { role: "ASSISTANT", message: assistantContent }
2217
+ { role: "ASSISTANT", message: assistantContentForSave }
2140
2218
  ];
2141
2219
  onSaveMessages(capturedSessionId, messagesToSave).catch((saveError) => {
2142
2220
  console.error("[useChatUI] Failed to save messages:", saveError);
2143
2221
  });
2144
2222
  }
2223
+ queueMicrotask(() => {
2224
+ const sessionToCache = sessionsRef.current.find((s) => s.id === capturedSessionId);
2225
+ if (sessionToCache && sessionToCache.messages.length > 0) {
2226
+ writeSessionCache(storageKey, sessionToCache);
2227
+ }
2228
+ });
2145
2229
  }
2146
2230
  if (enableAutoExtraction && globalMemory) {
2147
2231
  const currentMsgCount = existingMessages.length + 2;
@@ -2354,7 +2438,7 @@ ${formattedParts.join("\n")}
2354
2438
  }
2355
2439
  try {
2356
2440
  const parsed = JSON.parse(data);
2357
- const content = parsed.message?.content || parsed.content || "";
2441
+ const content = parsed.message?.content || parsed.content || parsed.text || "";
2358
2442
  const thinking = parsed.message?.thinking || "";
2359
2443
  if (content || thinking) {
2360
2444
  setSessions(
@@ -2393,7 +2477,7 @@ ${formattedParts.join("\n")}
2393
2477
  if (buffer.trim()) {
2394
2478
  try {
2395
2479
  const parsed = JSON.parse(buffer);
2396
- const content = parsed.message?.content || parsed.content || "";
2480
+ const content = parsed.message?.content || parsed.content || parsed.text || "";
2397
2481
  const thinking = parsed.message?.thinking || "";
2398
2482
  if (content || thinking) {
2399
2483
  setSessions(
@@ -2497,7 +2581,10 @@ ${currentSession.contextSummary}` },
2497
2581
  if (data === "[DONE]") continue;
2498
2582
  try {
2499
2583
  const parsed = JSON.parse(data);
2500
- if (parsed.content) responseContent += parsed.content;
2584
+ {
2585
+ const chunk = parsed.content ?? parsed.text ?? "";
2586
+ if (chunk) responseContent += chunk;
2587
+ }
2501
2588
  } catch {
2502
2589
  }
2503
2590
  }
@@ -2536,7 +2623,10 @@ ${currentSession.contextSummary}` },
2536
2623
  if (data === "[DONE]") continue;
2537
2624
  try {
2538
2625
  const parsed = JSON.parse(data);
2539
- if (parsed.content) responseContent += parsed.content;
2626
+ {
2627
+ const chunk = parsed.content ?? parsed.text ?? "";
2628
+ if (chunk) responseContent += chunk;
2629
+ }
2540
2630
  } catch {
2541
2631
  }
2542
2632
  }