@gendive/chatllm 0.12.1 → 0.12.3
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 +95 -20
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +95 -20
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -1154,6 +1154,37 @@ var formatPollResponse = (question, selectedOptions, otherText) => {
|
|
|
1154
1154
|
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.`;
|
|
1155
1155
|
};
|
|
1156
1156
|
|
|
1157
|
+
// src/react/utils/sessionCache.ts
|
|
1158
|
+
var buildCacheKey = (storageKey, sessionId) => `${storageKey}_cache_${sessionId}`;
|
|
1159
|
+
var writeSessionCache = (storageKey, session) => {
|
|
1160
|
+
if (typeof window === "undefined") return;
|
|
1161
|
+
try {
|
|
1162
|
+
const key = buildCacheKey(storageKey, session.id);
|
|
1163
|
+
localStorage.setItem(key, JSON.stringify(session));
|
|
1164
|
+
} catch (error) {
|
|
1165
|
+
console.warn("[sessionCache] Failed to write cache:", error);
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
var readSessionCache = (storageKey, sessionId) => {
|
|
1169
|
+
if (typeof window === "undefined") return null;
|
|
1170
|
+
try {
|
|
1171
|
+
const key = buildCacheKey(storageKey, sessionId);
|
|
1172
|
+
const data = localStorage.getItem(key);
|
|
1173
|
+
if (!data) return null;
|
|
1174
|
+
return JSON.parse(data);
|
|
1175
|
+
} catch {
|
|
1176
|
+
return null;
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
var removeSessionCache = (storageKey, sessionId) => {
|
|
1180
|
+
if (typeof window === "undefined") return;
|
|
1181
|
+
try {
|
|
1182
|
+
const key = buildCacheKey(storageKey, sessionId);
|
|
1183
|
+
localStorage.removeItem(key);
|
|
1184
|
+
} catch {
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
1187
|
+
|
|
1157
1188
|
// src/react/hooks/useChatUI.ts
|
|
1158
1189
|
var DEFAULT_STORAGE_KEY = "chatllm_sessions";
|
|
1159
1190
|
var DEFAULT_COMPRESSION_THRESHOLD = 20;
|
|
@@ -1225,6 +1256,10 @@ var useChatUI = (options) => {
|
|
|
1225
1256
|
const [deepResearchProgress, setDeepResearchProgress] = useState4(
|
|
1226
1257
|
null
|
|
1227
1258
|
);
|
|
1259
|
+
const sessionsRef = useRef3(sessions);
|
|
1260
|
+
useEffect2(() => {
|
|
1261
|
+
sessionsRef.current = sessions;
|
|
1262
|
+
}, [sessions]);
|
|
1228
1263
|
const abortControllerRef = useRef3(null);
|
|
1229
1264
|
const skipNextPollParsingRef = useRef3(false);
|
|
1230
1265
|
const skipNextSkillParsingRef = useRef3(false);
|
|
@@ -1554,7 +1589,7 @@ ${newConversation}
|
|
|
1554
1589
|
setIsSessionLoading(true);
|
|
1555
1590
|
try {
|
|
1556
1591
|
const sessionDetail = await onLoadSession(id);
|
|
1557
|
-
|
|
1592
|
+
let loadedMessages = sessionDetail.messages.map((m, idx) => ({
|
|
1558
1593
|
id: m.id || generateId2("msg"),
|
|
1559
1594
|
role: typeof m.role === "string" ? m.role.toLowerCase() : m.role,
|
|
1560
1595
|
// API는 message 필드, 내부는 content 필드 사용
|
|
@@ -1564,18 +1599,54 @@ ${newConversation}
|
|
|
1564
1599
|
alternatives: m.alternatives,
|
|
1565
1600
|
sources: m.sources
|
|
1566
1601
|
}));
|
|
1602
|
+
let resolvedTitle = sessionDetail.title;
|
|
1603
|
+
if (loadedMessages.length === 0) {
|
|
1604
|
+
const cached = readSessionCache(storageKey, id);
|
|
1605
|
+
if (cached && cached.messages.length > 0) {
|
|
1606
|
+
console.warn("[useChatUI] Server returned empty messages, using localStorage cache");
|
|
1607
|
+
loadedMessages = cached.messages;
|
|
1608
|
+
if (!resolvedTitle && cached.title) {
|
|
1609
|
+
resolvedTitle = cached.title;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1567
1613
|
setSessions(
|
|
1568
1614
|
(prev) => prev.map(
|
|
1569
|
-
(s) => s.id === id ? { ...s, title:
|
|
1615
|
+
(s) => s.id === id ? { ...s, title: resolvedTitle, messages: loadedMessages, updatedAt: Date.now() } : s
|
|
1570
1616
|
)
|
|
1571
1617
|
);
|
|
1572
1618
|
setCurrentSessionId(id);
|
|
1619
|
+
if (loadedMessages.length > 0) {
|
|
1620
|
+
const existingSession2 = sessions.find((s) => s.id === id);
|
|
1621
|
+
writeSessionCache(storageKey, {
|
|
1622
|
+
id,
|
|
1623
|
+
title: resolvedTitle,
|
|
1624
|
+
messages: loadedMessages,
|
|
1625
|
+
model: existingSession2?.model || initialModel || models[0]?.id || "",
|
|
1626
|
+
createdAt: existingSession2?.createdAt || Date.now(),
|
|
1627
|
+
updatedAt: Date.now()
|
|
1628
|
+
});
|
|
1629
|
+
}
|
|
1573
1630
|
const existingSession = sessions.find((s) => s.id === id);
|
|
1574
1631
|
if (existingSession) {
|
|
1575
1632
|
setSelectedModel(existingSession.model);
|
|
1576
1633
|
}
|
|
1577
1634
|
} catch (error) {
|
|
1578
1635
|
onError?.(error instanceof Error ? error : new Error("Failed to load session"));
|
|
1636
|
+
const cached = readSessionCache(storageKey, id);
|
|
1637
|
+
if (cached && cached.messages.length > 0) {
|
|
1638
|
+
console.warn("[useChatUI] onLoadSession failed, using localStorage cache");
|
|
1639
|
+
setSessions(
|
|
1640
|
+
(prev) => prev.map(
|
|
1641
|
+
(s) => s.id === id ? { ...s, title: cached.title || s.title, messages: cached.messages, updatedAt: Date.now() } : s
|
|
1642
|
+
)
|
|
1643
|
+
);
|
|
1644
|
+
setCurrentSessionId(id);
|
|
1645
|
+
const existingSession = sessions.find((s) => s.id === id);
|
|
1646
|
+
if (existingSession) {
|
|
1647
|
+
setSelectedModel(existingSession.model);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1579
1650
|
} finally {
|
|
1580
1651
|
setIsSessionLoading(false);
|
|
1581
1652
|
}
|
|
@@ -1586,11 +1657,12 @@ ${newConversation}
|
|
|
1586
1657
|
setCurrentSessionId(id);
|
|
1587
1658
|
setSelectedModel(session.model);
|
|
1588
1659
|
}
|
|
1589
|
-
}, [sessions, useExternalStorage, onLoadSession, onError]);
|
|
1660
|
+
}, [sessions, useExternalStorage, onLoadSession, onError, storageKey, initialModel, models]);
|
|
1590
1661
|
const deleteSession = useCallback4(async (id) => {
|
|
1591
1662
|
if (useExternalStorage && onDeleteSessionCallback) {
|
|
1592
1663
|
try {
|
|
1593
1664
|
await onDeleteSessionCallback(id);
|
|
1665
|
+
removeSessionCache(storageKey, id);
|
|
1594
1666
|
setSessions((prev) => {
|
|
1595
1667
|
const filtered = prev.filter((s) => s.id !== id);
|
|
1596
1668
|
if (currentSessionId === id) {
|
|
@@ -2081,20 +2153,23 @@ ${result.content}
|
|
|
2081
2153
|
};
|
|
2082
2154
|
})
|
|
2083
2155
|
);
|
|
2084
|
-
if (useExternalStorage &&
|
|
2085
|
-
const
|
|
2086
|
-
|
|
2087
|
-
(m) => m.id === assistantMessageId
|
|
2088
|
-
)?.content || "";
|
|
2089
|
-
if (assistantContent) {
|
|
2156
|
+
if (useExternalStorage && capturedSessionId) {
|
|
2157
|
+
const assistantContentForSave = accumulatedContent;
|
|
2158
|
+
if (assistantContentForSave && onSaveMessages) {
|
|
2090
2159
|
const messagesToSave = [
|
|
2091
2160
|
{ role: "USER", message: finalContent },
|
|
2092
|
-
{ role: "ASSISTANT", message:
|
|
2161
|
+
{ role: "ASSISTANT", message: assistantContentForSave }
|
|
2093
2162
|
];
|
|
2094
2163
|
onSaveMessages(capturedSessionId, messagesToSave).catch((saveError) => {
|
|
2095
2164
|
console.error("[useChatUI] Failed to save messages:", saveError);
|
|
2096
2165
|
});
|
|
2097
2166
|
}
|
|
2167
|
+
queueMicrotask(() => {
|
|
2168
|
+
const sessionToCache = sessionsRef.current.find((s) => s.id === capturedSessionId);
|
|
2169
|
+
if (sessionToCache && sessionToCache.messages.length > 0) {
|
|
2170
|
+
writeSessionCache(storageKey, sessionToCache);
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
2098
2173
|
}
|
|
2099
2174
|
if (enableAutoExtraction && globalMemory) {
|
|
2100
2175
|
const currentMsgCount = existingMessages.length + 2;
|
|
@@ -6030,7 +6105,7 @@ var MessageBubble = ({
|
|
|
6030
6105
|
display: "flex",
|
|
6031
6106
|
flexDirection: "column",
|
|
6032
6107
|
alignItems: "flex-end",
|
|
6033
|
-
padding: "
|
|
6108
|
+
padding: "4px 24px"
|
|
6034
6109
|
},
|
|
6035
6110
|
onMouseEnter: () => setShowActions(true),
|
|
6036
6111
|
onMouseLeave: () => setShowActions(false),
|
|
@@ -6096,7 +6171,7 @@ var MessageBubble = ({
|
|
|
6096
6171
|
display: "flex",
|
|
6097
6172
|
flexDirection: "column",
|
|
6098
6173
|
alignItems: "flex-start",
|
|
6099
|
-
padding: "
|
|
6174
|
+
padding: "4px 24px"
|
|
6100
6175
|
},
|
|
6101
6176
|
onMouseEnter: () => setShowActions(true),
|
|
6102
6177
|
onMouseLeave: () => setShowActions(false),
|
|
@@ -6108,25 +6183,25 @@ var MessageBubble = ({
|
|
|
6108
6183
|
className: "chatllm-sheet",
|
|
6109
6184
|
style: {
|
|
6110
6185
|
width: "100%",
|
|
6111
|
-
padding: "
|
|
6186
|
+
padding: "16px",
|
|
6112
6187
|
display: "flex",
|
|
6113
|
-
gap: "
|
|
6188
|
+
gap: "12px"
|
|
6114
6189
|
},
|
|
6115
6190
|
children: [
|
|
6116
6191
|
/* @__PURE__ */ jsx10("div", { style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10(
|
|
6117
6192
|
"div",
|
|
6118
6193
|
{
|
|
6119
6194
|
style: {
|
|
6120
|
-
width: "
|
|
6121
|
-
height: "
|
|
6122
|
-
borderRadius: "
|
|
6195
|
+
width: "32px",
|
|
6196
|
+
height: "32px",
|
|
6197
|
+
borderRadius: "10px",
|
|
6123
6198
|
backgroundColor: "var(--chatllm-primary-light)",
|
|
6124
6199
|
display: "flex",
|
|
6125
6200
|
alignItems: "center",
|
|
6126
6201
|
justifyContent: "center",
|
|
6127
6202
|
color: "var(--chatllm-primary)"
|
|
6128
6203
|
},
|
|
6129
|
-
children: /* @__PURE__ */ jsx10(IconSvg, { name: "magic-line", size:
|
|
6204
|
+
children: /* @__PURE__ */ jsx10(IconSvg, { name: "magic-line", size: 20 })
|
|
6130
6205
|
}
|
|
6131
6206
|
) }),
|
|
6132
6207
|
/* @__PURE__ */ jsxs9("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
@@ -6137,7 +6212,7 @@ var MessageBubble = ({
|
|
|
6137
6212
|
display: "flex",
|
|
6138
6213
|
alignItems: "center",
|
|
6139
6214
|
gap: "8px",
|
|
6140
|
-
marginBottom: "
|
|
6215
|
+
marginBottom: "8px"
|
|
6141
6216
|
},
|
|
6142
6217
|
children: /* @__PURE__ */ jsx10(
|
|
6143
6218
|
"span",
|
|
@@ -6387,7 +6462,7 @@ var MessageBubble = ({
|
|
|
6387
6462
|
display: "flex",
|
|
6388
6463
|
gap: "2px",
|
|
6389
6464
|
marginTop: "4px",
|
|
6390
|
-
marginLeft: "
|
|
6465
|
+
marginLeft: "44px",
|
|
6391
6466
|
height: "24px",
|
|
6392
6467
|
opacity: showActions ? 1 : 0,
|
|
6393
6468
|
transition: "opacity 0.15s ease"
|