@gendive/chatllm 0.17.0 → 0.17.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.d.mts +18 -0
- package/dist/react/index.d.ts +18 -0
- package/dist/react/index.js +90 -21
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +90 -21
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -1133,7 +1133,7 @@ var useProject = (options) => {
|
|
|
1133
1133
|
const currentProject = projects.find((p) => p.id === currentProjectId) || null;
|
|
1134
1134
|
useEffect2(() => {
|
|
1135
1135
|
if (!enabled || useExternalStorage || !initializedRef.current) return;
|
|
1136
|
-
if (projects.length > 0) {
|
|
1136
|
+
if (projects.length > 0 && typeof window !== "undefined") {
|
|
1137
1137
|
localStorage.setItem(storageKey, JSON.stringify(projects));
|
|
1138
1138
|
}
|
|
1139
1139
|
}, [enabled, projects, storageKey, useExternalStorage]);
|
|
@@ -1167,7 +1167,7 @@ var useProject = (options) => {
|
|
|
1167
1167
|
}
|
|
1168
1168
|
} else {
|
|
1169
1169
|
try {
|
|
1170
|
-
const saved = localStorage.getItem(storageKey);
|
|
1170
|
+
const saved = typeof window !== "undefined" ? localStorage.getItem(storageKey) : null;
|
|
1171
1171
|
if (saved) {
|
|
1172
1172
|
const parsed = JSON.parse(saved);
|
|
1173
1173
|
if (!parsed.find((p) => p.id === DEFAULT_PROJECT_ID)) {
|
|
@@ -1474,6 +1474,7 @@ var convertToolsToSkills = (tools, onToolCall) => {
|
|
|
1474
1474
|
label: tool.label || tool.name,
|
|
1475
1475
|
icon: tool.icon,
|
|
1476
1476
|
acceptedTypes: tool.acceptedTypes,
|
|
1477
|
+
autoConvertBase64: tool.autoConvertBase64,
|
|
1477
1478
|
parameters: {
|
|
1478
1479
|
type: "object",
|
|
1479
1480
|
properties: Object.fromEntries(
|
|
@@ -1547,6 +1548,20 @@ var DEFAULT_KEEP_RECENT = 6;
|
|
|
1547
1548
|
var DEFAULT_RECOMPRESSION_THRESHOLD = 10;
|
|
1548
1549
|
var DEFAULT_TOKEN_LIMIT = 8e3;
|
|
1549
1550
|
var generateId3 = (prefix) => `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
1551
|
+
var fileToBase64 = (file) => new Promise((resolve, reject) => {
|
|
1552
|
+
const reader = new FileReader();
|
|
1553
|
+
reader.onload = () => resolve(reader.result.split(",")[1] || "");
|
|
1554
|
+
reader.onerror = reject;
|
|
1555
|
+
reader.readAsDataURL(file);
|
|
1556
|
+
});
|
|
1557
|
+
var convertAttachmentsToBase64 = async (attachments) => Promise.all(
|
|
1558
|
+
attachments.map(async (att) => ({
|
|
1559
|
+
name: att.name,
|
|
1560
|
+
mimeType: att.mimeType,
|
|
1561
|
+
base64: await fileToBase64(att.file),
|
|
1562
|
+
size: att.size
|
|
1563
|
+
}))
|
|
1564
|
+
);
|
|
1550
1565
|
var generateTitle = (messages) => {
|
|
1551
1566
|
const firstUserMessage = messages.find((m) => m.role === "user");
|
|
1552
1567
|
if (!firstUserMessage) return "\uC0C8 \uB300\uD654";
|
|
@@ -1769,11 +1784,13 @@ var useChatUI = (options) => {
|
|
|
1769
1784
|
}).finally(() => {
|
|
1770
1785
|
setIsSessionsLoading(false);
|
|
1771
1786
|
});
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1787
|
+
if (typeof window !== "undefined") {
|
|
1788
|
+
const savedPersonalization2 = localStorage.getItem(`${storageKey}_personalization`);
|
|
1789
|
+
if (savedPersonalization2) {
|
|
1790
|
+
try {
|
|
1791
|
+
setPersonalization(JSON.parse(savedPersonalization2));
|
|
1792
|
+
} catch {
|
|
1793
|
+
}
|
|
1777
1794
|
}
|
|
1778
1795
|
}
|
|
1779
1796
|
return;
|
|
@@ -1781,6 +1798,7 @@ var useChatUI = (options) => {
|
|
|
1781
1798
|
if (enableProjects) {
|
|
1782
1799
|
migrateSessionsToProjects(storageKey);
|
|
1783
1800
|
}
|
|
1801
|
+
if (typeof window === "undefined") return;
|
|
1784
1802
|
const saved = localStorage.getItem(storageKey);
|
|
1785
1803
|
if (saved) {
|
|
1786
1804
|
try {
|
|
@@ -2269,7 +2287,8 @@ ${newConversation}
|
|
|
2269
2287
|
}, []);
|
|
2270
2288
|
const sendMessage = useCallback5(async (content, options2) => {
|
|
2271
2289
|
const messageContent = content || input;
|
|
2272
|
-
if (!messageContent.trim() || isLoading) return;
|
|
2290
|
+
if (!messageContent.trim() && attachments.length === 0 || isLoading) return;
|
|
2291
|
+
setIsLoading(true);
|
|
2273
2292
|
let sessionId = currentSessionId;
|
|
2274
2293
|
if (!sessionId) {
|
|
2275
2294
|
if (useExternalStorage && onCreateSessionRef.current) {
|
|
@@ -2360,7 +2379,8 @@ ${finalContent}`;
|
|
|
2360
2379
|
});
|
|
2361
2380
|
if (matchedFiles.length === 0) continue;
|
|
2362
2381
|
try {
|
|
2363
|
-
const
|
|
2382
|
+
const filesToPass = skillConfig.autoConvertBase64 ? await convertAttachmentsToBase64(matchedFiles) : matchedFiles;
|
|
2383
|
+
const result = await skillConfig.execute({ files: filesToPass, userMessage: finalContent });
|
|
2364
2384
|
attachmentResults.push({
|
|
2365
2385
|
type: "tool_result",
|
|
2366
2386
|
toolName: skillName,
|
|
@@ -2378,6 +2398,20 @@ ${finalContent}`;
|
|
|
2378
2398
|
}
|
|
2379
2399
|
}
|
|
2380
2400
|
}
|
|
2401
|
+
let shouldContinueAfterAttachment = continueAfterToolResult;
|
|
2402
|
+
if (attachmentResults.length > 0) {
|
|
2403
|
+
for (const part of attachmentResults) {
|
|
2404
|
+
if (part.type === "tool_result" && onSkillCompleteRef.current) {
|
|
2405
|
+
const decision = onSkillCompleteRef.current(part.toolName, {
|
|
2406
|
+
content: part.result.content,
|
|
2407
|
+
metadata: part.result.metadata,
|
|
2408
|
+
sources: part.result.sources
|
|
2409
|
+
});
|
|
2410
|
+
shouldContinueAfterAttachment = decision === "continue";
|
|
2411
|
+
if (!shouldContinueAfterAttachment) break;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2381
2415
|
const assistantMessageId = generateId3("msg");
|
|
2382
2416
|
const assistantMessage = {
|
|
2383
2417
|
id: assistantMessageId,
|
|
@@ -2425,7 +2459,10 @@ ${finalContent}`;
|
|
|
2425
2459
|
}).catch(() => {
|
|
2426
2460
|
});
|
|
2427
2461
|
}
|
|
2428
|
-
|
|
2462
|
+
if (attachmentResults.length > 0 && !shouldContinueAfterAttachment) {
|
|
2463
|
+
setIsLoading(false);
|
|
2464
|
+
return;
|
|
2465
|
+
}
|
|
2429
2466
|
abortControllerRef.current = new AbortController();
|
|
2430
2467
|
try {
|
|
2431
2468
|
let messagesToSend = [...existingMessages, userMessage];
|
|
@@ -2484,6 +2521,20 @@ ${currentContextSummary}` },
|
|
|
2484
2521
|
} else {
|
|
2485
2522
|
chatMessages = messagesToSend.map((m) => ({ role: m.role, content: m.content }));
|
|
2486
2523
|
}
|
|
2524
|
+
if (attachmentResults.length > 0 && shouldContinueAfterAttachment) {
|
|
2525
|
+
const attachmentContext = attachmentResults.filter((part) => part.type === "tool_result").map((part) => `[${part.label || part.toolName} \uACB0\uACFC]
|
|
2526
|
+
${part.result.content}`).join("\n\n");
|
|
2527
|
+
if (attachmentContext) {
|
|
2528
|
+
chatMessages.push({
|
|
2529
|
+
role: "user",
|
|
2530
|
+
content: `\uD30C\uC77C \uBD84\uC11D \uACB0\uACFC:
|
|
2531
|
+
|
|
2532
|
+
${attachmentContext}
|
|
2533
|
+
|
|
2534
|
+
\uC704 \uACB0\uACFC\uB97C \uCC38\uACE0\uD558\uC5EC \uB2F5\uBCC0\uD574\uC8FC\uC138\uC694.`
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2487
2538
|
console.log("[ChatUI] Messages to send:", chatMessages.length, chatMessages.map((m) => ({ role: m.role, content: m.content.slice(0, 50) })));
|
|
2488
2539
|
const baseSystemPrompt = buildSystemPrompt();
|
|
2489
2540
|
const combinedSystemPrompt = [baseSystemPrompt, actionPrompt].filter(Boolean).join("\n\n");
|
|
@@ -2491,8 +2542,8 @@ ${currentContextSummary}` },
|
|
|
2491
2542
|
const modelConfig = models.find((m) => m.id === selectedModel);
|
|
2492
2543
|
const provider = modelConfig?.provider || "ollama";
|
|
2493
2544
|
let response;
|
|
2494
|
-
if (
|
|
2495
|
-
const result = await
|
|
2545
|
+
if (onSendMessageRef.current) {
|
|
2546
|
+
const result = await onSendMessageRef.current({
|
|
2496
2547
|
messages: messagesForApi,
|
|
2497
2548
|
model: selectedModel,
|
|
2498
2549
|
provider,
|
|
@@ -2917,14 +2968,12 @@ ${result.content}
|
|
|
2917
2968
|
keepRecentMessages,
|
|
2918
2969
|
buildSystemPrompt,
|
|
2919
2970
|
compressContext,
|
|
2920
|
-
onSendMessage,
|
|
2921
|
-
onError,
|
|
2922
|
-
generateTitleCallback,
|
|
2923
|
-
onTitleChange,
|
|
2924
2971
|
useExternalStorage,
|
|
2925
|
-
onSaveMessages,
|
|
2926
2972
|
handleSkillCall,
|
|
2927
|
-
resolvedSkills
|
|
2973
|
+
resolvedSkills,
|
|
2974
|
+
/** @Todo vibecode - attachments, continueAfterToolResult를 deps에 추가하여 stale closure 방지 */
|
|
2975
|
+
attachments,
|
|
2976
|
+
continueAfterToolResult
|
|
2928
2977
|
]);
|
|
2929
2978
|
const handlePollSubmit = useCallback5(
|
|
2930
2979
|
(messageId, responses) => {
|
|
@@ -3192,8 +3241,8 @@ ${currentSession.contextSummary}` },
|
|
|
3192
3241
|
const provider = modelConfig?.provider || "ollama";
|
|
3193
3242
|
let responseContent = "";
|
|
3194
3243
|
let responseSources;
|
|
3195
|
-
if (
|
|
3196
|
-
const result = await
|
|
3244
|
+
if (onSendMessageRef.current) {
|
|
3245
|
+
const result = await onSendMessageRef.current({
|
|
3197
3246
|
messages: messagesForApi,
|
|
3198
3247
|
model: targetModel,
|
|
3199
3248
|
provider,
|
|
@@ -3471,7 +3520,25 @@ ${currentSession.contextSummary}` },
|
|
|
3471
3520
|
systemPrompt: `\uC0AC\uC6A9\uC790\uAC00 "${toolConfig.label || skillName}" \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD558\uB824\uACE0 \uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC758 \uBA54\uC2DC\uC9C0\uB97C \uBC14\uD0D5\uC73C\uB85C \uBC18\uB4DC\uC2DC <skill_use name="${skillName}"> \uD0DC\uADF8\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC774 \uB3C4\uAD6C\uB97C \uD638\uCD9C\uD558\uC138\uC694. \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uACE0 \uD14D\uC2A4\uD2B8\uB85C\uB9CC \uB2F5\uBCC0\uD558\uC9C0 \uB9C8\uC138\uC694.`
|
|
3472
3521
|
});
|
|
3473
3522
|
} else {
|
|
3474
|
-
|
|
3523
|
+
const currentQuery = input;
|
|
3524
|
+
executeManualSkill(skillName, { query: currentQuery }).then((result) => {
|
|
3525
|
+
if (!result || !result.content) return;
|
|
3526
|
+
let shouldContinue = continueAfterToolResult;
|
|
3527
|
+
if (onSkillCompleteRef.current) {
|
|
3528
|
+
const decision = onSkillCompleteRef.current(skillName, result);
|
|
3529
|
+
shouldContinue = decision === "continue";
|
|
3530
|
+
}
|
|
3531
|
+
if (!shouldContinue) return;
|
|
3532
|
+
skipNextSkillParsingRef.current = true;
|
|
3533
|
+
const resultPrompt = `\uC2A4\uD0AC "${skillName}" \uC2E4\uD589 \uACB0\uACFC:
|
|
3534
|
+
|
|
3535
|
+
${result.content}
|
|
3536
|
+
|
|
3537
|
+
\uC704 \uACB0\uACFC\uB97C \uBC14\uD0D5\uC73C\uB85C \uC0AC\uC6A9\uC790\uC758 \uC6D0\uB798 \uC9C8\uBB38\uC5D0 \uB2F5\uBCC0\uD574\uC8FC\uC138\uC694. skill_use \uD0DC\uADF8\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uB9C8\uC138\uC694.`;
|
|
3538
|
+
setTimeout(() => {
|
|
3539
|
+
sendMessage(resultPrompt, { hiddenUserMessage: true });
|
|
3540
|
+
}, 100);
|
|
3541
|
+
});
|
|
3475
3542
|
}
|
|
3476
3543
|
},
|
|
3477
3544
|
// Project
|
|
@@ -3902,6 +3969,7 @@ var ChatSidebar = ({
|
|
|
3902
3969
|
className: `chatllm-sidebar chatllm-sidebar-transition ${theme ? `chatllm-root ${themeClass}` : ""}`,
|
|
3903
3970
|
style: {
|
|
3904
3971
|
width: isOpen ? sidebarWidth : "0",
|
|
3972
|
+
height: "100%",
|
|
3905
3973
|
flexShrink: 0,
|
|
3906
3974
|
backgroundColor: "var(--chatllm-sidebar-bg)",
|
|
3907
3975
|
borderRight: isOpen ? "1px solid var(--chatllm-border)" : "none",
|
|
@@ -10305,6 +10373,7 @@ var ChatUIView = ({
|
|
|
10305
10373
|
currentProjectId,
|
|
10306
10374
|
onSelectProject: projects.length > 0 ? selectProject : void 0,
|
|
10307
10375
|
onNewProject: projects.length > 0 ? () => {
|
|
10376
|
+
if (typeof window === "undefined") return;
|
|
10308
10377
|
const title = window.prompt("\uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694");
|
|
10309
10378
|
if (title?.trim()) {
|
|
10310
10379
|
createProject({ title: title.trim() });
|