@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.
- package/dist/react/index.js +110 -20
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +110 -20
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -512,7 +512,10 @@ function useInfoExtraction(options) {
|
|
|
512
512
|
if (data === "[DONE]") continue;
|
|
513
513
|
try {
|
|
514
514
|
const parsed = JSON.parse(data);
|
|
515
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 &&
|
|
2132
|
-
const
|
|
2133
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
2626
|
+
{
|
|
2627
|
+
const chunk = parsed.content ?? parsed.text ?? "";
|
|
2628
|
+
if (chunk) responseContent += chunk;
|
|
2629
|
+
}
|
|
2540
2630
|
} catch {
|
|
2541
2631
|
}
|
|
2542
2632
|
}
|