@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.js
CHANGED
|
@@ -1210,6 +1210,37 @@ var formatPollResponse = (question, selectedOptions, otherText) => {
|
|
|
1210
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.`;
|
|
1211
1211
|
};
|
|
1212
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
|
+
|
|
1213
1244
|
// src/react/hooks/useChatUI.ts
|
|
1214
1245
|
var DEFAULT_STORAGE_KEY = "chatllm_sessions";
|
|
1215
1246
|
var DEFAULT_COMPRESSION_THRESHOLD = 20;
|
|
@@ -1281,6 +1312,10 @@ var useChatUI = (options) => {
|
|
|
1281
1312
|
const [deepResearchProgress, setDeepResearchProgress] = (0, import_react4.useState)(
|
|
1282
1313
|
null
|
|
1283
1314
|
);
|
|
1315
|
+
const sessionsRef = (0, import_react4.useRef)(sessions);
|
|
1316
|
+
(0, import_react4.useEffect)(() => {
|
|
1317
|
+
sessionsRef.current = sessions;
|
|
1318
|
+
}, [sessions]);
|
|
1284
1319
|
const abortControllerRef = (0, import_react4.useRef)(null);
|
|
1285
1320
|
const skipNextPollParsingRef = (0, import_react4.useRef)(false);
|
|
1286
1321
|
const skipNextSkillParsingRef = (0, import_react4.useRef)(false);
|
|
@@ -1610,7 +1645,7 @@ ${newConversation}
|
|
|
1610
1645
|
setIsSessionLoading(true);
|
|
1611
1646
|
try {
|
|
1612
1647
|
const sessionDetail = await onLoadSession(id);
|
|
1613
|
-
|
|
1648
|
+
let loadedMessages = sessionDetail.messages.map((m, idx) => ({
|
|
1614
1649
|
id: m.id || generateId2("msg"),
|
|
1615
1650
|
role: typeof m.role === "string" ? m.role.toLowerCase() : m.role,
|
|
1616
1651
|
// API는 message 필드, 내부는 content 필드 사용
|
|
@@ -1620,18 +1655,54 @@ ${newConversation}
|
|
|
1620
1655
|
alternatives: m.alternatives,
|
|
1621
1656
|
sources: m.sources
|
|
1622
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
|
+
}
|
|
1623
1669
|
setSessions(
|
|
1624
1670
|
(prev) => prev.map(
|
|
1625
|
-
(s) => s.id === id ? { ...s, title:
|
|
1671
|
+
(s) => s.id === id ? { ...s, title: resolvedTitle, messages: loadedMessages, updatedAt: Date.now() } : s
|
|
1626
1672
|
)
|
|
1627
1673
|
);
|
|
1628
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
|
+
}
|
|
1629
1686
|
const existingSession = sessions.find((s) => s.id === id);
|
|
1630
1687
|
if (existingSession) {
|
|
1631
1688
|
setSelectedModel(existingSession.model);
|
|
1632
1689
|
}
|
|
1633
1690
|
} catch (error) {
|
|
1634
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
|
+
}
|
|
1635
1706
|
} finally {
|
|
1636
1707
|
setIsSessionLoading(false);
|
|
1637
1708
|
}
|
|
@@ -1642,11 +1713,12 @@ ${newConversation}
|
|
|
1642
1713
|
setCurrentSessionId(id);
|
|
1643
1714
|
setSelectedModel(session.model);
|
|
1644
1715
|
}
|
|
1645
|
-
}, [sessions, useExternalStorage, onLoadSession, onError]);
|
|
1716
|
+
}, [sessions, useExternalStorage, onLoadSession, onError, storageKey, initialModel, models]);
|
|
1646
1717
|
const deleteSession = (0, import_react4.useCallback)(async (id) => {
|
|
1647
1718
|
if (useExternalStorage && onDeleteSessionCallback) {
|
|
1648
1719
|
try {
|
|
1649
1720
|
await onDeleteSessionCallback(id);
|
|
1721
|
+
removeSessionCache(storageKey, id);
|
|
1650
1722
|
setSessions((prev) => {
|
|
1651
1723
|
const filtered = prev.filter((s) => s.id !== id);
|
|
1652
1724
|
if (currentSessionId === id) {
|
|
@@ -2137,20 +2209,23 @@ ${result.content}
|
|
|
2137
2209
|
};
|
|
2138
2210
|
})
|
|
2139
2211
|
);
|
|
2140
|
-
if (useExternalStorage &&
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2143
|
-
(m) => m.id === assistantMessageId
|
|
2144
|
-
)?.content || "";
|
|
2145
|
-
if (assistantContent) {
|
|
2212
|
+
if (useExternalStorage && capturedSessionId) {
|
|
2213
|
+
const assistantContentForSave = accumulatedContent;
|
|
2214
|
+
if (assistantContentForSave && onSaveMessages) {
|
|
2146
2215
|
const messagesToSave = [
|
|
2147
2216
|
{ role: "USER", message: finalContent },
|
|
2148
|
-
{ role: "ASSISTANT", message:
|
|
2217
|
+
{ role: "ASSISTANT", message: assistantContentForSave }
|
|
2149
2218
|
];
|
|
2150
2219
|
onSaveMessages(capturedSessionId, messagesToSave).catch((saveError) => {
|
|
2151
2220
|
console.error("[useChatUI] Failed to save messages:", saveError);
|
|
2152
2221
|
});
|
|
2153
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
|
+
});
|
|
2154
2229
|
}
|
|
2155
2230
|
if (enableAutoExtraction && globalMemory) {
|
|
2156
2231
|
const currentMsgCount = existingMessages.length + 2;
|
|
@@ -6086,7 +6161,7 @@ var MessageBubble = ({
|
|
|
6086
6161
|
display: "flex",
|
|
6087
6162
|
flexDirection: "column",
|
|
6088
6163
|
alignItems: "flex-end",
|
|
6089
|
-
padding: "
|
|
6164
|
+
padding: "4px 24px"
|
|
6090
6165
|
},
|
|
6091
6166
|
onMouseEnter: () => setShowActions(true),
|
|
6092
6167
|
onMouseLeave: () => setShowActions(false),
|
|
@@ -6152,7 +6227,7 @@ var MessageBubble = ({
|
|
|
6152
6227
|
display: "flex",
|
|
6153
6228
|
flexDirection: "column",
|
|
6154
6229
|
alignItems: "flex-start",
|
|
6155
|
-
padding: "
|
|
6230
|
+
padding: "4px 24px"
|
|
6156
6231
|
},
|
|
6157
6232
|
onMouseEnter: () => setShowActions(true),
|
|
6158
6233
|
onMouseLeave: () => setShowActions(false),
|
|
@@ -6164,25 +6239,25 @@ var MessageBubble = ({
|
|
|
6164
6239
|
className: "chatllm-sheet",
|
|
6165
6240
|
style: {
|
|
6166
6241
|
width: "100%",
|
|
6167
|
-
padding: "
|
|
6242
|
+
padding: "16px",
|
|
6168
6243
|
display: "flex",
|
|
6169
|
-
gap: "
|
|
6244
|
+
gap: "12px"
|
|
6170
6245
|
},
|
|
6171
6246
|
children: [
|
|
6172
6247
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
6173
6248
|
"div",
|
|
6174
6249
|
{
|
|
6175
6250
|
style: {
|
|
6176
|
-
width: "
|
|
6177
|
-
height: "
|
|
6178
|
-
borderRadius: "
|
|
6251
|
+
width: "32px",
|
|
6252
|
+
height: "32px",
|
|
6253
|
+
borderRadius: "10px",
|
|
6179
6254
|
backgroundColor: "var(--chatllm-primary-light)",
|
|
6180
6255
|
display: "flex",
|
|
6181
6256
|
alignItems: "center",
|
|
6182
6257
|
justifyContent: "center",
|
|
6183
6258
|
color: "var(--chatllm-primary)"
|
|
6184
6259
|
},
|
|
6185
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "magic-line", size:
|
|
6260
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "magic-line", size: 20 })
|
|
6186
6261
|
}
|
|
6187
6262
|
) }),
|
|
6188
6263
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
@@ -6193,7 +6268,7 @@ var MessageBubble = ({
|
|
|
6193
6268
|
display: "flex",
|
|
6194
6269
|
alignItems: "center",
|
|
6195
6270
|
gap: "8px",
|
|
6196
|
-
marginBottom: "
|
|
6271
|
+
marginBottom: "8px"
|
|
6197
6272
|
},
|
|
6198
6273
|
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
6199
6274
|
"span",
|
|
@@ -6443,7 +6518,7 @@ var MessageBubble = ({
|
|
|
6443
6518
|
display: "flex",
|
|
6444
6519
|
gap: "2px",
|
|
6445
6520
|
marginTop: "4px",
|
|
6446
|
-
marginLeft: "
|
|
6521
|
+
marginLeft: "44px",
|
|
6447
6522
|
height: "24px",
|
|
6448
6523
|
opacity: showActions ? 1 : 0,
|
|
6449
6524
|
transition: "opacity 0.15s ease"
|